summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig3
-rw-r--r--.github/CODEOWNERS231
-rw-r--r--.github/workflows/android_builds.yml2
-rw-r--r--.github/workflows/ios_builds.yml2
-rw-r--r--.github/workflows/javascript_builds.disabled2
-rw-r--r--.github/workflows/linux_builds.yml20
-rw-r--r--.github/workflows/macos_builds.yml4
-rw-r--r--.github/workflows/static_checks.yml3
-rw-r--r--.github/workflows/windows_builds.yml6
-rw-r--r--.mailmap7
-rw-r--r--AUTHORS.md4
-rw-r--r--CHANGELOG.md4
-rw-r--r--CONTRIBUTING.md28
-rw-r--r--COPYRIGHT.txt9
-rw-r--r--DONORS.md102
-rw-r--r--README.md3
-rw-r--r--SConstruct56
-rw-r--r--core/config/project_settings.cpp242
-rw-r--r--core/config/project_settings.h14
-rw-r--r--core/core_bind.cpp95
-rw-r--r--core/core_bind.h25
-rw-r--r--core/core_constants.cpp50
-rw-r--r--core/core_string_names.cpp3
-rw-r--r--core/core_string_names.h1
-rw-r--r--core/crypto/crypto.cpp6
-rw-r--r--core/crypto/crypto.h2
-rw-r--r--core/debugger/engine_debugger.cpp2
-rw-r--r--core/debugger/remote_debugger.cpp1
-rw-r--r--core/debugger/remote_debugger_peer.cpp7
-rw-r--r--core/error/error_macros.h14
-rw-r--r--core/input/gamecontrollerdb.txt116
-rw-r--r--core/input/godotcontrollerdb.txt7
-rw-r--r--core/input/input.cpp113
-rw-r--r--core/input/input.h23
-rw-r--r--core/input/input_event.cpp123
-rw-r--r--core/input/input_event.h58
-rw-r--r--core/input/input_map.cpp549
-rw-r--r--core/input/input_map.h17
-rw-r--r--core/io/compression.cpp6
-rw-r--r--core/io/config_file.cpp5
-rw-r--r--core/io/config_file.h2
-rw-r--r--core/io/file_access_compressed.cpp6
-rw-r--r--core/io/file_access_encrypted.cpp4
-rw-r--r--core/io/file_access_memory.cpp2
-rw-r--r--core/io/file_access_network.cpp3
-rw-r--r--core/io/file_access_pack.cpp3
-rw-r--r--core/io/file_access_pack.h2
-rw-r--r--core/io/file_access_zip.cpp2
-rw-r--r--core/io/http_client.cpp5
-rw-r--r--core/io/image.cpp22
-rw-r--r--core/io/image.h2
-rw-r--r--core/io/image_loader.cpp2
-rw-r--r--core/io/image_loader.h2
-rw-r--r--core/io/ip.cpp24
-rw-r--r--core/io/json.cpp46
-rw-r--r--core/io/logger.cpp10
-rw-r--r--core/io/logger.h4
-rw-r--r--core/io/multiplayer_api.cpp8
-rw-r--r--core/io/packet_peer_udp.cpp2
-rw-r--r--core/io/resource.cpp37
-rw-r--r--core/io/resource.h2
-rw-r--r--core/io/resource_format_binary.cpp71
-rw-r--r--core/io/resource_format_binary.h4
-rw-r--r--core/io/resource_importer.cpp10
-rw-r--r--core/io/resource_importer.h6
-rw-r--r--core/io/resource_loader.cpp36
-rw-r--r--core/io/resource_loader.h18
-rw-r--r--core/io/translation_loader_po.cpp4
-rw-r--r--core/io/translation_loader_po.h2
-rw-r--r--core/io/xml_parser.cpp68
-rw-r--r--core/io/xml_parser.h2
-rw-r--r--core/math/basis.cpp6
-rw-r--r--core/math/color.cpp53
-rw-r--r--core/math/expression.cpp2
-rw-r--r--core/math/geometry_2d.cpp10
-rw-r--r--core/math/geometry_3d.cpp6
-rw-r--r--core/math/geometry_3d.h33
-rw-r--r--core/math/quick_hull.cpp2
-rw-r--r--core/math/transform.h4
-rw-r--r--core/math/triangulate.cpp2
-rw-r--r--core/math/vector3.h8
-rw-r--r--core/object/method_bind.h1
-rw-r--r--core/object/object.cpp34
-rw-r--r--core/object/object.h26
-rw-r--r--core/object/reference.cpp4
-rw-r--r--core/object/script_language.cpp10
-rw-r--r--core/object/undo_redo.cpp2
-rw-r--r--core/os/dir_access.cpp2
-rw-r--r--core/os/file_access.cpp2
-rw-r--r--core/os/keyboard.h2
-rw-r--r--core/os/memory.cpp26
-rw-r--r--core/os/memory.h6
-rw-r--r--core/os/os.h8
-rw-r--r--core/os/pool_allocator.cpp2
-rw-r--r--core/os/thread.cpp31
-rw-r--r--core/os/thread.h7
-rw-r--r--core/os/threaded_array_processor.h10
-rw-r--r--core/register_core_types.cpp4
-rw-r--r--core/string/optimized_translation.cpp (renamed from core/string/compressed_translation.cpp)32
-rw-r--r--core/string/optimized_translation.h (renamed from core/string/compressed_translation.h)14
-rw-r--r--core/string/translation.cpp33
-rw-r--r--core/string/translation_po.cpp4
-rw-r--r--core/string/ustring.cpp111
-rw-r--r--core/string/ustring.h4
-rw-r--r--core/templates/command_queue_mt.h5
-rw-r--r--core/templates/cowdata.h43
-rw-r--r--core/templates/rid_owner.cpp2
-rw-r--r--core/templates/rid_owner.h95
-rw-r--r--core/templates/safe_refcount.cpp161
-rw-r--r--core/templates/safe_refcount.h352
-rw-r--r--core/variant/array.cpp26
-rw-r--r--core/variant/array.h5
-rw-r--r--core/variant/binder_common.h165
-rw-r--r--core/variant/callable.cpp4
-rw-r--r--core/variant/variant.h3
-rw-r--r--core/variant/variant_call.cpp166
-rw-r--r--core/variant/variant_construct.cpp1
-rw-r--r--core/variant/variant_parser.cpp45
-rw-r--r--core/variant/variant_setget.cpp2
-rw-r--r--doc/Makefile11
-rw-r--r--doc/classes/@GlobalScope.xml644
-rw-r--r--doc/classes/AABB.xml48
-rw-r--r--doc/classes/AStar.xml2
-rw-r--r--doc/classes/AnimatedSprite3D.xml5
-rw-r--r--doc/classes/Animation.xml2
-rw-r--r--doc/classes/AnimationPlayer.xml10
-rw-r--r--doc/classes/AnimationTree.xml10
-rw-r--r--doc/classes/Area2D.xml8
-rw-r--r--doc/classes/Area3D.xml8
-rw-r--r--doc/classes/Array.xml44
-rw-r--r--doc/classes/AtlasTexture.xml5
-rw-r--r--doc/classes/AudioEffectCapture.xml2
-rw-r--r--doc/classes/BackBufferCopy.xml2
-rw-r--r--doc/classes/BakedLightmapData.xml6
-rw-r--r--doc/classes/BaseButton.xml2
-rw-r--r--doc/classes/BaseMaterial3D.xml72
-rw-r--r--doc/classes/Basis.xml30
-rw-r--r--doc/classes/Button.xml5
-rw-r--r--doc/classes/Callable.xml42
-rw-r--r--doc/classes/Camera2D.xml8
-rw-r--r--doc/classes/Camera3D.xml2
-rw-r--r--doc/classes/CanvasItem.xml2
-rw-r--r--doc/classes/CharFXTransform.xml2
-rw-r--r--doc/classes/CheckBox.xml6
-rw-r--r--doc/classes/CheckButton.xml6
-rw-r--r--doc/classes/ClippedCamera3D.xml8
-rw-r--r--doc/classes/CodeEdit.xml8
-rw-r--r--doc/classes/CodeHighlighter.xml40
-rw-r--r--doc/classes/CollisionPolygon3D.xml3
-rw-r--r--doc/classes/Color.xml130
-rw-r--r--doc/classes/ColorPicker.xml3
-rw-r--r--doc/classes/ColorPickerButton.xml6
-rw-r--r--doc/classes/ConcavePolygonShape3D.xml5
-rw-r--r--doc/classes/ConfigFile.xml2
-rw-r--r--doc/classes/Control.xml4
-rw-r--r--doc/classes/CryptoKey.xml4
-rw-r--r--doc/classes/Curve2D.xml2
-rw-r--r--doc/classes/Curve3D.xml2
-rw-r--r--doc/classes/Decal.xml4
-rw-r--r--doc/classes/Dictionary.xml22
-rw-r--r--doc/classes/Directory.xml4
-rw-r--r--doc/classes/DisplayServer.xml38
-rw-r--r--doc/classes/EditorFileSystem.xml2
-rw-r--r--doc/classes/EditorImportPlugin.xml12
-rw-r--r--doc/classes/EditorInspector.xml8
-rw-r--r--doc/classes/EditorInspectorPlugin.xml4
-rw-r--r--doc/classes/EditorNode3DGizmoPlugin.xml16
-rw-r--r--doc/classes/EditorPlugin.xml8
-rw-r--r--doc/classes/EditorSceneImporterMesh.xml2
-rw-r--r--doc/classes/EditorSettings.xml10
-rw-r--r--doc/classes/EditorSyntaxHighlighter.xml6
-rw-r--r--doc/classes/EditorVCSInterface.xml2
-rw-r--r--doc/classes/Engine.xml2
-rw-r--r--doc/classes/Environment.xml10
-rw-r--r--doc/classes/File.xml11
-rw-r--r--doc/classes/Font.xml9
-rw-r--r--doc/classes/FontData.xml86
-rw-r--r--doc/classes/GIProbe.xml2
-rw-r--r--doc/classes/Geometry3D.xml2
-rw-r--r--doc/classes/GraphEdit.xml2
-rw-r--r--doc/classes/GraphNode.xml9
-rw-r--r--doc/classes/HTTPClient.xml2
-rw-r--r--doc/classes/HTTPRequest.xml2
-rw-r--r--doc/classes/IP.xml2
-rw-r--r--doc/classes/Image.xml16
-rw-r--r--doc/classes/Input.xml26
-rw-r--r--doc/classes/InputEvent.xml8
-rw-r--r--doc/classes/InputEventAction.xml2
-rw-r--r--doc/classes/InputEventJoypadButton.xml2
-rw-r--r--doc/classes/InputEventJoypadMotion.xml2
-rw-r--r--doc/classes/InputEventKey.xml4
-rw-r--r--doc/classes/InputEventMouse.xml2
-rw-r--r--doc/classes/InputEventMouseButton.xml2
-rw-r--r--doc/classes/InputMap.xml2
-rw-r--r--doc/classes/ItemList.xml27
-rw-r--r--doc/classes/KinematicBody2D.xml5
-rw-r--r--doc/classes/KinematicBody3D.xml5
-rw-r--r--doc/classes/Label.xml2
-rw-r--r--doc/classes/Light3D.xml4
-rw-r--r--doc/classes/LineEdit.xml10
-rw-r--r--doc/classes/LinkButton.xml6
-rw-r--r--doc/classes/MarginContainer.xml20
-rw-r--r--doc/classes/MenuButton.xml8
-rw-r--r--doc/classes/MultiMesh.xml2
-rw-r--r--doc/classes/Navigation2D.xml59
-rw-r--r--doc/classes/Navigation3D.xml84
-rw-r--r--doc/classes/NavigationAgent2D.xml20
-rw-r--r--doc/classes/NavigationAgent3D.xml20
-rw-r--r--doc/classes/NavigationMesh.xml2
-rw-r--r--doc/classes/NavigationObstacle2D.xml18
-rw-r--r--doc/classes/NavigationObstacle3D.xml18
-rw-r--r--doc/classes/NavigationRegion2D.xml9
-rw-r--r--doc/classes/NavigationRegion3D.xml6
-rw-r--r--doc/classes/NavigationServer2D.xml71
-rw-r--r--doc/classes/NavigationServer3D.xml75
-rw-r--r--doc/classes/Node.xml44
-rw-r--r--doc/classes/Node3D.xml4
-rw-r--r--doc/classes/NodePath.xml18
-rw-r--r--doc/classes/OS.xml58
-rw-r--r--doc/classes/Object.xml250
-rw-r--r--doc/classes/OptimizedTranslation.xml (renamed from doc/classes/PHashTranslation.xml)2
-rw-r--r--doc/classes/OptionButton.xml6
-rw-r--r--doc/classes/PackedByteArray.xml24
-rw-r--r--doc/classes/PackedColorArray.xml8
-rw-r--r--doc/classes/PackedFloat32Array.xml8
-rw-r--r--doc/classes/PackedFloat64Array.xml8
-rw-r--r--doc/classes/PackedInt32Array.xml8
-rw-r--r--doc/classes/PackedInt64Array.xml8
-rw-r--r--doc/classes/PackedScene.xml2
-rw-r--r--doc/classes/PackedStringArray.xml8
-rw-r--r--doc/classes/PackedVector2Array.xml8
-rw-r--r--doc/classes/PackedVector3Array.xml8
-rw-r--r--doc/classes/PhysicalBone3D.xml2
-rw-r--r--doc/classes/PhysicalSkyMaterial.xml8
-rw-r--r--doc/classes/PhysicsServer2D.xml106
-rw-r--r--doc/classes/PhysicsServer3D.xml216
-rw-r--r--doc/classes/Plane.xml20
-rw-r--r--doc/classes/PopupMenu.xml16
-rw-r--r--doc/classes/PrimitiveMesh.xml2
-rw-r--r--doc/classes/ProgressBar.xml6
-rw-r--r--doc/classes/ProjectSettings.xml700
-rw-r--r--doc/classes/Quat.xml24
-rw-r--r--doc/classes/RID.xml2
-rw-r--r--doc/classes/RayCast3D.xml7
-rw-r--r--doc/classes/Rect2.xml28
-rw-r--r--doc/classes/Rect2i.xml26
-rw-r--r--doc/classes/RenderingDevice.xml34
-rw-r--r--doc/classes/RenderingServer.xml22
-rw-r--r--doc/classes/ResourceFormatLoader.xml13
-rw-r--r--doc/classes/ResourceLoader.xml10
-rw-r--r--doc/classes/RichTextEffect.xml10
-rw-r--r--doc/classes/RichTextLabel.xml27
-rw-r--r--doc/classes/RigidBody2D.xml2
-rw-r--r--doc/classes/SceneTree.xml39
-rw-r--r--doc/classes/SceneTreeTimer.xml14
-rw-r--r--doc/classes/ScriptCreateDialog.xml20
-rw-r--r--doc/classes/ScriptEditor.xml6
-rw-r--r--doc/classes/ScriptEditorBase.xml11
-rw-r--r--doc/classes/Shape3D.xml3
-rw-r--r--doc/classes/Signal.xml14
-rw-r--r--doc/classes/Skeleton3D.xml2
-rw-r--r--doc/classes/Sky.xml6
-rw-r--r--doc/classes/SoftBody3D.xml14
-rw-r--r--doc/classes/SpinBox.xml14
-rw-r--r--doc/classes/Sprite2D.xml29
-rw-r--r--doc/classes/Sprite3D.xml2
-rw-r--r--doc/classes/SpriteBase3D.xml4
-rw-r--r--doc/classes/StreamPeer.xml18
-rw-r--r--doc/classes/String.xml253
-rw-r--r--doc/classes/StringName.xml2
-rw-r--r--doc/classes/StyleBoxFlat.xml8
-rw-r--r--doc/classes/SurfaceTool.xml33
-rw-r--r--doc/classes/SyntaxHighlighter.xml37
-rw-r--r--doc/classes/TabContainer.xml6
-rw-r--r--doc/classes/Tabs.xml8
-rw-r--r--doc/classes/TextEdit.xml28
-rw-r--r--doc/classes/TextParagraph.xml2
-rw-r--r--doc/classes/TextServer.xml100
-rw-r--r--doc/classes/Theme.xml4
-rw-r--r--doc/classes/TileMap.xml17
-rw-r--r--doc/classes/Timer.xml10
-rw-r--r--doc/classes/TouchScreenButton.xml7
-rw-r--r--doc/classes/Transform.xml20
-rw-r--r--doc/classes/Transform2D.xml26
-rw-r--r--doc/classes/Tree.xml58
-rw-r--r--doc/classes/Tween.xml15
-rw-r--r--doc/classes/UDPServer.xml86
-rw-r--r--doc/classes/UndoRedo.xml39
-rw-r--r--doc/classes/Vector2.xml66
-rw-r--r--doc/classes/Vector2i.xml6
-rw-r--r--doc/classes/Vector3.xml79
-rw-r--r--doc/classes/Vector3i.xml8
-rw-r--r--doc/classes/VisualShaderNodeCustom.xml2
-rw-r--r--doc/classes/VisualShaderNodeDeterminant.xml2
-rw-r--r--doc/classes/VisualShaderNodeExpression.xml2
-rw-r--r--doc/classes/VisualShaderNodeFaceForward.xml2
-rw-r--r--doc/classes/VisualShaderNodeGroupBase.xml4
-rw-r--r--doc/classes/VisualShaderNodeIf.xml2
-rw-r--r--doc/classes/VisualShaderNodeInput.xml2
-rw-r--r--doc/classes/VisualShaderNodeSDFToScreenUV.xml2
-rw-r--r--doc/classes/VisualShaderNodeScreenUVToSDF.xml2
-rw-r--r--doc/classes/VisualShaderNodeSmoothStep.xml2
-rw-r--r--doc/classes/VisualShaderNodeTextureSDF.xml2
-rw-r--r--doc/classes/VisualShaderNodeTextureSDFNormal.xml2
-rw-r--r--doc/classes/Window.xml13
-rw-r--r--doc/classes/World2D.xml3
-rw-r--r--doc/classes/World3D.xml3
-rw-r--r--doc/classes/XRController3D.xml2
-rw-r--r--doc/classes/bool.xml3
-rwxr-xr-xdoc/tools/makerst.py15
-rw-r--r--doc/translations/README.md1
-rw-r--r--doc/translations/classes.pot14
-rw-r--r--doc/translations/fr.po14
-rw-r--r--drivers/alsa/SCsub3
-rw-r--r--drivers/alsa/asound-so_wrap.c14092
-rw-r--r--drivers/alsa/asound-so_wrap.h5134
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp25
-rw-r--r--drivers/alsa/audio_driver_alsa.h2
-rw-r--r--drivers/alsamidi/midi_driver_alsamidi.h2
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.cpp38
-rw-r--r--drivers/dummy/rasterizer_dummy.h446
-rw-r--r--drivers/dummy/texture_loader_dummy.cpp2
-rw-r--r--drivers/dummy/texture_loader_dummy.h2
-rw-r--r--drivers/pulseaudio/SCsub3
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp13
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.h2
-rw-r--r--drivers/pulseaudio/pulse-so_wrap.c3950
-rw-r--r--drivers/pulseaudio/pulse-so_wrap.h1446
-rw-r--r--drivers/unix/file_access_unix.cpp2
-rw-r--r--drivers/unix/thread_posix.cpp4
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp332
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h17
-rw-r--r--drivers/vulkan/vulkan_context.cpp70
-rw-r--r--drivers/vulkan/vulkan_context.h9
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp2
-rw-r--r--drivers/windows/file_access_windows.cpp2
-rw-r--r--drivers/xaudio2/audio_driver_xaudio2.cpp4
-rw-r--r--editor/action_map_editor.cpp1167
-rw-r--r--editor/action_map_editor.h203
-rw-r--r--editor/animation_bezier_editor.cpp18
-rw-r--r--editor/animation_track_editor.cpp115
-rw-r--r--editor/animation_track_editor.h4
-rw-r--r--editor/animation_track_editor_plugins.cpp4
-rw-r--r--editor/array_property_edit.cpp11
-rw-r--r--editor/array_property_edit.h1
-rw-r--r--editor/audio_stream_preview.cpp6
-rw-r--r--editor/audio_stream_preview.h14
-rw-r--r--editor/code_editor.cpp8
-rw-r--r--editor/connections_dialog.cpp2
-rw-r--r--editor/create_dialog.cpp5
-rw-r--r--editor/debugger/editor_debugger_inspector.h2
-rw-r--r--editor/debugger/editor_debugger_tree.cpp15
-rw-r--r--editor/debugger/editor_debugger_tree.h1
-rw-r--r--editor/debugger/editor_performance_profiler.cpp2
-rw-r--r--editor/debugger/editor_profiler.cpp4
-rw-r--r--editor/debugger/editor_visual_profiler.cpp4
-rw-r--r--editor/debugger/script_editor_debugger.cpp2
-rw-r--r--editor/dependency_editor.cpp8
-rw-r--r--editor/dictionary_property_edit.cpp11
-rw-r--r--editor/dictionary_property_edit.h1
-rw-r--r--editor/doc_tools.cpp25
-rw-r--r--editor/editor_audio_buses.cpp14
-rw-r--r--editor/editor_data.cpp56
-rw-r--r--editor/editor_data.h5
-rw-r--r--editor/editor_export.cpp93
-rw-r--r--editor/editor_feature_profile.cpp6
-rw-r--r--editor/editor_file_dialog.cpp5
-rw-r--r--editor/editor_file_system.cpp99
-rw-r--r--editor/editor_file_system.h9
-rw-r--r--editor/editor_folding.cpp16
-rw-r--r--editor/editor_inspector.cpp143
-rw-r--r--editor/editor_inspector.h16
-rw-r--r--editor/editor_node.cpp349
-rw-r--r--editor/editor_node.h22
-rw-r--r--editor/editor_plugin.cpp14
-rw-r--r--editor/editor_plugin.h4
-rw-r--r--editor/editor_properties.cpp108
-rw-r--r--editor/editor_properties.h5
-rw-r--r--editor/editor_properties_array_dict.cpp6
-rw-r--r--editor/editor_properties_array_dict.h8
-rw-r--r--editor/editor_resource_preview.cpp12
-rw-r--r--editor/editor_resource_preview.h5
-rw-r--r--editor/editor_sectioned_inspector.cpp12
-rw-r--r--editor/editor_sectioned_inspector.h3
-rw-r--r--editor/editor_settings.cpp168
-rw-r--r--editor/editor_settings.h6
-rw-r--r--editor/editor_spin_slider.cpp18
-rw-r--r--editor/editor_sub_scene.cpp265
-rw-r--r--editor/editor_themes.cpp107
-rw-r--r--editor/editor_themes.h3
-rw-r--r--editor/fileserver/editor_file_server.cpp5
-rw-r--r--editor/fileserver/editor_file_server.h2
-rw-r--r--editor/filesystem_dock.cpp53
-rw-r--r--editor/find_in_files.cpp5
-rw-r--r--editor/icons/ColorPickerBarArrow.svg1
-rw-r--r--editor/icons/GPUParticlesAttractorBox.svg1
-rw-r--r--editor/icons/GPUParticlesAttractorSphere.svg1
-rw-r--r--editor/icons/GPUParticlesAttractorVectorField.svg1
-rw-r--r--editor/icons/GPUParticlesCollisionBox.svg1
-rw-r--r--editor/icons/GPUParticlesCollisionHeightField.svg1
-rw-r--r--editor/icons/GPUParticlesCollisionSDF.svg1
-rw-r--r--editor/icons/GPUParticlesCollisionSphere.svg1
-rw-r--r--editor/icons/Logo.svg2
-rw-r--r--editor/icons/NodeDisabled.svg1
-rw-r--r--editor/import/editor_import_collada.cpp85
-rw-r--r--editor/import/resource_importer_csv_translation.cpp4
-rw-r--r--editor/import/resource_importer_layered_texture.cpp12
-rw-r--r--editor/import/resource_importer_obj.cpp2
-rw-r--r--editor/import/resource_importer_scene.cpp1296
-rw-r--r--editor/import/resource_importer_scene.h90
-rw-r--r--editor/import/resource_importer_texture.cpp16
-rw-r--r--editor/import/scene_import_settings.cpp1199
-rw-r--r--editor/import/scene_import_settings.h199
-rw-r--r--editor/import/scene_importer_mesh.cpp357
-rw-r--r--editor/import/scene_importer_mesh.h18
-rw-r--r--editor/import_defaults_editor.cpp216
-rw-r--r--editor/import_defaults_editor.h (renamed from editor/editor_sub_scene.h)58
-rw-r--r--editor/import_dock.cpp160
-rw-r--r--editor/import_dock.h4
-rw-r--r--editor/input_map_editor.cpp1033
-rw-r--r--editor/localization_editor.cpp96
-rw-r--r--editor/node_3d_editor_gizmos.cpp94
-rw-r--r--editor/node_3d_editor_gizmos.h12
-rw-r--r--editor/plugin_config_dialog.cpp8
-rw-r--r--editor/plugin_config_dialog.h2
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp16
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.cpp10
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.cpp12
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp5
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp12
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp47
-rw-r--r--editor/plugins/asset_library_editor_plugin.h1
-rw-r--r--editor/plugins/audio_stream_editor_plugin.cpp15
-rw-r--r--editor/plugins/audio_stream_editor_plugin.h22
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp214
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h10
-rw-r--r--editor/plugins/collision_polygon_3d_editor_plugin.cpp10
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.cpp4
-rw-r--r--editor/plugins/curve_editor_plugin.cpp8
-rw-r--r--editor/plugins/editor_preview_plugins.cpp18
-rw-r--r--editor/plugins/editor_preview_plugins.h8
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/item_list_editor_plugin.cpp12
-rw-r--r--editor/plugins/mesh_editor_plugin.cpp2
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp560
-rw-r--r--editor/plugins/node_3d_editor_plugin.h62
-rw-r--r--editor/plugins/packed_scene_translation_parser_plugin.cpp2
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp10
-rw-r--r--editor/plugins/path_3d_editor_plugin.cpp4
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp10
-rw-r--r--editor/plugins/script_editor_plugin.cpp18
-rw-r--r--editor/plugins/script_editor_plugin.h2
-rw-r--r--editor/plugins/script_text_editor.cpp42
-rw-r--r--editor/plugins/shader_editor_plugin.cpp34
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.cpp7
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp30
-rw-r--r--editor/plugins/text_editor.cpp30
-rw-r--r--editor/plugins/texture_3d_editor_plugin.cpp8
-rw-r--r--editor/plugins/texture_3d_editor_plugin.h4
-rw-r--r--editor/plugins/texture_editor_plugin.cpp8
-rw-r--r--editor/plugins/texture_editor_plugin.h2
-rw-r--r--editor/plugins/texture_layered_editor_plugin.cpp11
-rw-r--r--editor/plugins/texture_layered_editor_plugin.h3
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp74
-rw-r--r--editor/plugins/texture_region_editor_plugin.h4
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp33
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp59
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp4
-rw-r--r--editor/pot_generator.cpp6
-rw-r--r--editor/project_export.cpp2
-rw-r--r--editor/project_manager.cpp40
-rw-r--r--editor/project_manager.h2
-rw-r--r--editor/project_settings_editor.cpp262
-rw-r--r--editor/project_settings_editor.h25
-rw-r--r--editor/property_editor.cpp22
-rw-r--r--editor/rename_dialog.cpp5
-rw-r--r--editor/scene_tree_dock.cpp334
-rw-r--r--editor/scene_tree_dock.h23
-rw-r--r--editor/scene_tree_editor.cpp48
-rw-r--r--editor/scene_tree_editor.h6
-rw-r--r--editor/settings_config_dialog.cpp348
-rw-r--r--editor/settings_config_dialog.h33
-rw-r--r--editor/shader_globals_editor.cpp5
-rw-r--r--editor/translations/af.po115
-rw-r--r--editor/translations/ar.po138
-rw-r--r--editor/translations/bg.po422
-rw-r--r--editor/translations/bn.po186
-rw-r--r--editor/translations/br.po108
-rw-r--r--editor/translations/ca.po122
-rw-r--r--editor/translations/cs.po194
-rw-r--r--editor/translations/da.po152
-rw-r--r--editor/translations/de.po151
-rw-r--r--editor/translations/editor.pot108
-rw-r--r--editor/translations/el.po145
-rw-r--r--editor/translations/eo.po122
-rw-r--r--editor/translations/es.po271
-rw-r--r--editor/translations/es_AR.po209
-rw-r--r--editor/translations/et.po198
-rw-r--r--editor/translations/eu.po114
-rw-r--r--editor/translations/fa.po137
-rw-r--r--editor/translations/fi.po127
-rw-r--r--editor/translations/fil.po109
-rw-r--r--editor/translations/fr.po146
-rw-r--r--editor/translations/ga.po108
-rw-r--r--editor/translations/gl.po12861
-rw-r--r--editor/translations/he.po149
-rw-r--r--editor/translations/hi.po118
-rw-r--r--editor/translations/hr.po113
-rw-r--r--editor/translations/hu.po121
-rw-r--r--editor/translations/id.po219
-rw-r--r--editor/translations/is.po111
-rw-r--r--editor/translations/it.po335
-rw-r--r--editor/translations/ja.po167
-rw-r--r--editor/translations/ka.po112
-rw-r--r--editor/translations/ko.po420
-rw-r--r--editor/translations/lt.po124
-rw-r--r--editor/translations/lv.po115
-rw-r--r--editor/translations/mi.po108
-rw-r--r--editor/translations/mk.po108
-rw-r--r--editor/translations/ml.po108
-rw-r--r--editor/translations/mr.po108
-rw-r--r--editor/translations/ms.po120
-rw-r--r--editor/translations/nb.po575
-rw-r--r--editor/translations/nl.po343
-rw-r--r--editor/translations/or.po108
-rw-r--r--editor/translations/pl.po177
-rw-r--r--editor/translations/pr.po111
-rw-r--r--editor/translations/pt.po126
-rw-r--r--editor/translations/pt_BR.po176
-rw-r--r--editor/translations/ro.po122
-rw-r--r--editor/translations/ru.po138
-rw-r--r--editor/translations/si.po129
-rw-r--r--editor/translations/sk.po123
-rw-r--r--editor/translations/sl.po130
-rw-r--r--editor/translations/sq.po117
-rw-r--r--editor/translations/sr_Cyrl.po126
-rw-r--r--editor/translations/sr_Latn.po111
-rw-r--r--editor/translations/sv.po117
-rw-r--r--editor/translations/ta.po111
-rw-r--r--editor/translations/te.po108
-rw-r--r--editor/translations/th.po136
-rw-r--r--editor/translations/tr.po150
-rw-r--r--editor/translations/tzm.po108
-rw-r--r--editor/translations/uk.po135
-rw-r--r--editor/translations/ur_PK.po112
-rw-r--r--editor/translations/vi.po263
-rw-r--r--editor/translations/zh_CN.po230
-rw-r--r--editor/translations/zh_HK.po122
-rw-r--r--editor/translations/zh_TW.po189
-rw-r--r--main/main.cpp251
-rw-r--r--main/main.h2
-rw-r--r--main/main_builders.py5
-rw-r--r--main/performance.cpp2
-rw-r--r--methods.py105
-rw-r--r--misc/dist/html/editor.html199
-rw-r--r--misc/dist/html/full-size.html75
-rw-r--r--misc/dist/html/manifest.json18
-rw-r--r--misc/dist/html/offline.html42
-rw-r--r--misc/dist/html/service-worker.js84
-rw-r--r--misc/dist/linux/org.godotengine.Godot.xml29
-rw-r--r--misc/dist/linux/x-godot-project.xml8
-rw-r--r--misc/dist/project_icon.svg2
-rwxr-xr-xmisc/hooks/pre-commit-clang-format5
-rwxr-xr-xmisc/scripts/clang_format.sh2
-rwxr-xr-xmisc/scripts/file_format.sh11
-rw-r--r--modules/basis_universal/texture_basisu.cpp1
-rw-r--r--modules/basis_universal/texture_basisu.h2
-rw-r--r--modules/bmp/image_loader_bmp.h30
-rw-r--r--modules/bullet/area_bullet.h10
-rw-r--r--modules/bullet/btRayShape.cpp4
-rw-r--r--modules/bullet/btRayShape.h6
-rw-r--r--modules/bullet/bullet_physics_server.cpp104
-rw-r--r--modules/bullet/bullet_physics_server.h35
-rw-r--r--modules/bullet/bullet_types_converter.cpp2
-rw-r--r--modules/bullet/collision_object_bullet.cpp8
-rw-r--r--modules/bullet/collision_object_bullet.h2
-rw-r--r--modules/bullet/config.py3
-rw-r--r--modules/bullet/godot_collision_dispatcher.cpp4
-rw-r--r--modules/bullet/godot_motion_state.h2
-rw-r--r--modules/bullet/godot_ray_world_algorithm.h2
-rw-r--r--modules/bullet/godot_result_callbacks.cpp4
-rw-r--r--modules/bullet/godot_result_callbacks.h38
-rw-r--r--modules/bullet/rid_bullet.h2
-rw-r--r--modules/bullet/rigid_body_bullet.cpp4
-rw-r--r--modules/bullet/rigid_body_bullet.h22
-rw-r--r--modules/bullet/shape_bullet.cpp10
-rw-r--r--modules/bullet/shape_bullet.h10
-rw-r--r--modules/bullet/soft_body_bullet.cpp65
-rw-r--r--modules/bullet/soft_body_bullet.h24
-rw-r--r--modules/bullet/space_bullet.cpp14
-rw-r--r--modules/bullet/space_bullet.h6
-rw-r--r--modules/csg/csg.cpp10
-rw-r--r--modules/csg/csg.h32
-rw-r--r--modules/csg/csg_shape.cpp27
-rw-r--r--modules/csg/csg_shape.h28
-rw-r--r--modules/cvtt/image_compress_cvtt.cpp23
-rw-r--r--modules/dds/texture_loader_dds.cpp12
-rw-r--r--modules/dds/texture_loader_dds.h2
-rw-r--r--modules/enet/doc_classes/NetworkedMultiplayerENet.xml16
-rw-r--r--modules/enet/networked_multiplayer_enet.cpp27
-rw-r--r--modules/enet/networked_multiplayer_enet.h39
-rw-r--r--modules/etc/texture_loader_pkm.cpp12
-rw-r--r--modules/etc/texture_loader_pkm.h2
-rw-r--r--modules/fbx/data/fbx_mesh_data.cpp1
-rw-r--r--modules/fbx/editor_scene_importer_fbx.cpp4
-rw-r--r--modules/gdnative/gdnative.cpp12
-rw-r--r--modules/gdnative/gdnative.h4
-rw-r--r--modules/gdnative/gdnative/aabb.cpp4
-rw-r--r--modules/gdnative/gdnative/array.cpp14
-rw-r--r--modules/gdnative/gdnative/basis.cpp14
-rw-r--r--modules/gdnative/gdnative/callable.cpp4
-rw-r--r--modules/gdnative/gdnative/color.cpp14
-rw-r--r--modules/gdnative/gdnative/dictionary.cpp15
-rw-r--r--modules/gdnative/gdnative/gdnative.cpp11
-rw-r--r--modules/gdnative/gdnative/node_path.cpp4
-rw-r--r--modules/gdnative/gdnative/packed_arrays.cpp154
-rw-r--r--modules/gdnative/gdnative/plane.cpp4
-rw-r--r--modules/gdnative/gdnative/quat.cpp14
-rw-r--r--modules/gdnative/gdnative/rect2.cpp8
-rw-r--r--modules/gdnative/gdnative/rid.cpp4
-rw-r--r--modules/gdnative/gdnative/signal.cpp4
-rw-r--r--modules/gdnative/gdnative/string.cpp44
-rw-r--r--modules/gdnative/gdnative/string_name.cpp4
-rw-r--r--modules/gdnative/gdnative/transform.cpp4
-rw-r--r--modules/gdnative/gdnative/transform2d.cpp14
-rw-r--r--modules/gdnative/gdnative/variant.cpp97
-rw-r--r--modules/gdnative/gdnative/vector2.cpp28
-rw-r--r--modules/gdnative/gdnative/vector3.cpp28
-rw-r--r--modules/gdnative/gdnative_api.json1312
-rw-r--r--modules/gdnative/gdnative_library_editor_plugin.cpp2
-rw-r--r--modules/gdnative/gdnative_library_editor_plugin.h6
-rw-r--r--modules/gdnative/include/gdnative/aabb.h1
-rw-r--r--modules/gdnative/include/gdnative/array.h4
-rw-r--r--modules/gdnative/include/gdnative/basis.h3
-rw-r--r--modules/gdnative/include/gdnative/callable.h1
-rw-r--r--modules/gdnative/include/gdnative/color.h3
-rw-r--r--modules/gdnative/include/gdnative/dictionary.h4
-rw-r--r--modules/gdnative/include/gdnative/gdnative.h11
-rw-r--r--modules/gdnative/include/gdnative/node_path.h1
-rw-r--r--modules/gdnative/include/gdnative/packed_arrays.h40
-rw-r--r--modules/gdnative/include/gdnative/plane.h1
-rw-r--r--modules/gdnative/include/gdnative/quat.h3
-rw-r--r--modules/gdnative/include/gdnative/rect2.h2
-rw-r--r--modules/gdnative/include/gdnative/rid.h1
-rw-r--r--modules/gdnative/include/gdnative/signal.h1
-rw-r--r--modules/gdnative/include/gdnative/string.h10
-rw-r--r--modules/gdnative/include/gdnative/transform.h1
-rw-r--r--modules/gdnative/include/gdnative/transform2d.h3
-rw-r--r--modules/gdnative/include/gdnative/variant.h18
-rw-r--r--modules/gdnative/include/gdnative/variant_struct.h (renamed from platform/javascript/http_request.h)46
-rw-r--r--modules/gdnative/include/gdnative/vector2.h6
-rw-r--r--modules/gdnative/include/gdnative/vector3.h6
-rw-r--r--modules/gdnative/include/nativescript/godot_nativescript.h2
-rw-r--r--modules/gdnative/include/text/godot_text.h8
-rw-r--r--modules/gdnative/nativescript/api_generator.cpp43
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp19
-rw-r--r--modules/gdnative/nativescript/nativescript.h37
-rw-r--r--modules/gdnative/pluginscript/pluginscript_instance.h6
-rw-r--r--modules/gdnative/pluginscript/pluginscript_loader.cpp2
-rw-r--r--modules/gdnative/pluginscript/pluginscript_loader.h2
-rw-r--r--modules/gdnative/register_types.cpp2
-rw-r--r--modules/gdnative/tests/test_variant.h1
-rw-r--r--modules/gdnative/text/text_server_gdnative.cpp42
-rw-r--r--modules/gdnative/text/text_server_gdnative.h11
-rw-r--r--modules/gdnative/videodecoder/video_stream_gdnative.cpp4
-rw-r--r--modules/gdnative/videodecoder/video_stream_gdnative.h4
-rw-r--r--modules/gdnative/xr/xr_interface_gdnative.cpp2
-rw-r--r--modules/gdnavigation/gd_navigation_server.cpp58
-rw-r--r--modules/gdnavigation/gd_navigation_server.h11
-rw-r--r--modules/gdnavigation/nav_map.cpp518
-rw-r--r--modules/gdnavigation/nav_map.h3
-rw-r--r--modules/gdnavigation/nav_region.cpp30
-rw-r--r--modules/gdnavigation/nav_region.h16
-rw-r--r--modules/gdnavigation/nav_utils.h45
-rw-r--r--modules/gdnavigation/rvo_agent.h2
-rw-r--r--modules/gdscript/editor/gdscript_translation_parser_plugin.cpp2
-rw-r--r--modules/gdscript/editor/gdscript_translation_parser_plugin.h4
-rw-r--r--modules/gdscript/gdscript.cpp15
-rw-r--r--modules/gdscript/gdscript.h18
-rw-r--r--modules/gdscript/gdscript_compiler.cpp79
-rw-r--r--modules/gdscript/gdscript_compiler.h4
-rw-r--r--modules/gdscript/gdscript_editor.cpp3
-rw-r--r--modules/gdscript/gdscript_function.cpp9
-rw-r--r--modules/gdscript/gdscript_function.h16
-rw-r--r--modules/gdscript/gdscript_parser.cpp26
-rw-r--r--modules/gdscript/gdscript_parser.h7
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp5
-rw-r--r--modules/gdscript/gdscript_tokenizer.h1
-rw-r--r--modules/gdscript/gdscript_vm.cpp2
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.cpp2
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.cpp5
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.h8
-rw-r--r--modules/gdscript/language_server/lsp.hpp16
-rw-r--r--modules/gdscript/register_types.cpp2
-rw-r--r--modules/gdscript/tests/test_gdscript.cpp7
-rw-r--r--modules/gltf/config.py24
-rw-r--r--modules/gltf/doc_classes/EditorSceneImporterGLTF.xml (renamed from doc/classes/EditorSceneImporterGLTF.xml)0
-rw-r--r--modules/gltf/doc_classes/GLTFAccessor.xml (renamed from doc/classes/GLTFAccessor.xml)0
-rw-r--r--modules/gltf/doc_classes/GLTFAnimation.xml (renamed from doc/classes/GLTFAnimation.xml)0
-rw-r--r--modules/gltf/doc_classes/GLTFBufferView.xml (renamed from doc/classes/GLTFBufferView.xml)0
-rw-r--r--modules/gltf/doc_classes/GLTFCamera.xml (renamed from doc/classes/GLTFCamera.xml)0
-rw-r--r--modules/gltf/doc_classes/GLTFDocument.xml (renamed from doc/classes/GLTFDocument.xml)0
-rw-r--r--modules/gltf/doc_classes/GLTFLight.xml (renamed from doc/classes/GLTFLight.xml)0
-rw-r--r--modules/gltf/doc_classes/GLTFMesh.xml (renamed from doc/classes/GLTFMesh.xml)0
-rw-r--r--modules/gltf/doc_classes/GLTFNode.xml (renamed from doc/classes/GLTFNode.xml)0
-rw-r--r--modules/gltf/doc_classes/GLTFSkeleton.xml (renamed from doc/classes/GLTFSkeleton.xml)2
-rw-r--r--modules/gltf/doc_classes/GLTFSkin.xml (renamed from doc/classes/GLTFSkin.xml)0
-rw-r--r--modules/gltf/doc_classes/GLTFSpecGloss.xml (renamed from doc/classes/GLTFSpecGloss.xml)0
-rw-r--r--modules/gltf/doc_classes/GLTFState.xml (renamed from doc/classes/GLTFState.xml)20
-rw-r--r--modules/gltf/doc_classes/GLTFTexture.xml (renamed from doc/classes/GLTFTexture.xml)2
-rw-r--r--modules/gltf/doc_classes/PackedSceneGLTF.xml (renamed from doc/classes/PackedSceneGLTF.xml)0
-rw-r--r--modules/gltf/editor_scene_importer_gltf.cpp4
-rw-r--r--modules/gltf/gltf_camera.h4
-rw-r--r--modules/gltf/gltf_document.cpp71
-rw-r--r--modules/gltf/gltf_document.h3
-rw-r--r--modules/gltf/gltf_skeleton.cpp2
-rw-r--r--modules/gltf/gltf_skin.cpp2
-rw-r--r--modules/gltf/gltf_state.cpp17
-rw-r--r--modules/gltf/gltf_state.h4
-rw-r--r--modules/gltf/gltf_texture.h2
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml8
-rw-r--r--modules/gridmap/grid_map.cpp96
-rw-r--r--modules/gridmap/grid_map.h62
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp42
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h34
-rw-r--r--modules/lightmapper_rd/lightmapper_rd.cpp26
-rw-r--r--modules/lightmapper_rd/lightmapper_rd.h102
-rw-r--r--modules/lightmapper_rd/lm_common_inc.glsl4
-rw-r--r--modules/lightmapper_rd/lm_compute.glsl11
-rw-r--r--modules/lightmapper_rd/register_types.cpp22
-rw-r--r--modules/mbedtls/packet_peer_mbed_dtls.cpp1
-rw-r--r--modules/mbedtls/packet_peer_mbed_dtls.h2
-rw-r--r--modules/mbedtls/ssl_context_mbedtls.cpp2
-rw-r--r--modules/mbedtls/ssl_context_mbedtls.h4
-rw-r--r--modules/mbedtls/stream_peer_mbedtls.cpp3
-rw-r--r--modules/mbedtls/stream_peer_mbedtls.h2
-rw-r--r--modules/minimp3/audio_stream_mp3.cpp3
-rw-r--r--modules/minimp3/audio_stream_mp3.h6
-rw-r--r--modules/mobile_vr/mobile_vr_interface.cpp26
-rw-r--r--modules/mobile_vr/mobile_vr_interface.h26
-rw-r--r--modules/mono/Directory.Build.props3
-rw-r--r--modules/mono/SdkPackageVersions.props6
-rw-r--r--modules/mono/build_scripts/godot_net_sdk_build.py24
-rw-r--r--modules/mono/csharp_script.cpp144
-rw-r--r--modules/mono/csharp_script.h38
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln18
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj43
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec22
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt1
-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.NET.Sdk/Sdk/Sdk.targets5
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs15
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs11
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj31
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs33
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs89
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj40
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props7
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs9
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs182
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs47
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs31
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs86
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs8
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs61
-rw-r--r--modules/mono/editor/bindings_generator.cpp262
-rw-r--r--modules/mono/editor/bindings_generator.h1
-rw-r--r--modules/mono/editor/editor_internal_calls.cpp47
-rw-r--r--modules/mono/editor/script_class_parser.cpp753
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs22
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs9
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs15
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs27
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs21
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs20
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs21
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj6
-rw-r--r--modules/mono/godotsharp_dirs.cpp10
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp1
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp103
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h13
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.cpp10
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.h5
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp13
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.h3
-rw-r--r--modules/mono/mono_gd/gd_mono_log.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_log.h4
-rw-r--r--modules/mono/mono_gd/support/android_support.cpp4
-rw-r--r--modules/opensimplex/doc_classes/NoiseTexture.xml1
-rw-r--r--modules/opensimplex/doc_classes/OpenSimplexNoise.xml1
-rw-r--r--modules/opensimplex/noise_texture.cpp11
-rw-r--r--modules/opensimplex/noise_texture.h16
-rw-r--r--modules/opensimplex/open_simplex_noise.cpp6
-rw-r--r--modules/opensimplex/open_simplex_noise.h10
-rw-r--r--modules/pvr/texture_loader_pvr.cpp4
-rw-r--r--modules/pvr/texture_loader_pvr.h2
-rw-r--r--modules/regex/regex.cpp2
-rw-r--r--modules/regex/regex.h6
-rw-r--r--modules/stb_vorbis/audio_stream_ogg_vorbis.cpp13
-rw-r--r--modules/stb_vorbis/audio_stream_ogg_vorbis.h24
-rw-r--r--modules/text_server_adv/SCsub45
-rw-r--r--modules/text_server_adv/bitmap_font_adv.cpp115
-rw-r--r--modules/text_server_adv/bitmap_font_adv.h11
-rw-r--r--modules/text_server_adv/config.py2
-rw-r--r--modules/text_server_adv/dynamic_font_adv.cpp10
-rw-r--r--modules/text_server_adv/dynamic_font_adv.h19
-rw-r--r--modules/text_server_adv/font_adv.h23
-rw-r--r--modules/text_server_adv/script_iterator.h6
-rw-r--r--modules/text_server_adv/text_server_adv.cpp92
-rw-r--r--modules/text_server_adv/text_server_adv.h11
-rw-r--r--modules/text_server_fb/bitmap_font_fb.cpp94
-rw-r--r--modules/text_server_fb/bitmap_font_fb.h6
-rw-r--r--modules/text_server_fb/config.py2
-rw-r--r--modules/text_server_fb/dynamic_font_fb.cpp9
-rw-r--r--modules/text_server_fb/dynamic_font_fb.h19
-rw-r--r--modules/text_server_fb/font_fb.h23
-rw-r--r--modules/text_server_fb/text_server_fb.cpp84
-rw-r--r--modules/text_server_fb/text_server_fb.h11
-rw-r--r--modules/tga/image_loader_tga.cpp25
-rw-r--r--modules/tga/image_loader_tga.h24
-rw-r--r--modules/theora/video_stream_theora.cpp21
-rw-r--r--modules/theora/video_stream_theora.h51
-rw-r--r--modules/upnp/SCsub15
-rw-r--r--modules/upnp/upnp.cpp9
-rw-r--r--modules/upnp/upnp.h6
-rw-r--r--modules/visual_script/visual_script.cpp13
-rw-r--r--modules/visual_script/visual_script.h91
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp2
-rw-r--r--modules/visual_script/visual_script_editor.cpp36
-rw-r--r--modules/visual_script/visual_script_expression.cpp23
-rw-r--r--modules/visual_script/visual_script_expression.h47
-rw-r--r--modules/visual_script/visual_script_flow_control.cpp14
-rw-r--r--modules/visual_script/visual_script_flow_control.h2
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp54
-rw-r--r--modules/visual_script/visual_script_nodes.cpp61
-rw-r--r--modules/visual_script/visual_script_nodes.h4
-rw-r--r--modules/visual_script/visual_script_yield_nodes.cpp12
-rw-r--r--modules/webm/video_stream_webm.cpp4
-rw-r--r--modules/webm/video_stream_webm.h2
-rw-r--r--modules/webrtc/webrtc_data_channel_js.cpp7
-rw-r--r--modules/webrtc/webrtc_data_channel_js.h8
-rw-r--r--modules/websocket/emws_client.cpp4
-rw-r--r--modules/websocket/emws_client.h8
-rw-r--r--modules/websocket/emws_peer.cpp2
-rw-r--r--modules/websocket/emws_peer.h6
-rw-r--r--modules/websocket/websocket_client.cpp1
-rw-r--r--modules/websocket/websocket_client.h2
-rw-r--r--modules/websocket/websocket_multiplayer_peer.cpp15
-rw-r--r--modules/websocket/websocket_multiplayer_peer.h16
-rw-r--r--modules/websocket/wsl_client.cpp5
-rw-r--r--modules/websocket/wsl_client.h14
-rw-r--r--modules/websocket/wsl_peer.cpp4
-rw-r--r--modules/websocket/wsl_peer.h38
-rw-r--r--modules/websocket/wsl_server.cpp13
-rw-r--r--modules/websocket/wsl_server.h22
-rw-r--r--modules/webxr/native/webxr.externs.js4
-rw-r--r--modules/webxr/webxr_interface_js.cpp2
-rw-r--r--modules/xatlas_unwrap/register_types.cpp8
-rw-r--r--platform/android/audio_driver_jandroid.cpp4
-rw-r--r--platform/android/detect.py63
-rw-r--r--platform/android/display_server_android.cpp40
-rw-r--r--platform/android/export/export.cpp178
-rw-r--r--platform/android/export/gradle_export_util.h24
-rw-r--r--platform/android/file_access_android.cpp3
-rw-r--r--platform/android/java/app/AndroidManifest.xml10
-rw-r--r--platform/android/java/app/assets/.gitignore2
-rw-r--r--platform/android/java/app/build.gradle12
-rw-r--r--platform/android/java/app/config.gradle85
-rw-r--r--platform/android/java/app/res/drawable/splash_drawable.xml2
-rw-r--r--platform/android/java/build.gradle6
-rw-r--r--platform/android/java/lib/AndroidManifest.xml5
-rw-r--r--platform/android/java/lib/build.gradle10
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java25
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java107
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotHost.java (renamed from scene/3d/navigation_3d.h)66
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java247
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java13
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java121
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java (renamed from scene/2d/navigation_2d.h)67
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java38
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/UsedByGodot.java45
-rw-r--r--platform/android/java/nativeSrcsConfigs/README.md2
-rw-r--r--platform/android/java/nativeSrcsConfigs/build.gradle5
-rw-r--r--platform/android/java_class_wrapper.cpp3
-rw-r--r--platform/android/java_godot_io_wrapper.cpp20
-rw-r--r--platform/android/java_godot_lib_jni.cpp15
-rw-r--r--platform/android/java_godot_view_wrapper.cpp7
-rw-r--r--platform/android/java_godot_view_wrapper.h2
-rw-r--r--platform/android/java_godot_wrapper.cpp63
-rw-r--r--platform/android/java_godot_wrapper.h2
-rw-r--r--platform/android/plugin/godot_plugin_jni.cpp10
-rw-r--r--platform/android/plugin/godot_plugin_jni.h10
-rw-r--r--platform/android/thread_jandroid.cpp27
-rw-r--r--platform/iphone/detect.py2
-rw-r--r--platform/iphone/display_layer.mm2
-rw-r--r--platform/iphone/export/export.cpp28
-rw-r--r--platform/iphone/godot_view.mm12
-rw-r--r--platform/iphone/joypad_iphone.mm2
-rw-r--r--platform/javascript/.eslintrc.engine.js2
-rw-r--r--platform/javascript/SCsub44
-rw-r--r--platform/javascript/audio_driver_javascript.cpp4
-rw-r--r--platform/javascript/detect.py42
-rw-r--r--platform/javascript/display_server_javascript.cpp146
-rw-r--r--platform/javascript/display_server_javascript.h9
-rw-r--r--platform/javascript/emscripten_helpers.py67
-rw-r--r--platform/javascript/export/export.cpp79
-rw-r--r--platform/javascript/godot_js.h20
-rw-r--r--platform/javascript/http_client.h.inc13
-rw-r--r--platform/javascript/http_client_javascript.cpp182
-rw-r--r--platform/javascript/javascript_main.cpp7
-rw-r--r--platform/javascript/js/engine/config.js337
-rw-r--r--platform/javascript/js/engine/engine.externs.js1
-rw-r--r--platform/javascript/js/engine/engine.js496
-rw-r--r--platform/javascript/js/engine/preloader.js125
-rw-r--r--platform/javascript/js/engine/utils.js58
-rw-r--r--platform/javascript/js/jsdoc2rst/publish.js354
-rw-r--r--platform/javascript/js/libs/library_godot_audio.js5
-rw-r--r--platform/javascript/js/libs/library_godot_display.js428
-rw-r--r--platform/javascript/js/libs/library_godot_fetch.js258
-rw-r--r--platform/javascript/js/libs/library_godot_http_request.js160
-rw-r--r--platform/javascript/js/libs/library_godot_os.js44
-rw-r--r--platform/javascript/js/libs/library_godot_runtime.js16
-rw-r--r--platform/javascript/os_javascript.cpp4
-rw-r--r--platform/javascript/os_javascript.h1
-rw-r--r--platform/javascript/package-lock.json154
-rw-r--r--platform/javascript/package.json12
-rw-r--r--platform/linuxbsd/SCsub5
-rw-r--r--platform/linuxbsd/detect.py30
-rw-r--r--platform/linuxbsd/detect_prime_x11.cpp3
-rw-r--r--platform/linuxbsd/display_server_x11.cpp31
-rw-r--r--platform/linuxbsd/display_server_x11.h2
-rw-r--r--platform/linuxbsd/joypad_linux.cpp51
-rw-r--r--platform/linuxbsd/joypad_linux.h11
-rw-r--r--platform/linuxbsd/libudev-so_wrap.c1013
-rw-r--r--platform/linuxbsd/libudev-so_wrap.h378
-rw-r--r--platform/osx/SCsub2
-rw-r--r--platform/osx/detect.py15
-rw-r--r--platform/osx/display_server_osx.h1
-rw-r--r--platform/osx/display_server_osx.mm41
-rw-r--r--platform/osx/export/export.cpp182
-rw-r--r--platform/osx/joypad_osx.cpp4
-rw-r--r--platform/server/detect.py16
-rw-r--r--platform/uwp/app.cpp16
-rw-r--r--platform/uwp/detect.py11
-rw-r--r--platform/uwp/joypad_uwp.cpp4
-rw-r--r--platform/uwp/joypad_uwp.h2
-rw-r--r--platform/uwp/os_uwp.cpp9
-rw-r--r--platform/windows/SCsub2
-rw-r--r--platform/windows/crash_handler_windows.cpp2
-rw-r--r--platform/windows/detect.py28
-rw-r--r--platform/windows/display_server_windows.cpp110
-rw-r--r--platform/windows/display_server_windows.h9
-rw-r--r--platform/windows/godot.natvis10
-rw-r--r--platform/windows/joypad_windows.cpp15
-rw-r--r--platform/windows/joypad_windows.h2
-rw-r--r--platform/windows/os_windows.cpp68
-rw-r--r--platform/windows/os_windows.h8
-rw-r--r--platform/windows/windows_terminal_logger.cpp5
-rw-r--r--scene/2d/animated_sprite_2d.cpp232
-rw-r--r--scene/2d/animated_sprite_2d.h92
-rw-r--r--scene/2d/area_2d.cpp20
-rw-r--r--scene/2d/area_2d.h40
-rw-r--r--scene/2d/audio_stream_player_2d.cpp77
-rw-r--r--scene/2d/audio_stream_player_2d.h35
-rw-r--r--scene/2d/back_buffer_copy.cpp2
-rw-r--r--scene/2d/back_buffer_copy.h4
-rw-r--r--scene/2d/camera_2d.cpp92
-rw-r--r--scene/2d/camera_2d.h72
-rw-r--r--scene/2d/canvas_group.cpp8
-rw-r--r--scene/2d/canvas_group.h12
-rw-r--r--scene/2d/canvas_modulate.cpp1
-rw-r--r--scene/2d/canvas_modulate.h2
-rw-r--r--scene/2d/collision_object_2d.h26
-rw-r--r--scene/2d/collision_polygon_2d.cpp62
-rw-r--r--scene/2d/collision_polygon_2d.h14
-rw-r--r--scene/2d/collision_shape_2d.cpp7
-rw-r--r--scene/2d/collision_shape_2d.h12
-rw-r--r--scene/2d/cpu_particles_2d.cpp245
-rw-r--r--scene/2d/cpu_particles_2d.h102
-rw-r--r--scene/2d/gpu_particles_2d.cpp3
-rw-r--r--scene/2d/joints_2d.cpp88
-rw-r--r--scene/2d/joints_2d.h32
-rw-r--r--scene/2d/light_2d.cpp44
-rw-r--r--scene/2d/light_2d.h57
-rw-r--r--scene/2d/light_occluder_2d.cpp3
-rw-r--r--scene/2d/light_occluder_2d.h6
-rw-r--r--scene/2d/line_2d.cpp10
-rw-r--r--scene/2d/line_2d.h18
-rw-r--r--scene/2d/line_builder.cpp22
-rw-r--r--scene/2d/line_builder.h26
-rw-r--r--scene/2d/mesh_instance_2d.cpp1
-rw-r--r--scene/2d/multimesh_instance_2d.cpp1
-rw-r--r--scene/2d/navigation_2d.cpp92
-rw-r--r--scene/2d/navigation_agent_2d.cpp45
-rw-r--r--scene/2d/navigation_agent_2d.h15
-rw-r--r--scene/2d/navigation_obstacle_2d.cpp113
-rw-r--r--scene/2d/navigation_obstacle_2d.h14
-rw-r--r--scene/2d/navigation_region_2d.cpp118
-rw-r--r--scene/2d/navigation_region_2d.h7
-rw-r--r--scene/2d/node_2d.cpp55
-rw-r--r--scene/2d/node_2d.h40
-rw-r--r--scene/2d/parallax_background.cpp8
-rw-r--r--scene/2d/parallax_background.h10
-rw-r--r--scene/2d/parallax_layer.cpp7
-rw-r--r--scene/2d/parallax_layer.h4
-rw-r--r--scene/2d/path_2d.cpp34
-rw-r--r--scene/2d/path_2d.h28
-rw-r--r--scene/2d/physics_body_2d.cpp30
-rw-r--r--scene/2d/physics_body_2d.h46
-rw-r--r--scene/2d/polygon_2d.cpp35
-rw-r--r--scene/2d/polygon_2d.h31
-rw-r--r--scene/2d/position_2d.cpp10
-rw-r--r--scene/2d/position_2d.h4
-rw-r--r--scene/2d/ray_cast_2d.cpp77
-rw-r--r--scene/2d/ray_cast_2d.h18
-rw-r--r--scene/2d/remote_transform_2d.cpp5
-rw-r--r--scene/2d/remote_transform_2d.h8
-rw-r--r--scene/2d/skeleton_2d.cpp15
-rw-r--r--scene/2d/skeleton_2d.h20
-rw-r--r--scene/2d/sprite_2d.cpp73
-rw-r--r--scene/2d/sprite_2d.h26
-rw-r--r--scene/2d/tile_map.cpp113
-rw-r--r--scene/2d/tile_map.h66
-rw-r--r--scene/2d/touch_screen_button.cpp21
-rw-r--r--scene/2d/touch_screen_button.h10
-rw-r--r--scene/2d/visibility_notifier_2d.cpp4
-rw-r--r--scene/2d/visibility_notifier_2d.h2
-rw-r--r--scene/2d/y_sort.cpp1
-rw-r--r--scene/2d/y_sort.h2
-rw-r--r--scene/3d/area_3d.cpp31
-rw-r--r--scene/3d/area_3d.h50
-rw-r--r--scene/3d/audio_stream_player_3d.cpp99
-rw-r--r--scene/3d/audio_stream_player_3d.h68
-rw-r--r--scene/3d/baked_lightmap.cpp28
-rw-r--r--scene/3d/baked_lightmap.h51
-rw-r--r--scene/3d/bone_attachment_3d.cpp1
-rw-r--r--scene/3d/bone_attachment_3d.h2
-rw-r--r--scene/3d/camera_3d.cpp50
-rw-r--r--scene/3d/camera_3d.h45
-rw-r--r--scene/3d/collision_object_3d.cpp59
-rw-r--r--scene/3d/collision_object_3d.h26
-rw-r--r--scene/3d/collision_polygon_3d.cpp21
-rw-r--r--scene/3d/collision_polygon_3d.h14
-rw-r--r--scene/3d/collision_shape_3d.cpp35
-rw-r--r--scene/3d/collision_shape_3d.h10
-rw-r--r--scene/3d/cpu_particles_3d.cpp42
-rw-r--r--scene/3d/cpu_particles_3d.h82
-rw-r--r--scene/3d/decal.cpp20
-rw-r--r--scene/3d/decal.h23
-rw-r--r--scene/3d/gi_probe.cpp26
-rw-r--r--scene/3d/gi_probe.h24
-rw-r--r--scene/3d/gpu_particles_3d.cpp7
-rw-r--r--scene/3d/gpu_particles_collision_3d.h16
-rw-r--r--scene/3d/immediate_geometry_3d.cpp1
-rw-r--r--scene/3d/immediate_geometry_3d.h2
-rw-r--r--scene/3d/light_3d.cpp19
-rw-r--r--scene/3d/light_3d.h16
-rw-r--r--scene/3d/listener_3d.cpp2
-rw-r--r--scene/3d/listener_3d.h4
-rw-r--r--scene/3d/mesh_instance_3d.cpp8
-rw-r--r--scene/3d/mesh_instance_3d.h10
-rw-r--r--scene/3d/navigation_3d.cpp119
-rw-r--r--scene/3d/navigation_agent_3d.cpp45
-rw-r--r--scene/3d/navigation_agent_3d.h10
-rw-r--r--scene/3d/navigation_obstacle_3d.cpp130
-rw-r--r--scene/3d/navigation_obstacle_3d.h14
-rw-r--r--scene/3d/navigation_region_3d.cpp59
-rw-r--r--scene/3d/navigation_region_3d.h9
-rw-r--r--scene/3d/node_3d.cpp14
-rw-r--r--scene/3d/node_3d.h4
-rw-r--r--scene/3d/path_3d.cpp2
-rw-r--r--scene/3d/path_3d.h8
-rw-r--r--scene/3d/physics_body_3d.cpp64
-rw-r--r--scene/3d/physics_body_3d.h124
-rw-r--r--scene/3d/physics_joint_3d.cpp128
-rw-r--r--scene/3d/physics_joint_3d.h22
-rw-r--r--scene/3d/ray_cast_3d.cpp171
-rw-r--r--scene/3d/ray_cast_3d.h35
-rw-r--r--scene/3d/reflection_probe.cpp20
-rw-r--r--scene/3d/reflection_probe.h28
-rw-r--r--scene/3d/remote_transform_3d.cpp5
-rw-r--r--scene/3d/remote_transform_3d.h8
-rw-r--r--scene/3d/skeleton_3d.cpp6
-rw-r--r--scene/3d/skeleton_3d.h39
-rw-r--r--scene/3d/skeleton_ik_3d.cpp32
-rw-r--r--scene/3d/skeleton_ik_3d.h11
-rw-r--r--scene/3d/soft_body_3d.cpp82
-rw-r--r--scene/3d/soft_body_3d.h38
-rw-r--r--scene/3d/spring_arm_3d.h4
-rw-r--r--scene/3d/sprite_3d.cpp67
-rw-r--r--scene/3d/sprite_3d.h52
-rw-r--r--scene/3d/vehicle_body_3d.cpp38
-rw-r--r--scene/3d/vehicle_body_3d.h70
-rw-r--r--scene/3d/velocity_tracker_3d.cpp2
-rw-r--r--scene/3d/velocity_tracker_3d.h6
-rw-r--r--scene/3d/visibility_notifier_3d.cpp4
-rw-r--r--scene/3d/visibility_notifier_3d.h4
-rw-r--r--scene/3d/visual_instance_3d.cpp16
-rw-r--r--scene/3d/visual_instance_3d.h20
-rw-r--r--scene/3d/voxelizer.cpp7
-rw-r--r--scene/3d/voxelizer.h48
-rw-r--r--scene/3d/world_environment.cpp86
-rw-r--r--scene/3d/world_environment.h3
-rw-r--r--scene/animation/animation_blend_space_1d.cpp8
-rw-r--r--scene/animation/animation_blend_space_1d.h14
-rw-r--r--scene/animation/animation_blend_space_2d.cpp16
-rw-r--r--scene/animation/animation_blend_space_2d.h26
-rw-r--r--scene/animation/animation_blend_tree.cpp46
-rw-r--r--scene/animation/animation_blend_tree.h67
-rw-r--r--scene/animation/animation_cache.cpp3
-rw-r--r--scene/animation/animation_cache.h26
-rw-r--r--scene/animation/animation_node_state_machine.cpp32
-rw-r--r--scene/animation/animation_node_state_machine.h34
-rw-r--r--scene/animation/animation_player.cpp67
-rw-r--r--scene/animation/animation_player.h75
-rw-r--r--scene/animation/animation_tree.cpp49
-rw-r--r--scene/animation/animation_tree.h92
-rw-r--r--scene/animation/root_motion_view.cpp8
-rw-r--r--scene/animation/root_motion_view.h12
-rw-r--r--scene/animation/tween.cpp33
-rw-r--r--scene/animation/tween.h41
-rw-r--r--scene/audio/audio_stream_player.cpp65
-rw-r--r--scene/audio/audio_stream_player.h29
-rw-r--r--scene/debugger/scene_debugger.cpp2
-rw-r--r--scene/debugger/scene_debugger.h2
-rw-r--r--scene/gui/base_button.cpp13
-rw-r--r--scene/gui/base_button.h20
-rw-r--r--scene/gui/box_container.cpp15
-rw-r--r--scene/gui/box_container.h6
-rw-r--r--scene/gui/button.cpp20
-rw-r--r--scene/gui/button.h10
-rw-r--r--scene/gui/center_container.cpp4
-rw-r--r--scene/gui/center_container.h2
-rw-r--r--scene/gui/check_box.cpp6
-rw-r--r--scene/gui/color_picker.cpp142
-rw-r--r--scene/gui/color_picker.h37
-rw-r--r--scene/gui/container.cpp1
-rw-r--r--scene/gui/container.h2
-rw-r--r--scene/gui/control.cpp117
-rw-r--r--scene/gui/control.h45
-rw-r--r--scene/gui/dialogs.cpp11
-rw-r--r--scene/gui/dialogs.h4
-rw-r--r--scene/gui/file_dialog.cpp64
-rw-r--r--scene/gui/file_dialog.h8
-rw-r--r--scene/gui/gradient_edit.cpp2
-rw-r--r--scene/gui/gradient_edit.h4
-rw-r--r--scene/gui/graph_edit.cpp127
-rw-r--r--scene/gui/graph_edit.h45
-rw-r--r--scene/gui/graph_node.cpp149
-rw-r--r--scene/gui/graph_node.h37
-rw-r--r--scene/gui/grid_container.cpp4
-rw-r--r--scene/gui/grid_container.h2
-rw-r--r--scene/gui/item_list.cpp55
-rw-r--r--scene/gui/item_list.h46
-rw-r--r--scene/gui/label.cpp30
-rw-r--r--scene/gui/label.h2
-rw-r--r--scene/gui/line_edit.cpp856
-rw-r--r--scene/gui/line_edit.h36
-rw-r--r--scene/gui/link_button.cpp11
-rw-r--r--scene/gui/link_button.h2
-rw-r--r--scene/gui/menu_button.cpp1
-rw-r--r--scene/gui/menu_button.h6
-rw-r--r--scene/gui/nine_patch_rect.cpp25
-rw-r--r--scene/gui/nine_patch_rect.h7
-rw-r--r--scene/gui/option_button.cpp1
-rw-r--r--scene/gui/option_button.h2
-rw-r--r--scene/gui/popup_menu.cpp104
-rw-r--r--scene/gui/popup_menu.h59
-rw-r--r--scene/gui/progress_bar.cpp9
-rw-r--r--scene/gui/progress_bar.h2
-rw-r--r--scene/gui/range.cpp12
-rw-r--r--scene/gui/range.h15
-rw-r--r--scene/gui/rich_text_label.cpp200
-rw-r--r--scene/gui/rich_text_label.h111
-rw-r--r--scene/gui/scroll_bar.cpp8
-rw-r--r--scene/gui/scroll_bar.h14
-rw-r--r--scene/gui/scroll_container.cpp22
-rw-r--r--scene/gui/scroll_container.h24
-rw-r--r--scene/gui/separator.h2
-rw-r--r--scene/gui/slider.cpp15
-rw-r--r--scene/gui/slider.h18
-rw-r--r--scene/gui/spin_box.cpp32
-rw-r--r--scene/gui/spin_box.h7
-rw-r--r--scene/gui/split_container.cpp11
-rw-r--r--scene/gui/split_container.h20
-rw-r--r--scene/gui/subviewport_container.cpp2
-rw-r--r--scene/gui/subviewport_container.h4
-rw-r--r--scene/gui/tab_container.cpp29
-rw-r--r--scene/gui/tab_container.h28
-rw-r--r--scene/gui/tabs.cpp48
-rw-r--r--scene/gui/tabs.h50
-rw-r--r--scene/gui/text_edit.cpp2342
-rw-r--r--scene/gui/text_edit.h276
-rw-r--r--scene/gui/texture_button.cpp17
-rw-r--r--scene/gui/texture_button.h10
-rw-r--r--scene/gui/texture_progress_bar.cpp18
-rw-r--r--scene/gui/texture_progress_bar.h14
-rw-r--r--scene/gui/texture_rect.cpp4
-rw-r--r--scene/gui/texture_rect.h8
-rw-r--r--scene/gui/tree.cpp172
-rw-r--r--scene/gui/tree.h198
-rw-r--r--scene/gui/video_player.cpp20
-rw-r--r--scene/gui/video_player.h27
-rw-r--r--scene/main/canvas_item.cpp49
-rw-r--r--scene/main/canvas_item.h38
-rw-r--r--scene/main/canvas_layer.cpp17
-rw-r--r--scene/main/canvas_layer.h19
-rw-r--r--scene/main/http_request.cpp58
-rw-r--r--scene/main/http_request.h37
-rw-r--r--scene/main/node.cpp393
-rw-r--r--scene/main/node.h38
-rw-r--r--scene/main/scene_tree.cpp122
-rw-r--r--scene/main/scene_tree.h18
-rw-r--r--scene/main/shader_globals_override.cpp4
-rw-r--r--scene/main/shader_globals_override.h2
-rw-r--r--scene/main/timer.cpp34
-rw-r--r--scene/main/timer.h22
-rw-r--r--scene/main/viewport.cpp692
-rw-r--r--scene/main/viewport.h138
-rw-r--r--scene/main/window.cpp32
-rw-r--r--scene/main/window.h6
-rw-r--r--scene/register_scene_types.cpp17
-rw-r--r--scene/resources/animation.cpp22
-rw-r--r--scene/resources/animation.h46
-rw-r--r--scene/resources/audio_stream_sample.cpp17
-rw-r--r--scene/resources/audio_stream_sample.h36
-rw-r--r--scene/resources/bit_map.cpp13
-rw-r--r--scene/resources/bit_map.h4
-rw-r--r--scene/resources/box_shape_3d.cpp1
-rw-r--r--scene/resources/camera_effects.cpp13
-rw-r--r--scene/resources/camera_effects.h9
-rw-r--r--scene/resources/capsule_shape_2d.cpp7
-rw-r--r--scene/resources/capsule_shape_2d.h4
-rw-r--r--scene/resources/capsule_shape_3d.cpp4
-rw-r--r--scene/resources/capsule_shape_3d.h4
-rw-r--r--scene/resources/circle_shape_2d.cpp6
-rw-r--r--scene/resources/circle_shape_2d.h2
-rw-r--r--scene/resources/concave_polygon_shape_2d.cpp2
-rw-r--r--scene/resources/concave_polygon_shape_3d.cpp39
-rw-r--r--scene/resources/concave_polygon_shape_3d.h6
-rw-r--r--scene/resources/convex_polygon_shape_2d.cpp11
-rw-r--r--scene/resources/convex_polygon_shape_3d.cpp2
-rw-r--r--scene/resources/curve.cpp16
-rw-r--r--scene/resources/curve.h48
-rw-r--r--scene/resources/cylinder_shape_3d.cpp4
-rw-r--r--scene/resources/cylinder_shape_3d.h4
-rw-r--r--scene/resources/default_theme/bar_arrow.pngbin0 -> 208 bytes
-rw-r--r--scene/resources/default_theme/checked_disabled.pngbin0 -> 421 bytes
-rw-r--r--scene/resources/default_theme/default_theme.cpp131
-rw-r--r--scene/resources/default_theme/radio_checked_disabled.pngbin0 -> 235 bytes
-rw-r--r--scene/resources/default_theme/radio_unchecked_disabled.pngbin0 -> 183 bytes
-rw-r--r--scene/resources/default_theme/theme_data.h20
-rw-r--r--scene/resources/default_theme/unchecked_disabled.pngbin0 -> 246 bytes
-rw-r--r--scene/resources/environment.cpp76
-rw-r--r--scene/resources/environment.h19
-rw-r--r--scene/resources/font.cpp98
-rw-r--r--scene/resources/font.h27
-rw-r--r--scene/resources/gradient.cpp1
-rw-r--r--scene/resources/gradient.h4
-rw-r--r--scene/resources/height_map_shape_3d.cpp9
-rw-r--r--scene/resources/height_map_shape_3d.h8
-rw-r--r--scene/resources/line_shape_2d.cpp2
-rw-r--r--scene/resources/line_shape_2d.h4
-rw-r--r--scene/resources/material.cpp79
-rw-r--r--scene/resources/material.h42
-rw-r--r--scene/resources/mesh.cpp19
-rw-r--r--scene/resources/mesh.h14
-rw-r--r--scene/resources/mesh_data_tool.cpp38
-rw-r--r--scene/resources/mesh_data_tool.h8
-rw-r--r--scene/resources/mesh_library.cpp25
-rw-r--r--scene/resources/mesh_library.h1
-rw-r--r--scene/resources/multimesh.cpp7
-rw-r--r--scene/resources/multimesh.h10
-rw-r--r--scene/resources/navigation_mesh.cpp37
-rw-r--r--scene/resources/navigation_mesh.h48
-rw-r--r--scene/resources/packed_scene.cpp28
-rw-r--r--scene/resources/packed_scene.h34
-rw-r--r--scene/resources/particles_material.cpp12
-rw-r--r--scene/resources/particles_material.h6
-rw-r--r--scene/resources/physics_material.h4
-rw-r--r--scene/resources/polygon_path_finder.cpp4
-rw-r--r--scene/resources/polygon_path_finder.h8
-rw-r--r--scene/resources/primitive_meshes.cpp64
-rw-r--r--scene/resources/primitive_meshes.h66
-rw-r--r--scene/resources/ray_shape_2d.cpp30
-rw-r--r--scene/resources/ray_shape_2d.h4
-rw-r--r--scene/resources/ray_shape_3d.cpp7
-rw-r--r--scene/resources/ray_shape_3d.h4
-rw-r--r--scene/resources/rectangle_shape_2d.cpp24
-rw-r--r--scene/resources/resource_format_text.cpp142
-rw-r--r--scene/resources/resource_format_text.h36
-rw-r--r--scene/resources/shader.cpp4
-rw-r--r--scene/resources/shader.h6
-rw-r--r--scene/resources/shape_2d.cpp14
-rw-r--r--scene/resources/shape_2d.h5
-rw-r--r--scene/resources/skin.cpp8
-rw-r--r--scene/resources/skin.h5
-rw-r--r--scene/resources/sky.cpp2
-rw-r--r--scene/resources/sky.h4
-rw-r--r--scene/resources/sky_material.cpp1
-rw-r--r--scene/resources/sphere_shape_3d.cpp1
-rw-r--r--scene/resources/sprite_frames.cpp241
-rw-r--r--scene/resources/sprite_frames.h (renamed from editor/input_map_editor.h)129
-rw-r--r--scene/resources/style_box.cpp85
-rw-r--r--scene/resources/style_box.h45
-rw-r--r--scene/resources/surface_tool.cpp17
-rw-r--r--scene/resources/surface_tool.h17
-rw-r--r--scene/resources/syntax_highlighter.cpp17
-rw-r--r--scene/resources/syntax_highlighter.h2
-rw-r--r--scene/resources/text_line.cpp1
-rw-r--r--scene/resources/text_line.h2
-rw-r--r--scene/resources/text_paragraph.cpp2
-rw-r--r--scene/resources/text_paragraph.h2
-rw-r--r--scene/resources/texture.cpp88
-rw-r--r--scene/resources/texture.h82
-rw-r--r--scene/resources/theme.cpp35
-rw-r--r--scene/resources/theme.h2
-rw-r--r--scene/resources/tile_set.cpp17
-rw-r--r--scene/resources/tile_set.h2
-rw-r--r--scene/resources/visual_shader.cpp28
-rw-r--r--scene/resources/visual_shader.h37
-rw-r--r--scene/resources/visual_shader_nodes.cpp63
-rw-r--r--scene/resources/world_2d.cpp37
-rw-r--r--scene/resources/world_2d.h6
-rw-r--r--scene/resources/world_3d.cpp13
-rw-r--r--scene/resources/world_3d.h2
-rw-r--r--scene/resources/world_margin_shape_3d.cpp1
-rw-r--r--servers/audio/audio_driver_dummy.cpp4
-rw-r--r--servers/audio/audio_rb_resampler.cpp14
-rw-r--r--servers/audio/audio_rb_resampler.h57
-rw-r--r--servers/audio/audio_stream.cpp20
-rw-r--r--servers/audio/effects/audio_effect_capture.cpp10
-rw-r--r--servers/audio/effects/audio_effect_capture.h4
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp2
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp3
-rw-r--r--servers/audio_server.cpp18
-rw-r--r--servers/camera/camera_feed.cpp10
-rw-r--r--servers/camera/camera_feed.h6
-rw-r--r--servers/display_server.cpp7
-rw-r--r--servers/display_server.h7
-rw-r--r--servers/navigation_server_2d.cpp43
-rw-r--r--servers/navigation_server_2d.h15
-rw-r--r--servers/navigation_server_3d.cpp11
-rw-r--r--servers/navigation_server_3d.h15
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp43
-rw-r--r--servers/physics_2d/joints_2d_sw.cpp27
-rw-r--r--servers/physics_2d/joints_2d_sw.h25
-rw-r--r--servers/physics_2d/physics_server_2d_sw.cpp83
-rw-r--r--servers/physics_2d/physics_server_2d_sw.h23
-rw-r--r--servers/physics_2d/physics_server_2d_wrap_mt.cpp24
-rw-r--r--servers/physics_2d/physics_server_2d_wrap_mt.h66
-rw-r--r--servers/physics_2d/space_2d_sw.cpp110
-rw-r--r--servers/physics_3d/body_3d_sw.cpp32
-rw-r--r--servers/physics_3d/body_3d_sw.h6
-rw-r--r--servers/physics_3d/body_pair_3d_sw.cpp332
-rw-r--r--servers/physics_3d/body_pair_3d_sw.h85
-rw-r--r--servers/physics_3d/collision_object_3d_sw.cpp10
-rw-r--r--servers/physics_3d/collision_object_3d_sw.h7
-rw-r--r--servers/physics_3d/collision_solver_3d_sat.cpp897
-rw-r--r--servers/physics_3d/collision_solver_3d_sw.cpp197
-rw-r--r--servers/physics_3d/collision_solver_3d_sw.h6
-rw-r--r--servers/physics_3d/gjk_epa.cpp198
-rw-r--r--servers/physics_3d/gjk_epa.h2
-rw-r--r--servers/physics_3d/joints/cone_twist_joint_3d_sw.h2
-rw-r--r--servers/physics_3d/joints/generic_6dof_joint_3d_sw.h2
-rw-r--r--servers/physics_3d/joints/hinge_joint_3d_sw.h2
-rw-r--r--servers/physics_3d/joints/pin_joint_3d_sw.h2
-rw-r--r--servers/physics_3d/joints/slider_joint_3d_sw.h2
-rw-r--r--servers/physics_3d/joints_3d_sw.h20
-rw-r--r--servers/physics_3d/physics_server_3d_sw.cpp604
-rw-r--r--servers/physics_3d/physics_server_3d_sw.h136
-rw-r--r--servers/physics_3d/physics_server_3d_wrap_mt.cpp140
-rw-r--r--servers/physics_3d/physics_server_3d_wrap_mt.h413
-rw-r--r--servers/physics_3d/shape_3d_sw.cpp317
-rw-r--r--servers/physics_3d/shape_3d_sw.h84
-rw-r--r--servers/physics_3d/soft_body_3d_sw.cpp1221
-rw-r--r--servers/physics_3d/soft_body_3d_sw.h247
-rw-r--r--servers/physics_3d/space_3d_sw.cpp181
-rw-r--r--servers/physics_3d/space_3d_sw.h6
-rw-r--r--servers/physics_3d/step_3d_sw.cpp33
-rw-r--r--servers/physics_server_2d.cpp17
-rw-r--r--servers/physics_server_2d.h17
-rw-r--r--servers/physics_server_3d.cpp73
-rw-r--r--servers/physics_server_3d.h96
-rw-r--r--servers/register_server_types.cpp23
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp61
-rw-r--r--servers/rendering/renderer_canvas_cull.h34
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp21
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp194
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h18
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp14
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp126
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.h155
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp3403
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h668
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.cpp (renamed from servers/rendering/renderer_rd/renderer_scene_render_forward.cpp)953
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.h (renamed from servers/rendering/renderer_rd/renderer_scene_render_forward.h)328
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp5685
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h1091
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp1491
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h292
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp242
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h152
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp68
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.h1
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp19
-rw-r--r--servers/rendering/renderer_rd/shader_rd.h4
-rw-r--r--servers/rendering/renderer_rd/shaders/SCsub56
-rw-r--r--servers/rendering/renderer_rd/shaders/gi.glsl85
-rw-r--r--servers/rendering/renderer_rd/shaders/giprobe.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/giprobe_write.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl (renamed from servers/rendering/renderer_rd/shaders/scene_forward.glsl)109
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl (renamed from servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl)276
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl72
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl34
-rw-r--r--servers/rendering/renderer_rd/shaders/shadow_reduce.glsl105
-rw-r--r--servers/rendering/renderer_rd/shaders/skeleton.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog.glsl96
-rw-r--r--servers/rendering/renderer_scene.h26
-rw-r--r--servers/rendering/renderer_scene_cull.cpp243
-rw-r--r--servers/rendering/renderer_scene_cull.h45
-rw-r--r--servers/rendering/renderer_scene_render.h48
-rw-r--r--servers/rendering/renderer_storage.h83
-rw-r--r--servers/rendering/renderer_viewport.cpp20
-rw-r--r--servers/rendering/renderer_viewport.h8
-rw-r--r--servers/rendering/rendering_device.cpp14
-rw-r--r--servers/rendering/rendering_device.h10
-rw-r--r--servers/rendering/rendering_server_default.cpp112
-rw-r--r--servers/rendering/rendering_server_default.h1213
-rw-r--r--servers/rendering/rendering_server_wrap_mt.cpp174
-rw-r--r--servers/rendering/rendering_server_wrap_mt.h810
-rw-r--r--servers/rendering/shader_language.cpp146
-rw-r--r--servers/rendering/shader_language.h23
-rw-r--r--servers/rendering_server.cpp248
-rw-r--r--servers/rendering_server.h21
-rw-r--r--servers/server_wrap_mt_common.h860
-rw-r--r--servers/text_server.cpp13
-rw-r--r--servers/text_server.h23
-rw-r--r--tests/data/images/icon.bmpbin0 -> 262282 bytes
-rw-r--r--tests/data/images/icon.jpgbin0 -> 14866 bytes
-rw-r--r--tests/data/images/icon.pngbin0 -> 29261 bytes
-rw-r--r--tests/data/images/icon.tgabin0 -> 262162 bytes
-rw-r--r--tests/data/images/icon.webpbin0 -> 4522 bytes
-rw-r--r--tests/test_array.h186
-rw-r--r--tests/test_class_db.h43
-rw-r--r--tests/test_geometry_3d.h417
-rw-r--r--tests/test_hashing_context.h165
-rw-r--r--tests/test_image.h259
-rw-r--r--tests/test_main.cpp6
-rw-r--r--tests/test_path_follow_2d.h241
-rw-r--r--tests/test_path_follow_3d.h220
-rw-r--r--tests/test_physics_2d.cpp4
-rw-r--r--tests/test_physics_3d.cpp20
-rw-r--r--tests/test_render.cpp4
-rw-r--r--tests/test_resource.h114
-rw-r--r--tests/test_string.h60
-rw-r--r--tests/test_text_server.h3
-rw-r--r--tests/test_variant.h594
-rw-r--r--tests/test_xml_parser.h (renamed from modules/mono/editor/script_class_parser.h)102
-rw-r--r--thirdparty/README.md18
-rw-r--r--thirdparty/harfbuzz/NEWS15
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-common.hh115
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh32
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout.cc22
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout.h90
-rw-r--r--thirdparty/harfbuzz/src/hb-algs.hh183
-rw-r--r--thirdparty/harfbuzz/src/hb-array.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-atomic.hh129
-rw-r--r--thirdparty/harfbuzz/src/hb-blob.cc27
-rw-r--r--thirdparty/harfbuzz/src/hb-blob.h12
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-serialize.cc42
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.cc107
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.h59
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.hh97
-rw-r--r--thirdparty/harfbuzz/src/hb-common.cc50
-rw-r--r--thirdparty/harfbuzz/src/hb-common.h741
-rw-r--r--thirdparty/harfbuzz/src/hb-coretext.cc18
-rw-r--r--thirdparty/harfbuzz/src/hb-deprecated.h93
-rw-r--r--thirdparty/harfbuzz/src/hb-directwrite.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-dispatch.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-face.cc14
-rw-r--r--thirdparty/harfbuzz/src/hb-face.h15
-rw-r--r--thirdparty/harfbuzz/src/hb-face.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-font.cc76
-rw-r--r--thirdparty/harfbuzz/src/hb-font.h167
-rw-r--r--thirdparty/harfbuzz/src/hb-ft.cc38
-rw-r--r--thirdparty/harfbuzz/src/hb-gdi.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-gobject-structs.h32
-rw-r--r--thirdparty/harfbuzz/src/hb-graphite2.cc7
-rw-r--r--thirdparty/harfbuzz/src/hb-iter.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-machinery.hh5
-rw-r--r--thirdparty/harfbuzz/src/hb-map.cc9
-rw-r--r--thirdparty/harfbuzz/src/hb-map.h8
-rw-r--r--thirdparty/harfbuzz/src/hb-map.hh5
-rw-r--r--thirdparty/harfbuzz/src/hb-meta.hh15
-rw-r--r--thirdparty/harfbuzz/src/hb-mutex.hh18
-rw-r--r--thirdparty/harfbuzz/src/hb-object.hh17
-rw-r--r--thirdparty/harfbuzz/src/hb-open-file.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-open-type.hh46
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff-common.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff1-table.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff2-table.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cmap-table.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color.cc11
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color.h6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-deprecated.h18
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-font.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-glyf-table.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-head-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-common.hh51
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh124
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh12
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh250
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.cc127
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.h66
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-math.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-math.h85
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-meta.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-meta.h3
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-metrics.cc31
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-metrics.h6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name.cc8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-os2-table.hh9
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-post-table.hh1
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc47
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh111
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc112
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh22
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh705
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.rl113
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc104
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-machine-index.hh69
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh89
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc76
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc100
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh41
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc15
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh1099
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.cc)95
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc160
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use.hh96
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc61
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex.hh44
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc41
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-tag-table.hh15
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-tag.cc29
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var.cc10
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var.h29
-rw-r--r--thirdparty/harfbuzz/src/hb-sanitize.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-serialize.hh11
-rw-r--r--thirdparty/harfbuzz/src/hb-set.cc33
-rw-r--r--thirdparty/harfbuzz/src/hb-set.h8
-rw-r--r--thirdparty/harfbuzz/src/hb-set.hh87
-rw-r--r--thirdparty/harfbuzz/src/hb-shape-plan.cc6
-rw-r--r--thirdparty/harfbuzz/src/hb-shape-plan.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-shape.cc6
-rw-r--r--thirdparty/harfbuzz/src/hb-shape.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-style.cc1
-rw-r--r--thirdparty/harfbuzz/src/hb-style.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.cc27
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.hh15
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode.cc10
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode.h50
-rw-r--r--thirdparty/harfbuzz/src/hb-vector.hh11
-rw-r--r--thirdparty/harfbuzz/src/hb-version.h37
-rw-r--r--thirdparty/harfbuzz/src/hb.hh196
-rw-r--r--thirdparty/mbedtls/include/mbedtls/config.h17
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ctr_drbg.h45
-rw-r--r--thirdparty/mbedtls/include/mbedtls/entropy.h6
-rw-r--r--thirdparty/mbedtls/include/mbedtls/hmac_drbg.h58
-rw-r--r--thirdparty/mbedtls/include/mbedtls/net_sockets.h18
-rw-r--r--thirdparty/mbedtls/include/mbedtls/rsa.h6
-rw-r--r--thirdparty/mbedtls/include/mbedtls/threading.h3
-rw-r--r--thirdparty/mbedtls/include/mbedtls/version.h8
-rw-r--r--thirdparty/mbedtls/library/base64.c131
-rw-r--r--thirdparty/mbedtls/library/bignum.c6
-rw-r--r--thirdparty/mbedtls/library/ctr_drbg.c16
-rw-r--r--thirdparty/mbedtls/library/ecdsa.c8
-rw-r--r--thirdparty/mbedtls/library/ecjpake.c11
-rw-r--r--thirdparty/mbedtls/library/entropy.c7
-rw-r--r--thirdparty/mbedtls/library/hmac_drbg.c20
-rw-r--r--thirdparty/mbedtls/library/net_sockets.c14
-rw-r--r--thirdparty/mbedtls/library/pkwrite.c22
-rw-r--r--thirdparty/mbedtls/library/rsa.c28
-rw-r--r--thirdparty/mbedtls/library/threading.c6
-rw-r--r--thirdparty/mbedtls/library/version_features.c3
-rw-r--r--thirdparty/miniupnpc/LICENSE5
-rw-r--r--thirdparty/miniupnpc/miniupnpc/addr_is_reserved.c79
-rw-r--r--thirdparty/miniupnpc/miniupnpc/addr_is_reserved.h14
-rw-r--r--thirdparty/miniupnpc/miniupnpc/connecthostport.c6
-rw-r--r--thirdparty/miniupnpc/miniupnpc/listdevices.c197
-rw-r--r--thirdparty/miniupnpc/miniupnpc/minisoap.c6
-rw-r--r--thirdparty/miniupnpc/miniupnpc/minissdpc.c234
-rw-r--r--thirdparty/miniupnpc/miniupnpc/miniupnpc.c35
-rw-r--r--thirdparty/miniupnpc/miniupnpc/miniupnpc.h6
-rw-r--r--thirdparty/miniupnpc/miniupnpc/miniupnpc_socketdef.h2
-rw-r--r--thirdparty/miniupnpc/miniupnpc/miniupnpcmodule.c721
-rw-r--r--thirdparty/miniupnpc/miniupnpc/miniupnpcstrings.h2
-rw-r--r--thirdparty/miniupnpc/miniupnpc/miniwget.c15
-rw-r--r--thirdparty/miniupnpc/miniupnpc/portlistingparse.c2
-rw-r--r--thirdparty/miniupnpc/miniupnpc/receivedata.c10
-rw-r--r--thirdparty/miniupnpc/miniupnpc/upnpc.c864
-rw-r--r--thirdparty/miniupnpc/miniupnpc/upnpdev.h16
-rw-r--r--thirdparty/miniupnpc/miniupnpc/upnperrors.c112
-rw-r--r--thirdparty/miniupnpc/miniupnpc/upnperrors.h26
-rw-r--r--thirdparty/miniupnpc/miniupnpc/win32_snprintf.h71
-rw-r--r--thirdparty/miniupnpc/windows_fix.diff16
1631 files changed, 98497 insertions, 40264 deletions
diff --git a/.editorconfig b/.editorconfig
index 49517a5104..7743622e78 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -17,7 +17,8 @@ indent_size = 4
indent_style = space
indent_size = 4
-[.travis.yml]
+# YAML requires indentation with spaces instead of tabs.
+[*.{yml,yaml}]
indent_style = space
indent_size = 2
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 7ac70a4367..09ff2454ee 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -2,56 +2,181 @@
# Each line is a file pattern followed by one or more owners.
# Owners can be @users, @org/teams or emails
-/doc/ @godotengine/documentation
-doc_classes/* @godotengine/documentation
-
-# Rendering
-/drivers/gl_context/ @reduz
-/drivers/gles2/ @reduz
-/drivers/gles3/ @reduz
-
-# Audio
-/drivers/alsa/ @marcelofg55
-/drivers/alsamidi/ @marcelofg55
-/drivers/coreaudio/ @marcelofg55
-/drivers/coremidi/ @marcelofg55
-/drivers/pulseaudio/ @marcelofg55
-/drivers/wasapi/ @marcelofg55
-/drivers/winmidi/ @marcelofg55
-/drivers/xaudio2/ @marcelofg55
-
-/drivers/unix/ @hpvb
-/drivers/windows/ @hpvb
-
-/editor/icons/ @djrm
-
-/misc/ @akien-mga
-
-/modules/bullet/ @AndreaCatania
-/modules/csg/ @BastiaanOlij
-/modules/enet/ @godotengine/network
-/modules/gdnative/*arvr/ @BastiaanOlij
-/modules/gdnative/text/ @bruvzg
-/modules/gdscript/ @vnen
-/modules/mbedtls/ @godotengine/network
-/modules/mobile_vr/ @BastiaanOlij
-/modules/mono/ @neikeq
-/modules/mono/glue/GodotSharp @aaronfranke
-/modules/opensimplex/ @JFonS
-/modules/regex/ @LeeZH
-/modules/text_server_*/ @bruvzg
-/modules/upnp/ @godotengine/network
-/modules/websocket/ @godotengine/network
-
-/platform/javascript/ @eska014
-/platform/uwp/ @vnen
-
-/scene/resources/font.* @bruvzg
-/scene/resources/text_line.* @bruvzg
-/scene/resources/text_paragraph.* @bruvzg
-
-/servers/physics*/ @reduz @AndreaCatania
-/servers/text_server.* @bruvzg
-/servers/visual*/ @reduz
-
-/thirdparty/ @akien-mga
+# Buildsystem
+
+.* @godotengine/buildsystem
+.github/ @godotengine/buildsystem
+*.py @godotengine/buildsystem
+SConstruct @godotengine/buildsystem
+SCsub @godotengine/buildsystem
+
+# Core
+
+/core/ @godotengine/core
+/core/crypto/ @godotengine/network
+/core/debugger/ @godotengine/debugger
+/core/input/ @godotengine/input
+
+# Doc
+
+/doc/ @godotengine/documentation
+doc_classes/* @godotengine/documentation
+
+# Drivers
+
+## Audio
+/drivers/alsa/ @godotengine/audio
+/drivers/alsamidi/ @godotengine/audio
+/drivers/coreaudio/ @godotengine/audio
+/drivers/coremidi/ @godotengine/audio
+/drivers/pulseaudio/ @godotengine/audio
+/drivers/wasapi/ @godotengine/audio
+/drivers/winmidi/ @godotengine/audio
+/drivers/xaudio2/ @godotengine/audio
+
+## Rendering
+/drivers/dummy/ @godotengine/rendering
+/drivers/spirv-reflect/ @godotengine/rendering
+/drivers/vulkan/ @godotengine/rendering
+
+## OS
+/drivers/unix/ @godotengine/_platforms
+/drivers/windows/ @godotengine/windows
+
+## Misc
+/drivers/png/ @godotengine/import
+
+# Editor
+
+/editor/*debugger* @godotengine/debugger
+/editor/icons/ @godotengine/usability
+/editor/import/ @godotengine/import
+/editor/plugins/*2d_*.* @godotengine/2d-editor
+/editor/plugins/*3d_*.* @godotengine/3d-editor
+/editor/plugins/script_*.* @godotengine/script-editor
+/editor/plugins/*shader*.* @godotengine/shaders
+/editor/code_editor.* @godotengine/script-editor
+/editor/*dock*.* @godotengine/docks
+/editor/*shader*.* @godotengine/shaders
+
+# Main
+
+/main/ @godotengine/core
+
+# Misc
+
+/misc/ @godotengine/buildsystem
+
+# Modules
+
+## Audio (+ video)
+/modules/minimp3/ @godotengine/audio
+/modules/ogg/ @godotengine/audio
+/modules/opus/ @godotengine/audio
+/modules/stb_vorbis/ @godotengine/audio
+/modules/theora/ @godotengine/audio
+/modules/vorbis/ @godotengine/audio
+/modules/webm/ @godotengine/audio
+
+## Import
+/modules/basis_universal/ @godotengine/import
+/modules/bmp/ @godotengine/import
+/modules/cvtt/ @godotengine/import
+/modules/dds/ @godotengine/import
+/modules/etc/ @godotengine/import
+/modules/fbx/ @godotengine/import
+/modules/gltf/ @godotengine/import
+/modules/hdr/ @godotengine/import
+/modules/jpg/ @godotengine/import
+/modules/pvr/ @godotengine/import
+/modules/squish/ @godotengine/import
+/modules/svg/ @godotengine/import
+/modules/tga/ @godotengine/import
+/modules/tinyexr/ @godotengine/import
+/modules/webp/ @godotengine/import
+
+## Network
+/modules/enet/ @godotengine/network
+/modules/mbedtls/ @godotengine/network
+/modules/upnp/ @godotengine/network
+/modules/webrtc/ @godotengine/network
+/modules/websocket/ @godotengine/network
+
+## Rendering
+/modules/denoise/ @godotengine/rendering
+/modules/glslang/ @godotengine/rendering
+/modules/lightmapper_rd/ @godotengine/rendering
+/modules/meshoptimizer/ @godotengine/rendering
+/modules/vhacd/ @godotengine/rendering
+/modules/xatlas_unwrap/ @godotengine/rendering
+
+## Scripting
+/modules/gdnative/ @godotengine/gdnative
+/modules/gdscript/ @godotengine/gdscript
+/modules/jsonrpc/ @godotengine/gdscript
+/modules/mono/ @godotengine/mono
+/modules/visual_script/ @godotengine/visualscript
+
+## 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/mobile_vr/ @godotengine/xr
+/modules/webxr/ @godotengine/xr
+
+## Misc
+/modules/bullet/ @godotengine/physics
+/modules/csg/ @godotengine/3d-nodes
+/modules/gdnavigation/ @godotengine/navigation
+/modules/gridmap/ @godotengine/3d-nodes
+/modules/opensimplex/ @godotengine/3d-nodes
+/modules/regex/ @godotengine/core
+
+# Platform
+
+/platform/android/ @godotengine/android
+/platform/iphone/ @godotengine/ios
+/platform/javascript/ @godotengine/html5
+/platform/linuxbsd/ @godotengine/linux-bsd
+/platform/osx/ @godotengine/macos
+/platform/uwp/ @godotengine/uwp
+/platform/windows/ @godotengine/windows
+
+# Scene
+
+/scene/2d/ @godotengine/2d-nodes
+/scene/3d/ @godotengine/3d-nodes
+/scene/animation/ @godotengine/animation
+/scene/audio/ @godotengine/audio
+/scene/debugger/ @godotengine/debugger
+/scene/gui/ @godotengine/gui-nodes
+/scene/main/ @godotengine/core
+/scene/resources/default_theme/ @godotengine/gui-nodes
+/scene/resources/font.* @godotengine/gui-nodes
+/scene/resources/text_line.* @godotengine/gui-nodes
+/scene/resources/text_paragraph.* @godotengine/gui-nodes
+/scene/resources/visual_shader*.* @godotengine/shaders
+
+# Servers
+
+/servers/audio* @godotengine/audio
+/servers/camera* @godotengine/xr
+/servers/display_server.* @godotengine/_platforms
+/servers/navigation_server*.* @godotengine/navigation
+/servers/physics* @godotengine/physics
+/servers/rendering* @godotengine/rendering
+/servers/text_server.* @godotengine/gui-nodes
+/servers/xr* @godotengine/xr
+
+# Tests
+
+/tests/ @godotengine/tests
+
+# Thirdparty
+
+/thirdparty/ @godotengine/buildsystem
diff --git a/.github/workflows/android_builds.yml b/.github/workflows/android_builds.yml
index 697600abe3..b24a36beef 100644
--- a/.github/workflows/android_builds.yml
+++ b/.github/workflows/android_builds.yml
@@ -4,7 +4,7 @@ on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: master
- SCONSFLAGS: platform=android verbose=yes warnings=extra werror=yes --jobs=2 module_text_server_fb_enabled=yes
+ SCONSFLAGS: platform=android verbose=yes warnings=extra werror=yes debug_symbols=no --jobs=2 module_text_server_fb_enabled=yes
SCONS_CACHE_LIMIT: 4096
ANDROID_NDK_VERSION: 21.1.6352462
diff --git a/.github/workflows/ios_builds.yml b/.github/workflows/ios_builds.yml
index 73a1b2934e..c4da3cb683 100644
--- a/.github/workflows/ios_builds.yml
+++ b/.github/workflows/ios_builds.yml
@@ -4,7 +4,7 @@ on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: master
- SCONSFLAGS: platform=iphone verbose=yes warnings=extra werror=yes --jobs=2 module_text_server_fb_enabled=yes
+ SCONSFLAGS: platform=iphone verbose=yes warnings=extra werror=yes debug_symbols=no --jobs=2 module_text_server_fb_enabled=yes
SCONS_CACHE_LIMIT: 4096
jobs:
diff --git a/.github/workflows/javascript_builds.disabled b/.github/workflows/javascript_builds.disabled
index 015a1f314c..006981f3d4 100644
--- a/.github/workflows/javascript_builds.disabled
+++ b/.github/workflows/javascript_builds.disabled
@@ -4,7 +4,7 @@ on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: master
- SCONSFLAGS: platform=javascript verbose=yes warnings=extra werror=yes --jobs=2
+ SCONSFLAGS: platform=javascript verbose=yes warnings=extra werror=yes debug_symbols=no --jobs=2
SCONS_CACHE_LIMIT: 4096
EM_VERSION: 1.39.20
EM_CACHE_FOLDER: 'emsdk-cache'
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index 89e8f4d146..15a7be9c4f 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -4,13 +4,13 @@ on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: master
- SCONSFLAGS: platform=linuxbsd verbose=yes warnings=extra werror=yes --jobs=2 module_text_server_fb_enabled=yes
+ SCONSFLAGS: platform=linuxbsd verbose=yes warnings=extra werror=yes debug_symbols=no --jobs=2 module_text_server_fb_enabled=yes
SCONS_CACHE_LIMIT: 4096
jobs:
- linux-editor-mono:
+ linux-editor:
runs-on: "ubuntu-20.04"
- name: Editor w/ Mono (target=release_debug, tools=yes, tests=yes)
+ name: Editor (target=release_debug, tools=yes, tests=yes)
steps:
- uses: actions/checkout@v2
@@ -62,13 +62,13 @@ jobs:
env:
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
run: |
- scons tools=yes tests=yes target=release_debug module_mono_enabled=yes mono_glue=no
+ scons tools=yes tests=yes target=release_debug
ls -l bin/
# Execute unit tests for the editor
- name: Unit Tests
run: |
- ./bin/godot.linuxbsd.opt.tools.64.mono --test
+ ./bin/godot.linuxbsd.opt.tools.64 --test
- uses: actions/upload-artifact@v2
with:
@@ -76,9 +76,9 @@ jobs:
path: bin/*
retention-days: 14
- linux-editor-sanitizers:
+ linux-editor-sanitizers-mono:
runs-on: "ubuntu-20.04"
- name: Editor with sanitizers (target=debug, tools=yes, tests=yes, use_asan=yes, use_ubsan=yes)
+ name: Editor w/ Mono and sanitizers (target=debug, tools=yes, tests=yes, use_asan=yes, use_ubsan=yes)
steps:
- uses: actions/checkout@v2
@@ -130,13 +130,13 @@ jobs:
env:
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
run: |
- scons tools=yes tests=yes target=debug use_asan=yes use_ubsan=yes
+ scons tools=yes tests=yes target=debug module_mono_enabled=yes mono_glue=no use_asan=yes use_ubsan=yes
ls -l bin/
# Execute unit tests for the editor
- name: Unit Tests
run: |
- ./bin/godot.linuxbsd.tools.64s --test
+ ./bin/godot.linuxbsd.tools.64s.mono --test
linux-template-mono:
runs-on: "ubuntu-20.04"
@@ -191,7 +191,7 @@ jobs:
env:
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
run: |
- scons target=release tools=no module_mono_enabled=yes mono_glue=no debug_symbols=no
+ scons target=release tools=no module_mono_enabled=yes mono_glue=no
ls -l bin/
- uses: actions/upload-artifact@v2
diff --git a/.github/workflows/macos_builds.yml b/.github/workflows/macos_builds.yml
index 803c8f8ec4..a15ab92052 100644
--- a/.github/workflows/macos_builds.yml
+++ b/.github/workflows/macos_builds.yml
@@ -4,7 +4,7 @@ on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: master
- SCONSFLAGS: platform=osx verbose=yes warnings=extra werror=yes --jobs=2 module_text_server_fb_enabled=yes
+ SCONSFLAGS: platform=osx verbose=yes warnings=extra werror=yes debug_symbols=no --jobs=2 module_text_server_fb_enabled=yes
SCONS_CACHE_LIMIT: 4096
jobs:
@@ -104,7 +104,7 @@ jobs:
env:
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
run: |
- scons target=release tools=no debug_symbols=no
+ scons target=release tools=no
ls -l bin/
- uses: actions/upload-artifact@v2
diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml
index 12270a848a..30468034ff 100644
--- a/.github/workflows/static_checks.yml
+++ b/.github/workflows/static_checks.yml
@@ -35,11 +35,12 @@ jobs:
run: |
bash ./misc/scripts/black_format.sh
- - name: JavaScript style checks via ESLint
+ - name: JavaScript style and documentation checks via ESLint and JSDoc
run: |
cd platform/javascript
npm ci
npm run lint
+ npm run docs -- -d dry-run
- name: Documentation checks
run: |
diff --git a/.github/workflows/windows_builds.yml b/.github/workflows/windows_builds.yml
index b9bf510c71..b7cc127226 100644
--- a/.github/workflows/windows_builds.yml
+++ b/.github/workflows/windows_builds.yml
@@ -5,7 +5,7 @@ on: [push, pull_request]
# SCONS_CACHE for windows must be set in the build environment
env:
GODOT_BASE_BRANCH: master
- SCONSFLAGS: platform=windows verbose=yes warnings=all werror=yes --jobs=2 module_text_server_fb_enabled=yes
+ SCONSFLAGS: platform=windows verbose=yes warnings=all werror=yes debug_symbols=no --jobs=2 module_text_server_fb_enabled=yes
SCONS_CACHE_MSVC_CONFIG: true
SCONS_CACHE_LIMIT: 3072
@@ -24,7 +24,7 @@ jobs:
# Editing this is pretty dangerous for Windows since it can break and needs to be properly tested with a fresh cache.
- name: Load .scons_cache directory
id: windows-editor-cache
- uses: RevoluPowered/cache@v2.1
+ uses: actions/cache@v2
with:
path: /.scons_cache/
key: ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
@@ -110,7 +110,7 @@ jobs:
env:
SCONS_CACHE: /.scons_cache/
run: |
- scons target=release tools=no debug_symbols=no
+ scons target=release tools=no
ls -l bin/
- uses: actions/upload-artifact@v2
diff --git a/.mailmap b/.mailmap
index 73128d27db..dfbd13e612 100644
--- a/.mailmap
+++ b/.mailmap
@@ -6,6 +6,7 @@ Anish Bhobe <anishbhobe@hotmail.com>
Anutrix <numaanzaheerahmed@yahoo.com>
Aren Villanueva <arenvillanueva@yomogi-soft.com> <aren@displaysweet.com>
Ariel Manzur <ariel@godotengine.org>
+Ariel Manzur <ariel@godotengine.org> <puntob@gmail.com>
Ariel Manzur <ariel@godotengine.org> <punto@godotengine.org>
Ariel Manzur <ariel@godotengine.org> <ariel@okamstudio.com>
Ariel Manzur <ariel@godotengine.org> <punto@Ariels-Mac-mini.local>
@@ -25,6 +26,7 @@ Daniel J. Ramirez <djrmuv@gmail.com>
Dominik 'dreamsComeTrue' Jasiński <dominikjasinski@o2.pl>
Emmanuel Barroga <emmanuelbarroga@gmail.com>
Eric M <itsjusteza@gmail.com>
+Eric Rybicki <info@ericrybicki.com> <stratos695@googlemail.com>
Erik Selecký <35656626+rxlecky@users.noreply.github.com>
Erik Selecký <35656626+rxlecky@users.noreply.github.com> <35656626+SeleckyErik@users.noreply.github.com>
Fabian <supagu@gmail.com>
@@ -38,6 +40,7 @@ Gilles Roudiere <gilles.roudiere@gmail.com> <gilles.roudiere@laas.fr>
Gordon MacPherson <gordon@gordonite.tech>
Guilherme Felipe <guilhermefelipecgs@gmail.com>
Hanif Bin Ariffin <hanif.ariffin.4326@gmail.com>
+HaSa1002 <johawitt@outlook.de>
Hein-Pieter van Braam-Stewart <hp@tmm.cx>
Hubert Jarosz <marqin.pl@gmail.com>
Hubert Jarosz <marqin.pl@gmail.com> <marqin.pl+git@gmail.com>
@@ -84,6 +87,7 @@ Mateo Kuruk Miccino <mateomiccino@gmail.com>
Max Hilbrunner <m.hilbrunner@gmail.com>
Max Hilbrunner <m.hilbrunner@gmail.com> <mhilbrunner@users.noreply.github.com>
Michael Alexsander <michaelalexsander@protonmail.com>
+Nathan Franke <natfra@pm.me> <nathanwfranke@gmail.com>
Nathan Lovato <nathan@gdquest.com>
Nathan Warden <nathan@nathanwarden.com> <nathanwardenlee@icloud.com>
Nils ANDRÉ-CHANG <nils@nilsand.re>
@@ -97,7 +101,7 @@ Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
Pieter-Jan Briers <pieterjan.briers+git@gmail.com> <pieterjan.briers@gmail.com>
Poommetee Ketson <poommetee@protonmail.com>
Przemysław Gołąb (n-pigeon) <golab.przemyslaw@gmail.com>
-Rafał Mikrut <mikrutrafal54@gmail.com>
+Rafał Mikrut <mikrutrafal@protonmail.com> <mikrutrafal54@gmail.com>
Ralf Hölzemer <r.hoelzemer@posteo.de> <rollenrolm@posteo.de>
Ralf Hölzemer <r.hoelzemer@posteo.de> <rollenrolm@users.noreply.github.com>
Ramesh Ravone <ramesh.maran443@gmail.com>
@@ -123,5 +127,6 @@ Wilhem Barbier <nounoursheureux@openmailbox.org> <wilhem.b@free.fr>
Wilhem Barbier <nounoursheureux@openmailbox.org> <schtroumps31@gmail.com>
Will Nations <willnationsdev@gmail.com>
yg2f <yoann@terminajones.com>
+Yuri Sizov <yuris@humnom.net> <pycbouh@users.noreply.github.com>
Zak Stam <zakscomputers@hotmail.com>
Zher Huei Lee <lee.zh.92@gmail.com>
diff --git a/AUTHORS.md b/AUTHORS.md
index 1ebef77509..8c26d2892b 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -114,6 +114,7 @@ name is available.
Leon Krause (leonkrause)
Liz Haas (27thLiz)
Lucien Menassol (Kanabenki)
+ Lyuma
m4nu3lf
Maganty Rushyendra (mrushyendra)
Marcel Admiraal (madmiraal)
@@ -138,6 +139,7 @@ name is available.
MichiRecRoom (LikeLakers2)
mrezai
muiroc
+ Nathan Franke (nathanfranke)
Nathan Lovato (NathanLovato)
Nathan Warden (NathanWarden)
Nils André-Chang (NilsIrl)
@@ -161,6 +163,7 @@ name is available.
Ray Koopa (RayKoopa)
Rémi Verschelde (akien-mga)
Rhody Lugo (rraallvv)
+ Ricardo Subtil (Ev1lbl0w)
Roberto F. Arroyo (robfram)
Robin Hübner (profan)
romulox-x
@@ -191,6 +194,7 @@ name is available.
Xavier Cho (mysticfall)
yg2f (SuperUserNameMan)
Yuri Roubinsky (Chaosus)
+ Yuri Sizov (pycbouh)
Zak Stam (zaksnet)
Zher Huei Lee (leezh)
ZuBsPaCe
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88c9e1a8a0..fe5631cefd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -37,7 +37,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Ability to convert visual shaders to text-based shaders.
- See the [complete list of new functions](https://github.com/godotengine/godot/pull/26164).
- Improved visual scripting.
- - Visual scripting now uses an unified graph where all functions are represented.
+ - Visual scripting now uses a unified graph where all functions are represented.
- Nodes can now be edited directly in the graph.
- Support for fuzzy searching.
- The `tool` mode can now be enabled in visual scripts.
@@ -900,7 +900,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Removed many debugging prints in the console.
- Export templates now display an error dialog if no project was found when starting.
- DynamicFont oversampling is now enabled by default.
-- Nodes' internal logic now consistently use internal physics processing.
+- Nodes' internal logic now consistently uses internal physics processing.
- Allow attaching and clearing scripts on multiple nodes at once.
- Default values are no longer saved in scene and resource files.
- The selection rectangle of 2D nodes is now hidden when not pertinent (no more rectangle for collision shapes).
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4387750f28..d7a4f976bf 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -241,25 +241,21 @@ discussions and support, others more for development discussions.
To communicate with developers (e.g. to discuss a feature you want to implement
or a bug you want to fix), the following channels can be used:
-- [GitHub issues](https://github.com/godotengine/godot/issues): If there is an
- existing issue about a topic you want to discuss, just add a comment to it -
- all developers watch the repository and will get an email notification. You
- can also create a new issue - please keep in mind to create issues only to
- discuss quite specific points about the development, and not general user
- feedback or support requests.
-- [#godotengine-devel IRC channel on
- Freenode](https://webchat.freenode.net/?channels=godotengine-devel): You will
- find most core developers there, so it's the go-to channel for direct chat
+- [Godot Contributors Chat](https://chat.godotengine.org): You will
+ find most core developers there, so it's the go-to platform for direct chat
about Godot Engine development. Feel free to start discussing something there
to get some early feedback before writing up a detailed proposal in a GitHub
issue.
-- [devel@godotengine.org mailing
- list](https://listengine.tuxfamily.org/godotengine.org/devel/): Mailing list
- for Godot developers, used primarily to announce developer meetings on IRC
- and other important discussions that need to reach people directly in their
- mailbox. See the [index
- page](https://listengine.tuxfamily.org/godotengine.org/devel/) for
- subscription instructions.
+- [Bug tracker](https://github.com/godotengine/godot/issues): If there is an
+ existing issue about a topic you want to discuss, just add a comment to it -
+ many developers watch the repository and will get a notification. You can
+ also create a new issue - please keep in mind to create issues only to
+ discuss quite specific points about the development, and not general user
+ feedback or support requests.
+- [Feature proposals](https://github.com/godotengine/godot-proposals/issues):
+ To propose a new feature, we have a dedicated issue tracker for that. Don't
+ hesitate to start by talking about your idea on the Godot Contributors Chat
+ to make sure that it makes sense in Godot's context.
Thanks for your interest in contributing!
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index b9b15abf5d..6684978318 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -72,6 +72,11 @@ Copyright: 2008-2016, The Android Open Source Project
2002, Google, Inc.
License: Apache-2.0
+Files: ./servers/physics_3d/collision_solver_3d_sat.cpp
+Comment: Open Dynamics Engine
+Copyright: 2001-2003, Russell L. Smith, Alen Ladavac, Nguyen Binh
+License: BSD-3-clause
+
Files: ./servers/physics_3d/gjk_epa.cpp
./servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp
./servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
@@ -82,6 +87,8 @@ Files: ./servers/physics_3d/gjk_epa.cpp
./servers/physics_3d/joints/pin_joint_3d_sw.h
./servers/physics_3d/joints/slider_joint_3d_sw.cpp
./servers/physics_3d/joints/slider_joint_3d_sw.h
+ ./servers/physics_3d/soft_body_3d_sw.cpp
+ ./servers/physics_3d/soft_body_3d_sw.h
Comment: Bullet Continuous Collision Detection and Physics Library
Copyright: 2003-2008, Erwin Coumans
2007-2021, Juan Linietsky, Ariel Manzur.
@@ -264,7 +271,7 @@ License: CC0-1.0
Files: ./thirdparty/miniupnpc/
Comment: MiniUPnPc
-Copyright: 2005-2019, Thomas Bernard
+Copyright: 2005-2021, Thomas Bernard
License: BSD-3-clause
Files: ./thirdparty/minizip/
diff --git a/DONORS.md b/DONORS.md
index a852f08287..614ef1486a 100644
--- a/DONORS.md
+++ b/DONORS.md
@@ -32,6 +32,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Garry Newman
Gordon MacPherson
Hunter Dickson
+ Kyle Szklenski
## Mini sponsors
@@ -39,6 +40,8 @@ generous deed immortalized in the next stable release of Godot Engine.
Alejandro Saucedo
alex brown
Andrew Dunai
+ Ben Nolan
+ blurp
CD
Christian Baune
Christoffer Sundbom
@@ -58,6 +61,7 @@ generous deed immortalized in the next stable release of Godot Engine.
John G Gentzel
Jonah Stich
Justin Arnold
+ Kamil Brzezinski
Marcel Kräml
Matthieu Huvé
Maxim Karsten
@@ -67,6 +71,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Patrick Horn
Patrick Schmidt
Péter Magyar
+ Rami
Ronnie Cheng
Slobodan Milnovic
Stephan Lanfermann
@@ -75,6 +80,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Tristan Pemble
VilliHaukka
Violin Iliev
+ Xwdit
## Gold donors
@@ -82,7 +88,7 @@ generous deed immortalized in the next stable release of Godot Engine.
albinaask
Alvaro A Baena R
Asher Glick
- Bernhard Werner
+ Barugon
Carlo Cabanilla
Chris Goddard
Christopher Case
@@ -96,11 +102,9 @@ generous deed immortalized in the next stable release of Godot Engine.
Florian Rämisch
Forge
Gamejunkey
- Grady
Hoojib
Jakub Grzesik
Javier Roman
- Jeff Nyte
Joan Fons
Johnny IV Young
Jon Woodward
@@ -115,13 +119,9 @@ generous deed immortalized in the next stable release of Godot Engine.
Matthew Hillier
Michael
m kaersten
- Mohamed Ikbel Boulabiar
Monster Vial
Officine Pixel S.n.c.
- Pixel Booty
- Rami
Rene
- Rene Tailleur
Retro Village
Rob Messick
Roland Fredenhagen
@@ -142,7 +142,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Xeno Coliseum
Zaven Muradyan
- Aaron Winter
Adam Nakonieczny
Adrian Adamiak
Aleksey Korotkevich
@@ -154,14 +153,12 @@ generous deed immortalized in the next stable release of Godot Engine.
Andreas Funke
André Frélicot
Andrew Cunningham
- Anm
Antanas Paskauskas
Antoni Batchelli
Arisaka Mayuki
Arthur S. Muszynski
- Aubin Detrez
- Barugon
Ben Botwin
+ Brandon Hawkinson
Caleb Sizemore
Can Eris
Charlie Whitfield
@@ -170,8 +167,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Chris Petrich
Chris Serino
Christian Leth Jeppesen
- Cody Brooks
- Conrad Curry
Craig Ostrin
Craig Smith
Cristopher
@@ -191,15 +186,13 @@ generous deed immortalized in the next stable release of Godot Engine.
Gabrielius Vaiškūnas
Gary Hulst
gavlig
+ General Chicken
GGGames.org
- GiulianoB
- Green Fox
Guilherme Felipe de C. G. da Silva
Harvey Fong
Heath Hayes
Horváth Péter
Hu Hund
- Idilio Alfaro
Jake Burga
James Couzens
Jared
@@ -209,6 +202,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Joel Höglund
Johnathan Kupferer
Jose Malheiro
+ Jose Manuel Muñoz Perez
Joseph Crane
Joshie Sparks
Joshua Flores
@@ -223,9 +217,11 @@ generous deed immortalized in the next stable release of Godot Engine.
kickmaniac
kinfox
Kos
+ kuku
Lachie
Lain Ballard
Laszlo Kiss
+ leetNightshade
Leo Fidel R Liban
Liam Smyth
Luc-Frédéric Langis
@@ -234,10 +230,8 @@ generous deed immortalized in the next stable release of Godot Engine.
Marcelo Dornbusch Lopes
Marcus Dobler
Marcus Richter
- Marisa Clardy
+ Marek Belski
Mark Barrett
- Mark Diaz
- Markus Fehr
Martin Eigel
Martin Kotz
Martin Soucek
@@ -249,16 +243,17 @@ generous deed immortalized in the next stable release of Godot Engine.
Michael Dürwald
Michael Noll
Michael Policastro
+ MightyPossum
MikadoSC
MuffinManKen
Nick Abousselam
Nick Barovic
Oliver Dick
Oscar Campos
- Patrick Brock
Patrick Ting
Paul Hocker
Paul Von Zimmerman
+ Pavel Kotlyar
Pedro Silva
Pete Goodwin
Petr Malac
@@ -266,6 +261,7 @@ generous deed immortalized in the next stable release of Godot Engine.
pl
Raymond Harris
Raz A
+ Rene Tailleur
Ricardo Alcantara
Robert Larnach
Robert Willes
@@ -277,11 +273,11 @@ generous deed immortalized in the next stable release of Godot Engine.
Ryan Scott
Ryszard Sommefeldt
Samuel Judd
- Scott Pilet
Sean Morgan
Sebastian Hutter
Sébastien
Serban Serafimescu
+ Sergey Fonaryov
Sergey Minakov
Shishir Tandale
SKison
@@ -290,12 +286,11 @@ generous deed immortalized in the next stable release of Godot Engine.
Stephan Hennion
Steven Landow
Stoned Xander
- TheLevelOfDetail
Thomas Bjarnelöf
Thomas Kurz
Tim Howard
- tinyBigGAMES LLC
Tobias Bocanegra
+ Todd Smith
Turntsnaco
tweaklab
Valryia
@@ -303,7 +298,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Vlad Ceru Opran
VoidPointer
voxelv
- William Foster
Wojciech Chojnacki
xzibiting
Yuancheng Zhang
@@ -341,9 +335,9 @@ generous deed immortalized in the next stable release of Godot Engine.
Alexander Walter (SilvanuZ)
Alexandre Beaudoin
alex clavelle
+ Alex Schmidt
Allan Davis
Allen Schade
- Ancient Phoenix
Anders Marstein Kruke
Andreas Krampitz
Andre Stackhouse
@@ -352,11 +346,11 @@ generous deed immortalized in the next stable release of Godot Engine.
Andrew Thomas
Ano Nim
Anthony Avina
+ Anton Bouwer
aomimezura11
AP Condomines
Arch Toasty
Arda Erol
- Aria
Armin Preiml
Arseniy M
Ashley Claymore
@@ -365,10 +359,10 @@ generous deed immortalized in the next stable release of Godot Engine.
AzulCrescent
Balázs Batári
Bartosz Bielecki
- Bekhoucha Danyl
Benedikt
Ben Vercammen
Bernd Jänichen
+ Bernhard Werner
Bjarne Voigtländer
Black Block
blackjacksike
@@ -383,6 +377,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Bronson Zgeb
Bùi Việt Thành
Burney Waring
+ bwhirt
Caleb Gartner
Cameron Meyer
Carlos Cejudo
@@ -401,8 +396,8 @@ generous deed immortalized in the next stable release of Godot Engine.
Christian Winter
Christoffer Dahlblom
Christophe Gagnier
+ Christopher Chin
Christopher Schmitt
- Christoph Woinke
Chris Truebe
Clay Heaton
Cody Parker
@@ -422,6 +417,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Dmitry Fisher
Dmytro Korchynskyi
Dominik Wetzel
+ Douglas Plumley
Dragontrapper
Dr Ewan Murray
Dr.Raccoon
@@ -435,11 +431,10 @@ generous deed immortalized in the next stable release of Godot Engine.
Elgenzay
Elias Nykrem
Ephemeral
- Eric Ellingson
+ Eric Walkingshaw
Eric Williams
Erkki Seppälä
Evan Rose
- Fain
Faisal Alkubaisi
Fancy Ants Studios
Fekinox
@@ -449,15 +444,15 @@ generous deed immortalized in the next stable release of Godot Engine.
Francois Holland
Frank
FuDiggity
- Gadzhi Kharkharov
gamedev by Celio
Game Endeavor
+ Gareth Knowles
Gary Thomas
George Marques
- Gerard Ruiz Torruella
+ georgios katsanakis
+ GFizz
Greg Lincoln
Greg Olson
- GREGORY C FEIN
Greyson Richey
Grid
Guillaume Audirac
@@ -467,7 +462,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Hal A
helija
Heribert Hirth
- Hieu Thanh
Hunter Jones
Ian Williams
Iiari
@@ -484,10 +478,9 @@ generous deed immortalized in the next stable release of Godot Engine.
James
James A F Manley
James Thomas
- Jamiee H
Jamie Massey
+ Jan Vetulani
JARKKO PARVIAINEN
- Jasiek Vetulani
Jason Uechi
Jean-Baptiste LEPESME
Jeff Hungerford
@@ -496,6 +489,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Jhon Adams
Joe Klemmer
John Gabriel
+ Jonah Branch
Jonas
Jonas Bernemann
Jonas Rudlang
@@ -507,21 +501,23 @@ generous deed immortalized in the next stable release of Godot Engine.
Jon Sully
Jordy Goodridge
Jorge Antunes
- Jorge Javier Araya Navarro
+ Jorge Araya Navarro
Jose C. Rubio
Joseph Catrambone
Josh Taylor
Josue David
+ jromkjrom
Juanfran
+ Juan Uys
Jueast
Julian Murgia
June Little
Justin Hamilton
Justin Oaksford
Justin Spedding
+ Justin W. Flory
KaDokta
Kalin
- Kauzig
Keedong Park
Keinan Powers
Keith Bradner
@@ -539,8 +535,8 @@ generous deed immortalized in the next stable release of Godot Engine.
KsyTek Games
kycho
Kyle Jacobs
- Kyle Szklenski
Kyuppin
+ Lasse le Dous
Laurent CHEA
Laurent Tréguier
Laxman Pradhan
@@ -558,19 +554,16 @@ generous deed immortalized in the next stable release of Godot Engine.
Malcolm
Marco Lardelli
Mark Jad
- Mark Krenz
Mark Malone
Markus Martin
Markus Michael Egger
Martin FIbik
Martin Holas
- Martin Linklater
Martin Trbola
Marvin
Mathieu
Matt Edwards
Matthew Booe
- Max Brister
Max Fiedler
Maxime Blade
Maxwell
@@ -582,13 +575,13 @@ generous deed immortalized in the next stable release of Godot Engine.
Michael Bruce-Lockhart
Michael Haney
Michał Skwarek
+ MidoriBunn 'tis BS
Mikayla
Mike Birkhead
Mike Cunningham
Mitchell J. Wagner
Molinghu
Molly Jameson
- MoM
MrAZIE
Nathan Fish
Nathaniel
@@ -612,30 +605,31 @@ generous deed immortalized in the next stable release of Godot Engine.
OKV
Oleg Reva
Oleksandr Kryvonos
- Olivier
Omar Delarosa
+ Oriol Muñoz Princep
Oscar Domingo
Parinya Teerakasemsuk
patricio lara briones
+ Patrick Brock
Patrick Dully
Patrick Nafarrete
Paul Gieske
- Paul Mason
Paweł Kowal
Paweł Łyczkowski
Peter Höglund
+ Peter Richmond
Petrus Prinsloo
Philip Cohoe
- Phillip Zolla
+ Pierre Caye
Piotr Góral
Pipo
Point08
Preethi Vaidyanathan
pwab
- pyacier
Rad Cat
Rafa Laguna
Raffaele Aramo
+ Rami Hanano
RAMupgrade
Remi Rampin
Rémi Verschelde
@@ -652,6 +646,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Ronan
Ross Squires
Ryan Groom
+ Sam Caulfield
Sam Edson
Samuele Zolfanelli
scapegoat57
@@ -659,8 +654,9 @@ generous deed immortalized in the next stable release of Godot Engine.
Scott Longley
Sean Lynch
Sebastian Michailidis
- Sebastian Vetter
SeongWan Kim
+ Serenitor
+ Sergey
Sergiy Onenko
Shane
Shane Sicienski
@@ -683,6 +679,7 @@ generous deed immortalized in the next stable release of Godot Engine.
tannhauser_gate
Tarch
Terry
+ The Liquidator
Theodore Lindsey
TheVoiceInMyHead
thomas
@@ -693,8 +690,8 @@ generous deed immortalized in the next stable release of Godot Engine.
Tim Erskine
Tim Gleason
Timothy B. MacDonald
- Tobbun
Tobias Bradtke
+ Tom Coxon
Toni Duran
Tony Zhao
Torgeir Lilleskog
@@ -712,11 +709,11 @@ generous deed immortalized in the next stable release of Godot Engine.
Uther
Vaughan Ling
Victor
- Vigilant Watch
Viktor Ismagilov
+ Vi Watch
Vladimir Savin
Vladislav Smirnov
- Výrus Hemomancer
+ Vytenis Narušis
waka nya
Wayne Haak
werner mendizabal
@@ -725,13 +722,12 @@ generous deed immortalized in the next stable release of Godot Engine.
William F Siqueira
William Hogben
Wyatt Goodin
- Xaver Fischer
+ x1212
xenomat
Yegor Smirnov
Zack Yang
Zak Stephens
蕭惟允
- 郝晨煜
## Bronze donors
diff --git a/README.md b/README.md
index 1f2aa00f08..72a85492fd 100644
--- a/README.md
+++ b/README.md
@@ -50,8 +50,7 @@ Godot is not only an engine but an ever-growing community of users and engine
developers. The main community channels are listed [on the homepage](https://godotengine.org/community).
To get in touch with the engine developers, the best way is to join the
-[#godotengine-devel IRC channel](https://webchat.freenode.net/?channels=godotengine-devel)
-on Freenode.
+[Godot Contributors Chat](https://chat.godotengine.org).
To get started contributing to the project, see the [contributing guide](CONTRIBUTING.md).
diff --git a/SConstruct b/SConstruct
index 065019d591..3edf81129b 100644
--- a/SConstruct
+++ b/SConstruct
@@ -55,17 +55,21 @@ custom_tools = ["default"]
platform_arg = ARGUMENTS.get("platform", ARGUMENTS.get("p", False))
-if os.name == "nt" and (platform_arg == "android" or ARGUMENTS.get("use_mingw", False)):
+if os.name == "nt" and (platform_arg == "android" or methods.get_cmdline_bool("use_mingw", False)):
custom_tools = ["mingw"]
elif platform_arg == "javascript":
# Use generic POSIX build toolchain for Emscripten.
custom_tools = ["cc", "c++", "ar", "link", "textfile", "zip"]
+# We let SCons build its default ENV as it includes OS-specific things which we don't
+# want to have to pull in manually.
+# Then we prepend PATH to make it take precedence, while preserving SCons' own entries.
env_base = Environment(tools=custom_tools)
-if "TERM" in os.environ:
+env_base.PrependENVPath("PATH", os.getenv("PATH"))
+env_base.PrependENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH"))
+if "TERM" in os.environ: # Used for colored output.
env_base["ENV"]["TERM"] = os.environ["TERM"]
-env_base.AppendENVPath("PATH", os.getenv("PATH"))
-env_base.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH"))
+
env_base.disabled_modules = []
env_base.module_version_string = ""
env_base.msvc = False
@@ -95,7 +99,7 @@ env_base.SConsignFile(".sconsign{0}.dblite".format(pickle.HIGHEST_PROTOCOL))
customs = ["custom.py"]
-profile = ARGUMENTS.get("profile", False)
+profile = ARGUMENTS.get("profile", "")
if profile:
if os.path.isfile(profile):
customs.append(profile)
@@ -111,7 +115,7 @@ opts.Add(BoolVariable("tools", "Build the tools (a.k.a. the Godot editor)", True
opts.Add(EnumVariable("target", "Compilation target", "debug", ("debug", "release_debug", "release")))
opts.Add("arch", "Platform-dependent architecture (arm/arm64/x86/x64/mips/...)", "")
opts.Add(EnumVariable("bits", "Target platform bits", "default", ("default", "32", "64")))
-opts.Add(EnumVariable("optimize", "Optimization type", "speed", ("speed", "size")))
+opts.Add(EnumVariable("optimize", "Optimization type", "speed", ("speed", "size", "none")))
opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False))
opts.Add(BoolVariable("use_lto", "Use link-time optimization", False))
@@ -120,6 +124,7 @@ opts.Add(BoolVariable("deprecated", "Enable deprecated features", True))
opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True))
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False))
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
+opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
# Advanced options
opts.Add(BoolVariable("dev", "If yes, alias for verbose=yes warnings=extra werror=yes", False))
@@ -237,11 +242,20 @@ if env_base["custom_modules"]:
Exit(255)
for path in module_search_paths:
+ if path == "modules":
+ # Built-in modules don't have nested modules,
+ # so save the time it takes to parse directories.
+ modules = methods.detect_modules(path, recursive=False)
+ else: # Custom.
+ modules = methods.detect_modules(path, env_base["custom_modules_recursive"])
+ # Provide default include path for both the custom module search `path`
+ # and the base directory containing custom modules, as it may be different
+ # from the built-in "modules" name (e.g. "custom_modules/summator/summator.h"),
+ # so it can be referenced simply as `#include "summator/summator.h"`
+ # independently of where a module is located on user's filesystem.
+ env_base.Prepend(CPPPATH=[path, os.path.dirname(path)])
# Note: custom modules can override built-in ones.
- modules_detected.update(methods.detect_modules(path))
- include_path = os.path.dirname(path)
- if include_path:
- env_base.Prepend(CPPPATH=[include_path])
+ modules_detected.update(modules)
# Add module options.
for name, path in modules_detected.items():
@@ -288,10 +302,6 @@ if env_base["target"] == "debug":
# http://scons.org/doc/production/HTML/scons-user/ch06s04.html
env_base.SetOption("implicit_cache", 1)
-if not env_base["tools"]:
- # Export templates can't run unit test tool.
- env_base["tests"] = False
-
if env_base["no_editor_splash"]:
env_base.Append(CPPDEFINES=["NO_EDITOR_SPLASH"])
@@ -318,17 +328,17 @@ if selected_platform in platform_list:
env.Alias("compiledb", env.CompilationDatabase())
# 'dev' and 'production' are aliases to set default options if they haven't been set
- # manually by the user. We use `ARGUMENTS.get()` to check if they were manually set.
+ # manually by the user.
if env["dev"]:
- env["verbose"] = ARGUMENTS.get("verbose", True)
+ env["verbose"] = methods.get_cmdline_bool("verbose", True)
env["warnings"] = ARGUMENTS.get("warnings", "extra")
- env["werror"] = ARGUMENTS.get("werror", True)
+ env["werror"] = methods.get_cmdline_bool("werror", True)
if env["tools"]:
- env["tests"] = ARGUMENTS.get("tests", True)
+ env["tests"] = methods.get_cmdline_bool("tests", True)
if env["production"]:
- env["use_static_cpp"] = ARGUMENTS.get("use_static_cpp", True)
- env["use_lto"] = ARGUMENTS.get("use_lto", True)
- env["debug_symbols"] = ARGUMENTS.get("debug_symbols", False)
+ env["use_static_cpp"] = methods.get_cmdline_bool("use_static_cpp", True)
+ env["use_lto"] = methods.get_cmdline_bool("use_lto", True)
+ env["debug_symbols"] = methods.get_cmdline_bool("debug_symbols", False)
if not env["tools"] and env["target"] == "debug":
print(
"WARNING: Requested `production` build with `tools=no target=debug`, "
@@ -374,7 +384,7 @@ if selected_platform in platform_list:
if not (f[0] in ARGUMENTS): # allow command line to override platform flags
env[f[0]] = f[1]
- # Must happen after the flags definition, so that they can be used by platform detect
+ # Must happen after the flags' definition, so that they can be used by platform detect
detect.configure(env)
# Set our C and C++ standard requirements.
@@ -610,7 +620,7 @@ if selected_platform in platform_list:
if env["minizip"]:
env.Append(CPPDEFINES=["MINIZIP_ENABLED"])
- editor_module_list = ["regex"]
+ editor_module_list = ["freetype", "regex"]
if env["tools"] and not env.module_check_dependencies("tools", editor_module_list):
print(
"Build option 'module_"
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 70e8133eaa..f87dc6704e 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -32,6 +32,7 @@
#include "core/core_bind.h"
#include "core/core_string_names.h"
+#include "core/input/input_map.h"
#include "core/io/file_access_network.h"
#include "core/io/file_access_pack.h"
#include "core/io/marshalls.h"
@@ -124,6 +125,11 @@ void ProjectSettings::set_restart_if_changed(const String &p_name, bool p_restar
props[p_name].restart_if_changed = p_restart;
}
+void ProjectSettings::set_as_basic(const String &p_name, bool p_basic) {
+ ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
+ props[p_name].basic = p_basic;
+}
+
void ProjectSettings::set_ignore_value_in_docs(const String &p_name, bool p_ignore) {
ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
#ifdef DEBUG_METHODS_ENABLED
@@ -269,6 +275,10 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const {
vc.flags = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE;
}
+ if (v->basic) {
+ vc.flags |= PROPERTY_USAGE_EDITOR_BASIC_SETTING;
+ }
+
if (v->restart_if_changed) {
vc.flags |= PROPERTY_USAGE_RESTART_IF_CHANGED;
}
@@ -278,7 +288,7 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const {
for (Set<_VCSort>::Element *E = vclist.front(); E; E = E->next()) {
String prop_info_name = E->get().name;
int dot = prop_info_name.find(".");
- if (dot != -1) {
+ if (dot != -1 && !custom_prop_info.has(prop_info_name)) {
prop_info_name = prop_info_name.substr(0, dot);
}
@@ -383,7 +393,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
if (exec_path != "") {
// We do several tests sequentially until one succeeds to find a PCK,
- // and if so we attempt loading it at the end.
+ // and if so, we attempt loading it at the end.
// Attempt with PCK bundled into executable.
bool found = _load_resource_pack(exec_path);
@@ -597,6 +607,7 @@ Error ProjectSettings::_load_settings_text(const String &p_path) {
// If we're loading a project.godot from source code, we can operate some
// ProjectSettings conversions if need be.
_convert_to_last_version(config_version);
+ last_save_time = FileAccess::get_modified_time(get_resource_path().plus_file("project.godot"));
return OK;
} else if (err != OK) {
ERR_PRINT("Error parsing " + p_path + " at line " + itos(lines) + ": " + error_text + " File might be corrupted.");
@@ -632,7 +643,6 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path,
} else if (err != ERR_FILE_NOT_FOUND) {
// If the file exists but can't be loaded, we want to know it.
ERR_PRINT("Couldn't load file '" + p_bin_path + "', error code " + itos(err) + ".");
- return err;
}
// Fallback to text-based project.godot file if binary was not found.
@@ -641,7 +651,6 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path,
return OK;
} else if (err != ERR_FILE_NOT_FOUND) {
ERR_PRINT("Couldn't load file '" + p_text_path + "', error code " + itos(err) + ".");
- return err;
}
return err;
@@ -676,7 +685,11 @@ void ProjectSettings::clear(const String &p_name) {
}
Error ProjectSettings::save() {
- return save_custom(get_resource_path().plus_file("project.godot"));
+ Error error = save_custom(get_resource_path().plus_file("project.godot"));
+ if (error == OK) {
+ last_save_time = FileAccess::get_modified_time(get_resource_path().plus_file("project.godot"));
+ }
+ return error;
}
Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<String, List<String>> &props, const CustomMap &p_custom, const String &p_custom_features) {
@@ -894,7 +907,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
custom_features += f;
}
- if (p_path.ends_with(".godot")) {
+ if (p_path.ends_with(".godot") || p_path.ends_with("override.cfg")) {
return _save_settings_text(p_path, props, p_custom, custom_features);
} else if (p_path.ends_with(".binary")) {
return _save_settings_binary(p_path, props, p_custom, custom_features);
@@ -903,7 +916,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
}
}
-Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed, bool p_ignore_value_in_docs) {
+Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed, bool p_ignore_value_in_docs, bool p_basic) {
Variant ret;
if (!ProjectSettings::get_singleton()->has_setting(p_var)) {
ProjectSettings::get_singleton()->set(p_var, p_default);
@@ -912,6 +925,7 @@ Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restar
ProjectSettings::get_singleton()->set_initial_value(p_var, p_default);
ProjectSettings::get_singleton()->set_builtin_order(p_var);
+ ProjectSettings::get_singleton()->set_as_basic(p_var, p_basic);
ProjectSettings::get_singleton()->set_restart_if_changed(p_var, p_restart_if_changed);
ProjectSettings::get_singleton()->set_ignore_value_in_docs(p_var, p_ignore_value_in_docs);
return ret;
@@ -1042,29 +1056,47 @@ void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("save_custom", "file"), &ProjectSettings::_save_custom_bnd);
}
+void ProjectSettings::_add_builtin_input_map() {
+ if (InputMap::get_singleton()) {
+ OrderedHashMap<String, List<Ref<InputEvent>>> builtins = InputMap::get_singleton()->get_builtins();
+
+ for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
+ Array events;
+
+ // Convert list of input events into array
+ for (List<Ref<InputEvent>>::Element *I = E.get().front(); I; I = I->next()) {
+ events.push_back(I->get());
+ }
+
+ Dictionary action;
+ action["deadzone"] = Variant(0.5f);
+ action["events"] = events;
+
+ String action_name = "input/" + E.key();
+ GLOBAL_DEF(action_name, action);
+ input_presets.push_back(action_name);
+ }
+ }
+}
+
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.
singleton = this;
- Array events;
- Dictionary action;
- Ref<InputEventKey> key;
- Ref<InputEventJoypadButton> joyb;
-
- GLOBAL_DEF("application/config/name", "");
- GLOBAL_DEF("application/config/description", "");
+ GLOBAL_DEF_BASIC("application/config/name", "");
+ GLOBAL_DEF_BASIC("application/config/description", "");
custom_prop_info["application/config/description"] = PropertyInfo(Variant::STRING, "application/config/description", PROPERTY_HINT_MULTILINE_TEXT);
- GLOBAL_DEF("application/run/main_scene", "");
+ GLOBAL_DEF_BASIC("application/run/main_scene", "");
custom_prop_info["application/run/main_scene"] = PropertyInfo(Variant::STRING, "application/run/main_scene", PROPERTY_HINT_FILE, "*.tscn,*.scn,*.res");
GLOBAL_DEF("application/run/disable_stdout", false);
GLOBAL_DEF("application/run/disable_stderr", false);
GLOBAL_DEF("application/config/use_custom_user_dir", false);
GLOBAL_DEF("application/config/custom_user_dir_name", "");
GLOBAL_DEF("application/config/project_settings_override", "");
- GLOBAL_DEF("audio/default_bus_layout", "res://default_bus_layout.tres");
- custom_prop_info["audio/default_bus_layout"] = PropertyInfo(Variant::STRING, "audio/default_bus_layout", PROPERTY_HINT_FILE, "*.tres");
+ 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");
PackedStringArray extensions = PackedStringArray();
extensions.push_back("gd");
@@ -1073,174 +1105,18 @@ ProjectSettings::ProjectSettings() {
}
extensions.push_back("shader");
- GLOBAL_DEF("editor/search_in_file_extensions", extensions);
- custom_prop_info["editor/search_in_file_extensions"] = PropertyInfo(Variant::PACKED_STRING_ARRAY, "editor/search_in_file_extensions");
-
- GLOBAL_DEF("editor/script_templates_search_path", "res://script_templates");
- custom_prop_info["editor/script_templates_search_path"] = PropertyInfo(Variant::STRING, "editor/script_templates_search_path", PROPERTY_HINT_DIR);
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_ENTER);
- events.push_back(key);
- key.instance();
- key->set_keycode(KEY_KP_ENTER);
- events.push_back(key);
- key.instance();
- key->set_keycode(KEY_SPACE);
- events.push_back(key);
- joyb.instance();
- joyb->set_button_index(JOY_BUTTON_A);
- events.push_back(joyb);
- action["events"] = events;
- GLOBAL_DEF("input/ui_accept", action);
- input_presets.push_back("input/ui_accept");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_SPACE);
- events.push_back(key);
- joyb.instance();
- joyb->set_button_index(JOY_BUTTON_Y);
- events.push_back(joyb);
- action["events"] = events;
- GLOBAL_DEF("input/ui_select", action);
- input_presets.push_back("input/ui_select");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_ESCAPE);
- events.push_back(key);
- joyb.instance();
- joyb->set_button_index(JOY_BUTTON_B);
- events.push_back(joyb);
- action["events"] = events;
- GLOBAL_DEF("input/ui_cancel", action);
- input_presets.push_back("input/ui_cancel");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_TAB);
- events.push_back(key);
- action["events"] = events;
- GLOBAL_DEF("input/ui_focus_next", action);
- input_presets.push_back("input/ui_focus_next");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_TAB);
- key->set_shift(true);
- events.push_back(key);
- action["events"] = events;
- GLOBAL_DEF("input/ui_focus_prev", action);
- input_presets.push_back("input/ui_focus_prev");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_LEFT);
- events.push_back(key);
- joyb.instance();
- joyb->set_button_index(JOY_BUTTON_DPAD_LEFT);
- events.push_back(joyb);
- action["events"] = events;
- GLOBAL_DEF("input/ui_left", action);
- input_presets.push_back("input/ui_left");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_RIGHT);
- events.push_back(key);
- joyb.instance();
- joyb->set_button_index(JOY_BUTTON_DPAD_RIGHT);
- events.push_back(joyb);
- action["events"] = events;
- GLOBAL_DEF("input/ui_right", action);
- input_presets.push_back("input/ui_right");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_UP);
- events.push_back(key);
- joyb.instance();
- joyb->set_button_index(JOY_BUTTON_DPAD_UP);
- events.push_back(joyb);
- action["events"] = events;
- GLOBAL_DEF("input/ui_up", action);
- input_presets.push_back("input/ui_up");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_DOWN);
- events.push_back(key);
- joyb.instance();
- joyb->set_button_index(JOY_BUTTON_DPAD_DOWN);
- events.push_back(joyb);
- action["events"] = events;
- GLOBAL_DEF("input/ui_down", action);
- input_presets.push_back("input/ui_down");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_PAGEUP);
- events.push_back(key);
- action["events"] = events;
- GLOBAL_DEF("input/ui_page_up", action);
- input_presets.push_back("input/ui_page_up");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_PAGEDOWN);
- events.push_back(key);
- action["events"] = events;
- GLOBAL_DEF("input/ui_page_down", action);
- input_presets.push_back("input/ui_page_down");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_HOME);
- events.push_back(key);
- action["events"] = events;
- GLOBAL_DEF("input/ui_home", action);
- input_presets.push_back("input/ui_home");
-
- action = Dictionary();
- action["deadzone"] = Variant(0.5f);
- events = Array();
- key.instance();
- key->set_keycode(KEY_END);
- events.push_back(key);
- action["events"] = events;
- GLOBAL_DEF("input/ui_end", action);
- input_presets.push_back("input/ui_end");
+ GLOBAL_DEF("editor/script/search_in_file_extensions", extensions);
+ custom_prop_info["editor/script/search_in_file_extensions"] = PropertyInfo(Variant::PACKED_STRING_ARRAY, "editor/script/search_in_file_extensions");
+
+ GLOBAL_DEF("editor/script/templates_search_path", "res://script_templates");
+ custom_prop_info["editor/script/templates_search_path"] = PropertyInfo(Variant::STRING, "editor/script/templates_search_path", PROPERTY_HINT_DIR);
+
+ _add_builtin_input_map();
custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::STRING, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor");
- custom_prop_info["rendering/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/threads/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
- custom_prop_info["physics/2d/thread_model"] = PropertyInfo(Variant::INT, "physics/2d/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
- custom_prop_info["rendering/quality/intended_usage/framebuffer_allocation"] = PropertyInfo(Variant::INT, "rendering/quality/intended_usage/framebuffer_allocation", PROPERTY_HINT_ENUM, "2D,2D Without Sampling,3D,3D Without Effects");
+ custom_prop_info["rendering/driver/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/driver/threads/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
+ GLOBAL_DEF("physics/2d/run_on_thread", false);
+ GLOBAL_DEF("physics/3d/run_on_thread", 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 59c56c23c2..ed8fb19fa0 100644
--- a/core/config/project_settings.h
+++ b/core/config/project_settings.h
@@ -58,6 +58,7 @@ protected:
struct VariantContainer {
int order = 0;
bool persist = false;
+ bool basic = false;
Variant variant;
Variant initial;
bool hide_from_editor = false;
@@ -78,6 +79,8 @@ protected:
int last_order = NO_BUILTIN_ORDER_BASE;
int last_builtin_order = 0;
+ uint64_t last_save_time = 0;
+
Map<StringName, VariantContainer> props;
String resource_path;
Map<StringName, PropertyInfo> custom_prop_info;
@@ -113,6 +116,8 @@ protected:
Error _setup(const String &p_path, const String &p_main_pack, bool p_upwards = false);
+ void _add_builtin_input_map();
+
protected:
static void _bind_methods();
@@ -127,6 +132,7 @@ public:
String globalize_path(const String &p_path) const;
void set_initial_value(const String &p_name, const Variant &p_value);
+ void set_as_basic(const String &p_name, bool p_basic);
void set_restart_if_changed(const String &p_name, bool p_restart);
void set_ignore_value_in_docs(const String &p_name, bool p_ignore);
bool get_ignore_value_in_docs(const String &p_name) const;
@@ -150,6 +156,7 @@ public:
Error save();
void set_custom_property_info(const String &p_prop, const PropertyInfo &p_info);
const Map<StringName, PropertyInfo> &get_custom_property_info() const;
+ uint64_t get_last_saved_time() { return last_save_time; }
Vector<String> get_optimizer_presets() const;
@@ -172,11 +179,16 @@ public:
};
//not a macro any longer
-Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed = false, bool p_ignore_value_in_docs = false);
+Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed = false, bool p_ignore_value_in_docs = false, bool p_basic = false);
#define GLOBAL_DEF(m_var, m_value) _GLOBAL_DEF(m_var, m_value)
#define GLOBAL_DEF_RST(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true)
#define GLOBAL_DEF_NOVAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, true)
#define GLOBAL_DEF_RST_NOVAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, true)
#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get(m_var)
+#define GLOBAL_DEF_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, false, true)
+#define GLOBAL_DEF_RST_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, false, true)
+#define GLOBAL_DEF_NOVAL_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, true, true)
+#define GLOBAL_DEF_RST_NOVAL_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, true, true)
+
#endif // PROJECT_SETTINGS_H
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 456a97e5e5..c3d547c2c7 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -86,9 +86,9 @@ RES _ResourceLoader::load_threaded_get(const String &p_path) {
return res;
}
-RES _ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p_no_cache) {
+RES _ResourceLoader::load(const String &p_path, const String &p_type_hint, CacheMode p_cache_mode) {
Error err = OK;
- RES ret = ResourceLoader::load(p_path, p_type_hint, p_no_cache, &err);
+ RES ret = ResourceLoader::load(p_path, p_type_hint, ResourceFormatLoader::CacheMode(p_cache_mode), &err);
ERR_FAIL_COND_V_MSG(err != OK, ret, "Error loading resource: '" + p_path + "'.");
return ret;
@@ -135,7 +135,7 @@ void _ResourceLoader::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &_ResourceLoader::load_threaded_get_status, DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("load_threaded_get", "path"), &_ResourceLoader::load_threaded_get);
- ClassDB::bind_method(D_METHOD("load", "path", "type_hint", "no_cache"), &_ResourceLoader::load, DEFVAL(""), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("load", "path", "type_hint", "cache_mode"), &_ResourceLoader::load, DEFVAL(""), DEFVAL(CACHE_MODE_REUSE));
ClassDB::bind_method(D_METHOD("get_recognized_extensions_for_type", "type"), &_ResourceLoader::get_recognized_extensions_for_type);
ClassDB::bind_method(D_METHOD("set_abort_on_missing_resources", "abort"), &_ResourceLoader::set_abort_on_missing_resources);
ClassDB::bind_method(D_METHOD("get_dependencies", "path"), &_ResourceLoader::get_dependencies);
@@ -146,6 +146,10 @@ void _ResourceLoader::_bind_methods() {
BIND_ENUM_CONSTANT(THREAD_LOAD_IN_PROGRESS);
BIND_ENUM_CONSTANT(THREAD_LOAD_FAILED);
BIND_ENUM_CONSTANT(THREAD_LOAD_LOADED);
+
+ BIND_ENUM_CONSTANT(CACHE_MODE_IGNORE);
+ BIND_ENUM_CONSTANT(CACHE_MODE_REUSE);
+ BIND_ENUM_CONSTANT(CACHE_MODE_REPLACE);
}
////// _ResourceSaver //////
@@ -272,6 +276,10 @@ String _OS::get_environment(const String &p_var) const {
return OS::get_singleton()->get_environment(p_var);
}
+bool _OS::set_environment(const String &p_var, const String &p_value) const {
+ return OS::get_singleton()->set_environment(p_var, p_value);
+}
+
String _OS::get_name() const {
return OS::get_singleton()->get_name();
}
@@ -314,18 +322,6 @@ uint64_t _OS::get_static_memory_peak_usage() const {
return OS::get_singleton()->get_static_memory_peak_usage();
}
-int _OS::get_exit_code() const {
- return OS::get_singleton()->get_exit_code();
-}
-
-void _OS::set_exit_code(int p_code) {
- if (p_code < 0 || p_code > 125) {
- WARN_PRINT("For portability reasons, the exit code should be set between 0 and 125 (inclusive).");
- }
-
- OS::get_singleton()->set_exit_code(p_code);
-}
-
/**
* Get current datetime with consideration for utc and
* dst
@@ -377,6 +373,9 @@ Dictionary _OS::get_time(bool utc) const {
* @return epoch calculated
*/
int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
+ // if datetime is an empty Dictionary throws an error
+ ERR_FAIL_COND_V_MSG(datetime.is_empty(), 0, "Invalid datetime Dictionary: Dictionary is empty");
+
// Bunch of conversion constants
static const unsigned int SECONDS_PER_MINUTE = 60;
static const unsigned int MINUTES_PER_HOUR = 60;
@@ -515,11 +514,19 @@ double _OS::get_unix_time() const {
return OS::get_singleton()->get_unix_time();
}
-void _OS::delay_usec(uint32_t p_usec) const {
+/** This method uses a signed argument for better error reporting as it's used from the scripting API. */
+void _OS::delay_usec(int p_usec) const {
+ ERR_FAIL_COND_MSG(
+ p_usec < 0,
+ vformat("Can't sleep for %d microseconds. The delay provided must be greater than or equal to 0 microseconds.", p_usec));
OS::get_singleton()->delay_usec(p_usec);
}
-void _OS::delay_msec(uint32_t p_msec) const {
+/** This method uses a signed argument for better error reporting as it's used from the scripting API. */
+void _OS::delay_msec(int p_msec) const {
+ ERR_FAIL_COND_MSG(
+ p_msec < 0,
+ vformat("Can't sleep for %d milliseconds. The delay provided must be greater than or equal to 0 milliseconds.", p_msec));
OS::get_singleton()->delay_usec(int64_t(p_msec) * 1000);
}
@@ -562,7 +569,7 @@ struct _OSCoreBindImg {
void _OS::print_all_textures_by_size() {
List<_OSCoreBindImg> imgs;
- int total = 0;
+ uint64_t total = 0;
{
List<Ref<Resource>> rsrc;
ResourceCache::get_cached_resources(&rsrc);
@@ -677,22 +684,6 @@ String _OS::get_unique_id() const {
return OS::get_singleton()->get_unique_id();
}
-int _OS::get_tablet_driver_count() const {
- return OS::get_singleton()->get_tablet_driver_count();
-}
-
-String _OS::get_tablet_driver_name(int p_driver) const {
- return OS::get_singleton()->get_tablet_driver_name(p_driver);
-}
-
-String _OS::get_current_tablet_driver() const {
- return OS::get_singleton()->get_current_tablet_driver();
-}
-
-void _OS::set_current_tablet_driver(const String &p_driver) {
- OS::get_singleton()->set_current_tablet_driver(p_driver);
-}
-
_OS *_OS::singleton = nullptr;
void _OS::_bind_methods() {
@@ -715,8 +706,9 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("shell_open", "uri"), &_OS::shell_open);
ClassDB::bind_method(D_METHOD("get_process_id"), &_OS::get_process_id);
- ClassDB::bind_method(D_METHOD("get_environment", "environment"), &_OS::get_environment);
- ClassDB::bind_method(D_METHOD("has_environment", "environment"), &_OS::has_environment);
+ ClassDB::bind_method(D_METHOD("get_environment", "variable"), &_OS::get_environment);
+ ClassDB::bind_method(D_METHOD("set_environment", "variable", "value"), &_OS::set_environment);
+ ClassDB::bind_method(D_METHOD("has_environment", "variable"), &_OS::has_environment);
ClassDB::bind_method(D_METHOD("get_name"), &_OS::get_name);
ClassDB::bind_method(D_METHOD("get_cmdline_args"), &_OS::get_cmdline_args);
@@ -729,9 +721,6 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_datetime_from_unix_time", "unix_time_val"), &_OS::get_datetime_from_unix_time);
ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime", "datetime"), &_OS::get_unix_time_from_datetime);
- ClassDB::bind_method(D_METHOD("get_exit_code"), &_OS::get_exit_code);
- ClassDB::bind_method(D_METHOD("set_exit_code", "code"), &_OS::set_exit_code);
-
ClassDB::bind_method(D_METHOD("delay_usec", "usec"), &_OS::delay_usec);
ClassDB::bind_method(D_METHOD("delay_msec", "msec"), &_OS::delay_msec);
ClassDB::bind_method(D_METHOD("get_ticks_msec"), &_OS::get_ticks_msec);
@@ -776,19 +765,11 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("request_permissions"), &_OS::request_permissions);
ClassDB::bind_method(D_METHOD("get_granted_permissions"), &_OS::get_granted_permissions);
- ClassDB::bind_method(D_METHOD("get_tablet_driver_count"), &_OS::get_tablet_driver_count);
- ClassDB::bind_method(D_METHOD("get_tablet_driver_name", "idx"), &_OS::get_tablet_driver_name);
- ClassDB::bind_method(D_METHOD("get_current_tablet_driver"), &_OS::get_current_tablet_driver);
- ClassDB::bind_method(D_METHOD("set_current_tablet_driver", "name"), &_OS::set_current_tablet_driver);
-
- ADD_PROPERTY(PropertyInfo(Variant::INT, "exit_code"), "set_exit_code", "get_exit_code");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec"), "set_low_processor_usage_mode_sleep_usec", "get_low_processor_usage_mode_sleep_usec");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "tablet_driver"), "set_current_tablet_driver", "get_current_tablet_driver");
// Those default values need to be specified for the docs generator,
// to avoid using values from the documentation writer's own OS instance.
- ADD_PROPERTY_DEFAULT("tablet_driver", "");
ADD_PROPERTY_DEFAULT("exit_code", 0);
ADD_PROPERTY_DEFAULT("low_processor_usage_mode", false);
ADD_PROPERTY_DEFAULT("low_processor_usage_mode_sleep_usec", 6900);
@@ -1250,6 +1231,11 @@ Error _File::open(const String &p_path, ModeFlags p_mode_flags) {
return err;
}
+void _File::flush() {
+ ERR_FAIL_COND_MSG(!f, "File must be opened before flushing.");
+ f->flush();
+}
+
void _File::close() {
if (f) {
memdelete(f);
@@ -1391,9 +1377,9 @@ Vector<String> _File::get_csv_line(const String &p_delim) const {
return f->get_csv_line(p_delim);
}
-/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
+/**< use this for files WRITTEN in _big_ endian machines (i.e. amiga/mac)
* It's not about the current CPU type but file formats.
- * this flags get reset to false (little endian) on each open
+ * These flags get reset to false (little endian) on each open
*/
void _File::set_endian_swap(bool p_swap) {
@@ -1543,6 +1529,7 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &_File::open_compressed, DEFVAL(0));
ClassDB::bind_method(D_METHOD("open", "path", "flags"), &_File::open);
+ ClassDB::bind_method(D_METHOD("flush"), &_File::flush);
ClassDB::bind_method(D_METHOD("close"), &_File::close);
ClassDB::bind_method(D_METHOD("get_path"), &_File::get_path);
ClassDB::bind_method(D_METHOD("get_path_absolute"), &_File::get_path_absolute);
@@ -1980,7 +1967,7 @@ void _Thread::_start_func(void *ud) {
}
Error _Thread::start(Object *p_instance, const StringName &p_method, const Variant &p_userdata, Priority p_priority) {
- ERR_FAIL_COND_V_MSG(active, ERR_ALREADY_IN_USE, "Thread already started.");
+ ERR_FAIL_COND_V_MSG(active.is_set(), ERR_ALREADY_IN_USE, "Thread already started.");
ERR_FAIL_COND_V(!p_instance, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_method == StringName(), ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_priority, PRIORITY_MAX, ERR_INVALID_PARAMETER);
@@ -1989,7 +1976,7 @@ Error _Thread::start(Object *p_instance, const StringName &p_method, const Varia
target_method = p_method;
target_instance = p_instance;
userdata = p_userdata;
- active = true;
+ active.set();
Ref<_Thread> *ud = memnew(Ref<_Thread>(this));
@@ -2005,14 +1992,14 @@ String _Thread::get_id() const {
}
bool _Thread::is_active() const {
- return active;
+ return active.is_set();
}
Variant _Thread::wait_to_finish() {
- ERR_FAIL_COND_V_MSG(!active, Variant(), "Thread must be active to wait for its completion.");
+ ERR_FAIL_COND_V_MSG(!active.is_set(), Variant(), "Thread must be active to wait for its completion.");
thread.wait_to_finish();
Variant r = ret;
- active = false;
+ active.clear();
target_method = StringName();
target_instance = nullptr;
userdata = Variant();
diff --git a/core/core_bind.h b/core/core_bind.h
index 3305c93089..3920116ca4 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -40,6 +40,7 @@
#include "core/os/os.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
+#include "core/templates/safe_refcount.h"
class _ResourceLoader : public Object {
GDCLASS(_ResourceLoader, Object);
@@ -56,13 +57,19 @@ public:
THREAD_LOAD_LOADED
};
+ enum CacheMode {
+ CACHE_MODE_IGNORE, //resource and subresources do not use path cache, no path is set into resource.
+ CACHE_MODE_REUSE, //resource and subresources use patch cache, reuse existing loaded resources instead of loading from disk when available
+ CACHE_MODE_REPLACE, //resource and and subresource use path cache, but replace existing loaded resources when available with information from disk
+ };
+
static _ResourceLoader *get_singleton() { return singleton; }
Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false);
ThreadLoadStatus load_threaded_get_status(const String &p_path, Array r_progress = Array());
RES load_threaded_get(const String &p_path);
- RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false);
+ RES load(const String &p_path, const String &p_type_hint = "", CacheMode p_cache_mode = CACHE_MODE_REUSE);
Vector<String> get_recognized_extensions_for_type(const String &p_type);
void set_abort_on_missing_resources(bool p_abort);
PackedStringArray get_dependencies(const String &p_path);
@@ -73,6 +80,7 @@ public:
};
VARIANT_ENUM_CAST(_ResourceLoader::ThreadLoadStatus);
+VARIANT_ENUM_CAST(_ResourceLoader::CacheMode);
class _ResourceSaver : public Object {
GDCLASS(_ResourceSaver, Object);
@@ -164,6 +172,7 @@ public:
bool has_environment(const String &p_var) const;
String get_environment(const String &p_var) const;
+ bool set_environment(const String &p_var, const String &p_value) const;
String get_name() const;
Vector<String> get_cmdline_args();
@@ -190,8 +199,6 @@ public:
void set_use_file_access_save_and_swap(bool p_enable);
- int get_exit_code() const;
- void set_exit_code(int p_code);
Dictionary get_date(bool utc) const;
Dictionary get_time(bool utc) const;
Dictionary get_datetime(bool utc) const;
@@ -203,8 +210,8 @@ public:
uint64_t get_static_memory_usage() const;
uint64_t get_static_memory_peak_usage() const;
- void delay_usec(uint32_t p_usec) const;
- void delay_msec(uint32_t p_msec) const;
+ void delay_usec(int p_usec) const;
+ void delay_msec(int p_msec) const;
uint32_t get_ticks_msec() const;
uint64_t get_ticks_usec() const;
@@ -240,11 +247,6 @@ public:
bool request_permissions();
Vector<String> get_granted_permissions() const;
- int get_tablet_driver_count() const;
- String get_tablet_driver_name(int p_driver) const;
- String get_current_tablet_driver() const;
- void set_current_tablet_driver(const String &p_driver);
-
static _OS *get_singleton() { return singleton; }
_OS() { singleton = this; }
@@ -379,6 +381,7 @@ public:
Error open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode = COMPRESSION_FASTLZ);
Error open(const String &p_path, ModeFlags p_mode_flags); // open a file.
+ void flush(); // Flush a file (write its buffer to disk).
void close(); // Close a file.
bool is_open() const; // True when file is open.
@@ -551,7 +554,7 @@ class _Thread : public Reference {
protected:
Variant ret;
Variant userdata;
- volatile bool active = false;
+ SafeFlag active;
Object *target_instance = nullptr;
StringName target_method;
Thread thread;
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 3df121b9cb..f40928350a 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -104,12 +104,12 @@ static Vector<_CoreConstant> _global_constants;
#endif
-VARIANT_ENUM_CAST(KeyList);
+VARIANT_ENUM_CAST(Key);
VARIANT_ENUM_CAST(KeyModifierMask);
-VARIANT_ENUM_CAST(ButtonList);
-VARIANT_ENUM_CAST(JoyButtonList);
-VARIANT_ENUM_CAST(JoyAxisList);
-VARIANT_ENUM_CAST(MidiMessageList);
+VARIANT_ENUM_CAST(MouseButton);
+VARIANT_ENUM_CAST(JoyButton);
+VARIANT_ENUM_CAST(JoyAxis);
+VARIANT_ENUM_CAST(MIDIMessage);
void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(SIDE_LEFT);
@@ -125,6 +125,9 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(VERTICAL);
BIND_CORE_ENUM_CONSTANT(HORIZONTAL);
+ BIND_CORE_ENUM_CONSTANT(CLOCKWISE);
+ BIND_CORE_ENUM_CONSTANT(COUNTERCLOCKWISE);
+
BIND_CORE_ENUM_CONSTANT(HALIGN_LEFT);
BIND_CORE_ENUM_CONSTANT(HALIGN_CENTER);
BIND_CORE_ENUM_CONSTANT(HALIGN_RIGHT);
@@ -394,20 +397,20 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(KEY_MASK_GROUP_SWITCH);
// mouse
- BIND_CORE_ENUM_CONSTANT(BUTTON_LEFT);
- BIND_CORE_ENUM_CONSTANT(BUTTON_RIGHT);
- BIND_CORE_ENUM_CONSTANT(BUTTON_MIDDLE);
- BIND_CORE_ENUM_CONSTANT(BUTTON_XBUTTON1);
- BIND_CORE_ENUM_CONSTANT(BUTTON_XBUTTON2);
- BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_UP);
- BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_DOWN);
- BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_LEFT);
- BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_RIGHT);
- BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_LEFT);
- BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_RIGHT);
- BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_MIDDLE);
- BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_XBUTTON1);
- BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_XBUTTON2);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_LEFT);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_RIGHT);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MIDDLE);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_XBUTTON1);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_XBUTTON2);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_UP);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_DOWN);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_LEFT);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_RIGHT);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_LEFT);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_RIGHT);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_MIDDLE);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_XBUTTON1);
+ BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_XBUTTON2);
// Joypad buttons
BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_INVALID);
@@ -426,6 +429,12 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_DOWN);
BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_LEFT);
BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_RIGHT);
+ BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_MISC1);
+ BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE1);
+ BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE2);
+ BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE3);
+ BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE4);
+ BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_TOUCHPAD);
BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_SDL_MAX);
BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_MAX);
@@ -512,8 +521,10 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_RENDER);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_PHYSICS);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_NAVIGATION);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_RENDER);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_PHYSICS);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_NAVIGATION);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FILE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_DIR);
@@ -553,6 +564,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_REVERSE);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VIRTUAL);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_FROM_SCRIPT);
+ BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_STATIC);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAGS_DEFAULT);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL);
diff --git a/core/core_string_names.cpp b/core/core_string_names.cpp
index 18ac2a2d43..ff8569e45d 100644
--- a/core/core_string_names.cpp
+++ b/core/core_string_names.cpp
@@ -76,5 +76,6 @@ CoreStringNames::CoreStringNames() :
bind(StaticCString::create("bind")),
unbind(StaticCString::create("unbind")),
emit(StaticCString::create("emit")),
- notification(StaticCString::create("notification")) {
+ notification(StaticCString::create("notification")),
+ property_list_changed(StaticCString::create("property_list_changed")) {
}
diff --git a/core/core_string_names.h b/core/core_string_names.h
index b4e386f3bc..abe751372e 100644
--- a/core/core_string_names.h
+++ b/core/core_string_names.h
@@ -96,6 +96,7 @@ public:
StringName unbind;
StringName emit;
StringName notification;
+ StringName property_list_changed;
};
#endif // CORE_STRING_NAMES_H
diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp
index 99f4fb232d..6b3953f588 100644
--- a/core/crypto/crypto.cpp
+++ b/core/crypto/crypto.cpp
@@ -100,7 +100,7 @@ void Crypto::load_default_certificates(String p_path) {
PackedByteArray Crypto::hmac_digest(HashingContext::HashType p_hash_type, PackedByteArray p_key, PackedByteArray p_msg) {
Ref<HMACContext> ctx = Ref<HMACContext>(HMACContext::create());
- ERR_FAIL_COND_V_MSG(ctx.is_null(), PackedByteArray(), "HMAC is not available witout mbedtls module.");
+ ERR_FAIL_COND_V_MSG(ctx.is_null(), PackedByteArray(), "HMAC is not available without mbedtls module.");
Error err = ctx->start(p_hash_type, p_key);
ERR_FAIL_COND_V(err != OK, PackedByteArray());
err = ctx->update(p_msg);
@@ -108,7 +108,7 @@ PackedByteArray Crypto::hmac_digest(HashingContext::HashType p_hash_type, Packed
return ctx->finish();
}
-// Compares two HMACS for equality without leaking timing information in order to prevent timing attakcs.
+// Compares two HMACS for equality without leaking timing information in order to prevent timing attacks.
// @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy
bool Crypto::constant_time_compare(PackedByteArray p_trusted, PackedByteArray p_received) {
const uint8_t *t = p_trusted.ptr();
@@ -141,7 +141,7 @@ void Crypto::_bind_methods() {
/// Resource loader/saver
-RES ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderCrypto::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) {
String el = p_path.get_extension().to_lower();
if (el == "crt") {
X509Certificate *cert = X509Certificate::create();
diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h
index 30d2129e3d..9438fcfea5 100644
--- a/core/crypto/crypto.h
+++ b/core/crypto/crypto.h
@@ -116,7 +116,7 @@ public:
class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp
index 895b8c23a9..e5dba029c9 100644
--- a/core/debugger/engine_debugger.cpp
+++ b/core/debugger/engine_debugger.cpp
@@ -192,7 +192,7 @@ void EngineDebugger::deinitialize() {
singleton = nullptr;
}
- // Clear profilers/captuers/protocol handlers.
+ // Clear profilers/captures/protocol handlers.
profilers.clear();
captures.clear();
protocols.clear();
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index 7392e6b9a6..bdbb7766fa 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -76,6 +76,7 @@ public:
NetworkProfiler() {}
int bandwidth_usage(const Vector<BandwidthFrame> &p_buffer, int p_pointer) {
+ ERR_FAIL_COND_V(p_buffer.size() == 0, 0);
int total_bandwidth = 0;
uint32_t timestamp = OS::get_singleton()->get_ticks_msec();
diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp
index 857e3af268..90b0975159 100644
--- a/core/debugger/remote_debugger_peer.cpp
+++ b/core/debugger/remote_debugger_peer.cpp
@@ -190,13 +190,18 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po
}
void RemoteDebuggerPeerTCP::_thread_func(void *p_ud) {
+ const uint64_t min_tick = 100;
RemoteDebuggerPeerTCP *peer = (RemoteDebuggerPeerTCP *)p_ud;
while (peer->running && peer->is_peer_connected()) {
+ uint64_t ticks_usec = OS::get_singleton()->get_ticks_usec();
peer->_poll();
if (!peer->is_peer_connected()) {
break;
}
- peer->tcp_client->poll(NetSocket::POLL_TYPE_IN_OUT, 1);
+ ticks_usec = OS::get_singleton()->get_ticks_usec() - ticks_usec;
+ if (ticks_usec < min_tick) {
+ OS::get_singleton()->delay_usec(min_tick - ticks_usec);
+ }
}
}
diff --git a/core/error/error_macros.h b/core/error/error_macros.h
index 8eb6217ce8..f909a67d55 100644
--- a/core/error/error_macros.h
+++ b/core/error/error_macros.h
@@ -33,6 +33,8 @@
#include "core/typedefs.h"
+#include "core/templates/safe_refcount.h"
+
class String;
enum ErrorHandlerType {
@@ -577,10 +579,10 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
*/
#define WARN_DEPRECATED \
if (true) { \
- static volatile bool warning_shown = false; \
- if (!warning_shown) { \
+ static SafeFlag warning_shown; \
+ if (!warning_shown.is_set()) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", ERR_HANDLER_WARNING); \
- warning_shown = true; \
+ warning_shown.set(); \
} \
} else \
((void)0)
@@ -590,10 +592,10 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
*/
#define WARN_DEPRECATED_MSG(m_msg) \
if (true) { \
- static volatile bool warning_shown = false; \
- if (!warning_shown) { \
+ static SafeFlag warning_shown; \
+ if (!warning_shown.is_set()) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", DEBUG_STR(m_msg), ERR_HANDLER_WARNING); \
- warning_shown = true; \
+ warning_shown.set(); \
} \
} else \
((void)0)
diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt
index 180708cea6..668a531b1f 100644
--- a/core/input/gamecontrollerdb.txt
+++ b/core/input/gamecontrollerdb.txt
@@ -1,4 +1,4 @@
-# Game Controller DB for SDL in 2.0.10 format
+# Game Controller DB for SDL in 2.0.9 format
# Source: https://github.com/gabomdq/SDL_GameControllerDB
# Windows
@@ -35,7 +35,7 @@
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,
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,
-03000000c82d00000031000000000000,8BitDo Wireless Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000031000000000000,8BitDo Wireless Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
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,
03000000a00500003232000000000000,8Bitdo Zero GamePad,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,
@@ -80,14 +80,15 @@
030000007d0400000840000000000000,Destroyer Tiltpad,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows,
03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000bd12000002e0000000000000,Dual USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
+030000008f0e00000910000000000000,DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
030000006f0e00003001000000000000,EA SPORTS PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000b80500000410000000000000,Elecom Gamepad,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:b0,y:b1,platform:Windows,
03000000b80500000610000000000000,Elecom Gamepad,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:b0,y:b1,platform:Windows,
03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
-030000006f0e00008001000000000000,Faceoff Wired Pro Controller for Nintendo Switch,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
-030000006f0e00008401000000000000,Faceoff Deluxe+ Audio Wired Controller for Nintendo Switch,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
+030000006f0e00008401000000000000,Faceoff Deluxe+ Audio Wired Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00008001000000000000,Faceoff Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000852100000201000000000000,FF-GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -98,6 +99,7 @@
03000000790000002201000000000000,Game Controller for PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,
+03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b2,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:b0,y:b3,platform:Windows,
030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000ac0500003d03000000000000,GameSir,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,
@@ -119,6 +121,7 @@
030000007d0400000540000000000000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000001008000001e1000000000000,Havit HV-G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows,
03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
03000000632500002605000000000000,HJD-X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -164,7 +167,8 @@
030000006d04000016c2000000000000,Logitech Dual Action,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,
030000006d04000018c2000000000000,Logitech F510 Gamepad,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,
030000006d04000019c2000000000000,Logitech F710 Gamepad,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,
-030000006d0400001ac2000000000000,Logitech Precision Gamepad,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,lefttrigger:b6,righttrigger:b7,platform:Windows,
+030000006d0400001ac2000000000000,Logitech Precision Gamepad,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,
03000000380700006652000000000000,Mad Catz C.T.R.L.R,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -193,6 +197,8 @@
03000000380700006382000000000000,MLG GamePad PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000c62400002a89000000000000,MOGA XP5-A Plus,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,
03000000c62400002b89000000000000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c62400001a89000000000000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c62400001b89000000000000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000efbe0000edfe000000000000,Monect Virtual Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
030000006b140000010c000000000000,NACON GC-400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
@@ -234,6 +240,7 @@
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,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,
03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,
@@ -244,7 +251,6 @@
03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000321500000204000000000000,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:Windows,
03000000321500000104000000000000,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:Windows,
-03000000321500000810000011010000,Razer Panthera Evo Arcade Stick for PS4,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b13,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,
03000000321500000507000000000000,Razer Raiju Mobile,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,
03000000321500000707000000000000,Razer Raiju Mobile,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,
03000000321500000011000000000000,Razer Raion Fightpad for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -259,6 +265,7 @@
030000000d0f00005b00000000000000,Real Arcade Pro.V4,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,
030000000d0f00005c00000000000000,Real Arcade Pro.V4,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,
03000000790000001100000000000000,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:Windows,
+03000000bd12000013d0000000000000,Retrolink USB SEGA Saturn Classic,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,
0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -271,8 +278,8 @@
03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,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:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
-03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b0,y:b1,platform:Windows,
-03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,x:b0,y:b1,platform:Windows,
+03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows,
+03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,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:b10,x:b0,y:b1,platform:Windows,
03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
@@ -283,6 +290,8 @@
03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
+03000000a30c00002500000000000000,Sega Genesis Mini 3B controller,a:b2,b:b1,start:b9,dpup:-a4,dpdown:+a4,dpleft:-a3,dpright:+a3,righttrigger:b5,platform:Windows,
+03000000a30c00002400000000000000,Sega Mega Drive Mini 6B controller,a:b2,b:b1,start:b9,dpup:-a4,dpdown:+a4,dpleft:-a3,dpright:+a3,rightshoulder:b4,righttrigger:b5,x:b3,y:b0,platform:Windows,
030000005e0400008e02000000007801,ShanWan PS3/PC Wired GamePad,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,
03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
03000000341a00000908000000000000,SL-6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
@@ -328,6 +337,8 @@
030000006f0e00000702000000000000,Victrix Pro Fight Stick for 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:Windows,
0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:+a3,righty:+a4,start:b4,x:b2,y:b3,platform:Windows,
030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000ff02000000007801,Xbox One Elite Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000341a00000608000000000000,Xeox,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,
03000000450c00002043000000000000,XEOX Gamepad SL-6556-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:Windows,
03000000ac0500005b05000000000000,Xiaoji 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,
@@ -338,7 +349,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000120c0000101e000000000000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
# Mac OS X
-030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,
+030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
@@ -355,12 +366,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
-03000000c82d00000031000001000000,8BitDo Wireless Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000031000001000000,8BitDo Wireless Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000a00500003232000008010000,8Bitdo Zero GamePad,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 GamePad,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,
03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
+03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008305000031b0000000000000,Cideko AK08b,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,
03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,
@@ -427,6 +440,7 @@ 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,
+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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
03000000321500000204000000010000,Razer Panthera (PS3),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,
03000000321500000104000000010000,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:Mac OS X,
@@ -446,6 +460,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,
030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X,
+030000004c050000e60c000000010000,Sony DualSense,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:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,
@@ -474,6 +489,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000d102000000000000,Xbox One Wired 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 Wired 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,
030000005e040000e302000000000000,Xbox One Wired 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,
030000005e040000e002000000000000,Xbox Wireless 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,
030000005e040000e002000003090000,Xbox Wireless 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,
030000005e040000ea02000000000000,Xbox Wireless 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,
@@ -506,12 +523,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,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,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,
05000000202800000900000000010000,8BitDo SNES30 Gamepad,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,
-030000005e0400008e02000020010000,8BitDo Wireless Adapter,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
-03000000c82d00000031000011010000,8BitDo Wireless Adapter,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,
+030000005e0400008e02000020010000,8BitDo Wireless Adapter (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c82d00000031000011010000,8BitDo Wireless Adapter (DInput),a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+050000005e040000e002000030110000,8BitDo Zero 2 (XInput),a:b0,b:b1,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,start:b7,x:b2,y:b3,platform:Linux,
05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
05000000a00500003232000008010000,8Bitdo Zero GamePad,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,
@@ -521,11 +539,16 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e00003901000013020000,Afterglow Prismatic Wired Controller 048-007-NA,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,
03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000007c1800000006000010010000,Alienware Dual Compatible Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
-05000000491900000204000021000000,Amazon Fire Game 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,
+05000000491900000204000021000000,Amazon Fire Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
03000000120c00000500000010010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,
+03000000c62400001b89000011010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000c21100000791000011010000,Be1 GC101 Controller 1.03 mode,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 GAMEPAD 1.03 mode,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 Controller mode,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,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,
03000000ffff0000ffff000000010000,Chinese-made Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
@@ -567,6 +590,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f0000aa00000011010000,HORI Real Arcade Pro,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+030000000d0f0000d800000072056800,HORI Real Arcade Pro S,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:Linux,
030000000d0f00001600000000010000,Hori Real Arcade Pro.EX-SE (Xbox 360),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
030000000d0f00006e00000011010000,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:Linux,
030000000d0f00006600000011010000,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:Linux,
@@ -592,6 +616,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000242f00002d00000011010000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000242f00008a00000011010000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,
030000006f0e00000103000000020000,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,
+030000006d040000d1ca000000000000,Logitech ChillStream,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,
030000006d04000019c2000010010000,Logitech Cordless 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:Linux,
030000006d04000016c2000010010000,Logitech Dual Action,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,
030000006d04000016c2000011010000,Logitech Dual Action,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,
@@ -600,10 +625,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),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,
030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),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,
030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),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,
-030000006d0400000ac2000010010000,Logitech Inc. WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux,
-030000006d04000015c2000010010000,Logitech Logitech Extreme 3D,a:b0,b:b4,back:b6,guide:b8,leftshoulder:b9,leftstick:h0.8,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:h0.2,start:b7,x:b2,y:b5,platform:Linux,
+030000006d0400000ac2000010010000,Logitech Inc. WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux,
030000006d04000018c2000010010000,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:Linux,
030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,
+050000004d4f435554452d3035305800,M54-PC,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,platform:Linux,
05000000380700006652000025010000,Mad Catz C.T.R.L.R ,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,
03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
@@ -635,6 +660,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000d102000003020000,Microsoft X-Box One pad v2,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,
030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
+030000005e040000000b000008040000,Microsoft Xbox One Elite 2 pad - Wired,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,
+030000005e040000ea02000008040000,Microsoft Xbox One S pad - Wired,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,
03000000c62400001a53000000010000,Mini PE,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,
03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
05000000d6200000e589000001000000,Moga 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
@@ -642,12 +669,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
03000000c62400002b89000011010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000c62400002a89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000c62400001a89000000010000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000250900006688000000010000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
030000006b140000010c000010010000,NACON GC-400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux,
-060000007e0500000820000000000000,Nintendo Combined Joy-Cons (joycond),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
+060000007e0500000820000000000000,Nintendo Combined Joy-Cons (joycond),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,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux,
+03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b2,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:b0,y:b3,platform:Linux,
050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
050000007e0500000920000001800000,Nintendo Switch Pro Controller (joycond),a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
030000007e0500000920000011810000,Nintendo Switch Pro Controller Wired (joycond),a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
@@ -666,21 +695,23 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000830500005020000010010000,Padix Co. Ltd. Rockfire PSX/USB 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 Game 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 Game 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 Wired Xbox One Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
+030000006f0e0000b802000001010000,PDP AFTERGLOW Wired 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 Wired Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
-030000006f0e00008001000011010000,PDP CO. LTD. Faceoff Wired Pro Controller for Nintendo Switch,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,
+030000006f0e00008001000011010000,PDP CO. LTD. Faceoff Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006f0e00008701000011010000,PDP Rock Candy Wired Controller for Nintendo Switch,a:b2,b:b1,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:b3,y:b0,platform:Linux,
030000006f0e00000901000011010000,PDP Versus Fighting Pad,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 Wired Controller for Xbox One,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,
030000006f0e00008501000011010000,PDP Wired Fight Pad Pro for Nintendo Switch,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,
+05000000491900000204000000000000,PG-9118,x:b76,a:b73,b:b74,y:b77,back:b83,start:b84,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b79,lefttrigger:b81,rightshoulder:b80,righttrigger:b82,leftstick:b86,rightstick:b87,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,
0500000049190000030400001b010000,PG-9099,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,
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,
03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
-03000000c62400001a58000001010000,PowerA Xbox One Cabled,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
+03000000c62400001a58000001010000,PowerA Xbox One Cabled,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,
030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
@@ -709,6 +740,8 @@ 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,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,
030000009b2800003200000001010000,Raphnet Technologies GC/N64 to USB v3.4,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 Technologies GC/N64 to USB v3.6,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,
@@ -717,6 +750,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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 Evo Arcade Stick for PS4,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,
03000000321500000010000011010000,Razer RAIJU,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,
03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,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,
03000000321500000011000011010000,Razer Raion Fightpad for 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,
@@ -735,14 +769,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e00001e01000011010000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,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:a4,start:b9,x:b0,y:b3,platform:Linux,
-03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,
+03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux,
+03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux,
+03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,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:b10,x:b0,y:b1,platform:Linux,
03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,
03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,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,x:b0,y:b1,platform:Linux,
03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,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:b8,x:b0,y:b3,platform:Linux,
03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000a306000020f6000011010000,Saitek PS2700 Rumble Pad,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:a4,start:b9,x:b0,y:b3,platform:Linux,
-03000000a30600001005000000010000,Saitek Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux,
03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux,
03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux,
03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired 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,
@@ -754,15 +789,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000d11800000094000011010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
-03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
-03000000de2800000211000001000000,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:Linux,
-03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
+03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
+03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
+03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800004211000001000000,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:Linux,
03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
-05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
-05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
-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:Linux,
+05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
+05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
+05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -774,11 +809,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,
03000000457500002211000010010000,SZMY-POWER CO. LTD. 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,
030000008f0e00000d31000010010000,SZMY-POWER CO. LTD. GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000008f0e00001431000010010000,SZMY-POWER CO. LTD. PS3 gamepad,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,
030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,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,
030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
030000004f0400000ed0000011010000,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:Linux,
03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux,
+030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux,
030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,
030000004f04000026b3000002040000,Thrustmaster Gamepad GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c6240000025b000002020000,Thrustmaster GPX Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -815,6 +852,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005e040000e002000003090000,Xbox One Wireless 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:Linux,
050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,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,
030000005e040000ea02000001030000,Xbox One Wireless Controller (Model 1708),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,
+030000005e040000120b000001050000,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,
+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:Linux,
+050000005e040000130b000001050000,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:Linux,
+050000005e040000130b000005050000,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:Linux,
030000005e0400008e02000000010000,xbox360 Wireless EasySMX,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,
03000000450c00002043000010010000,XEOX Gamepad SL-6556-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,
03000000ac0500005b05000010010000,Xiaoji 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,
@@ -823,6 +864,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
xinput,XInput 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,
03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000c0160000dc27000001010000,OnyxSoft Dual JoyDivision,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b6,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,
# Android
05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android,
@@ -857,20 +899,27 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
030000004c050000cc09000000006800,PS4 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,
050000004c050000c4050000fffe3f00,PS4 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,
+050000004c050000c4050000ffff3f00,PS4 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,
050000004c050000cc090000fffe3f00,PS4 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,
050000004c050000cc090000ffff3f00,PS4 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,
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,
+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,
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,
050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,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,x:b2,y:b3,platform:Android,
+32633532643734376632656664383733,Sony DualSense,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,Sony DualSense,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,
05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,
05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,
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 USB 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,
30306539356238653637313730656134,Wireless 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,
+050000005e040000fd020000ff7f3f00,Xbox One S 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,
050000005e040000e00200000ffe3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android,
050000005e040000fd020000ffff3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000130b0000ffff3f00,Xbox Series 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,
+65633038363832353634653836396239,Xbox Series 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,
050000005e04000091020000ff073f00,Xbox Wireless Controller,a:b0,b:b1,back:b4,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,
34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android,
050000001727000044310000ffff3f00,XiaoMi Game Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,
@@ -879,13 +928,20 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000ac0500000100000000006d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS,
05000000ac050000010000004f066d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS,
05000000ac05000001000000cf076d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS,
+05000000ac05000001000000df076d01,*,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,
+05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
05000000ac0500000200000000006d02,*,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,
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,
-050000004c050000cc090000df070000,DUALSHOCK 4 Wireless 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,
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,
+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,
+050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
+050000004c050000cc090000ff876d01,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,,platform:iOS,
+050000004c050000cc090000ff870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS,
05000000ac0500000300000000006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS,
05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS,
05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,
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:iOS,
+050000005e040000050b0000ff070001,Xbox Elite Wireless 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,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
050000005e040000e0020000df070000,Xbox Wireless 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,
+050000005e040000e0020000ff070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
diff --git a/core/input/godotcontrollerdb.txt b/core/input/godotcontrollerdb.txt
index e8e250e3be..db612f04d2 100644
--- a/core/input/godotcontrollerdb.txt
+++ b/core/input/godotcontrollerdb.txt
@@ -22,6 +22,13 @@ MacOSX045e028e,Xbox 360 Wired Controller,a:b11,b:b12,y:b14,x:b13,start:b4,back:b
MacOSX045e02d1,Xbox One Controller,a:b11,b:b12,y:b14,x:b13,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpleft:b2,dpdown:b1,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Javascript
MacOSX045e02ea,Xbox One S Controller,a:b11,b:b12,y:b14,x:b13,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpleft:b2,dpdown:b1,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Javascript
MacOSX045e0b12,Xbox Series X Controller,a:b11,b:b12,y:b14,x:b13,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpleft:b2,dpdown:b1,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Javascript
+Linux15320a14,Razer Wolverine Ultimate,a:b0,b:b1,y:b3,x:b2,start:b7,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:-a7,dpleft:-a6,dpdown:+a7,dpright:+a6,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Javascript
+Linux05832060,iBuffalo BSGP801,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpleft:-a0,dpdown:+a1,dpright:+a0,platform:Javascript
+MacOSX05832060,iBuffalo BSGP801,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpleft:-a0,dpdown:+a1,dpright:+a0,platform:Javascript
+Linux0e8f3013,HuiJia USB GamePad,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftshoulder:b6,rightshoulder:b7,dpup:-a1,dpleft:-a0,dpdown:+a1,dpright:+a0,platform:Javascript
+Windows0e8f3013,HuiJia USB GamePad,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftshoulder:b6,rightshoulder:b7,dpup:-a1,dpleft:-a0,dpdown:+a1,dpright:+a0,platform:Javascript
+MacOSX0e8f3013,HuiJia USB GamePad,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftshoulder:b6,rightshoulder:b7,dpup:-a4,dpleft:-a3,dpdown:+a4,dpright:+a3,platform:Javascript
+Linux046dc216,046d-c216-Logitech Logitech Dual Action,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:-a5,dpleft:-a4,dpdown:+a5,dpright:+a4,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Javascript
# UWP
__UWP_GAMEPAD__,Xbox Controller,a:b2,b:b3,x:b4,y:b5,start:b0,back:b1,leftstick:b12,rightstick:b13,leftshoulder:b10,rightshoulder:b11,dpup:b6,dpdown:b7,dpleft:b8,dpright:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:UWP,
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 2e3f112ebc..627944210f 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -55,6 +55,12 @@ static const char *_joy_buttons[JOY_BUTTON_SDL_MAX] = {
"dpdown",
"dpleft",
"dpright",
+ "misc1",
+ "paddle1",
+ "paddle2",
+ "paddle3",
+ "paddle4",
+ "touchpad",
};
static const char *_joy_axes[JOY_AXIS_SDL_MAX] = {
@@ -91,11 +97,11 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &Input::is_key_pressed);
ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &Input::is_mouse_button_pressed);
ClassDB::bind_method(D_METHOD("is_joy_button_pressed", "device", "button"), &Input::is_joy_button_pressed);
- ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &Input::is_action_pressed);
- ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action"), &Input::is_action_just_pressed);
- ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &Input::is_action_just_released);
- ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &Input::get_action_strength);
- ClassDB::bind_method(D_METHOD("get_action_raw_strength", "action"), &Input::get_action_strength);
+ ClassDB::bind_method(D_METHOD("is_action_pressed", "action", "exact_match"), &Input::is_action_pressed, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action", "exact_match"), &Input::is_action_just_pressed, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("is_action_just_released", "action", "exact_match"), &Input::is_action_just_released, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_action_strength", "action", "exact_match"), &Input::get_action_strength, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_action_raw_strength", "action", "exact_match"), &Input::get_action_strength, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_axis", "negative_action", "positive_action"), &Input::get_axis);
ClassDB::bind_method(D_METHOD("get_vector", "negative_x", "positive_x", "negative_y", "positive_y", "deadzone"), &Input::get_vector, DEFVAL(-1.0f));
ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false));
@@ -234,16 +240,28 @@ bool Input::is_joy_button_pressed(int p_device, int p_button) const {
return joy_buttons_pressed.has(_combine_device(p_button, p_device));
}
-bool Input::is_action_pressed(const StringName &p_action) const {
- return action_state.has(p_action) && action_state[p_action].pressed;
+bool Input::is_action_pressed(const StringName &p_action, bool p_exact) const {
+#ifdef DEBUG_ENABLED
+ bool has_action = InputMap::get_singleton()->has_action(p_action);
+ ERR_FAIL_COND_V_MSG(!has_action, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
+#endif
+ return action_state.has(p_action) && action_state[p_action].pressed && (p_exact ? action_state[p_action].exact : true);
}
-bool Input::is_action_just_pressed(const StringName &p_action) const {
+bool Input::is_action_just_pressed(const StringName &p_action, bool p_exact) const {
+#ifdef DEBUG_ENABLED
+ bool has_action = InputMap::get_singleton()->has_action(p_action);
+ ERR_FAIL_COND_V_MSG(!has_action, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
+#endif
const Map<StringName, Action>::Element *E = action_state.find(p_action);
if (!E) {
return false;
}
+ if (p_exact && E->get().exact == false) {
+ return false;
+ }
+
if (Engine::get_singleton()->is_in_physics_frame()) {
return E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames();
} else {
@@ -251,12 +269,20 @@ bool Input::is_action_just_pressed(const StringName &p_action) const {
}
}
-bool Input::is_action_just_released(const StringName &p_action) const {
+bool Input::is_action_just_released(const StringName &p_action, bool p_exact) const {
+#ifdef DEBUG_ENABLED
+ bool has_action = InputMap::get_singleton()->has_action(p_action);
+ ERR_FAIL_COND_V_MSG(!has_action, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
+#endif
const Map<StringName, Action>::Element *E = action_state.find(p_action);
if (!E) {
return false;
}
+ if (p_exact && E->get().exact == false) {
+ return false;
+ }
+
if (Engine::get_singleton()->is_in_physics_frame()) {
return !E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames();
} else {
@@ -264,21 +290,33 @@ bool Input::is_action_just_released(const StringName &p_action) const {
}
}
-float Input::get_action_strength(const StringName &p_action) const {
+float Input::get_action_strength(const StringName &p_action, bool p_exact) const {
+#ifdef DEBUG_ENABLED
+ bool has_action = InputMap::get_singleton()->has_action(p_action);
+ ERR_FAIL_COND_V_MSG(!has_action, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
+#endif
const Map<StringName, Action>::Element *E = action_state.find(p_action);
if (!E) {
return 0.0f;
}
+ if (p_exact && E->get().exact == false) {
+ return 0.0f;
+ }
+
return E->get().strength;
}
-float Input::get_action_raw_strength(const StringName &p_action) const {
+float Input::get_action_raw_strength(const StringName &p_action, bool p_exact) const {
const Map<StringName, Action>::Element *E = action_state.find(p_action);
if (!E) {
return 0.0f;
}
+ if (p_exact && E->get().exact == false) {
+ return 0.0f;
+ }
+
return E->get().raw_strength;
}
@@ -522,11 +560,11 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
button_event->set_position(st->get_position());
button_event->set_global_position(st->get_position());
button_event->set_pressed(st->is_pressed());
- button_event->set_button_index(BUTTON_LEFT);
+ button_event->set_button_index(MOUSE_BUTTON_LEFT);
if (st->is_pressed()) {
- button_event->set_button_mask(mouse_button_mask | (1 << (BUTTON_LEFT - 1)));
+ button_event->set_button_mask(mouse_button_mask | (1 << (MOUSE_BUTTON_LEFT - 1)));
} else {
- button_event->set_button_mask(mouse_button_mask & ~(1 << (BUTTON_LEFT - 1)));
+ button_event->set_button_mask(mouse_button_mask & ~(1 << (MOUSE_BUTTON_LEFT - 1)));
}
_parse_input_event_impl(button_event, true);
@@ -582,20 +620,21 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
}
}
- for (const Map<StringName, InputMap::Action>::Element *E = InputMap::get_singleton()->get_action_map().front(); E; E = E->next()) {
- if (InputMap::get_singleton()->event_is_action(p_event, E->key())) {
- // Save the action's state
- if (!p_event->is_echo() && is_action_pressed(E->key()) != p_event->is_action_pressed(E->key())) {
+ for (OrderedHashMap<StringName, InputMap::Action>::ConstElement E = InputMap::get_singleton()->get_action_map().front(); E; E = E.next()) {
+ if (InputMap::get_singleton()->event_is_action(p_event, E.key())) {
+ // If not echo and action pressed state has changed
+ if (!p_event->is_echo() && is_action_pressed(E.key(), false) != p_event->is_action_pressed(E.key())) {
Action action;
action.physics_frame = Engine::get_singleton()->get_physics_frames();
action.process_frame = Engine::get_singleton()->get_process_frames();
- action.pressed = p_event->is_action_pressed(E->key());
+ action.pressed = p_event->is_action_pressed(E.key());
action.strength = 0.0f;
action.raw_strength = 0.0f;
- action_state[E->key()] = action;
+ action.exact = InputMap::get_singleton()->event_is_action(p_event, E.key(), true);
+ action_state[E.key()] = action;
}
- action_state[E->key()].strength = p_event->get_action_strength(E->key());
- action_state[E->key()].raw_strength = p_event->get_action_raw_strength(E->key());
+ action_state[E.key()].strength = p_event->get_action_strength(E.key());
+ action_state[E.key()].raw_strength = p_event->get_action_raw_strength(E.key());
}
}
@@ -684,7 +723,7 @@ void Input::warp_mouse_position(const Vector2 &p_to) {
Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) {
// The relative distance reported for the next event after a warp is in the boundaries of the
- // size of the rect on that axis, but it may be greater, in which case there's not problem as fmod()
+ // size of the rect on that axis, but it may be greater, in which case there's no problem as fmod()
// will warp it, but if the pointer has moved in the opposite direction between the pointer relocation
// and the subsequent event, the reported relative distance will be less than the size of the rect
// and thus fmod() will be disabled for handling the situation.
@@ -740,7 +779,7 @@ bool Input::is_emulating_touch_from_mouse() const {
return emulate_touch_from_mouse;
}
-// Calling this whenever the game window is focused helps unstucking the "touch mouse"
+// Calling this whenever the game window is focused helps unsticking the "touch mouse"
// if the OS or its abstraction class hasn't properly reported that touch pointers raised
void Input::ensure_touch_mouse_raised() {
if (mouse_from_touch_index != -1) {
@@ -753,8 +792,8 @@ void Input::ensure_touch_mouse_raised() {
button_event->set_position(mouse_pos);
button_event->set_global_position(mouse_pos);
button_event->set_pressed(false);
- button_event->set_button_index(BUTTON_LEFT);
- button_event->set_button_mask(mouse_button_mask & ~(1 << (BUTTON_LEFT - 1)));
+ button_event->set_button_index(MOUSE_BUTTON_LEFT);
+ button_event->set_button_mask(mouse_button_mask & ~(1 << (MOUSE_BUTTON_LEFT - 1)));
_parse_input_event_impl(button_event, true);
}
@@ -868,7 +907,7 @@ void Input::joy_button(int p_device, int p_button, bool p_pressed) {
// no event?
}
-void Input::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) {
+void Input::joy_axis(int p_device, int p_axis, const JoyAxisValue &p_value) {
_THREAD_SAFE_METHOD_;
ERR_FAIL_INDEX(p_axis, JOY_AXIS_MAX);
@@ -882,12 +921,12 @@ void Input::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) {
//when changing direction quickly, insert fake event to release pending inputmap actions
float last = joy.last_axis[p_axis];
if (p_value.min == 0 && (last < 0.25 || last > 0.75) && (last - 0.5) * (p_value.value - 0.5) < 0) {
- JoyAxis jx;
+ JoyAxisValue jx;
jx.min = p_value.min;
jx.value = p_value.value < 0.5 ? 0.6 : 0.4;
joy_axis(p_device, p_axis, jx);
} else if (ABS(last) > 0.5 && last * p_value.value <= 0) {
- JoyAxis jx;
+ JoyAxisValue jx;
jx.min = p_value.min;
jx.value = last > 0 ? 0.1 : -0.1;
joy_axis(p_device, p_axis, jx);
@@ -1167,22 +1206,22 @@ void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, J
}
}
-JoyButtonList Input::_get_output_button(String output) {
+JoyButton Input::_get_output_button(String output) {
for (int i = 0; i < JOY_BUTTON_SDL_MAX; i++) {
if (output == _joy_buttons[i]) {
- return JoyButtonList(i);
+ return JoyButton(i);
}
}
- return JoyButtonList::JOY_BUTTON_INVALID;
+ return JoyButton::JOY_BUTTON_INVALID;
}
-JoyAxisList Input::_get_output_axis(String output) {
+JoyAxis Input::_get_output_axis(String output) {
for (int i = 0; i < JOY_AXIS_SDL_MAX; i++) {
if (output == _joy_axes[i]) {
- return JoyAxisList(i);
+ return JoyAxis(i);
}
}
- return JoyAxisList::JOY_AXIS_INVALID;
+ return JoyAxis::JOY_AXIS_INVALID;
}
void Input::parse_mapping(String p_mapping) {
@@ -1240,8 +1279,8 @@ void Input::parse_mapping(String p_mapping) {
input = input.left(input.length() - 1);
}
- JoyButtonList output_button = _get_output_button(output);
- JoyAxisList output_axis = _get_output_axis(output);
+ JoyButton output_button = _get_output_button(output);
+ JoyAxis output_axis = _get_output_axis(output);
ERR_CONTINUE_MSG(output_button == JOY_BUTTON_INVALID && output_axis == JOY_AXIS_INVALID,
String(entry[idx] + "\nUnrecognised output string: " + output));
ERR_CONTINUE_MSG(output_button != JOY_BUTTON_INVALID && output_axis != JOY_AXIS_INVALID,
diff --git a/core/input/input.h b/core/input/input.h
index 445b7ff0cf..99b45db325 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -91,7 +91,7 @@ public:
JOYPADS_MAX = 16,
};
- struct JoyAxis {
+ struct JoyAxisValue {
int min;
float value;
};
@@ -116,6 +116,7 @@ private:
uint64_t physics_frame;
uint64_t process_frame;
bool pressed;
+ bool exact;
float strength;
float raw_strength;
};
@@ -198,10 +199,10 @@ private:
JoyType outputType;
union {
- JoyButtonList button;
+ JoyButton button;
struct {
- JoyAxisList axis;
+ JoyAxis axis;
JoyAxisRange range;
} axis;
@@ -219,8 +220,8 @@ private:
JoyEvent _get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button);
JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, float p_value);
void _get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, JoyEvent r_events[HAT_MAX]);
- JoyButtonList _get_output_button(String output);
- JoyAxisList _get_output_axis(String output);
+ JoyButton _get_output_button(String output);
+ JoyAxis _get_output_axis(String output);
void _button_event(int p_device, int p_index, bool p_pressed);
void _axis_event(int p_device, int p_axis, float p_value);
@@ -261,11 +262,11 @@ public:
bool is_key_pressed(int p_keycode) const;
bool is_mouse_button_pressed(int p_button) const;
bool is_joy_button_pressed(int p_device, int p_button) const;
- bool is_action_pressed(const StringName &p_action) const;
- bool is_action_just_pressed(const StringName &p_action) const;
- bool is_action_just_released(const StringName &p_action) const;
- float get_action_strength(const StringName &p_action) const;
- float get_action_raw_strength(const StringName &p_action) const;
+ bool is_action_pressed(const StringName &p_action, bool p_exact = false) const;
+ bool is_action_just_pressed(const StringName &p_action, bool p_exact = false) const;
+ bool is_action_just_released(const StringName &p_action, bool p_exact = false) const;
+ float get_action_strength(const StringName &p_action, bool p_exact = false) const;
+ float get_action_raw_strength(const StringName &p_action, bool p_exact = false) const;
float get_axis(const StringName &p_negative_action, const StringName &p_positive_action) const;
Vector2 get_vector(const StringName &p_negative_x, const StringName &p_positive_x, const StringName &p_negative_y, const StringName &p_positive_y, float p_deadzone = -1.0f) const;
@@ -324,7 +325,7 @@ public:
void parse_mapping(String p_mapping);
void joy_button(int p_device, int p_button, bool p_pressed);
- void joy_axis(int p_device, int p_axis, const JoyAxis &p_value);
+ void joy_axis(int p_device, int p_axis, const JoyAxisValue &p_value);
void joy_hat(int p_device, int p_val);
void add_joy_mapping(String p_mapping, bool p_update_existing = false);
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 2771a15b80..99cc51b95e 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -44,31 +44,31 @@ int InputEvent::get_device() const {
return device;
}
-bool InputEvent::is_action(const StringName &p_action) const {
- return InputMap::get_singleton()->event_is_action(Ref<InputEvent>((InputEvent *)this), p_action);
+bool InputEvent::is_action(const StringName &p_action, bool p_exact_match) const {
+ return InputMap::get_singleton()->event_is_action(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match);
}
-bool InputEvent::is_action_pressed(const StringName &p_action, bool p_allow_echo) const {
+bool InputEvent::is_action_pressed(const StringName &p_action, bool p_allow_echo, bool p_exact_match) const {
bool pressed;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, &pressed, nullptr, nullptr);
return valid && pressed && (p_allow_echo || !is_echo());
}
-bool InputEvent::is_action_released(const StringName &p_action) const {
+bool InputEvent::is_action_released(const StringName &p_action, bool p_exact_match) const {
bool pressed;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, &pressed, nullptr, nullptr);
return valid && !pressed;
}
-float InputEvent::get_action_strength(const StringName &p_action) const {
+float InputEvent::get_action_strength(const StringName &p_action, bool p_exact_match) const {
float strength;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, nullptr, &strength);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, nullptr, &strength, nullptr);
return valid ? strength : 0.0f;
}
-float InputEvent::get_action_raw_strength(const StringName &p_action) const {
+float InputEvent::get_action_raw_strength(const StringName &p_action, bool p_exact_match) const {
float raw_strength;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, nullptr, nullptr, &raw_strength);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, nullptr, nullptr, &raw_strength);
return valid ? raw_strength : 0.0f;
}
@@ -100,10 +100,10 @@ void InputEvent::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_device", "device"), &InputEvent::set_device);
ClassDB::bind_method(D_METHOD("get_device"), &InputEvent::get_device);
- ClassDB::bind_method(D_METHOD("is_action", "action"), &InputEvent::is_action);
- ClassDB::bind_method(D_METHOD("is_action_pressed", "action", "allow_echo"), &InputEvent::is_action_pressed, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("is_action_released", "action"), &InputEvent::is_action_released);
- ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &InputEvent::get_action_strength);
+ ClassDB::bind_method(D_METHOD("is_action", "action", "exact_match"), &InputEvent::is_action, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("is_action_pressed", "action", "allow_echo", "exact_match"), &InputEvent::is_action_pressed, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("is_action_released", "action", "exact_match"), &InputEvent::is_action_released, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_action_strength", "action", "exact_match"), &InputEvent::get_action_strength, DEFVAL(false));
ClassDB::bind_method(D_METHOD("is_pressed"), &InputEvent::is_pressed);
ClassDB::bind_method(D_METHOD("is_echo"), &InputEvent::is_echo);
@@ -384,6 +384,31 @@ String InputEventKey::to_string() {
return vformat("InputEventKey: keycode=%s mods=%s physical=%s pressed=%s echo=%s", kc, mods, physical, p, e);
}
+Ref<InputEventKey> InputEventKey::create_reference(uint32_t p_keycode) {
+ Ref<InputEventKey> ie;
+ ie.instance();
+ ie->set_keycode(p_keycode & KEY_CODE_MASK);
+ ie->set_unicode(p_keycode & KEY_CODE_MASK);
+
+ if (p_keycode & KEY_MASK_SHIFT) {
+ ie->set_shift(true);
+ }
+ if (p_keycode & KEY_MASK_ALT) {
+ ie->set_alt(true);
+ }
+ if (p_keycode & KEY_MASK_CTRL) {
+ ie->set_control(true);
+ }
+ if (p_keycode & KEY_MASK_CMD) {
+ ie->set_command(true);
+ }
+ if (p_keycode & KEY_MASK_META) {
+ ie->set_metakey(true);
+ }
+
+ return ie;
+}
+
bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
Ref<InputEventKey> key = p_event;
if (key.is_null()) {
@@ -594,15 +619,15 @@ String InputEventMouseButton::as_text() const {
// Button
int idx = get_button_index();
switch (idx) {
- case BUTTON_LEFT:
- case BUTTON_RIGHT:
- case BUTTON_MIDDLE:
- case BUTTON_WHEEL_UP:
- case BUTTON_WHEEL_DOWN:
- case BUTTON_WHEEL_LEFT:
- case BUTTON_WHEEL_RIGHT:
- case BUTTON_XBUTTON1:
- case BUTTON_XBUTTON2:
+ case MOUSE_BUTTON_LEFT:
+ case MOUSE_BUTTON_RIGHT:
+ case MOUSE_BUTTON_MIDDLE:
+ case MOUSE_BUTTON_WHEEL_UP:
+ case MOUSE_BUTTON_WHEEL_DOWN:
+ case MOUSE_BUTTON_WHEEL_LEFT:
+ case MOUSE_BUTTON_WHEEL_RIGHT:
+ case MOUSE_BUTTON_XBUTTON1:
+ case MOUSE_BUTTON_XBUTTON2:
full_string += RTR(_mouse_button_descriptions[idx - 1]); // button index starts from 1, array index starts from 0, so subtract 1
break;
default:
@@ -626,15 +651,15 @@ String InputEventMouseButton::to_string() {
String button_string = itos(idx);
switch (idx) {
- case BUTTON_LEFT:
- case BUTTON_RIGHT:
- case BUTTON_MIDDLE:
- case BUTTON_WHEEL_UP:
- case BUTTON_WHEEL_DOWN:
- case BUTTON_WHEEL_LEFT:
- case BUTTON_WHEEL_RIGHT:
- case BUTTON_XBUTTON1:
- case BUTTON_XBUTTON2:
+ case MOUSE_BUTTON_LEFT:
+ case MOUSE_BUTTON_RIGHT:
+ case MOUSE_BUTTON_MIDDLE:
+ case MOUSE_BUTTON_WHEEL_UP:
+ case MOUSE_BUTTON_WHEEL_DOWN:
+ case MOUSE_BUTTON_WHEEL_LEFT:
+ case MOUSE_BUTTON_WHEEL_RIGHT:
+ case MOUSE_BUTTON_XBUTTON1:
+ case MOUSE_BUTTON_XBUTTON2:
button_string += " (" + RTR(_mouse_button_descriptions[idx - 1]) + ")"; // button index starts from 1, array index starts from 0, so subtract 1
break;
default:
@@ -736,20 +761,20 @@ String InputEventMouseMotion::to_string() {
int button_mask = get_button_mask();
String button_mask_string = itos(button_mask);
switch (get_button_mask()) {
- case BUTTON_MASK_LEFT:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_LEFT - 1]) + ")";
+ case MOUSE_BUTTON_MASK_LEFT:
+ button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_LEFT - 1]) + ")";
break;
- case BUTTON_MASK_MIDDLE:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_MIDDLE - 1]) + ")";
+ case MOUSE_BUTTON_MASK_MIDDLE:
+ button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_MIDDLE - 1]) + ")";
break;
- case BUTTON_MASK_RIGHT:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_RIGHT - 1]) + ")";
+ case MOUSE_BUTTON_MASK_RIGHT:
+ button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_RIGHT - 1]) + ")";
break;
- case BUTTON_MASK_XBUTTON1:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_XBUTTON1 - 1]) + ")";
+ case MOUSE_BUTTON_MASK_XBUTTON1:
+ button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_XBUTTON1 - 1]) + ")";
break;
- case BUTTON_MASK_XBUTTON2:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_XBUTTON2 - 1]) + ")";
+ case MOUSE_BUTTON_MASK_XBUTTON2:
+ button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_XBUTTON2 - 1]) + ")";
break;
default:
break;
@@ -985,6 +1010,12 @@ static const char *_joy_button_descriptions[JOY_BUTTON_SDL_MAX] = {
TTRC("D-pad Down"),
TTRC("D-pad Left"),
TTRC("D-pad Right"),
+ TTRC("Xbox Share, PS5 Microphone, Nintendo Capture"),
+ TTRC("Xbox Paddle 1"),
+ TTRC("Xbox Paddle 2"),
+ TTRC("Xbox Paddle 3"),
+ TTRC("Xbox Paddle 4"),
+ TTRC("PS4/5 Touchpad"),
};
String InputEventJoypadButton::as_text() const {
@@ -1005,6 +1036,14 @@ String InputEventJoypadButton::to_string() {
return "InputEventJoypadButton : button_index=" + itos(button_index) + ", pressed=" + (pressed ? "true" : "false") + ", pressure=" + String(Variant(pressure));
}
+Ref<InputEventJoypadButton> InputEventJoypadButton::create_reference(int p_btn_index) {
+ Ref<InputEventJoypadButton> ie;
+ ie.instance();
+ ie->set_button_index(p_btn_index);
+
+ return ie;
+}
+
void InputEventJoypadButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_button_index", "button_index"), &InputEventJoypadButton::set_button_index);
ClassDB::bind_method(D_METHOD("get_button_index"), &InputEventJoypadButton::get_button_index);
diff --git a/core/input/input_event.h b/core/input/input_event.h
index 1500faa24c..a1e7df5969 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -42,24 +42,24 @@
* The events are pretty obvious.
*/
-enum ButtonList {
- BUTTON_LEFT = 1,
- BUTTON_RIGHT = 2,
- BUTTON_MIDDLE = 3,
- BUTTON_WHEEL_UP = 4,
- BUTTON_WHEEL_DOWN = 5,
- BUTTON_WHEEL_LEFT = 6,
- BUTTON_WHEEL_RIGHT = 7,
- BUTTON_XBUTTON1 = 8,
- BUTTON_XBUTTON2 = 9,
- BUTTON_MASK_LEFT = (1 << (BUTTON_LEFT - 1)),
- BUTTON_MASK_RIGHT = (1 << (BUTTON_RIGHT - 1)),
- BUTTON_MASK_MIDDLE = (1 << (BUTTON_MIDDLE - 1)),
- BUTTON_MASK_XBUTTON1 = (1 << (BUTTON_XBUTTON1 - 1)),
- BUTTON_MASK_XBUTTON2 = (1 << (BUTTON_XBUTTON2 - 1))
+enum MouseButton {
+ MOUSE_BUTTON_LEFT = 1,
+ MOUSE_BUTTON_RIGHT = 2,
+ MOUSE_BUTTON_MIDDLE = 3,
+ MOUSE_BUTTON_WHEEL_UP = 4,
+ MOUSE_BUTTON_WHEEL_DOWN = 5,
+ MOUSE_BUTTON_WHEEL_LEFT = 6,
+ MOUSE_BUTTON_WHEEL_RIGHT = 7,
+ MOUSE_BUTTON_XBUTTON1 = 8,
+ MOUSE_BUTTON_XBUTTON2 = 9,
+ MOUSE_BUTTON_MASK_LEFT = (1 << (MOUSE_BUTTON_LEFT - 1)),
+ MOUSE_BUTTON_MASK_RIGHT = (1 << (MOUSE_BUTTON_RIGHT - 1)),
+ MOUSE_BUTTON_MASK_MIDDLE = (1 << (MOUSE_BUTTON_MIDDLE - 1)),
+ MOUSE_BUTTON_MASK_XBUTTON1 = (1 << (MOUSE_BUTTON_XBUTTON1 - 1)),
+ MOUSE_BUTTON_MASK_XBUTTON2 = (1 << (MOUSE_BUTTON_XBUTTON2 - 1))
};
-enum JoyButtonList {
+enum JoyButton {
JOY_BUTTON_INVALID = -1,
JOY_BUTTON_A = 0,
JOY_BUTTON_B = 1,
@@ -76,11 +76,17 @@ enum JoyButtonList {
JOY_BUTTON_DPAD_DOWN = 12,
JOY_BUTTON_DPAD_LEFT = 13,
JOY_BUTTON_DPAD_RIGHT = 14,
- JOY_BUTTON_SDL_MAX = 15,
+ JOY_BUTTON_MISC1 = 15,
+ JOY_BUTTON_PADDLE1 = 16,
+ JOY_BUTTON_PADDLE2 = 17,
+ JOY_BUTTON_PADDLE3 = 18,
+ JOY_BUTTON_PADDLE4 = 19,
+ JOY_BUTTON_TOUCHPAD = 20,
+ JOY_BUTTON_SDL_MAX = 21,
JOY_BUTTON_MAX = 36, // Android supports up to 36 buttons.
};
-enum JoyAxisList {
+enum JoyAxis {
JOY_AXIS_INVALID = -1,
JOY_AXIS_LEFT_X = 0,
JOY_AXIS_LEFT_Y = 1,
@@ -92,7 +98,7 @@ enum JoyAxisList {
JOY_AXIS_MAX = 10, // OpenVR supports up to 5 Joysticks making a total of 10 axes.
};
-enum MidiMessageList {
+enum MIDIMessage {
MIDI_MESSAGE_NOTE_OFF = 0x8,
MIDI_MESSAGE_NOTE_ON = 0x9,
MIDI_MESSAGE_AFTERTOUCH = 0xA,
@@ -122,11 +128,11 @@ public:
void set_device(int p_device);
int get_device() const;
- bool is_action(const StringName &p_action) const;
- bool is_action_pressed(const StringName &p_action, bool p_allow_echo = false) const;
- bool is_action_released(const StringName &p_action) const;
- float get_action_strength(const StringName &p_action) const;
- float get_action_raw_strength(const StringName &p_action) const;
+ bool is_action(const StringName &p_action, bool p_exact_match = false) const;
+ bool is_action_pressed(const StringName &p_action, bool p_allow_echo = false, bool p_exact_match = false) const;
+ bool is_action_released(const StringName &p_action, bool p_exact_match = false) const;
+ float get_action_strength(const StringName &p_action, bool p_exact_match = false) const;
+ float get_action_raw_strength(const StringName &p_action, bool p_exact_match = false) const;
// To be removed someday, since they do not make sense for all events
virtual bool is_pressed() const;
@@ -254,6 +260,8 @@ public:
virtual String as_text() const override;
virtual String to_string() override;
+ static Ref<InputEventKey> create_reference(uint32_t p_keycode_with_modifier_masks);
+
InputEventKey() {}
};
@@ -400,6 +408,8 @@ public:
virtual String as_text() const override;
virtual String to_string() override;
+ static Ref<InputEventJoypadButton> create_reference(int p_btn_index);
+
InputEventJoypadButton() {}
};
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index 53ed925c1f..7d85fd6492 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -50,7 +50,7 @@ void InputMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("action_erase_event", "action", "event"), &InputMap::action_erase_event);
ClassDB::bind_method(D_METHOD("action_erase_events", "action"), &InputMap::action_erase_events);
ClassDB::bind_method(D_METHOD("action_get_events", "action"), &InputMap::_action_get_events);
- ClassDB::bind_method(D_METHOD("event_is_action", "event", "action"), &InputMap::event_is_action);
+ ClassDB::bind_method(D_METHOD("event_is_action", "event", "action", "exact_match"), &InputMap::event_is_action, DEFVAL(false));
ClassDB::bind_method(D_METHOD("load_from_project_settings"), &InputMap::load_from_project_settings);
}
@@ -88,14 +88,14 @@ List<StringName> InputMap::get_actions() const {
return actions;
}
- for (Map<StringName, Action>::Element *E = input_map.front(); E; E = E->next()) {
- actions.push_back(E->key());
+ for (OrderedHashMap<StringName, Action>::Element E = input_map.front(); E; E = E.next()) {
+ actions.push_back(E.key());
}
return actions;
}
-List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
+List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
ERR_FAIL_COND_V(!p_event.is_valid(), nullptr);
for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) {
@@ -106,7 +106,9 @@ List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Re
int device = e->get_device();
if (device == ALL_DEVICES || device == p_event->get_device()) {
- if (e->action_match(p_event, p_pressed, p_strength, p_raw_strength, p_action.deadzone)) {
+ if (p_exact_match && e->shortcut_match(p_event)) {
+ return E;
+ } else if (!p_exact_match && e->action_match(p_event, p_pressed, p_strength, p_raw_strength, p_action.deadzone)) {
return E;
}
}
@@ -134,7 +136,7 @@ void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone)
void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
ERR_FAIL_COND_MSG(p_event.is_null(), "It's not a reference to a valid InputEvent object.");
ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
- if (_find_event(input_map[p_action], p_event)) {
+ if (_find_event(input_map[p_action], p_event, true)) {
return; // Already addded.
}
@@ -143,13 +145,13 @@ void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent
bool InputMap::action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
ERR_FAIL_COND_V_MSG(!input_map.has(p_action), false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
- return (_find_event(input_map[p_action], p_event) != nullptr);
+ return (_find_event(input_map[p_action], p_event, true) != nullptr);
}
void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
- List<Ref<InputEvent>>::Element *E = _find_event(input_map[p_action], p_event);
+ List<Ref<InputEvent>>::Element *E = _find_event(input_map[p_action], p_event, true);
if (E) {
input_map[p_action].inputs.erase(E);
if (Input::get_singleton()->is_action_pressed(p_action)) {
@@ -177,20 +179,20 @@ Array InputMap::_action_get_events(const StringName &p_action) {
}
const List<Ref<InputEvent>> *InputMap::action_get_events(const StringName &p_action) {
- const Map<StringName, Action>::Element *E = input_map.find(p_action);
+ const OrderedHashMap<StringName, Action>::Element E = input_map.find(p_action);
if (!E) {
return nullptr;
}
- return &E->get().inputs;
+ return &E.get().inputs;
}
-bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const {
- return event_get_action_status(p_event, p_action);
+bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match) const {
+ return event_get_action_status(p_event, p_action, p_exact_match);
}
-bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
- Map<StringName, Action>::Element *E = input_map.find(p_action);
+bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
+ OrderedHashMap<StringName, Action>::Element E = input_map.find(p_action);
ERR_FAIL_COND_V_MSG(!E, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
Ref<InputEventAction> input_event_action = p_event;
@@ -207,7 +209,7 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str
bool pressed;
float strength;
float raw_strength;
- List<Ref<InputEvent>>::Element *event = _find_event(E->get(), p_event, &pressed, &strength, &raw_strength);
+ List<Ref<InputEvent>>::Element *event = _find_event(E.get(), p_event, p_exact_match, &pressed, &strength, &raw_strength);
if (event != nullptr) {
if (p_pressed != nullptr) {
*p_pressed = pressed;
@@ -224,7 +226,7 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str
}
}
-const Map<StringName, InputMap::Action> &InputMap::get_action_map() const {
+const OrderedHashMap<StringName, InputMap::Action> &InputMap::get_action_map() const {
return input_map;
}
@@ -258,84 +260,445 @@ void InputMap::load_from_project_settings() {
}
}
+struct _BuiltinActionDisplayName {
+ const char *name;
+ const char *display_name;
+};
+
+static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
+ /* clang-format off */
+ { "ui_accept", TTRC("Accept") },
+ { "ui_select", TTRC("Select") },
+ { "ui_cancel", TTRC("Cancel") },
+ { "ui_focus_next", TTRC("Focus Next") },
+ { "ui_focus_prev", TTRC("Focus Prev") },
+ { "ui_left", TTRC("Left") },
+ { "ui_right", TTRC("Right") },
+ { "ui_up", TTRC("Up") },
+ { "ui_down", TTRC("Down") },
+ { "ui_page_up", TTRC("Page Up") },
+ { "ui_page_down", TTRC("Page Down") },
+ { "ui_home", TTRC("Home") },
+ { "ui_end", TTRC("End") },
+ { "ui_cut", TTRC("Cut") },
+ { "ui_copy", TTRC("Copy") },
+ { "ui_paste", TTRC("Paste") },
+ { "ui_undo", TTRC("Undo") },
+ { "ui_redo", TTRC("Redo") },
+ { "ui_text_completion_query", TTRC("Completion Query") },
+ { "ui_text_newline", TTRC("New Line") },
+ { "ui_text_newline_blank", TTRC("New Blank Line") },
+ { "ui_text_newline_above", TTRC("New Line Above") },
+ { "ui_text_indent", TTRC("Indent") },
+ { "ui_text_dedent", TTRC("Dedent") },
+ { "ui_text_backspace", TTRC("Backspace") },
+ { "ui_text_backspace_word", TTRC("Backspace Word") },
+ { "ui_text_backspace_word.OSX", TTRC("Backspace Word") },
+ { "ui_text_backspace_all_to_left", TTRC("Backspace all to Left") },
+ { "ui_text_backspace_all_to_left.OSX", TTRC("Backspace all to Left") },
+ { "ui_text_delete", TTRC("Delete") },
+ { "ui_text_delete_word", TTRC("Delete Word") },
+ { "ui_text_delete_word.OSX", TTRC("Delete Word") },
+ { "ui_text_delete_all_to_right", TTRC("Delete all to Right") },
+ { "ui_text_delete_all_to_right.OSX", TTRC("Delete all to Right") },
+ { "ui_text_caret_left", TTRC("Caret Left") },
+ { "ui_text_caret_word_left", TTRC("Caret Word Left") },
+ { "ui_text_caret_word_left.OSX", TTRC("Caret Word Left") },
+ { "ui_text_caret_right", TTRC("Caret Right") },
+ { "ui_text_caret_word_right", TTRC("Caret Word Right") },
+ { "ui_text_caret_word_right.OSX", TTRC("Caret Word Right") },
+ { "ui_text_caret_up", TTRC("Caret Up") },
+ { "ui_text_caret_down", TTRC("Caret Down") },
+ { "ui_text_caret_line_start", TTRC("Caret Line Start") },
+ { "ui_text_caret_line_start.OSX", TTRC("Caret Line Start") },
+ { "ui_text_caret_line_end", TTRC("Caret Line End") },
+ { "ui_text_caret_line_end.OSX", TTRC("Caret Line End") },
+ { "ui_text_caret_page_up", TTRC("Caret Page Up") },
+ { "ui_text_caret_page_down", TTRC("Caret Page Down") },
+ { "ui_text_caret_document_start", TTRC("Caret Document Start") },
+ { "ui_text_caret_document_start.OSX", TTRC("Caret Document Start") },
+ { "ui_text_caret_document_end", TTRC("Caret Document End") },
+ { "ui_text_caret_document_end.OSX", TTRC("Caret Document End") },
+ { "ui_text_scroll_up", TTRC("Scroll Up") },
+ { "ui_text_scroll_up.OSX", TTRC("Scroll Up") },
+ { "ui_text_scroll_down", TTRC("Scroll Down") },
+ { "ui_text_scroll_down.OSX", TTRC("Scroll Down") },
+ { "ui_text_select_all", TTRC("Select All") },
+ { "ui_text_toggle_insert_mode", TTRC("Toggle Insert Mode") },
+ { "ui_graph_duplicate", TTRC("Duplicate Nodes") },
+ { "ui_graph_delete", TTRC("Delete Nodes") },
+ { "ui_filedialog_up_one_level", TTRC("Go Up One Level") },
+ { "ui_filedialog_refresh", TTRC("Refresh") },
+ { "ui_filedialog_show_hidden", TTRC("Show Hidden") },
+ { "ui_swap_input_direction ", TTRC("Swap Input Direction") },
+ { "", TTRC("")}
+ /* clang-format on */
+};
+
+String InputMap::get_builtin_display_name(const String &p_name) const {
+ int len = sizeof(_builtin_action_display_names) / sizeof(_BuiltinActionDisplayName);
+
+ for (int i = 0; i < len; i++) {
+ if (_builtin_action_display_names[i].name == p_name) {
+ return RTR(_builtin_action_display_names[i].display_name);
+ }
+ }
+
+ return p_name;
+}
+
+const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
+ // Return cache if it has already been built.
+ if (default_builtin_cache.size()) {
+ return default_builtin_cache;
+ }
+
+ List<Ref<InputEvent>> inputs;
+ inputs.push_back(InputEventKey::create_reference(KEY_ENTER));
+ inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER));
+ inputs.push_back(InputEventKey::create_reference(KEY_SPACE));
+ default_builtin_cache.insert("ui_accept", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_Y));
+ inputs.push_back(InputEventKey::create_reference(KEY_SPACE));
+ default_builtin_cache.insert("ui_select", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_ESCAPE));
+ default_builtin_cache.insert("ui_cancel", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_TAB));
+ default_builtin_cache.insert("ui_focus_next", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_TAB | KEY_MASK_SHIFT));
+ default_builtin_cache.insert("ui_focus_prev", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_LEFT));
+ inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_LEFT));
+ default_builtin_cache.insert("ui_left", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_RIGHT));
+ inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_RIGHT));
+ default_builtin_cache.insert("ui_right", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_UP));
+ inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_UP));
+ default_builtin_cache.insert("ui_up", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_DOWN));
+ inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_DOWN));
+ default_builtin_cache.insert("ui_down", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_PAGEUP));
+ default_builtin_cache.insert("ui_page_up", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_PAGEDOWN));
+ default_builtin_cache.insert("ui_page_down", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_HOME));
+ default_builtin_cache.insert("ui_home", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_END));
+ default_builtin_cache.insert("ui_end", inputs);
+
+ // ///// UI basic Shortcuts /////
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_X | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_SHIFT));
+ default_builtin_cache.insert("ui_cut", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_C | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(KEY_INSERT | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_copy", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_V | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(KEY_INSERT | KEY_MASK_SHIFT));
+ default_builtin_cache.insert("ui_paste", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_Z | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_undo", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_Z | KEY_MASK_CMD | KEY_MASK_SHIFT));
+ inputs.push_back(InputEventKey::create_reference(KEY_Y | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_redo", inputs);
+
+ // ///// UI Text Input Shortcuts /////
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_SPACE | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_completion_query", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_TAB));
+ default_builtin_cache.insert("ui_text_completion_accept", inputs);
+
+ // Newlines
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_ENTER));
+ inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER));
+ default_builtin_cache.insert("ui_text_newline", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+
+ inputs.push_back(InputEventKey::create_reference(KEY_ENTER | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_newline_blank", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_ENTER | KEY_MASK_SHIFT | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER | KEY_MASK_SHIFT | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_newline_above", inputs);
+
+ // Indentation
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_TAB));
+ default_builtin_cache.insert("ui_text_indent", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_TAB | KEY_MASK_SHIFT));
+ default_builtin_cache.insert("ui_text_dedent", inputs);
+
+ // Text Backspace and Delete
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE));
+ default_builtin_cache.insert("ui_text_backspace", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_backspace_word", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_ALT));
+ default_builtin_cache.insert("ui_text_backspace_word.OSX", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ default_builtin_cache.insert("ui_text_backspace_all_to_left", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_backspace_all_to_left.OSX", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_DELETE));
+ default_builtin_cache.insert("ui_text_delete", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_delete_word", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_ALT));
+ default_builtin_cache.insert("ui_text_delete_word.OSX", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ default_builtin_cache.insert("ui_text_delete_all_to_right", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_delete_all_to_right.OSX", inputs);
+
+ // Text Caret Movement Left/Right
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_LEFT));
+ default_builtin_cache.insert("ui_text_caret_left", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_LEFT | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_caret_word_left", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_LEFT | KEY_MASK_ALT));
+ default_builtin_cache.insert("ui_text_caret_word_left.OSX", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_RIGHT));
+ default_builtin_cache.insert("ui_text_caret_right", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_RIGHT | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_caret_word_right", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_RIGHT | KEY_MASK_ALT));
+ default_builtin_cache.insert("ui_text_caret_word_right.OSX", inputs);
+
+ // Text Caret Movement Up/Down
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_UP));
+ default_builtin_cache.insert("ui_text_caret_up", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_DOWN));
+ default_builtin_cache.insert("ui_text_caret_down", inputs);
+
+ // Text Caret Movement Line Start/End
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_HOME));
+ default_builtin_cache.insert("ui_text_caret_line_start", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_A | KEY_MASK_CTRL));
+ inputs.push_back(InputEventKey::create_reference(KEY_LEFT | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_caret_line_start.OSX", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_END));
+ default_builtin_cache.insert("ui_text_caret_line_end", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_E | KEY_MASK_CTRL));
+ inputs.push_back(InputEventKey::create_reference(KEY_RIGHT | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_caret_line_end.OSX", inputs);
+
+ // Text Caret Movement Page Up/Down
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_PAGEUP));
+ default_builtin_cache.insert("ui_text_caret_page_up", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_PAGEDOWN));
+ default_builtin_cache.insert("ui_text_caret_page_down", inputs);
+
+ // Text Caret Movement Document Start/End
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_HOME | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_caret_document_start", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_UP | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_caret_document_start.OSX", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_END | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_caret_document_end", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_DOWN | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_caret_document_end.OSX", inputs);
+
+ // Text Scrolling
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_UP | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_scroll_up", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_UP | KEY_MASK_CMD | KEY_MASK_ALT));
+ default_builtin_cache.insert("ui_text_scroll_up.OSX", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_DOWN | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_scroll_down", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_DOWN | KEY_MASK_CMD | KEY_MASK_ALT));
+ default_builtin_cache.insert("ui_text_scroll_down.OSX", inputs);
+
+ // Text Misc
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_A | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_text_select_all", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_INSERT));
+ default_builtin_cache.insert("ui_text_toggle_insert_mode", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_MENU));
+ default_builtin_cache.insert("ui_menu", inputs);
+
+ // ///// UI Graph Shortcuts /////
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_D | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_graph_duplicate", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_DELETE));
+ default_builtin_cache.insert("ui_graph_delete", inputs);
+
+ // ///// UI File Dialog Shortcuts /////
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE));
+ default_builtin_cache.insert("ui_filedialog_up_one_level", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_F5));
+ default_builtin_cache.insert("ui_filedialog_refresh", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_H));
+ default_builtin_cache.insert("ui_filedialog_show_hidden", inputs);
+
+ inputs = List<Ref<InputEvent>>();
+ inputs.push_back(InputEventKey::create_reference(KEY_QUOTELEFT | KEY_MASK_CMD));
+ default_builtin_cache.insert("ui_swap_input_direction", inputs);
+
+ return default_builtin_cache;
+}
+
void InputMap::load_default() {
- Ref<InputEventKey> key;
-
- add_action("ui_accept");
- key.instance();
- key->set_keycode(KEY_ENTER);
- action_add_event("ui_accept", key);
-
- key.instance();
- key->set_keycode(KEY_KP_ENTER);
- action_add_event("ui_accept", key);
-
- key.instance();
- key->set_keycode(KEY_SPACE);
- action_add_event("ui_accept", key);
-
- add_action("ui_select");
- key.instance();
- key->set_keycode(KEY_SPACE);
- action_add_event("ui_select", key);
-
- add_action("ui_cancel");
- key.instance();
- key->set_keycode(KEY_ESCAPE);
- action_add_event("ui_cancel", key);
-
- add_action("ui_focus_next");
- key.instance();
- key->set_keycode(KEY_TAB);
- action_add_event("ui_focus_next", key);
-
- add_action("ui_focus_prev");
- key.instance();
- key->set_keycode(KEY_TAB);
- key->set_shift(true);
- action_add_event("ui_focus_prev", key);
-
- add_action("ui_left");
- key.instance();
- key->set_keycode(KEY_LEFT);
- action_add_event("ui_left", key);
-
- add_action("ui_right");
- key.instance();
- key->set_keycode(KEY_RIGHT);
- action_add_event("ui_right", key);
-
- add_action("ui_up");
- key.instance();
- key->set_keycode(KEY_UP);
- action_add_event("ui_up", key);
-
- add_action("ui_down");
- key.instance();
- key->set_keycode(KEY_DOWN);
- action_add_event("ui_down", key);
-
- add_action("ui_page_up");
- key.instance();
- key->set_keycode(KEY_PAGEUP);
- action_add_event("ui_page_up", key);
-
- add_action("ui_page_down");
- key.instance();
- key->set_keycode(KEY_PAGEDOWN);
- action_add_event("ui_page_down", key);
-
- add_action("ui_home");
- key.instance();
- key->set_keycode(KEY_HOME);
- action_add_event("ui_home", key);
-
- add_action("ui_end");
- key.instance();
- key->set_keycode(KEY_END);
- action_add_event("ui_end", key);
-
- //set("display/window/handheld/orientation", "landscape");
+ OrderedHashMap<String, List<Ref<InputEvent>>> builtins = get_builtins();
+
+ // List of Builtins which have an override for OSX.
+ Vector<String> osx_builtins;
+ for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
+ if (String(E.key()).ends_with(".OSX")) {
+ // Strip .OSX from name: some_input_name.OSX -> some_input_name
+ osx_builtins.push_back(String(E.key()).split(".")[0]);
+ }
+ }
+
+ for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
+ String fullname = E.key();
+ String name = fullname.split(".")[0];
+ String override_for = fullname.split(".").size() > 1 ? fullname.split(".")[1] : "";
+
+#ifdef APPLE_STYLE_KEYS
+ if (osx_builtins.has(name) && override_for != "OSX") {
+ // Name has osx builtin but this particular one is for non-osx systems - so skip.
+ continue;
+ }
+#else
+ if (override_for == "OSX") {
+ // Override for OSX - not needed on non-osx platforms.
+ continue;
+ }
+#endif
+
+ add_action(name);
+
+ List<Ref<InputEvent>> inputs = E.get();
+ for (List<Ref<InputEvent>>::Element *I = inputs.front(); I; I = I->next()) {
+ Ref<InputEventKey> iek = I->get();
+
+ // For the editor, only add keyboard actions.
+ if (iek.is_valid()) {
+ action_add_event(name, I->get());
+ }
+ }
+ }
}
InputMap::InputMap() {
diff --git a/core/input/input_map.h b/core/input/input_map.h
index 1646e7fadb..99c71e1e53 100644
--- a/core/input/input_map.h
+++ b/core/input/input_map.h
@@ -33,6 +33,8 @@
#include "core/input/input_event.h"
#include "core/object/class_db.h"
+#include "core/object/object.h"
+#include "core/templates/ordered_hash_map.h"
class InputMap : public Object {
GDCLASS(InputMap, Object);
@@ -52,9 +54,10 @@ public:
private:
static InputMap *singleton;
- mutable Map<StringName, Action> input_map;
+ mutable OrderedHashMap<StringName, Action> input_map;
+ OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_cache;
- List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
+ List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
Array _action_get_events(const StringName &p_action);
Array _get_actions();
@@ -78,13 +81,17 @@ public:
void action_erase_events(const StringName &p_action);
const List<Ref<InputEvent>> *action_get_events(const StringName &p_action);
- bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const;
- bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
+ bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false) const;
+ bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
- const Map<StringName, Action> &get_action_map() const;
+ const OrderedHashMap<StringName, Action> &get_action_map() const;
void load_from_project_settings();
void load_default();
+ String get_builtin_display_name(const String &p_name) const;
+ // Use an Ordered Map so insertion order is preserved. We want the elements to be 'grouped' somewhat.
+ const OrderedHashMap<String, List<Ref<InputEvent>>> &get_builtins();
+
InputMap();
};
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index 456023e2a6..980234cbfc 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -181,8 +181,8 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
}
/**
- This will handle both Gzip and Deflat streams. It will automatically allocate the output buffer into the provided p_dst_vect Vector.
- This is required for compressed data who's final uncompressed size is unknown, as is the case for HTTP response bodies.
+ This will handle both Gzip and Deflate streams. It will automatically allocate the output buffer into the provided p_dst_vect Vector.
+ This is required for compressed data whose final uncompressed size is unknown, as is the case for HTTP response bodies.
This is much slower however than using Compression::decompress because it may result in multiple full copies of the output buffer.
*/
int Compression::decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_size, const uint8_t *p_src, int p_src_size, Mode p_mode) {
@@ -248,7 +248,7 @@ int Compression::decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_s
out_mark += gzip_chunk;
- // Encorce max output size
+ // Enforce max output size
if (p_max_dst_size > -1 && strm.total_out > (uint64_t)p_max_dst_size) {
(void)inflateEnd(&strm);
p_dst_vect->resize(0);
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index 015c1f0d90..10f68f3cef 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -295,6 +295,9 @@ Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream)
return OK;
}
+void ConfigFile::clear() {
+ values.clear();
+}
void ConfigFile::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_value", "section", "key", "value"), &ConfigFile::set_value);
ClassDB::bind_method(D_METHOD("get_value", "section", "key", "default"), &ConfigFile::get_value, DEFVAL(Variant()));
@@ -317,4 +320,6 @@ void ConfigFile::_bind_methods() {
ClassDB::bind_method(D_METHOD("save_encrypted", "path", "key"), &ConfigFile::save_encrypted);
ClassDB::bind_method(D_METHOD("save_encrypted_pass", "path", "password"), &ConfigFile::save_encrypted_pass);
+
+ ClassDB::bind_method(D_METHOD("clear"), &ConfigFile::clear);
}
diff --git a/core/io/config_file.h b/core/io/config_file.h
index 386d304f07..1b28257c60 100644
--- a/core/io/config_file.h
+++ b/core/io/config_file.h
@@ -68,6 +68,8 @@ public:
Error load(const String &p_path);
Error parse(const String &p_data);
+ void clear();
+
Error load_encrypted(const String &p_path, const Vector<uint8_t> &p_key);
Error load_encrypted_pass(const String &p_path, const String &p_pass);
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 9ec2b27e88..b2440629e3 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -286,8 +286,10 @@ uint8_t FileAccessCompressed::get_8() const {
}
int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
- ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
+ ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
if (at_end) {
read_eof = true;
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 8b4c57ce64..8ace897f18 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -237,7 +237,9 @@ uint8_t FileAccessEncrypted::get_8() const {
}
int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const {
- ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
+ ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
int to_copy = MIN(p_length, data.size() - pos);
for (int i = 0; i < to_copy; i++) {
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 04270de77f..58670d5246 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -138,6 +138,8 @@ uint8_t FileAccessMemory::get_8() const {
}
int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V(!data, -1);
int left = length - pos;
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 97838fd14c..31b7d658d0 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -366,6 +366,9 @@ void FileAccessNetwork::_queue_page(int p_page) const {
}
int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
+
//bool eof=false;
if (pos + p_length > total_size) {
eof_flag = true;
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index faf4fca14f..e24dc40166 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -299,6 +299,9 @@ uint8_t FileAccessPack::get_8() const {
}
int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
+
if (eof) {
return 0;
}
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 3c84e6b656..343adbe592 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -92,7 +92,7 @@ private:
PathMD5() {}
- PathMD5(const Vector<uint8_t> p_buf) {
+ PathMD5(const Vector<uint8_t> &p_buf) {
a = *((uint64_t *)&p_buf[0]);
b = *((uint64_t *)&p_buf[8]);
}
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index 01f9337a80..586c988974 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -303,6 +303,8 @@ uint8_t FileAccessZip::get_8() const {
}
int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V(!zfile, -1);
at_eof = unzeof(zfile);
if (at_eof) {
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index 18afdc678e..3863dce0f6 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -96,6 +96,11 @@ Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl,
void HTTPClient::set_connection(const Ref<StreamPeer> &p_connection) {
ERR_FAIL_COND_MSG(p_connection.is_null(), "Connection is not a reference to a valid StreamPeer object.");
+ if (ssl) {
+ ERR_FAIL_NULL_MSG(Object::cast_to<StreamPeerSSL>(p_connection.ptr()),
+ "Connection is not a reference to a valid StreamPeerSSL object.");
+ }
+
if (connection == p_connection) {
return;
}
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 986c29b539..5d46d75efe 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -2985,6 +2985,26 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
_set_color_at_ofs(data.ptrw(), ofs, p_color);
}
+void Image::adjust_bcs(float p_brightness, float p_contrast, float p_saturation) {
+ uint8_t *w = data.ptrw();
+ uint32_t pixel_size = get_format_pixel_size(format);
+ uint32_t pixel_count = data.size() / pixel_size;
+
+ for (uint32_t i = 0; i < pixel_count; i++) {
+ Color c = _get_color_at_ofs(w, i);
+ Vector3 rgb(c.r, c.g, c.b);
+
+ rgb *= p_brightness;
+ rgb = Vector3(0.5, 0.5, 0.5).lerp(rgb, p_contrast);
+ float center = (rgb.x + rgb.y + rgb.z) / 3.0;
+ rgb = Vector3(center, center, center).lerp(rgb, p_saturation);
+ c.r = rgb.x;
+ c.g = rgb.y;
+ c.b = rgb.z;
+ _set_color_at_ofs(w, i, c);
+ }
+}
+
Image::UsedChannels Image::detect_used_channels(CompressSource p_source) {
ERR_FAIL_COND_V(data.size() == 0, USED_CHANNELS_RGBA);
ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA);
@@ -3132,6 +3152,8 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pixelv", "point", "color"), &Image::set_pixelv);
ClassDB::bind_method(D_METHOD("set_pixel", "x", "y", "color"), &Image::set_pixel);
+ ClassDB::bind_method(D_METHOD("adjust_bcs", "brightness", "contrast", "saturation"), &Image::adjust_bcs);
+
ClassDB::bind_method(D_METHOD("load_png_from_buffer", "buffer"), &Image::load_png_from_buffer);
ClassDB::bind_method(D_METHOD("load_jpg_from_buffer", "buffer"), &Image::load_jpg_from_buffer);
ClassDB::bind_method(D_METHOD("load_webp_from_buffer", "buffer"), &Image::load_webp_from_buffer);
diff --git a/core/io/image.h b/core/io/image.h
index b894be7df4..df8f9b35a1 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -390,6 +390,8 @@ public:
void set_pixelv(const Point2i &p_point, const Color &p_color);
void set_pixel(int p_x, int p_y, const Color &p_color);
+ void adjust_bcs(float p_brightness, float p_contrast, float p_saturation);
+
void set_as_black();
void copy_internals_from(const Ref<Image> &p_image) {
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index 8ca1cb3beb..7de038e6fe 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -122,7 +122,7 @@ void ImageLoader::cleanup() {
/////////////////
-RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderImage::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) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
if (r_error) {
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index bf67e1486f..a5d588e0b5 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -72,7 +72,7 @@ public:
class ResourceFormatLoaderImage : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index df95785000..e1d9c19f10 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -40,13 +40,13 @@ VARIANT_ENUM_CAST(IP::ResolverStatus);
struct _IP_ResolverPrivate {
struct QueueItem {
- volatile IP::ResolverStatus status;
+ SafeNumeric<IP::ResolverStatus> status;
IP_Address response;
String hostname;
IP::Type type;
void clear() {
- status = IP::RESOLVER_STATUS_NONE;
+ status.set(IP::RESOLVER_STATUS_NONE);
response = IP_Address();
type = IP::TYPE_NONE;
hostname = "";
@@ -61,7 +61,7 @@ struct _IP_ResolverPrivate {
IP::ResolverID find_empty_id() const {
for (int i = 0; i < IP::RESOLVER_MAX_QUERIES; i++) {
- if (queue[i].status == IP::RESOLVER_STATUS_NONE) {
+ if (queue[i].status.get() == IP::RESOLVER_STATUS_NONE) {
return i;
}
}
@@ -77,15 +77,15 @@ struct _IP_ResolverPrivate {
void resolve_queues() {
for (int i = 0; i < IP::RESOLVER_MAX_QUERIES; i++) {
- if (queue[i].status != IP::RESOLVER_STATUS_WAITING) {
+ if (queue[i].status.get() != IP::RESOLVER_STATUS_WAITING) {
continue;
}
queue[i].response = IP::get_singleton()->resolve_hostname(queue[i].hostname, queue[i].type);
if (!queue[i].response.is_valid()) {
- queue[i].status = IP::RESOLVER_STATUS_ERROR;
+ queue[i].status.set(IP::RESOLVER_STATUS_ERROR);
} else {
- queue[i].status = IP::RESOLVER_STATUS_DONE;
+ queue[i].status.set(IP::RESOLVER_STATUS_DONE);
}
}
}
@@ -137,10 +137,10 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ
resolver->queue[id].type = p_type;
if (resolver->cache.has(key) && resolver->cache[key].is_valid()) {
resolver->queue[id].response = resolver->cache[key];
- resolver->queue[id].status = IP::RESOLVER_STATUS_DONE;
+ resolver->queue[id].status.set(IP::RESOLVER_STATUS_DONE);
} else {
resolver->queue[id].response = IP_Address();
- resolver->queue[id].status = IP::RESOLVER_STATUS_WAITING;
+ resolver->queue[id].status.set(IP::RESOLVER_STATUS_WAITING);
if (resolver->thread.is_started()) {
resolver->sem.post();
} else {
@@ -156,12 +156,12 @@ IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const {
MutexLock lock(resolver->mutex);
- if (resolver->queue[p_id].status == IP::RESOLVER_STATUS_NONE) {
+ if (resolver->queue[p_id].status.get() == IP::RESOLVER_STATUS_NONE) {
ERR_PRINT("Condition status == IP::RESOLVER_STATUS_NONE");
resolver->mutex.unlock();
return IP::RESOLVER_STATUS_NONE;
}
- return resolver->queue[p_id].status;
+ return resolver->queue[p_id].status.get();
}
IP_Address IP::get_resolve_item_address(ResolverID p_id) const {
@@ -169,7 +169,7 @@ IP_Address IP::get_resolve_item_address(ResolverID p_id) const {
MutexLock lock(resolver->mutex);
- if (resolver->queue[p_id].status != IP::RESOLVER_STATUS_DONE) {
+ if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) {
ERR_PRINT("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet.");
resolver->mutex.unlock();
return IP_Address();
@@ -183,7 +183,7 @@ void IP::erase_resolve_item(ResolverID p_id) {
MutexLock lock(resolver->mutex);
- resolver->queue[p_id].status = IP::RESOLVER_STATUS_NONE;
+ resolver->queue[p_id].status.set(IP::RESOLVER_STATUS_NONE);
}
void IP::clear_cache(const String &p_hostname) {
diff --git a/core/io/json.cpp b/core/io/json.cpp
index f51f0ceca4..394cf216e8 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -234,6 +234,52 @@ Error JSON::_get_token(const char32_t *p_str, int &index, int p_len, Token &r_to
}
index += 4; //will add at the end anyway
+ if ((res & 0xfffffc00) == 0xd800) {
+ if (p_str[index + 1] != '\\' || p_str[index + 2] != 'u') {
+ r_err_str = "Invalid UTF-16 sequence in string, unpaired lead surrogate";
+ return ERR_PARSE_ERROR;
+ }
+ index += 2;
+ char32_t trail = 0;
+ for (int j = 0; j < 4; j++) {
+ char32_t c = p_str[index + j + 1];
+ if (c == 0) {
+ r_err_str = "Unterminated String";
+ return ERR_PARSE_ERROR;
+ }
+ if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) {
+ r_err_str = "Malformed hex constant in string";
+ return ERR_PARSE_ERROR;
+ }
+ char32_t v;
+ if (c >= '0' && c <= '9') {
+ v = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ v = c - 'a';
+ v += 10;
+ } else if (c >= 'A' && c <= 'F') {
+ v = c - 'A';
+ v += 10;
+ } else {
+ ERR_PRINT("Bug parsing hex constant.");
+ v = 0;
+ }
+
+ trail <<= 4;
+ trail |= v;
+ }
+ if ((trail & 0xfffffc00) == 0xdc00) {
+ res = (res << 10UL) + trail - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
+ index += 4; //will add at the end anyway
+ } else {
+ r_err_str = "Invalid UTF-16 sequence in string, unpaired lead surrogate";
+ return ERR_PARSE_ERROR;
+ }
+ } else if ((res & 0xfffffc00) == 0xdc00) {
+ r_err_str = "Invalid UTF-16 sequence in string, unpaired trail surrogate";
+ return ERR_PARSE_ERROR;
+ }
+
} break;
default: {
res = next;
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index da200f5717..8a07459a1d 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -43,6 +43,12 @@ bool Logger::should_log(bool p_err) {
return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled);
}
+bool Logger::_flush_stdout_on_print = true;
+
+void Logger::set_flush_stdout_on_print(bool value) {
+ _flush_stdout_on_print = value;
+}
+
void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
if (!should_log(true)) {
return;
@@ -207,7 +213,7 @@ void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) {
Memory::free_static(buf);
}
- if (p_err || GLOBAL_GET("application/run/flush_stdout_on_print")) {
+ if (p_err || _flush_stdout_on_print) {
// Don't always flush when printing stdout to avoid performance
// issues when `print()` is spammed in release builds.
file->flush();
@@ -228,7 +234,7 @@ void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) {
vfprintf(stderr, p_format, p_list);
} else {
vprintf(p_format, p_list);
- if (GLOBAL_GET("application/run/flush_stdout_on_print")) {
+ if (_flush_stdout_on_print) {
// Don't always flush when printing stdout to avoid performance
// issues when `print()` is spammed in release builds.
fflush(stdout);
diff --git a/core/io/logger.h b/core/io/logger.h
index b8e615b436..a12945911c 100644
--- a/core/io/logger.h
+++ b/core/io/logger.h
@@ -41,6 +41,8 @@ class Logger {
protected:
bool should_log(bool p_err);
+ static bool _flush_stdout_on_print;
+
public:
enum ErrorType {
ERR_ERROR,
@@ -49,6 +51,8 @@ public:
ERR_SHADER
};
+ static void set_flush_stdout_on_print(bool value);
+
virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0 = 0;
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 6b550e69c8..94060cfe0b 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -50,7 +50,7 @@ _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_mas
// Do nothing.
} break;
case MultiplayerAPI::RPC_MODE_REMOTE: {
- // Do nothing also. Remote cannot produce a local call.
+ // Do nothing. Remote cannot produce a local call.
} break;
case MultiplayerAPI::RPC_MODE_MASTERSYNC: {
if (is_master) {
@@ -675,7 +675,7 @@ Error MultiplayerAPI::_encode_and_compress_variant(const Variant &p_variant, uin
return err;
}
if (r_buffer) {
- // The first byte is not used by the marshaling, so store the type
+ // The first byte is not used by the marshalling, so store the type
// so we know how to decompress and decode this variant.
r_buffer[0] = p_variant.get_type();
}
@@ -791,7 +791,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
packet_cache.resize(m_amount);
// Encode meta.
- // The meta is composed by a single byte that contains (starting from the least segnificant bit):
+ // The meta is composed by a single byte that contains (starting from the least significant bit):
// - `NetworkCommands` in the first three bits.
// - `NetworkNodeIdCompression` in the next 2 bits.
// - `NetworkNameIdCompression` in the next 1 bit.
@@ -830,7 +830,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
ofs += 4;
}
} else {
- // The targets doesn't know the node yet, so we need to use 32 bits int.
+ // The targets don't know the node yet, so we need to use 32 bits int.
node_id_compression = NETWORK_NODE_ID_COMPRESSION_32;
MAKE_ROOM(ofs + 4);
encode_uint32(psc->id, &(packet_cache.write[ofs]));
diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp
index d8d63d976f..3f46f2706e 100644
--- a/core/io/packet_peer_udp.cpp
+++ b/core/io/packet_peer_udp.cpp
@@ -224,7 +224,7 @@ Error PacketPeerUDP::connect_to_host(const IP_Address &p_host, int p_port) {
// I see no reason why we should get ERR_BUSY (wouldblock/eagain) here.
// This is UDP, so connect is only used to tell the OS to which socket
- // it shuold deliver packets when multiple are bound on the same address/port.
+ // it should deliver packets when multiple are bound on the same address/port.
if (err != OK) {
close();
ERR_FAIL_V_MSG(FAILED, "Unable to connect");
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index db79998a90..8560e2abc7 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -87,7 +87,6 @@ void Resource::set_path(const String &p_path, bool p_take_over) {
ResourceCache::lock.write_unlock();
}
- _change_notify("resource_path");
_resource_path_changed();
}
@@ -105,7 +104,6 @@ int Resource::get_subindex() const {
void Resource::set_name(const String &p_name) {
name = p_name;
- _change_notify("resource_name");
}
String Resource::get_name() const {
@@ -116,20 +114,18 @@ bool Resource::editor_can_reload_from_file() {
return true; //by default yes
}
-void Resource::reload_from_file() {
- String path = get_path();
- if (!path.is_resource_file()) {
- return;
+void Resource::reset_state() {
+}
+Error Resource::copy_from(const Ref<Resource> &p_resource) {
+ ERR_FAIL_COND_V(p_resource.is_null(), ERR_INVALID_PARAMETER);
+ if (get_class() != p_resource->get_class()) {
+ return ERR_INVALID_PARAMETER;
}
- Ref<Resource> s = ResourceLoader::load(ResourceLoader::path_remap(path), get_class(), true);
-
- if (!s.is_valid()) {
- return;
- }
+ reset_state(); //may want to reset state
List<PropertyInfo> pi;
- s->get_property_list(&pi);
+ p_resource->get_property_list(&pi);
for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
@@ -139,8 +135,23 @@ void Resource::reload_from_file() {
continue; //do not change path
}
- set(E->get().name, s->get(E->get().name));
+ set(E->get().name, p_resource->get(E->get().name));
}
+ return OK;
+}
+void Resource::reload_from_file() {
+ String path = get_path();
+ if (!path.is_resource_file()) {
+ return;
+ }
+
+ Ref<Resource> s = ResourceLoader::load(ResourceLoader::path_remap(path), get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE);
+
+ if (!s.is_valid()) {
+ return;
+ }
+
+ copy_from(s);
}
Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource>> &remap_cache) {
diff --git a/core/io/resource.h b/core/io/resource.h
index d0cd6ea3ac..ae18ac0c8a 100644
--- a/core/io/resource.h
+++ b/core/io/resource.h
@@ -90,6 +90,8 @@ public:
static Node *(*_get_local_scene_func)(); //used by editor
virtual bool editor_can_reload_from_file();
+ virtual void reset_state(); //for resources that use variable amount of properties, either via _validate_property or _get_property_list, this function needs to be implemented to correctly clear state
+ virtual Error copy_from(const Ref<Resource> &p_resource);
virtual void reload_from_file();
void register_owner(Object *p_owner);
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index fad58d65fd..c4eb2a20bb 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -313,17 +313,12 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
uint32_t index = f->get_32();
String path = res_path + "::" + itos(index);
- if (use_nocache) {
- if (!internal_index_cache.has(path)) {
- WARN_PRINT(String("Couldn't load resource (no cache): " + path).utf8().get_data());
- }
- r_v = internal_index_cache[path];
+ //always use internal cache for loading internal resources
+ if (!internal_index_cache.has(path)) {
+ WARN_PRINT(String("Couldn't load resource (no cache): " + path).utf8().get_data());
+ r_v = Variant();
} else {
- RES res = ResourceLoader::load(path);
- if (res.is_null()) {
- WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data());
- }
- r_v = res;
+ r_v = internal_index_cache[path];
}
} break;
@@ -645,7 +640,7 @@ Error ResourceLoaderBinary::load() {
}
} else {
- Error err = ResourceLoader::load_threaded_request(path, external_resources[i].type, use_sub_threads, local_path);
+ Error err = ResourceLoader::load_threaded_request(path, external_resources[i].type, use_sub_threads, ResourceFormatLoader::CACHE_MODE_REUSE, local_path);
if (err != OK) {
if (!ResourceLoader::get_abort_on_missing_resources()) {
ResourceLoader::notify_dependency_error(local_path, path, external_resources[i].type);
@@ -675,7 +670,7 @@ Error ResourceLoaderBinary::load() {
path = res_path + "::" + path;
}
- if (!use_nocache) {
+ if (cache_mode == ResourceFormatLoader::CACHE_MODE_REUSE) {
if (ResourceCache::has(path)) {
//already loaded, don't do anything
stage++;
@@ -684,7 +679,7 @@ Error ResourceLoaderBinary::load() {
}
}
} else {
- if (!use_nocache && !ResourceCache::has(res_path)) {
+ if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE && !ResourceCache::has(res_path)) {
path = res_path;
}
}
@@ -695,26 +690,40 @@ Error ResourceLoaderBinary::load() {
String t = get_unicode_string();
- Object *obj = ClassDB::instance(t);
- if (!obj) {
- error = ERR_FILE_CORRUPT;
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource of unrecognized type in file: " + t + ".");
- }
+ RES res;
- Resource *r = Object::cast_to<Resource>(obj);
- if (!r) {
- String obj_class = obj->get_class();
- error = ERR_FILE_CORRUPT;
- memdelete(obj); //bye
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource type in resource field not a resource, type is: " + obj_class + ".");
+ if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(path)) {
+ //use the existing one
+ Resource *r = ResourceCache::get(path);
+ if (r->get_class() == t) {
+ r->reset_state();
+ res = Ref<Resource>(r);
+ }
}
- RES res = RES(r);
+ if (res.is_null()) {
+ //did not replace
- if (path != String()) {
- r->set_path(path);
+ Object *obj = ClassDB::instance(t);
+ if (!obj) {
+ error = ERR_FILE_CORRUPT;
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource of unrecognized type in file: " + t + ".");
+ }
+
+ Resource *r = Object::cast_to<Resource>(obj);
+ if (!r) {
+ String obj_class = obj->get_class();
+ error = ERR_FILE_CORRUPT;
+ memdelete(obj); //bye
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource type in resource field not a resource, type is: " + obj_class + ".");
+ }
+
+ res = RES(r);
+ if (path != String() && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
+ r->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE); //if got here because the resource with same path has different type, replace it
+ }
+ r->set_subindex(subindex);
}
- r->set_subindex(subindex);
if (!main) {
internal_index_cache[path] = res;
@@ -961,7 +970,7 @@ ResourceLoaderBinary::~ResourceLoaderBinary() {
}
}
-RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
}
@@ -972,7 +981,7 @@ RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_origi
ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot open file '" + p_path + "'.");
ResourceLoaderBinary loader;
- loader.use_nocache = p_no_cache;
+ loader.cache_mode = p_cache_mode;
loader.use_sub_threads = p_use_sub_threads;
loader.progress = r_progress;
String path = p_original_path != "" ? p_original_path : p_path;
@@ -1236,7 +1245,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
- return ""; //could not rwead
+ return ""; //could not read
}
ResourceLoaderBinary loader;
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 428725f1d2..3592bbdbc4 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -78,7 +78,7 @@ class ResourceLoaderBinary {
Map<String, String> remaps;
Error error = OK;
- bool use_nocache = false;
+ ResourceFormatLoader::CacheMode cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE;
friend class ResourceFormatLoaderBinary;
@@ -103,7 +103,7 @@ public:
class ResourceFormatLoaderBinary : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp
index d86877ee14..5ca0eb884a 100644
--- a/core/io/resource_importer.cpp
+++ b/core/io/resource_importer.cpp
@@ -116,7 +116,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
return OK;
}
-RES ResourceFormatImporter::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatImporter::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) {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
@@ -128,7 +128,7 @@ RES ResourceFormatImporter::load(const String &p_path, const String &p_original_
return RES();
}
- RES res = ResourceLoader::_load(pat.path, p_path, pat.type, p_no_cache, r_error, p_use_sub_threads, r_progress);
+ RES res = ResourceLoader::_load(pat.path, p_path, pat.type, p_cache_mode, r_error, p_use_sub_threads, r_progress);
#ifdef TOOLS_ENABLED
if (res.is_valid()) {
@@ -352,6 +352,12 @@ void ResourceFormatImporter::get_importers_for_extension(const String &p_extensi
}
}
+void ResourceFormatImporter::get_importers(List<Ref<ResourceImporter>> *r_importers) {
+ for (int i = 0; i < importers.size(); i++) {
+ r_importers->push_back(importers[i]);
+ }
+}
+
Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const String &p_extension) const {
Ref<ResourceImporter> importer;
float priority = 0;
diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h
index d31273e3cb..eeb486073e 100644
--- a/core/io/resource_importer.h
+++ b/core/io/resource_importer.h
@@ -57,7 +57,7 @@ class ResourceFormatImporter : public ResourceFormatLoader {
public:
static ResourceFormatImporter *get_singleton() { return singleton; }
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const;
@@ -82,6 +82,7 @@ public:
Ref<ResourceImporter> get_importer_by_name(const String &p_name) const;
Ref<ResourceImporter> get_importer_by_extension(const String &p_extension) const;
void get_importers_for_extension(const String &p_extension, List<Ref<ResourceImporter>> *r_importers);
+ void get_importers(List<Ref<ResourceImporter>> *r_importers);
bool are_import_settings_valid(const String &p_path) const;
String get_import_settings_hash() const;
@@ -114,6 +115,9 @@ public:
ImportOption() {}
};
+ virtual bool has_advanced_options() const { return false; }
+ virtual void show_advanced_options(const String &p_path) {}
+
virtual int get_preset_count() const { return 0; }
virtual String get_preset_name(int p_idx) const { return String(); }
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index d66511a39f..dcf71bb4a9 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -113,9 +113,9 @@ void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions)
}
}
-RES ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (get_script_instance() && get_script_instance()->has_method("load")) {
- Variant res = get_script_instance()->call("load", p_path, p_original_path, p_use_sub_threads);
+ Variant res = get_script_instance()->call("load", p_path, p_original_path, p_use_sub_threads, p_cache_mode);
if (res.get_type() == Variant::INT) {
if (r_error) {
@@ -164,7 +164,7 @@ Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Map<
void ResourceFormatLoader::_bind_methods() {
{
- MethodInfo info = MethodInfo(Variant::NIL, "load", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "original_path"));
+ MethodInfo info = MethodInfo(Variant::NIL, "load", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "original_path"), PropertyInfo(Variant::BOOL, "use_sub_threads"), PropertyInfo(Variant::INT, "cache_mode"));
info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
ClassDB::add_virtual_method(get_class_static(), info);
}
@@ -174,11 +174,15 @@ void ResourceFormatLoader::_bind_methods() {
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_resource_type", PropertyInfo(Variant::STRING, "path")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo("get_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "add_types")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "rename_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "renames")));
+
+ BIND_ENUM_CONSTANT(CACHE_MODE_IGNORE);
+ BIND_ENUM_CONSTANT(CACHE_MODE_REUSE);
+ BIND_ENUM_CONSTANT(CACHE_MODE_REPLACE);
}
///////////////////////////////////
-RES ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, bool p_no_cache, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress) {
bool found = false;
// Try all loaders and pick the first match for the type hint
@@ -187,7 +191,7 @@ RES ResourceLoader::_load(const String &p_path, const String &p_original_path, c
continue;
}
found = true;
- RES res = loader[i]->load(p_path, p_original_path != String() ? p_original_path : p_path, r_error, p_use_sub_threads, r_progress, p_no_cache);
+ RES res = loader[i]->load(p_path, p_original_path != String() ? p_original_path : p_path, r_error, p_use_sub_threads, r_progress, p_cache_mode);
if (res.is_null()) {
continue;
}
@@ -211,10 +215,10 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
load_task.loader_id = Thread::get_caller_id();
if (load_task.semaphore) {
- //this is an actual thread, so wait for Ok fom semaphore
+ //this is an actual thread, so wait for Ok from semaphore
thread_load_semaphore->wait(); //wait until its ok to start loading
}
- load_task.resource = _load(load_task.remapped_path, load_task.remapped_path != load_task.local_path ? load_task.local_path : String(), load_task.type_hint, false, &load_task.error, load_task.use_sub_threads, &load_task.progress);
+ load_task.resource = _load(load_task.remapped_path, load_task.remapped_path != load_task.local_path ? load_task.local_path : String(), load_task.type_hint, load_task.cache_mode, &load_task.error, load_task.use_sub_threads, &load_task.progress);
load_task.progress = 1.0; //it was fully loaded at this point, so force progress to 1.0
@@ -267,7 +271,7 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
thread_load_mutex->unlock();
}
-Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, const String &p_source_resource) {
+Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, ResourceFormatLoader::CacheMode p_cache_mode, const String &p_source_resource) {
String local_path;
if (p_path.is_rel_path()) {
local_path = "res://" + p_path;
@@ -314,6 +318,7 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String &
load_task.remapped_path = _path_remap(local_path, &load_task.xl_remapped);
load_task.local_path = local_path;
load_task.type_hint = p_type_hint;
+ load_task.cache_mode = p_cache_mode;
load_task.use_sub_threads = p_use_sub_threads;
{ //must check if resource is already loaded before attempting to load it in a thread
@@ -438,7 +443,7 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
ThreadLoadTask &load_task = thread_load_tasks[local_path];
- //semaphore still exists, meaning its still loading, request poll
+ //semaphore still exists, meaning it's still loading, request poll
Semaphore *semaphore = load_task.semaphore;
if (semaphore) {
load_task.poll_requests++;
@@ -447,7 +452,7 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
// As we got a semaphore, this means we are going to have to wait
// until the sub-resource is done loading
//
- // As this thread will become 'blocked' we should "echange" its
+ // As this thread will become 'blocked' we should "exchange" its
// active status with a waiting one, to ensure load continues.
//
// This ensures loading is never blocked and that is also within
@@ -501,7 +506,7 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
return resource;
}
-RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) {
+RES ResourceLoader::load(const String &p_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
@@ -513,7 +518,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p
local_path = ProjectSettings::get_singleton()->localize_path(p_path);
}
- if (!p_no_cache) {
+ if (p_cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
thread_load_mutex->lock();
//Is it already being loaded? poll until done
@@ -561,6 +566,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p
load_task.local_path = local_path;
load_task.remapped_path = _path_remap(local_path, &load_task.xl_remapped);
load_task.type_hint = p_type_hint;
+ load_task.cache_mode = p_cache_mode; //ignore
load_task.loader_id = Thread::get_caller_id();
thread_load_tasks[local_path] = load_task;
@@ -581,7 +587,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p
print_verbose("Loading resource: " + path);
float p;
- RES res = _load(path, local_path, p_type_hint, p_no_cache, r_error, false, &p);
+ RES res = _load(path, local_path, p_type_hint, p_cache_mode, r_error, false, &p);
if (res.is_null()) {
print_verbose("Failed loading resource: " + path);
@@ -966,11 +972,11 @@ void ResourceLoader::reload_translation_remaps() {
}
void ResourceLoader::load_translation_remaps() {
- if (!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) {
+ if (!ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) {
return;
}
- Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
+ Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps");
List<Variant> keys;
remaps.get_key_list(&keys);
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index dbf6be46c5..914d988caa 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -38,11 +38,18 @@
class ResourceFormatLoader : public Reference {
GDCLASS(ResourceFormatLoader, Reference);
+public:
+ enum CacheMode {
+ CACHE_MODE_IGNORE, //resource and subresources do not use path cache, no path is set into resource.
+ CACHE_MODE_REUSE, //resource and subresources use patch cache, reuse existing loaded resources instead of loading from disk when available
+ CACHE_MODE_REPLACE, //resource and and subresource use path cache, but replace existing loaded resources when available with information from disk
+ };
+
protected:
static void _bind_methods();
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual bool exists(const String &p_path) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
@@ -59,6 +66,8 @@ public:
virtual ~ResourceFormatLoader() {}
};
+VARIANT_ENUM_CAST(ResourceFormatLoader::CacheMode)
+
typedef void (*ResourceLoadErrorNotify)(void *p_ud, const String &p_text);
typedef void (*DependencyErrorNotify)(void *p_ud, const String &p_loading, const String &p_which, const String &p_type);
@@ -99,7 +108,7 @@ private:
friend class ResourceFormatImporter;
friend class ResourceInteractiveLoader;
//internal load function
- static RES _load(const String &p_path, const String &p_original_path, const String &p_type_hint, bool p_no_cache, Error *r_error, bool p_use_sub_threads, float *r_progress);
+ static RES _load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress);
static ResourceLoadedCallback _loaded_callback;
@@ -114,6 +123,7 @@ private:
String type_hint;
float progress = 0.0;
ThreadLoadStatus status = THREAD_LOAD_IN_PROGRESS;
+ ResourceFormatLoader::CacheMode cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE;
Error error = OK;
RES resource;
bool xl_remapped = false;
@@ -136,11 +146,11 @@ private:
static float _dependency_get_progress(const String &p_path);
public:
- static Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, const String &p_source_resource = String());
+ static Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, ResourceFormatLoader::CacheMode p_cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE, const String &p_source_resource = String());
static ThreadLoadStatus load_threaded_get_status(const String &p_path, float *r_progress = nullptr);
static RES load_threaded_get(const String &p_path, Error *r_error = nullptr);
- static RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = nullptr);
+ static RES load(const String &p_path, const String &p_type_hint = "", ResourceFormatLoader::CacheMode p_cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE, Error *r_error = nullptr);
static bool exists(const String &p_path, const String &p_type_hint = "");
static void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions);
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index ce2c3eb1cd..9adf912224 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -194,7 +194,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
l = l.substr(1, l.length());
// Find final quote, ignoring escaped ones (\").
// The escape_next logic is necessary to properly parse things like \\"
- // where the blackslash is the one being escaped, not the quote.
+ // where the backslash is the one being escaped, not the quote.
int end_pos = -1;
bool escape_next = false;
for (int i = 0; i < l.length(); i++) {
@@ -277,7 +277,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
return translation;
}
-RES TranslationLoaderPO::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES TranslationLoaderPO::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h
index a524972588..36d33fcac3 100644
--- a/core/io/translation_loader_po.h
+++ b/core/io/translation_loader_po.h
@@ -38,7 +38,7 @@
class TranslationLoaderPO : public ResourceFormatLoader {
public:
static RES load_translation(FileAccess *f, Error *r_error = nullptr);
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 905be6089d..d5eb32513b 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -36,63 +36,6 @@
VARIANT_ENUM_CAST(XMLParser::NodeType);
-static bool _equalsn(const char32_t *str1, const char32_t *str2, int len) {
- int i;
- for (i = 0; i < len && str1[i] && str2[i]; ++i) {
- if (str1[i] != str2[i]) {
- return false;
- }
- }
-
- // if one (or both) of the strings was smaller then they
- // are only equal if they have the same length
- return (i == len) || (str1[i] == 0 && str2[i] == 0);
-}
-
-String XMLParser::_replace_special_characters(const String &origstr) {
- int pos = origstr.find("&");
- int oldPos = 0;
-
- if (pos == -1) {
- return origstr;
- }
-
- String newstr;
-
- while (pos != -1 && pos < origstr.length() - 2) {
- // check if it is one of the special characters
-
- int specialChar = -1;
- for (int i = 0; i < (int)special_characters.size(); ++i) {
- const char32_t *p = &origstr[pos] + 1;
-
- if (_equalsn(&special_characters[i][1], p, special_characters[i].length() - 1)) {
- specialChar = i;
- break;
- }
- }
-
- if (specialChar != -1) {
- newstr += (origstr.substr(oldPos, pos - oldPos));
- newstr += (special_characters[specialChar][0]);
- pos += special_characters[specialChar].length();
- } else {
- newstr += (origstr.substr(oldPos, pos - oldPos + 1));
- pos += 1;
- }
-
- // find next &
- oldPos = pos;
- pos = origstr.find("&", pos);
- }
-
- if (oldPos < origstr.length() - 1) {
- newstr += (origstr.substr(oldPos, origstr.length() - oldPos));
- }
-
- return newstr;
-}
-
static inline bool _is_white_space(char c) {
return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
}
@@ -116,7 +59,7 @@ bool XMLParser::_set_text(char *start, char *end) {
// set current text to the parsed text, and replace xml special characters
String s = String::utf8(start, (int)(end - start));
- node_name = _replace_special_characters(s);
+ node_name = s.xml_unescape();
// current XML node type is text
node_type = NODE_TEXT;
@@ -292,7 +235,7 @@ void XMLParser::_parse_opening_xml_element() {
String s = String::utf8(attributeValueBegin,
(int)(attributeValueEnd - attributeValueBegin));
- attr.value = _replace_special_characters(s);
+ attr.value = s.xml_unescape();
attributes.push_back(attr);
} else {
// tag is closed directly
@@ -401,7 +344,7 @@ void XMLParser::_bind_methods() {
}
Error XMLParser::read() {
- // if not end reached, parse the node
+ // if end not reached, parse the node
if (P && (P - data) < (int64_t)length - 1 && *P != 0) {
_parse_current_node();
return OK;
@@ -555,11 +498,6 @@ int XMLParser::get_current_line() const {
}
XMLParser::XMLParser() {
- special_characters.push_back("&amp;");
- special_characters.push_back("<lt;");
- special_characters.push_back(">gt;");
- special_characters.push_back("\"quot;");
- special_characters.push_back("'apos;");
}
XMLParser::~XMLParser() {
diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h
index 01af6a90ad..847edf958d 100644
--- a/core/io/xml_parser.h
+++ b/core/io/xml_parser.h
@@ -68,8 +68,6 @@ private:
char *data = nullptr;
char *P = nullptr;
uint64_t length = 0;
- void unescape(String &p_str);
- Vector<String> special_characters;
String node_name;
bool node_empty = false;
NodeType node_type = NODE_NONE;
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index cbdd8a8c9f..cc2b7c6611 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -132,7 +132,7 @@ bool Basis::is_symmetric() const {
Basis Basis::diagonalize() {
//NOTE: only implemented for symmetric matrices
-//with the Jacobi iterative method method
+//with the Jacobi iterative method
#ifdef MATH_CHECKS
ERR_FAIL_COND_V(!is_symmetric(), Basis());
#endif
@@ -317,7 +317,7 @@ Vector3 Basis::rotref_posscale_decomposition(Basis &rotref) const {
// Multiplies the matrix from left by the rotation matrix: M -> R.M
// Note that this does *not* rotate the matrix itself.
//
-// The main use of Basis is as Transform.basis, which is used a the transformation matrix
+// The main use of Basis is as Transform.basis, which is used by the transformation matrix
// of 3D object. Rotate here refers to rotation of the object (which is R * (*this)),
// not the matrix itself (which is R * (*this) * R.transposed()).
Basis Basis::rotated(const Vector3 &p_axis, real_t p_phi) const {
@@ -881,7 +881,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
if ((Math::abs(elements[1][0] - elements[0][1]) < epsilon) && (Math::abs(elements[2][0] - elements[0][2]) < epsilon) && (Math::abs(elements[2][1] - elements[1][2]) < epsilon)) {
// singularity found
// first check for identity matrix which must have +1 for all terms
- // in leading diagonaland zero in other terms
+ // in leading diagonal and zero in other terms
if ((Math::abs(elements[1][0] + elements[0][1]) < epsilon2) && (Math::abs(elements[2][0] + elements[0][2]) < epsilon2) && (Math::abs(elements[2][1] + elements[1][2]) < epsilon2) && (Math::abs(elements[0][0] + elements[1][1] + elements[2][2] - 3) < epsilon2)) {
// this singularity is identity matrix so angle = 0
r_axis = Vector3(0, 1, 0);
diff --git a/core/math/color.cpp b/core/math/color.cpp
index e1b45cac9c..8affb07e8c 100644
--- a/core/math/color.cpp
+++ b/core/math/color.cpp
@@ -452,56 +452,9 @@ String Color::to_html(bool p_alpha) const {
}
Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
- p_h = Math::fmod(p_h * 360.0f, 360.0f);
- if (p_h < 0.0) {
- p_h += 360.0f;
- }
-
- const float h_ = p_h / 60.0f;
- const float c = p_v * p_s;
- const float x = c * (1.0f - Math::abs(Math::fmod(h_, 2.0f) - 1.0f));
- float r, g, b;
-
- switch ((int)h_) {
- case 0: {
- r = c;
- g = x;
- b = 0;
- } break;
- case 1: {
- r = x;
- g = c;
- b = 0;
- } break;
- case 2: {
- r = 0;
- g = c;
- b = x;
- } break;
- case 3: {
- r = 0;
- g = x;
- b = c;
- } break;
- case 4: {
- r = x;
- g = 0;
- b = c;
- } break;
- case 5: {
- r = c;
- g = 0;
- b = x;
- } break;
- default: {
- r = 0;
- g = 0;
- b = 0;
- } break;
- }
-
- const float m = p_v - c;
- return Color(m + r, m + g, m + b, p_a);
+ Color c;
+ c.set_hsv(p_h, p_s, p_v, p_a);
+ return c;
}
Color::operator String() const {
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 636ea601c7..f7ac44d321 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -978,7 +978,7 @@ Expression::ENode *Expression::_parse_expression() {
}
}
- /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */
+ /* Reduce the set of expressions and place them in an operator tree, respecting precedence */
while (expression.size() > 1) {
int next_op = -1;
diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp
index 783750b9e6..feb1fb2fb8 100644
--- a/core/math/geometry_2d.cpp
+++ b/core/math/geometry_2d.cpp
@@ -87,13 +87,17 @@ struct _AtlasWorkRectResult {
void Geometry2D::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size) {
// Super simple, almost brute force scanline stacking fitter.
// It's pretty basic for now, but it tries to make sure that the aspect ratio of the
- // resulting atlas is somehow square. This is necessary because video cards have limits.
- // On texture size (usually 2048 or 4096), so the more square a texture, the more chances.
- // It will work in every hardware.
+ // resulting atlas is somehow square. This is necessary because video cards have limits
+ // on texture size (usually 2048 or 4096), so the squarer a texture, the more the chances
+ // that it will work in every hardware.
// For example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a
// 256x8192 atlas (won't work anywhere).
ERR_FAIL_COND(p_rects.size() == 0);
+ for (int i = 0; i < p_rects.size(); i++) {
+ ERR_FAIL_COND(p_rects[i].width <= 0);
+ ERR_FAIL_COND(p_rects[i].height <= 0);
+ }
Vector<_AtlasWorkRect> wrects;
wrects.resize(p_rects.size());
diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp
index a4a7463bfd..6628b760e0 100644
--- a/core/math/geometry_3d.cpp
+++ b/core/math/geometry_3d.cpp
@@ -775,6 +775,8 @@ Vector<Plane> Geometry3D::build_box_planes(const Vector3 &p_extents) {
}
Vector<Plane> Geometry3D::build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis) {
+ ERR_FAIL_INDEX_V(p_axis, 3, Vector<Plane>());
+
Vector<Plane> planes;
const double sides_step = Math_TAU / p_sides;
@@ -796,6 +798,8 @@ Vector<Plane> Geometry3D::build_cylinder_planes(real_t p_radius, real_t p_height
}
Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis) {
+ ERR_FAIL_INDEX_V(p_axis, 3, Vector<Plane>());
+
Vector<Plane> planes;
Vector3 axis;
@@ -827,6 +831,8 @@ Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p
}
Vector<Plane> Geometry3D::build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis) {
+ ERR_FAIL_INDEX_V(p_axis, 3, Vector<Plane>());
+
Vector<Plane> planes;
Vector3 axis;
diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h
index 825817af5e..4ef9b4dbe6 100644
--- a/core/math/geometry_3d.h
+++ b/core/math/geometry_3d.h
@@ -252,27 +252,34 @@ public:
return true;
}
- static inline bool segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, real_t p_height, real_t p_radius, Vector3 *r_res = nullptr, Vector3 *r_norm = nullptr) {
+ static inline bool segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, real_t p_height, real_t p_radius, Vector3 *r_res = nullptr, Vector3 *r_norm = nullptr, int p_cylinder_axis = 2) {
Vector3 rel = (p_to - p_from);
real_t rel_l = rel.length();
if (rel_l < CMP_EPSILON) {
return false; // Both points are the same.
}
+ ERR_FAIL_COND_V(p_cylinder_axis < 0, false);
+ ERR_FAIL_COND_V(p_cylinder_axis > 2, false);
+ Vector3 cylinder_axis;
+ cylinder_axis[p_cylinder_axis] = 1.0;
+
// First check if they are parallel.
Vector3 normal = (rel / rel_l);
- Vector3 crs = normal.cross(Vector3(0, 0, 1));
+ Vector3 crs = normal.cross(cylinder_axis);
real_t crs_l = crs.length();
- Vector3 z_dir;
+ Vector3 axis_dir;
if (crs_l < CMP_EPSILON) {
- z_dir = Vector3(1, 0, 0); // Any x/y vector OK.
+ Vector3 side_axis;
+ side_axis[(p_cylinder_axis + 1) % 3] = 1.0; // Any side axis OK.
+ axis_dir = side_axis;
} else {
- z_dir = crs / crs_l;
+ axis_dir = crs / crs_l;
}
- real_t dist = z_dir.dot(p_from);
+ real_t dist = axis_dir.dot(p_from);
if (dist >= p_radius) {
return false; // Too far away.
@@ -285,10 +292,10 @@ public:
}
Size2 size(Math::sqrt(w2), p_height * 0.5);
- Vector3 x_dir = z_dir.cross(Vector3(0, 0, 1)).normalized();
+ Vector3 side_dir = axis_dir.cross(cylinder_axis).normalized();
- Vector2 from2D(x_dir.dot(p_from), p_from.z);
- Vector2 to2D(x_dir.dot(p_to), p_to.z);
+ Vector2 from2D(side_dir.dot(p_from), p_from[p_cylinder_axis]);
+ Vector2 to2D(side_dir.dot(p_to), p_to[p_cylinder_axis]);
real_t min = 0, max = 1;
@@ -335,10 +342,12 @@ public:
Vector3 res_normal = result;
if (axis == 0) {
- res_normal.z = 0;
+ res_normal[p_cylinder_axis] = 0;
} else {
- res_normal.x = 0;
- res_normal.y = 0;
+ int axis_side = (p_cylinder_axis + 1) % 3;
+ res_normal[axis_side] = 0;
+ axis_side = (axis_side + 1) % 3;
+ res_normal[axis_side] = 0;
}
res_normal.normalize();
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index ad28967d7a..fe18cc3d41 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -268,7 +268,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
for (Map<Edge, FaceConnect>::Element *E = lit_edges.front(); E; E = E->next()) {
FaceConnect &fc = E->get();
if (fc.left && fc.right) {
- continue; //edge is uninteresting, not on horizont
+ continue; //edge is uninteresting, not on horizon
}
//create new face!
diff --git a/core/math/transform.h b/core/math/transform.h
index 60da6f5593..1c05dbe554 100644
--- a/core/math/transform.h
+++ b/core/math/transform.h
@@ -51,8 +51,8 @@ public:
void rotate(const Vector3 &p_axis, real_t p_phi);
void rotate_basis(const Vector3 &p_axis, real_t p_phi);
- void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up);
- Transform looking_at(const Vector3 &p_target, const Vector3 &p_up) const;
+ void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
+ Transform looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)) const;
void scale(const Vector3 &p_scale);
Transform scaled(const Vector3 &p_scale) const;
diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp
index 0047c0705d..fa1588dbc5 100644
--- a/core/math/triangulate.cpp
+++ b/core/math/triangulate.cpp
@@ -97,7 +97,7 @@ bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, in
// It can happen that the triangulation ends up with three aligned vertices to deal with.
// In this scenario, making the check below strict may reject the possibility of
- // forming a last triangle with these aligned vertices, preventing the triangulatiom
+ // forming a last triangle with these aligned vertices, preventing the triangulation
// from completing.
// To avoid that we allow zero-area triangles if all else failed.
float threshold = relaxed ? -CMP_EPSILON : CMP_EPSILON;
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 6b4ff3f9a8..377581bb45 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -110,6 +110,7 @@ struct Vector3 {
_FORCE_INLINE_ Vector3 project(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t angle_to(const Vector3 &p_to) const;
+ _FORCE_INLINE_ real_t signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const;
_FORCE_INLINE_ Vector3 direction_to(const Vector3 &p_to) const;
_FORCE_INLINE_ Vector3 slide(const Vector3 &p_normal) const;
@@ -230,6 +231,13 @@ real_t Vector3::angle_to(const Vector3 &p_to) const {
return Math::atan2(cross(p_to).length(), dot(p_to));
}
+real_t Vector3::signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const {
+ Vector3 cross_to = cross(p_to);
+ real_t unsigned_angle = Math::atan2(cross_to.length(), dot(p_to));
+ real_t sign = cross_to.dot(p_axis);
+ return (sign < 0) ? -unsigned_angle : unsigned_angle;
+}
+
Vector3 Vector3::direction_to(const Vector3 &p_to) const {
Vector3 ret(p_to.x - x, p_to.y - y, p_to.z - z);
ret.normalize();
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index 7cf4f8d4e8..7030ae201b 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -42,6 +42,7 @@ enum MethodFlags {
METHOD_FLAG_VIRTUAL = 32,
METHOD_FLAG_FROM_SCRIPT = 64,
METHOD_FLAG_VARARG = 128,
+ METHOD_FLAG_STATIC = 256,
METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL,
};
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 171bc4dc2c..413f917518 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -596,7 +596,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
_get_property_listv(p_list, p_reversed);
- if (!is_class("Script")) { // can still be set, but this is for userfriendlyness
+ if (!is_class("Script")) { // can still be set, but this is for user-friendliness
p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
}
if (!metadata.is_empty()) {
@@ -808,21 +808,6 @@ String Object::to_string() {
return "[" + get_class() + ":" + itos(get_instance_id()) + "]";
}
-void Object::_changed_callback(Object *p_changed, const char *p_prop) {
-}
-
-void Object::add_change_receptor(Object *p_receptor) {
- change_receptors.insert(p_receptor);
-}
-
-void Object::remove_change_receptor(Object *p_receptor) {
- change_receptors.erase(p_receptor);
-}
-
-void Object::property_list_changed_notify() {
- _change_notify();
-}
-
void Object::set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance) {
//this function is not meant to be used in any of these ways
ERR_FAIL_COND(p_script.is_null());
@@ -856,7 +841,7 @@ void Object::set_script(const Variant &p_script) {
}
}
- _change_notify(); //scripts may add variables, so refresh is desired
+ notify_property_list_changed(); //scripts may add variables, so refresh is desired
emit_signal(CoreStringNames::get_singleton()->script_changed);
}
@@ -1496,6 +1481,10 @@ void Object::clear_internal_resource_paths() {
}
}
+void Object::notify_property_list_changed() {
+ emit_signal(CoreStringNames::get_singleton()->property_list_changed);
+}
+
void Object::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_class"), &Object::get_class);
ClassDB::bind_method(D_METHOD("is_class", "class"), &Object::is_class);
@@ -1562,7 +1551,7 @@ void Object::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_block_signals", "enable"), &Object::set_block_signals);
ClassDB::bind_method(D_METHOD("is_blocking_signals"), &Object::is_blocking_signals);
- ClassDB::bind_method(D_METHOD("property_list_changed_notify"), &Object::property_list_changed_notify);
+ ClassDB::bind_method(D_METHOD("notify_property_list_changed"), &Object::notify_property_list_changed);
ClassDB::bind_method(D_METHOD("set_message_translation", "enable"), &Object::set_message_translation);
ClassDB::bind_method(D_METHOD("can_translate_messages"), &Object::can_translate_messages);
@@ -1574,6 +1563,7 @@ void Object::_bind_methods() {
ClassDB::add_virtual_method("Object", MethodInfo("free"), false);
ADD_SIGNAL(MethodInfo("script_changed"));
+ ADD_SIGNAL(MethodInfo("property_list_changed"));
BIND_VMETHOD(MethodInfo("_notification", PropertyInfo(Variant::INT, "what")));
BIND_VMETHOD(MethodInfo(Variant::BOOL, "_set", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value")));
@@ -1681,7 +1671,7 @@ Variant::Type Object::get_static_property_type_indexed(const Vector<StringName>
for (int i = 1; i < p_path.size(); i++) {
if (check.get_type() == Variant::OBJECT || check.get_type() == Variant::DICTIONARY || check.get_type() == Variant::ARRAY) {
- // We cannot be sure about the type of properties this types can have
+ // We cannot be sure about the type of properties this type can have
if (r_valid) {
*r_valid = false;
}
@@ -1729,15 +1719,15 @@ void *Object::get_script_instance_binding(int p_script_language_index) {
ERR_FAIL_INDEX_V(p_script_language_index, MAX_SCRIPT_INSTANCE_BINDINGS, nullptr);
#endif
- //it's up to the script language to make this thread safe, if the function is called twice due to threads being out of syncro
+ //it's up to the script language to make this thread safe, if the function is called twice due to threads being out of sync
//just return the same pointer.
//if you want to put a big lock in the entire function and keep allocated pointers in a map or something, feel free to do it
- //as it should not really affect performance much (won't be called too often), as in far most caes the condition below will be false afterwards
+ //as it should not really affect performance much (won't be called too often), as in far most cases the condition below will be false afterwards
if (!_script_instance_bindings[p_script_language_index]) {
void *script_data = ScriptServer::get_language(p_script_language_index)->alloc_instance_binding_data(this);
if (script_data) {
- atomic_increment(&instance_binding_count);
+ instance_binding_count.increment();
_script_instance_bindings[p_script_language_index] = script_data;
}
}
diff --git a/core/object/object.h b/core/object/object.h
index 7e460462cf..448a33d3bc 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -37,6 +37,7 @@
#include "core/templates/hash_map.h"
#include "core/templates/list.h"
#include "core/templates/map.h"
+#include "core/templates/safe_refcount.h"
#include "core/templates/set.h"
#include "core/templates/vmap.h"
#include "core/variant/callable_bind.h"
@@ -65,8 +66,10 @@ enum PropertyHint {
PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags)
PROPERTY_HINT_LAYERS_2D_RENDER,
PROPERTY_HINT_LAYERS_2D_PHYSICS,
+ PROPERTY_HINT_LAYERS_2D_NAVIGATION,
PROPERTY_HINT_LAYERS_3D_RENDER,
PROPERTY_HINT_LAYERS_3D_PHYSICS,
+ PROPERTY_HINT_LAYERS_3D_NAVIGATION,
PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
PROPERTY_HINT_DIR, ///< a directory path must be passed
PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
@@ -125,6 +128,7 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 25, // Used in inspector to increment property when keyed in animation player
PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 26, // when loading, the resource for this property can be set at the end of loading
PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 27, // For Object properties, instantiate them when creating in editor.
+ PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 28, //for project or editor settings, show when basic settings are selected
PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK,
PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED,
@@ -454,7 +458,6 @@ private:
#endif
bool _block_signals = false;
int _predelete_ok = 0;
- Set<Object *> change_receptors;
ObjectID _instance_id;
bool _predelete();
void _postinitialize();
@@ -486,7 +489,7 @@ private:
friend class Reference;
bool type_is_reference = false;
- uint32_t instance_binding_count = 0;
+ SafeNumeric<uint32_t> instance_binding_count;
void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
Object(bool p_reference);
@@ -523,9 +526,6 @@ protected:
static void get_valid_parents_static(List<String> *p_parents);
static void _get_valid_parents_static(List<String> *p_parents);
- void property_list_changed_notify();
- virtual void _changed_callback(Object *p_changed, const char *p_prop);
-
//Variant _call_bind(const StringName& p_name, const Variant& p_arg1 = Variant(), const Variant& p_arg2 = Variant(), const Variant& p_arg3 = Variant(), const Variant& p_arg4 = Variant());
//void _call_deferred_bind(const StringName& p_name, const Variant& p_arg1 = Variant(), const Variant& p_arg2 = Variant(), const Variant& p_arg3 = Variant(), const Variant& p_arg4 = Variant());
@@ -555,16 +555,8 @@ public: //should be protected, but bug in clang++
_FORCE_INLINE_ static void register_custom_data_to_otdb() {}
public:
-#ifdef TOOLS_ENABLED
- _FORCE_INLINE_ void _change_notify(const char *p_property = "") {
- _edited = true;
- for (Set<Object *>::Element *E = change_receptors.front(); E; E = E->next()) {
- ((Object *)(E->get()))->_changed_callback(this, p_property);
- }
- }
-#else
- _FORCE_INLINE_ void _change_notify(const char *p_what = "") {}
-#endif
+ void notify_property_list_changed();
+
static void *get_class_ptr_static() {
static int ptr;
return &ptr;
@@ -574,10 +566,6 @@ public:
_FORCE_INLINE_ ObjectID get_instance_id() const { return _instance_id; }
- // this is used for editors
- void add_change_receptor(Object *p_receptor);
- void remove_change_receptor(Object *p_receptor);
-
template <class T>
static T *cast_to(Object *p_object) {
#ifndef NO_SAFE_CAST
diff --git a/core/object/reference.cpp b/core/object/reference.cpp
index 71a52a9ba5..22e4e8a336 100644
--- a/core/object/reference.cpp
+++ b/core/object/reference.cpp
@@ -62,7 +62,7 @@ bool Reference::reference() {
if (get_script_instance()) {
get_script_instance()->refcount_incremented();
}
- if (instance_binding_count > 0 && !ScriptServer::are_languages_finished()) {
+ if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) {
for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
if (_script_instance_bindings[i]) {
ScriptServer::get_language(i)->refcount_incremented_instance_binding(this);
@@ -83,7 +83,7 @@ bool Reference::unreference() {
bool script_ret = get_script_instance()->refcount_decremented();
die = die && script_ret;
}
- if (instance_binding_count > 0 && !ScriptServer::are_languages_finished()) {
+ if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) {
for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
if (_script_instance_bindings[i]) {
bool script_ret = ScriptServer::get_language(i)->refcount_decremented_instance_binding(this);
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index c3f109a147..42fb0a0caf 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -275,6 +275,14 @@ void ScriptServer::save_global_classes() {
gcarr.push_back(d);
}
+ Array old;
+ if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) {
+ old = ProjectSettings::get_singleton()->get("_global_script_classes");
+ }
+ if ((!old.is_empty() || gcarr.is_empty()) && gcarr.hash() == old.hash()) {
+ return;
+ }
+
if (gcarr.is_empty()) {
if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) {
ProjectSettings::get_singleton()->clear("_global_script_classes");
@@ -515,7 +523,7 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c
}
if (owner && owner->get_script_instance() == this) {
- owner->_change_notify();
+ owner->notify_property_list_changed();
}
//change notify
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index 3b1165b8f6..e8735e335c 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -532,7 +532,7 @@ void UndoRedo::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_history_count"), &UndoRedo::get_history_count);
ClassDB::bind_method(D_METHOD("get_current_action"), &UndoRedo::get_current_action);
- ClassDB::bind_method(D_METHOD("get_action_name"), &UndoRedo::get_action_name);
+ ClassDB::bind_method(D_METHOD("get_action_name", "id"), &UndoRedo::get_action_name);
ClassDB::bind_method(D_METHOD("clear_history", "increase_version"), &UndoRedo::clear_history, DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_current_action_name"), &UndoRedo::get_current_action_name);
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index fb9da9fbed..b7c3a17ba9 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -170,7 +170,7 @@ Error DirAccess::make_dir_recursive(String p_dir) {
curpath = curpath.plus_file(subdirs[i]);
Error err = make_dir(curpath);
if (err != OK && err != ERR_ALREADY_EXISTS) {
- ERR_FAIL_V(err);
+ ERR_FAIL_V_MSG(err, "Could not create directory: " + curpath);
}
}
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 5a3df88619..ad234c2d49 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -368,6 +368,8 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
}
int FileAccess::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
int i = 0;
for (i = 0; i < p_length && !eof_reached(); i++) {
p_dst[i] = get_8();
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index 3ef70e786f..f6fe5fc070 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -45,7 +45,7 @@ enum {
SPKEY = (1 << 24)
};
-enum KeyList {
+enum Key {
/* CURSOR/FUNCTION/BROWSER/MULTIMEDIA/MISC KEYS */
KEY_ESCAPE = SPKEY | 0x01,
KEY_TAB = SPKEY | 0x02,
diff --git a/core/os/memory.cpp b/core/os/memory.cpp
index 14808c2ce6..5910cb0e7b 100644
--- a/core/os/memory.cpp
+++ b/core/os/memory.cpp
@@ -60,11 +60,11 @@ void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_d
#endif
#ifdef DEBUG_ENABLED
-uint64_t Memory::mem_usage = 0;
-uint64_t Memory::max_usage = 0;
+SafeNumeric<uint64_t> Memory::mem_usage;
+SafeNumeric<uint64_t> Memory::max_usage;
#endif
-uint64_t Memory::alloc_count = 0;
+SafeNumeric<uint64_t> Memory::alloc_count;
void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
#ifdef DEBUG_ENABLED
@@ -77,7 +77,7 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
ERR_FAIL_COND_V(!mem, nullptr);
- atomic_increment(&alloc_count);
+ alloc_count.increment();
if (prepad) {
uint64_t *s = (uint64_t *)mem;
@@ -86,8 +86,8 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
uint8_t *s8 = (uint8_t *)mem;
#ifdef DEBUG_ENABLED
- atomic_add(&mem_usage, p_bytes);
- atomic_exchange_if_greater(&max_usage, mem_usage);
+ uint64_t new_mem_usage = mem_usage.add(p_bytes);
+ max_usage.exchange_if_greater(new_mem_usage);
#endif
return s8 + PAD_ALIGN;
} else {
@@ -114,10 +114,10 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
#ifdef DEBUG_ENABLED
if (p_bytes > *s) {
- atomic_add(&mem_usage, p_bytes - *s);
- atomic_exchange_if_greater(&max_usage, mem_usage);
+ uint64_t new_mem_usage = mem_usage.add(p_bytes - *s);
+ max_usage.exchange_if_greater(new_mem_usage);
} else {
- atomic_sub(&mem_usage, *s - p_bytes);
+ mem_usage.sub(*s - p_bytes);
}
#endif
@@ -156,14 +156,14 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) {
bool prepad = p_pad_align;
#endif
- atomic_decrement(&alloc_count);
+ alloc_count.decrement();
if (prepad) {
mem -= PAD_ALIGN;
#ifdef DEBUG_ENABLED
uint64_t *s = (uint64_t *)mem;
- atomic_sub(&mem_usage, *s);
+ mem_usage.sub(*s);
#endif
free(mem);
@@ -178,7 +178,7 @@ uint64_t Memory::get_mem_available() {
uint64_t Memory::get_mem_usage() {
#ifdef DEBUG_ENABLED
- return mem_usage;
+ return mem_usage.get();
#else
return 0;
#endif
@@ -186,7 +186,7 @@ uint64_t Memory::get_mem_usage() {
uint64_t Memory::get_mem_max_usage() {
#ifdef DEBUG_ENABLED
- return max_usage;
+ return max_usage.get();
#else
return 0;
#endif
diff --git a/core/os/memory.h b/core/os/memory.h
index c2ae3f4ae7..10e678103d 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -43,11 +43,11 @@
class Memory {
Memory();
#ifdef DEBUG_ENABLED
- static uint64_t mem_usage;
- static uint64_t max_usage;
+ static SafeNumeric<uint64_t> mem_usage;
+ static SafeNumeric<uint64_t> max_usage;
#endif
- static uint64_t alloc_count;
+ static SafeNumeric<uint64_t> alloc_count;
public:
static void *alloc_static(size_t p_bytes, bool p_pad_align = false);
diff --git a/core/os/os.h b/core/os/os.h
index e02ce7d5ec..e41d788e12 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -40,6 +40,7 @@
#include "core/templates/vector.h"
#include <stdarg.h>
+#include <stdlib.h>
class OS {
static OS *singleton;
@@ -53,7 +54,7 @@ class OS {
bool _debug_stdout = false;
String _local_clipboard;
bool _no_window = false;
- int _exit_code = 0;
+ int _exit_code = EXIT_FAILURE; // unexpected exit is marked as failure
int _orientation;
bool _allow_hidpi = false;
bool _allow_layered = false;
@@ -149,11 +150,6 @@ public:
bool is_layered_allowed() const { return _allow_layered; }
bool is_hidpi_allowed() const { return _allow_hidpi; }
- virtual int get_tablet_driver_count() const { return 0; };
- virtual String get_tablet_driver_name(int p_driver) const { return ""; };
- virtual String get_current_tablet_driver() const { return ""; };
- virtual void set_current_tablet_driver(const String &p_driver){};
-
void ensure_user_data_dir();
virtual MainLoop *get_main_loop() const = 0;
diff --git a/core/os/pool_allocator.cpp b/core/os/pool_allocator.cpp
index b538ca0c96..9be3a62e2f 100644
--- a/core/os/pool_allocator.cpp
+++ b/core/os/pool_allocator.cpp
@@ -136,7 +136,7 @@ void PoolAllocator::compact_up(int p_from) {
for (int i = entry_count - 1; i >= p_from; i--) {
Entry &entry = entry_array[entry_indices[i]];
- /* determine hole size to nextious entry */
+ /* determine hole size for next entry */
int hole_size = next_entry_end_pos - (entry.pos + aligned(entry.len));
diff --git a/core/os/thread.cpp b/core/os/thread.cpp
index 936e5d5500..73e31bdb3d 100644
--- a/core/os/thread.cpp
+++ b/core/os/thread.cpp
@@ -34,14 +34,20 @@
#if !defined(NO_THREADS)
+#include "core/templates/safe_refcount.h"
+
Error (*Thread::set_name_func)(const String &) = nullptr;
void (*Thread::set_priority_func)(Thread::Priority) = nullptr;
void (*Thread::init_func)() = nullptr;
void (*Thread::term_func)() = nullptr;
-Thread::ID Thread::main_thread_id = 1;
-Thread::ID Thread::last_thread_id = 1;
-thread_local Thread::ID Thread::caller_id = 1;
+uint64_t Thread::_thread_id_hash(const std::thread::id &p_t) {
+ static std::hash<std::thread::id> hasher;
+ return hasher(p_t);
+}
+
+Thread::ID Thread::main_thread_id = _thread_id_hash(std::this_thread::get_id());
+thread_local Thread::ID Thread::caller_id = 0;
void Thread::_set_platform_funcs(
Error (*p_set_name_func)(const String &),
@@ -55,7 +61,7 @@ void Thread::_set_platform_funcs(
}
void Thread::callback(Thread *p_self, const Settings &p_settings, Callback p_callback, void *p_userdata) {
- Thread::caller_id = p_self->id;
+ Thread::caller_id = _thread_id_hash(p_self->thread.get_id());
if (set_priority_func) {
set_priority_func(p_settings.priority);
}
@@ -71,7 +77,7 @@ void Thread::callback(Thread *p_self, const Settings &p_settings, Callback p_cal
}
void Thread::start(Thread::Callback p_callback, void *p_user, const Settings &p_settings) {
- if (id != 0) {
+ if (id != _thread_id_hash(std::thread::id())) {
#ifdef DEBUG_ENABLED
WARN_PRINT("A Thread object has been re-started without wait_to_finish() having been called on it. Please do so to ensure correct cleanup of the thread.");
#endif
@@ -79,21 +85,22 @@ void Thread::start(Thread::Callback p_callback, void *p_user, const Settings &p_
std::thread empty_thread;
thread.swap(empty_thread);
}
- id = atomic_increment(&last_thread_id);
std::thread new_thread(&Thread::callback, this, p_settings, p_callback, p_user);
thread.swap(new_thread);
+ id = _thread_id_hash(thread.get_id());
}
bool Thread::is_started() const {
- return id != 0;
+ return id != _thread_id_hash(std::thread::id());
}
void Thread::wait_to_finish() {
- if (id != 0) {
+ if (id != _thread_id_hash(std::thread::id())) {
+ ERR_FAIL_COND_MSG(id == get_caller_id(), "A Thread can't wait for itself to finish.");
thread.join();
std::thread empty_thread;
thread.swap(empty_thread);
- id = 0;
+ id = _thread_id_hash(std::thread::id());
}
}
@@ -105,8 +112,12 @@ Error Thread::set_name(const String &p_name) {
return ERR_UNAVAILABLE;
}
+Thread::Thread() {
+ caller_id = _thread_id_hash(std::this_thread::get_id());
+}
+
Thread::~Thread() {
- if (id != 0) {
+ if (id != _thread_id_hash(std::thread::id())) {
#ifdef DEBUG_ENABLED
WARN_PRINT("A Thread object has been destroyed without wait_to_finish() having been called on it. Please do so to ensure correct cleanup of the thread.");
#endif
diff --git a/core/os/thread.h b/core/os/thread.h
index b5449d2ed6..17ac82c650 100644
--- a/core/os/thread.h
+++ b/core/os/thread.h
@@ -34,6 +34,7 @@
#include "core/typedefs.h"
#if !defined(NO_THREADS)
+#include "core/templates/safe_refcount.h"
#include <thread>
#endif
@@ -61,9 +62,10 @@ private:
friend class Main;
static ID main_thread_id;
- static ID last_thread_id;
- ID id = 0;
+ static uint64_t _thread_id_hash(const std::thread::id &p_t);
+
+ ID id = _thread_id_hash(std::thread::id());
static thread_local ID caller_id;
std::thread thread;
@@ -96,6 +98,7 @@ public:
///< waits until thread is finished, and deallocates it.
void wait_to_finish();
+ Thread();
~Thread();
#else
_FORCE_INLINE_ ID get_id() const { return 0; }
diff --git a/core/os/threaded_array_processor.h b/core/os/threaded_array_processor.h
index 9538ac5957..fec6473589 100644
--- a/core/os/threaded_array_processor.h
+++ b/core/os/threaded_array_processor.h
@@ -40,7 +40,7 @@
template <class C, class U>
struct ThreadArrayProcessData {
uint32_t elements;
- uint32_t index;
+ SafeNumeric<uint32_t> index;
C *instance;
U userdata;
void (C::*method)(uint32_t, U);
@@ -56,7 +56,7 @@ template <class T>
void process_array_thread(void *ud) {
T &data = *(T *)ud;
while (true) {
- uint32_t index = atomic_increment(&data.index);
+ uint32_t index = data.index.increment();
if (index >= data.elements) {
break;
}
@@ -70,9 +70,9 @@ void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_us
data.method = p_method;
data.instance = p_instance;
data.userdata = p_userdata;
- data.index = 0;
+ data.index.set(0);
data.elements = p_elements;
- data.process(data.index); //process first, let threads increment for next
+ data.process(0); //process first, let threads increment for next
int thread_count = OS::get_singleton()->get_processor_count();
Thread *threads = memnew_arr(Thread, thread_count);
@@ -95,7 +95,7 @@ void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_us
data.method = p_method;
data.instance = p_instance;
data.userdata = p_userdata;
- data.index = 0;
+ data.index.set(0);
data.elements = p_elements;
for (uint32_t i = 0; i < p_elements; i++) {
data.process(i);
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index b58abc81d1..d6a5eff10d 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -68,7 +68,7 @@
#include "core/object/class_db.h"
#include "core/object/undo_redo.h"
#include "core/os/main_loop.h"
-#include "core/string/compressed_translation.h"
+#include "core/string/optimized_translation.h"
#include "core/string/translation.h"
static Ref<ResourceFormatSaverBinary> resource_saver_binary;
@@ -183,7 +183,7 @@ void register_core_types() {
ClassDB::register_class<MultiplayerAPI>();
ClassDB::register_class<MainLoop>();
ClassDB::register_class<Translation>();
- ClassDB::register_class<PHashTranslation>();
+ ClassDB::register_class<OptimizedTranslation>();
ClassDB::register_class<UndoRedo>();
ClassDB::register_class<HTTPClient>();
ClassDB::register_class<TriangleMesh>();
diff --git a/core/string/compressed_translation.cpp b/core/string/optimized_translation.cpp
index ad90924293..53d0a8924d 100644
--- a/core/string/compressed_translation.cpp
+++ b/core/string/optimized_translation.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* compressed_translation.cpp */
+/* optimized_translation.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "compressed_translation.h"
+#include "optimized_translation.h"
#include "core/templates/pair.h"
@@ -36,15 +36,15 @@ extern "C" {
#include "thirdparty/misc/smaz.h"
}
-struct _PHashTranslationCmp {
+struct CompressedString {
int orig_len;
CharString compressed;
int offset;
};
-void PHashTranslation::generate(const Ref<Translation> &p_from) {
+void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
// This method compresses a Translation instance.
- // Right now it doesn't handle context or plurals, so Translation subclasses using plurals or context (i.e TranslationPO) shouldn't be compressed.
+ // Right now, it doesn't handle context or plurals, so Translation subclasses using plurals or context (i.e TranslationPO) shouldn't be compressed.
#ifdef TOOLS_ENABLED
List<StringName> keys;
p_from->get_message_list(&keys);
@@ -54,7 +54,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
Vector<Vector<Pair<int, CharString>>> buckets;
Vector<Map<uint32_t, int>> table;
Vector<uint32_t> hfunc_table;
- Vector<_PHashTranslationCmp> compressed;
+ Vector<CompressedString> compressed;
table.resize(size);
hfunc_table.resize(size);
@@ -76,7 +76,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
//compress string
CharString src_s = p_from->get_message(E->get()).operator String().utf8();
- _PHashTranslationCmp ps;
+ CompressedString ps;
ps.orig_len = src_s.size();
ps.offset = total_compression_size;
@@ -182,7 +182,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
#endif
}
-bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) {
+bool OptimizedTranslation::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name.operator String();
if (name == "hash_table") {
hash_table = p_value;
@@ -199,7 +199,7 @@ bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) {
return true;
}
-bool PHashTranslation::_get(const StringName &p_name, Variant &r_ret) const {
+bool OptimizedTranslation::_get(const StringName &p_name, Variant &r_ret) const {
String name = p_name.operator String();
if (name == "hash_table") {
r_ret = hash_table;
@@ -214,8 +214,8 @@ bool PHashTranslation::_get(const StringName &p_name, Variant &r_ret) const {
return true;
}
-StringName PHashTranslation::get_message(const StringName &p_src_text, const StringName &p_context) const {
- // p_context passed in is ignore. The use of context is not yet supported in PHashTranslation.
+StringName OptimizedTranslation::get_message(const StringName &p_src_text, const StringName &p_context) const {
+ // p_context passed in is ignore. The use of context is not yet supported in OptimizedTranslation.
int htsize = hash_table.size();
@@ -271,18 +271,18 @@ StringName PHashTranslation::get_message(const StringName &p_src_text, const Str
}
}
-StringName PHashTranslation::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 PHashTranslation.
+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);
}
-void PHashTranslation::_get_property_list(List<PropertyInfo> *p_list) const {
+void OptimizedTranslation::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "hash_table"));
p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "bucket_table"));
p_list->push_back(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "strings"));
p_list->push_back(PropertyInfo(Variant::OBJECT, "load_from", PROPERTY_HINT_RESOURCE_TYPE, "Translation", PROPERTY_USAGE_EDITOR));
}
-void PHashTranslation::_bind_methods() {
- ClassDB::bind_method(D_METHOD("generate", "from"), &PHashTranslation::generate);
+void OptimizedTranslation::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("generate", "from"), &OptimizedTranslation::generate);
}
diff --git a/core/string/compressed_translation.h b/core/string/optimized_translation.h
index 0abb770178..bccf932383 100644
--- a/core/string/compressed_translation.h
+++ b/core/string/optimized_translation.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* compressed_translation.h */
+/* optimized_translation.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COMPRESSED_TRANSLATION_H
-#define COMPRESSED_TRANSLATION_H
+#ifndef OPTIMIZED_TRANSLATION_H
+#define OPTIMIZED_TRANSLATION_H
#include "core/string/translation.h"
-class PHashTranslation : public Translation {
- GDCLASS(PHashTranslation, Translation);
+class OptimizedTranslation : public Translation {
+ GDCLASS(OptimizedTranslation, Translation);
//this translation uses a sort of modified perfect hash algorithm
//it requires hashing strings twice and then does a binary search,
@@ -83,7 +83,7 @@ public:
virtual StringName get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context = "") const override;
void generate(const Ref<Translation> &p_from);
- PHashTranslation() {}
+ OptimizedTranslation() {}
};
-#endif // COMPRESSED_TRANSLATION_H
+#endif // OPTIMIZED_TRANSLATION_H
diff --git a/core/string/translation.cpp b/core/string/translation.cpp
index 5337d46aa3..ade5f7b4d8 100644
--- a/core/string/translation.cpp
+++ b/core/string/translation.cpp
@@ -39,13 +39,14 @@
#include "main/main.h"
#endif
-// ISO 639-1 language codes, with the addition of glibc locales with their
-// regional identifiers. This list must match the language names (in English)
-// of locale_names.
+// ISO 639-1 language codes (and a couple of three-letter ISO 639-2 codes),
+// with the addition of glibc locales with their regional identifiers.
+// This list must match the language names (in English) of locale_names.
//
// References:
// - https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
// - https://lh.2xlibre.net/locales/
+// - https://iso639-3.sil.org/
static const char *locale_list[] = {
"aa", // Afar
@@ -100,6 +101,7 @@ static const char *locale_list[] = {
"bo", // Tibetan
"bo_CN", // Tibetan (China)
"bo_IN", // Tibetan (India)
+ "br", // Breton
"br_FR", // Breton (France)
"brx_IN", // Bodo (India)
"bs_BA", // Bosnian (Bosnia and Herzegovina)
@@ -201,6 +203,7 @@ static const char *locale_list[] = {
"gd_GB", // Scottish Gaelic (United Kingdom)
"gez_ER", // Geez (Eritrea)
"gez_ET", // Geez (Ethiopia)
+ "gl", // Galician
"gl_ES", // Galician (Spain)
"gu_IN", // Gujarati (India)
"gv_GB", // Manx (United Kingdom)
@@ -273,6 +276,7 @@ static const char *locale_list[] = {
"ml_IN", // Malayalam (India)
"mni_IN", // Manipuri (India)
"mn_MN", // Mongolian (Mongolia)
+ "mr", // Marathi
"mr_IN", // Marathi (India)
"ms", // Malay
"ms_MY", // Malay (Malaysia)
@@ -302,6 +306,7 @@ static const char *locale_list[] = {
"om", // Oromo
"om_ET", // Oromo (Ethiopia)
"om_KE", // Oromo (Kenya)
+ "or", // Oriya
"or_IN", // Oriya (India)
"os_RU", // Ossetian (Russia)
"pa_IN", // Panjabi (India)
@@ -386,6 +391,8 @@ static const char *locale_list[] = {
"tr_TR", // Turkish (Turkey)
"ts_ZA", // Tsonga (South Africa)
"tt_RU", // Tatar (Russia)
+ "tzm", // Central Atlas Tamazight
+ "tzm_MA", // Central Atlas Tamazight (Marrocos)
"ug_CN", // Uighur (China)
"uk", // Ukrainian
"uk_UA", // Ukrainian (Ukraine)
@@ -468,6 +475,7 @@ static const char *locale_names[] = {
"Tibetan",
"Tibetan (China)",
"Tibetan (India)",
+ "Breton",
"Breton (France)",
"Bodo (India)",
"Bosnian (Bosnia and Herzegovina)",
@@ -569,6 +577,7 @@ static const char *locale_names[] = {
"Scottish Gaelic (United Kingdom)",
"Geez (Eritrea)",
"Geez (Ethiopia)",
+ "Galician",
"Galician (Spain)",
"Gujarati (India)",
"Manx (United Kingdom)",
@@ -641,6 +650,7 @@ static const char *locale_names[] = {
"Malayalam (India)",
"Manipuri (India)",
"Mongolian (Mongolia)",
+ "Marathi",
"Marathi (India)",
"Malay",
"Malay (Malaysia)",
@@ -670,6 +680,7 @@ static const char *locale_names[] = {
"Oromo",
"Oromo (Ethiopia)",
"Oromo (Kenya)",
+ "Oriya",
"Oriya (India)",
"Ossetian (Russia)",
"Panjabi (India)",
@@ -754,6 +765,8 @@ static const char *locale_names[] = {
"Turkish (Turkey)",
"Tsonga (South Africa)",
"Tatar (Russia)",
+ "Central Atlas Tamazight",
+ "Central Atlas Tamazight (Marrocos)",
"Uighur (China)",
"Ukrainian",
"Ukrainian (Ukraine)",
@@ -840,7 +853,7 @@ void Translation::set_locale(const String &p_locale) {
locale = univ_locale;
}
- if (OS::get_singleton()->get_main_loop()) {
+ if (OS::get_singleton()->get_main_loop() && TranslationServer::get_singleton()->get_loaded_locales().has(this)) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED);
}
}
@@ -1191,14 +1204,14 @@ bool TranslationServer::_load_translations(const String &p_from) {
}
void TranslationServer::setup() {
- String test = GLOBAL_DEF("locale/test", "");
+ String test = GLOBAL_DEF("internationalization/locale/test", "");
test = test.strip_edges();
if (test != "") {
set_locale(test);
} else {
set_locale(OS::get_singleton()->get_locale());
}
- fallback = GLOBAL_DEF("locale/fallback", "en");
+ fallback = GLOBAL_DEF("internationalization/locale/fallback", "en");
#ifdef TOOLS_ENABLED
{
String options = "";
@@ -1210,7 +1223,7 @@ void TranslationServer::setup() {
options += locale_list[idx];
idx++;
}
- ProjectSettings::get_singleton()->set_custom_property_info("locale/fallback", PropertyInfo(Variant::STRING, "locale/fallback", PROPERTY_HINT_ENUM, options));
+ ProjectSettings::get_singleton()->set_custom_property_info("internationalization/locale/fallback", PropertyInfo(Variant::STRING, "internationalization/locale/fallback", PROPERTY_HINT_ENUM, options));
}
#endif
}
@@ -1307,11 +1320,11 @@ void TranslationServer::_bind_methods() {
void TranslationServer::load_translations() {
String locale = get_locale();
- _load_translations("locale/translations"); //all
- _load_translations("locale/translations_" + locale.substr(0, 2));
+ _load_translations("internationalization/locale/translations"); //all
+ _load_translations("internationalization/locale/translations_" + locale.substr(0, 2));
if (locale.substr(0, 2) != locale) {
- _load_translations("locale/translations_" + locale);
+ _load_translations("internationalization/locale/translations_" + locale);
}
}
diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp
index 846afe761b..2efadaa9b7 100644
--- a/core/string/translation_po.cpp
+++ b/core/string/translation_po.cpp
@@ -158,7 +158,7 @@ int TranslationPO::_get_plural_index(int p_n) const {
void TranslationPO::_cache_plural_tests(const String &p_plural_rule) {
// Some examples of p_plural_rule passed in can have the form:
// "n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5" (Arabic)
- // "n >= 2" (French) // When evaluating the last, esp careful with this one.
+ // "n >= 2" (French) // When evaluating the last, especially careful with this one.
// "n != 1" (English)
int first_ques_mark = p_plural_rule.find("?");
if (first_ques_mark == -1) {
@@ -275,7 +275,7 @@ void TranslationPO::erase_message(const StringName &p_src_text, const StringName
}
void TranslationPO::get_message_list(List<StringName> *r_messages) const {
- // PHashTranslation uses this function to get the list of msgid.
+ // OptimizedTranslation uses this function to get the list of msgid.
// Return all the keys of translation_map under "" context.
List<StringName> context_l;
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 0b6311dadf..28228e4a83 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -1764,7 +1764,7 @@ bool String::parse_utf8(const char *p_utf8, int p_len) {
if (skip) {
_UNICERROR("no space left");
- return true; //not enough spac
+ return true; //not enough space
}
}
@@ -3072,39 +3072,46 @@ int String::rfindn(const String &p_str, int p_from) const {
bool String::ends_with(const String &p_string) const {
int l = p_string.length();
+ if (l > length()) {
+ return false;
+ }
+
if (l == 0) {
return true;
}
- int pos = rfind(p_string);
- if (pos == -1) {
- return false;
+ const char32_t *p = &p_string[0];
+ const char32_t *s = &operator[](length() - l);
+
+ for (int i = 0; i < l; i++) {
+ if (p[i] != s[i]) {
+ return false;
+ }
}
- return pos + l == length();
+
+ return true;
}
bool String::begins_with(const String &p_string) const {
- if (p_string.length() > length()) {
+ int l = p_string.length();
+ if (l > length()) {
return false;
}
- int l = p_string.length();
if (l == 0) {
return true;
}
- const char32_t *src = &p_string[0];
- const char32_t *str = &operator[](0);
+ const char32_t *p = &p_string[0];
+ const char32_t *s = &operator[](0);
- int i = 0;
- for (; i < l; i++) {
- if (src[i] != str[i]) {
+ for (int i = 0; i < l; i++) {
+ if (p[i] != s[i]) {
return false;
}
}
- // only if i == l the p_string matches the beginning
- return i == l;
+ return true;
}
bool String::begins_with(const char *p_string) const {
@@ -3881,25 +3888,55 @@ static _FORCE_INLINE_ int _xml_unescape(const char32_t *p_src, int p_src_len, ch
if (p_src_len >= 4 && p_src[1] == '#') {
char32_t c = 0;
-
- for (int i = 2; i < p_src_len; i++) {
- eat = i + 1;
- char32_t ct = p_src[i];
- if (ct == ';') {
- break;
- } else if (ct >= '0' && ct <= '9') {
- ct = ct - '0';
- } else if (ct >= 'a' && ct <= 'f') {
- ct = (ct - 'a') + 10;
- } else if (ct >= 'A' && ct <= 'F') {
- ct = (ct - 'A') + 10;
- } else {
- continue;
+ bool overflow = false;
+ if (p_src[2] == 'x') {
+ // Hex entity &#x<num>;
+ for (int i = 3; i < p_src_len; i++) {
+ eat = i + 1;
+ char32_t ct = p_src[i];
+ if (ct == ';') {
+ break;
+ } else if (ct >= '0' && ct <= '9') {
+ ct = ct - '0';
+ } else if (ct >= 'a' && ct <= 'f') {
+ ct = (ct - 'a') + 10;
+ } else if (ct >= 'A' && ct <= 'F') {
+ ct = (ct - 'A') + 10;
+ } else {
+ break;
+ }
+ if (c > (UINT32_MAX >> 4)) {
+ overflow = true;
+ break;
+ }
+ c <<= 4;
+ c |= ct;
+ }
+ } else {
+ // Decimal entity &#<num>;
+ for (int i = 2; i < p_src_len; i++) {
+ eat = i + 1;
+ char32_t ct = p_src[i];
+ if (ct == ';' || ct < '0' || ct > '9') {
+ break;
+ }
+ }
+ if (p_src[eat - 1] == ';') {
+ int64_t val = String::to_int(p_src + 2, eat - 3);
+ if (val > 0 && val <= UINT32_MAX) {
+ c = (char32_t)val;
+ } else {
+ overflow = true;
+ }
}
- c <<= 4;
- c |= ct;
}
+ // Value must be non-zero, in the range of char32_t,
+ // actually end with ';'. If invalid, leave the entity as-is
+ if (c == '\0' || overflow || p_src[eat - 1] != ';') {
+ eat = 1;
+ c = *p_src;
+ }
if (p_dst) {
*p_dst = c;
}
@@ -4357,6 +4394,18 @@ String String::property_name_encode() const {
return *this;
}
+// Changes made to the set of invalid characters must also be reflected in the String documentation.
+const String String::invalid_node_name_characters = ". : @ / \"";
+
+String String::validate_node_name() const {
+ Vector<String> chars = String::invalid_node_name_characters.split(" ");
+ String name = this->replace(chars[0], "");
+ for (int i = 1; i < chars.size(); i++) {
+ name = name.replace(chars[i], "");
+ }
+ return name;
+}
+
String String::get_basename() const {
int pos = rfind(".");
if (pos < 0 || pos < MAX(rfind("/"), rfind("\\"))) {
@@ -4431,7 +4480,7 @@ String String::sprintf(const Array &values, bool *error) const {
for (; *self; self++) {
const char32_t c = *self;
- if (in_format) { // We have % - lets see what else we get.
+ if (in_format) { // We have % - let's see what else we get.
switch (c) {
case '%': { // Replace %% with %
formatted += chr(c);
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 821941036f..1e362d7683 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -419,6 +419,10 @@ public:
String property_name_encode() const;
+ // node functions
+ static const String invalid_node_name_characters;
+ String validate_node_name() const;
+
bool is_valid_identifier() const;
bool is_valid_integer() const;
bool is_valid_float() const;
diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h
index 7861c76153..0012cea72d 100644
--- a/core/templates/command_queue_mt.h
+++ b/core/templates/command_queue_mt.h
@@ -498,6 +498,11 @@ public:
flush_one();
}
+ _FORCE_INLINE_ void flush_if_pending() {
+ if (unlikely(read_ptr_and_epoch != write_ptr_and_epoch)) {
+ flush_all();
+ }
+ }
void flush_all() {
//ERR_FAIL_COND(sync);
lock();
diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h
index 4becb1be59..c985593473 100644
--- a/core/templates/cowdata.h
+++ b/core/templates/cowdata.h
@@ -45,6 +45,10 @@ class CharString;
template <class T, class V>
class VMap;
+#if !defined(NO_THREADS)
+SAFE_NUMERIC_TYPE_PUN_GUARANTEES(uint32_t)
+#endif
+
template <class T>
class CowData {
template <class TV>
@@ -60,12 +64,12 @@ private:
// internal helpers
- _FORCE_INLINE_ uint32_t *_get_refcount() const {
+ _FORCE_INLINE_ SafeNumeric<uint32_t> *_get_refcount() const {
if (!_ptr) {
return nullptr;
}
- return reinterpret_cast<uint32_t *>(_ptr) - 2;
+ return reinterpret_cast<SafeNumeric<uint32_t> *>(_ptr) - 2;
}
_FORCE_INLINE_ uint32_t *_get_size() const {
@@ -111,7 +115,7 @@ private:
void _unref(void *p_data);
void _ref(const CowData *p_from);
void _ref(const CowData &p_from);
- void _copy_on_write();
+ uint32_t _copy_on_write();
public:
void operator=(const CowData<T> &p_from) { _ref(p_from); }
@@ -138,7 +142,7 @@ public:
_FORCE_INLINE_ bool is_empty() const { return _ptr == nullptr; }
_FORCE_INLINE_ void set(int p_index, const T &p_elem) {
- CRASH_BAD_INDEX(p_index, size());
+ ERR_FAIL_INDEX(p_index, size());
_copy_on_write();
_get_data()[p_index] = p_elem;
}
@@ -192,9 +196,9 @@ void CowData<T>::_unref(void *p_data) {
return;
}
- uint32_t *refc = _get_refcount();
+ SafeNumeric<uint32_t> *refc = _get_refcount();
- if (atomic_decrement(refc) > 0) {
+ if (refc->decrement() > 0) {
return; // still in use
}
// clean up
@@ -214,20 +218,21 @@ void CowData<T>::_unref(void *p_data) {
}
template <class T>
-void CowData<T>::_copy_on_write() {
+uint32_t CowData<T>::_copy_on_write() {
if (!_ptr) {
- return;
+ return 0;
}
- uint32_t *refc = _get_refcount();
+ SafeNumeric<uint32_t> *refc = _get_refcount();
- if (unlikely(*refc > 1)) {
+ uint32_t rc = refc->get();
+ if (unlikely(rc > 1)) {
/* in use by more than me */
uint32_t current_size = *_get_size();
uint32_t *mem_new = (uint32_t *)Memory::alloc_static(_get_alloc_size(current_size), true);
- *(mem_new - 2) = 1; //refcount
+ new (mem_new - 2, sizeof(uint32_t), "") SafeNumeric<uint32_t>(1); //refcount
*(mem_new - 1) = current_size; //size
T *_data = (T *)(mem_new);
@@ -244,7 +249,10 @@ void CowData<T>::_copy_on_write() {
_unref(_ptr);
_ptr = _data;
+
+ rc = 1;
}
+ return rc;
}
template <class T>
@@ -265,7 +273,7 @@ Error CowData<T>::resize(int p_size) {
}
// possibly changing size, copy on write
- _copy_on_write();
+ uint32_t rc = _copy_on_write();
size_t current_alloc_size = _get_alloc_size(current_size);
size_t alloc_size;
@@ -278,13 +286,15 @@ Error CowData<T>::resize(int p_size) {
uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size, true);
ERR_FAIL_COND_V(!ptr, ERR_OUT_OF_MEMORY);
*(ptr - 1) = 0; //size, currently none
- *(ptr - 2) = 1; //refcount
+ new (ptr - 2, sizeof(uint32_t), "") SafeNumeric<uint32_t>(1); //refcount
_ptr = (T *)ptr;
} else {
- void *_ptrnew = (T *)Memory::realloc_static(_ptr, alloc_size, true);
+ uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY);
+ new (_ptrnew - 2, sizeof(uint32_t), "") SafeNumeric<uint32_t>(rc); //refcount
+
_ptr = (T *)(_ptrnew);
}
}
@@ -311,8 +321,9 @@ Error CowData<T>::resize(int p_size) {
}
if (alloc_size != current_alloc_size) {
- void *_ptrnew = (T *)Memory::realloc_static(_ptr, alloc_size, true);
+ uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY);
+ new (_ptrnew - 2, sizeof(uint32_t), "") SafeNumeric<uint32_t>(rc); //refcount
_ptr = (T *)(_ptrnew);
}
@@ -359,7 +370,7 @@ void CowData<T>::_ref(const CowData &p_from) {
return; //nothing to do
}
- if (atomic_conditional_increment(p_from._get_refcount()) > 0) { // could reference
+ if (p_from._get_refcount()->conditional_increment() > 0) { // could reference
_ptr = p_from._ptr;
}
}
diff --git a/core/templates/rid_owner.cpp b/core/templates/rid_owner.cpp
index f75a2eb9df..56f39ab779 100644
--- a/core/templates/rid_owner.cpp
+++ b/core/templates/rid_owner.cpp
@@ -30,4 +30,4 @@
#include "rid_owner.h"
-volatile uint64_t RID_AllocBase::base_id = 1;
+SafeNumeric<uint64_t> RID_AllocBase::base_id{ 1 };
diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h
index d26c445eb4..c4aa93c394 100644
--- a/core/templates/rid_owner.h
+++ b/core/templates/rid_owner.h
@@ -44,7 +44,7 @@
#include <typeinfo>
class RID_AllocBase {
- static volatile uint64_t base_id;
+ static SafeNumeric<uint64_t> base_id;
protected:
static RID _make_from_id(uint64_t p_id) {
@@ -54,7 +54,7 @@ protected:
}
static uint64_t _gen_id() {
- return atomic_increment(&base_id);
+ return base_id.increment();
}
static RID _gen_rid() {
@@ -79,8 +79,7 @@ class RID_Alloc : public RID_AllocBase {
SpinLock spin_lock;
-public:
- RID make_rid(const T &p_value) {
+ _FORCE_INLINE_ RID _allocate_rid(const T *p_initializer) {
if (THREAD_SAFE) {
spin_lock.lock();
}
@@ -115,15 +114,22 @@ public:
uint32_t free_chunk = free_index / elements_in_chunk;
uint32_t free_element = free_index % elements_in_chunk;
- T *ptr = &chunks[free_chunk][free_element];
- memnew_placement(ptr, T(p_value));
+ if (p_initializer) {
+ T *ptr = &chunks[free_chunk][free_element];
+ memnew_placement(ptr, T(*p_initializer));
+ }
- uint32_t validator = (uint32_t)(_gen_id() & 0xFFFFFFFF);
+ uint32_t validator = (uint32_t)(_gen_id() & 0x7FFFFFFF);
uint64_t id = validator;
id <<= 32;
id |= free_index;
validator_chunks[free_chunk][free_element] = validator;
+
+ if (!p_initializer) {
+ validator_chunks[free_chunk][free_element] |= 0x80000000; //mark uninitialized bit
+ }
+
alloc_count++;
if (THREAD_SAFE) {
@@ -133,7 +139,20 @@ public:
return _make_from_id(id);
}
- _FORCE_INLINE_ T *getornull(const RID &p_rid) {
+public:
+ RID make_rid(const T &p_value) {
+ return _allocate_rid(&p_value);
+ }
+
+ //allocate but don't initialize, use initialize_rid afterwards
+ RID allocate_rid() {
+ return _allocate_rid(nullptr);
+ }
+
+ _FORCE_INLINE_ T *getornull(const RID &p_rid, bool p_initialize = false) {
+ if (p_rid == RID()) {
+ return nullptr;
+ }
if (THREAD_SAFE) {
spin_lock.lock();
}
@@ -151,10 +170,32 @@ public:
uint32_t idx_element = idx % elements_in_chunk;
uint32_t validator = uint32_t(id >> 32);
- if (unlikely(validator_chunks[idx_chunk][idx_element] != validator)) {
+
+ if (unlikely(p_initialize)) {
+ if (unlikely(!(validator_chunks[idx_chunk][idx_element] & 0x80000000))) {
+ if (THREAD_SAFE) {
+ spin_lock.unlock();
+ }
+ ERR_FAIL_V_MSG(nullptr, "Initializing already initialized RID");
+ }
+
+ if (unlikely((validator_chunks[idx_chunk][idx_element] & 0x7FFFFFFF) != validator)) {
+ if (THREAD_SAFE) {
+ spin_lock.unlock();
+ }
+ ERR_FAIL_V_MSG(nullptr, "Attempting to initialize the wrong RID");
+ return nullptr;
+ }
+
+ validator_chunks[idx_chunk][idx_element] &= 0x7FFFFFFF; //initialized
+
+ } else if (unlikely(validator_chunks[idx_chunk][idx_element] != validator)) {
if (THREAD_SAFE) {
spin_lock.unlock();
}
+ if (validator_chunks[idx_chunk][idx_element] & 0x80000000) {
+ ERR_FAIL_V_MSG(nullptr, "Attempting to use an uninitialized RID");
+ }
return nullptr;
}
@@ -166,6 +207,11 @@ public:
return ptr;
}
+ void initialize_rid(RID p_rid, const T &p_value) {
+ T *mem = getornull(p_rid, true);
+ ERR_FAIL_COND(!mem);
+ memnew_placement(mem, T(p_value));
+ }
_FORCE_INLINE_ bool owns(const RID &p_rid) {
if (THREAD_SAFE) {
@@ -186,7 +232,7 @@ public:
uint32_t validator = uint32_t(id >> 32);
- bool owned = validator_chunks[idx_chunk][idx_element] == validator;
+ bool owned = (validator_chunks[idx_chunk][idx_element] & 0x7FFFFFFF) == validator;
if (THREAD_SAFE) {
spin_lock.unlock();
@@ -213,7 +259,12 @@ public:
uint32_t idx_element = idx % elements_in_chunk;
uint32_t validator = uint32_t(id >> 32);
- if (unlikely(validator_chunks[idx_chunk][idx_element] != validator)) {
+ if (unlikely(validator_chunks[idx_chunk][idx_element] & 0x80000000)) {
+ if (THREAD_SAFE) {
+ spin_lock.unlock();
+ }
+ ERR_FAIL_MSG("Attempted to free an uninitialized or invalid RID");
+ } else if (unlikely(validator_chunks[idx_chunk][idx_element] != validator)) {
if (THREAD_SAFE) {
spin_lock.unlock();
}
@@ -330,6 +381,14 @@ public:
return alloc.make_rid(p_ptr);
}
+ _FORCE_INLINE_ RID allocate_rid() {
+ return alloc.allocate_rid();
+ }
+
+ _FORCE_INLINE_ void initialize_rid(RID p_rid, T *p_ptr) {
+ alloc.initialize_rid(p_rid, p_ptr);
+ }
+
_FORCE_INLINE_ T *getornull(const RID &p_rid) {
T **ptr = alloc.getornull(p_rid);
if (unlikely(!ptr)) {
@@ -338,6 +397,12 @@ public:
return *ptr;
}
+ _FORCE_INLINE_ void replace(const RID &p_rid, T *p_new_ptr) {
+ T **ptr = alloc.getornull(p_rid);
+ ERR_FAIL_COND(!ptr);
+ *ptr = p_new_ptr;
+ }
+
_FORCE_INLINE_ bool owns(const RID &p_rid) {
return alloc.owns(p_rid);
}
@@ -379,6 +444,14 @@ public:
return alloc.make_rid(p_ptr);
}
+ _FORCE_INLINE_ RID allocate_rid() {
+ return alloc.allocate_rid();
+ }
+
+ _FORCE_INLINE_ void initialize_rid(RID p_rid, const T &p_ptr) {
+ alloc.initialize_rid(p_rid, p_ptr);
+ }
+
_FORCE_INLINE_ T *getornull(const RID &p_rid) {
return alloc.getornull(p_rid);
}
diff --git a/core/templates/safe_refcount.cpp b/core/templates/safe_refcount.cpp
deleted file mode 100644
index a915ee662f..0000000000
--- a/core/templates/safe_refcount.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/*************************************************************************/
-/* safe_refcount.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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 "safe_refcount.h"
-
-#if defined(_MSC_VER)
-
-/* Implementation for MSVC-Windows */
-
-// don't pollute my namespace!
-#include <windows.h>
-
-#define ATOMIC_CONDITIONAL_INCREMENT_BODY(m_pw, m_win_type, m_win_cmpxchg, m_cpp_type) \
- /* try to increment until it actually works */ \
- /* taken from boost */ \
- while (true) { \
- m_cpp_type tmp = static_cast<m_cpp_type const volatile &>(*(m_pw)); \
- if (tmp == 0) { \
- return 0; /* if zero, can't add to it anymore */ \
- } \
- if (m_win_cmpxchg((m_win_type volatile *)(m_pw), tmp + 1, tmp) == tmp) { \
- return tmp + 1; \
- } \
- }
-
-#define ATOMIC_EXCHANGE_IF_GREATER_BODY(m_pw, m_val, m_win_type, m_win_cmpxchg, m_cpp_type) \
- while (true) { \
- m_cpp_type tmp = static_cast<m_cpp_type const volatile &>(*(m_pw)); \
- if (tmp >= m_val) { \
- return tmp; /* already greater, or equal */ \
- } \
- if (m_win_cmpxchg((m_win_type volatile *)(m_pw), m_val, tmp) == tmp) { \
- return m_val; \
- } \
- }
-
-_ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(volatile uint32_t *pw) {
- ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONG, InterlockedCompareExchange, uint32_t);
-}
-
-_ALWAYS_INLINE_ uint32_t _atomic_decrement_impl(volatile uint32_t *pw) {
- return InterlockedDecrement((LONG volatile *)pw);
-}
-
-_ALWAYS_INLINE_ uint32_t _atomic_increment_impl(volatile uint32_t *pw) {
- return InterlockedIncrement((LONG volatile *)pw);
-}
-
-_ALWAYS_INLINE_ uint32_t _atomic_sub_impl(volatile uint32_t *pw, volatile uint32_t val) {
- return InterlockedExchangeAdd((LONG volatile *)pw, -(int32_t)val) - val;
-}
-
-_ALWAYS_INLINE_ uint32_t _atomic_add_impl(volatile uint32_t *pw, volatile uint32_t val) {
- return InterlockedAdd((LONG volatile *)pw, val);
-}
-
-_ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(volatile uint32_t *pw, volatile uint32_t val) {
- ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONG, InterlockedCompareExchange, uint32_t);
-}
-
-_ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(volatile uint64_t *pw) {
- ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONGLONG, InterlockedCompareExchange64, uint64_t);
-}
-
-_ALWAYS_INLINE_ uint64_t _atomic_decrement_impl(volatile uint64_t *pw) {
- return InterlockedDecrement64((LONGLONG volatile *)pw);
-}
-
-_ALWAYS_INLINE_ uint64_t _atomic_increment_impl(volatile uint64_t *pw) {
- return InterlockedIncrement64((LONGLONG volatile *)pw);
-}
-
-_ALWAYS_INLINE_ uint64_t _atomic_sub_impl(volatile uint64_t *pw, volatile uint64_t val) {
- return InterlockedExchangeAdd64((LONGLONG volatile *)pw, -(int64_t)val) - val;
-}
-
-_ALWAYS_INLINE_ uint64_t _atomic_add_impl(volatile uint64_t *pw, volatile uint64_t val) {
- return InterlockedAdd64((LONGLONG volatile *)pw, val);
-}
-
-_ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(volatile uint64_t *pw, volatile uint64_t val) {
- ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONGLONG, InterlockedCompareExchange64, uint64_t);
-}
-
-// The actual advertised functions; they'll call the right implementation
-
-uint32_t atomic_conditional_increment(volatile uint32_t *pw) {
- return _atomic_conditional_increment_impl(pw);
-}
-
-uint32_t atomic_decrement(volatile uint32_t *pw) {
- return _atomic_decrement_impl(pw);
-}
-
-uint32_t atomic_increment(volatile uint32_t *pw) {
- return _atomic_increment_impl(pw);
-}
-
-uint32_t atomic_sub(volatile uint32_t *pw, volatile uint32_t val) {
- return _atomic_sub_impl(pw, val);
-}
-
-uint32_t atomic_add(volatile uint32_t *pw, volatile uint32_t val) {
- return _atomic_add_impl(pw, val);
-}
-
-uint32_t atomic_exchange_if_greater(volatile uint32_t *pw, volatile uint32_t val) {
- return _atomic_exchange_if_greater_impl(pw, val);
-}
-
-uint64_t atomic_conditional_increment(volatile uint64_t *pw) {
- return _atomic_conditional_increment_impl(pw);
-}
-
-uint64_t atomic_decrement(volatile uint64_t *pw) {
- return _atomic_decrement_impl(pw);
-}
-
-uint64_t atomic_increment(volatile uint64_t *pw) {
- return _atomic_increment_impl(pw);
-}
-
-uint64_t atomic_sub(volatile uint64_t *pw, volatile uint64_t val) {
- return _atomic_sub_impl(pw, val);
-}
-
-uint64_t atomic_add(volatile uint64_t *pw, volatile uint64_t val) {
- return _atomic_add_impl(pw, val);
-}
-
-uint64_t atomic_exchange_if_greater(volatile uint64_t *pw, volatile uint64_t val) {
- return _atomic_exchange_if_greater_impl(pw, val);
-}
-#endif
diff --git a/core/templates/safe_refcount.h b/core/templates/safe_refcount.h
index d94444fad6..91a34ecd54 100644
--- a/core/templates/safe_refcount.h
+++ b/core/templates/safe_refcount.h
@@ -31,167 +31,291 @@
#ifndef SAFE_REFCOUNT_H
#define SAFE_REFCOUNT_H
-#include "core/os/mutex.h"
#include "core/typedefs.h"
-#include "platform_config.h"
-// Atomic functions, these are used for multithread safe reference counters!
+#if !defined(NO_THREADS)
-#ifdef NO_THREADS
+#include <atomic>
-/* Bogus implementation unaware of multiprocessing */
+// Design goals for these classes:
+// - No automatic conversions or arithmetic operators,
+// to keep explicit the use of atomics everywhere.
+// - Using acquire-release semantics, even to set the first value.
+// The first value may be set relaxedly in many cases, but adding the distinction
+// between relaxed and unrelaxed operation to the interface would make it needlessly
+// flexible. There's negligible waste in having release semantics for the initial
+// value and, as an important benefit, you can be sure the value is properly synchronized
+// even with threads that are already running.
+
+// This is used in very specific areas of the engine where it's critical that these guarantees are held
+#define SAFE_NUMERIC_TYPE_PUN_GUARANTEES(m_type) \
+ static_assert(sizeof(SafeNumeric<m_type>) == sizeof(m_type)); \
+ static_assert(alignof(SafeNumeric<m_type>) == alignof(m_type)); \
+ static_assert(std::is_trivially_destructible<std::atomic<m_type>>::value);
template <class T>
-static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) {
- if (*pw == 0) {
- return 0;
+class SafeNumeric {
+ std::atomic<T> value;
+
+ static_assert(std::atomic<T>::is_always_lock_free);
+
+public:
+ _ALWAYS_INLINE_ void set(T p_value) {
+ value.store(p_value, std::memory_order_release);
}
- (*pw)++;
+ _ALWAYS_INLINE_ T get() const {
+ return value.load(std::memory_order_acquire);
+ }
- return *pw;
-}
+ _ALWAYS_INLINE_ T increment() {
+ return value.fetch_add(1, std::memory_order_acq_rel) + 1;
+ }
-template <class T>
-static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) {
- (*pw)--;
+ // Returns the original value instead of the new one
+ _ALWAYS_INLINE_ T postincrement() {
+ return value.fetch_add(1, std::memory_order_acq_rel);
+ }
- return *pw;
-}
+ _ALWAYS_INLINE_ T decrement() {
+ return value.fetch_sub(1, std::memory_order_acq_rel) - 1;
+ }
-template <class T>
-static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) {
- (*pw)++;
+ // Returns the original value instead of the new one
+ _ALWAYS_INLINE_ T postdecrement() {
+ return value.fetch_sub(1, std::memory_order_acq_rel);
+ }
- return *pw;
-}
+ _ALWAYS_INLINE_ T add(T p_value) {
+ return value.fetch_add(p_value, std::memory_order_acq_rel) + p_value;
+ }
-template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) {
- (*pw) -= val;
+ // Returns the original value instead of the new one
+ _ALWAYS_INLINE_ T postadd(T p_value) {
+ return value.fetch_add(p_value, std::memory_order_acq_rel);
+ }
- return *pw;
-}
+ _ALWAYS_INLINE_ T sub(T p_value) {
+ return value.fetch_sub(p_value, std::memory_order_acq_rel) - p_value;
+ }
-template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) {
- (*pw) += val;
+ // Returns the original value instead of the new one
+ _ALWAYS_INLINE_ T postsub(T p_value) {
+ return value.fetch_sub(p_value, std::memory_order_acq_rel);
+ }
- return *pw;
-}
+ _ALWAYS_INLINE_ T exchange_if_greater(T p_value) {
+ while (true) {
+ T tmp = value.load(std::memory_order_acquire);
+ if (tmp >= p_value) {
+ return tmp; // already greater, or equal
+ }
+ if (value.compare_exchange_weak(tmp, p_value, std::memory_order_release)) {
+ return p_value;
+ }
+ }
+ }
-template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V val) {
- if (val > *pw) {
- *pw = val;
+ _ALWAYS_INLINE_ T conditional_increment() {
+ while (true) {
+ T c = value.load(std::memory_order_acquire);
+ if (c == 0) {
+ return 0;
+ }
+ if (value.compare_exchange_weak(c, c + 1, std::memory_order_release)) {
+ return c + 1;
+ }
+ }
}
- return *pw;
-}
+ _ALWAYS_INLINE_ explicit SafeNumeric<T>(T p_value = static_cast<T>(0)) {
+ set(p_value);
+ }
+};
-#elif defined(__GNUC__)
+class SafeFlag {
+ std::atomic_bool flag;
-/* Implementation for GCC & Clang */
+ static_assert(std::atomic_bool::is_always_lock_free);
-// GCC guarantees atomic intrinsics for sizes of 1, 2, 4 and 8 bytes.
-// Clang states it supports GCC atomic builtins.
+public:
+ _ALWAYS_INLINE_ bool is_set() const {
+ return flag.load(std::memory_order_acquire);
+ }
-template <class T>
-static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) {
- while (true) {
- T tmp = static_cast<T const volatile &>(*pw);
- if (tmp == 0) {
- return 0; // if zero, can't add to it anymore
- }
- if (__sync_val_compare_and_swap(pw, tmp, tmp + 1) == tmp) {
- return tmp + 1;
- }
+ _ALWAYS_INLINE_ void set() {
+ flag.store(true, std::memory_order_release);
}
-}
-template <class T>
-static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) {
- return __sync_sub_and_fetch(pw, 1);
-}
+ _ALWAYS_INLINE_ void clear() {
+ flag.store(false, std::memory_order_release);
+ }
+
+ _ALWAYS_INLINE_ void set_to(bool p_value) {
+ flag.store(p_value, std::memory_order_release);
+ }
+
+ _ALWAYS_INLINE_ explicit SafeFlag(bool p_value = false) {
+ set_to(p_value);
+ }
+};
+
+class SafeRefCount {
+ SafeNumeric<uint32_t> count;
+
+public:
+ _ALWAYS_INLINE_ bool ref() { // true on success
+ return count.conditional_increment() != 0;
+ }
+
+ _ALWAYS_INLINE_ uint32_t refval() { // none-zero on success
+ return count.conditional_increment();
+ }
+
+ _ALWAYS_INLINE_ bool unref() { // true if must be disposed of
+ return count.decrement() == 0;
+ }
+
+ _ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of
+ return count.decrement();
+ }
+
+ _ALWAYS_INLINE_ uint32_t get() const {
+ return count.get();
+ }
+
+ _ALWAYS_INLINE_ void init(uint32_t p_value = 1) {
+ count.set(p_value);
+ }
+};
+
+#else
template <class T>
-static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) {
- return __sync_add_and_fetch(pw, 1);
-}
-
-template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) {
- return __sync_sub_and_fetch(pw, val);
-}
-
-template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) {
- return __sync_add_and_fetch(pw, val);
-}
-
-template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V val) {
- while (true) {
- T tmp = static_cast<T const volatile &>(*pw);
- if (tmp >= val) {
- return tmp; // already greater, or equal
+class SafeNumeric {
+protected:
+ T value;
+
+public:
+ _ALWAYS_INLINE_ void set(T p_value) {
+ value = p_value;
+ }
+
+ _ALWAYS_INLINE_ T get() const {
+ return value;
+ }
+
+ _ALWAYS_INLINE_ T increment() {
+ return ++value;
+ }
+
+ _ALWAYS_INLINE_ T postincrement() {
+ return value++;
+ }
+
+ _ALWAYS_INLINE_ T decrement() {
+ return --value;
+ }
+
+ _ALWAYS_INLINE_ T postdecrement() {
+ return value--;
+ }
+
+ _ALWAYS_INLINE_ T add(T p_value) {
+ return value += p_value;
+ }
+
+ _ALWAYS_INLINE_ T postadd(T p_value) {
+ T old = value;
+ value += p_value;
+ return old;
+ }
+
+ _ALWAYS_INLINE_ T sub(T p_value) {
+ return value -= p_value;
+ }
+
+ _ALWAYS_INLINE_ T postsub(T p_value) {
+ T old = value;
+ value -= p_value;
+ return old;
+ }
+
+ _ALWAYS_INLINE_ T exchange_if_greater(T p_value) {
+ if (value < p_value) {
+ value = p_value;
}
- if (__sync_val_compare_and_swap(pw, tmp, val) == tmp) {
- return val;
+ return value;
+ }
+
+ _ALWAYS_INLINE_ T conditional_increment() {
+ if (value == 0) {
+ return 0;
+ } else {
+ return ++value;
}
}
-}
-
-#elif defined(_MSC_VER)
-// For MSVC use a separate compilation unit to prevent windows.h from polluting
-// the global namespace.
-uint32_t atomic_conditional_increment(volatile uint32_t *pw);
-uint32_t atomic_decrement(volatile uint32_t *pw);
-uint32_t atomic_increment(volatile uint32_t *pw);
-uint32_t atomic_sub(volatile uint32_t *pw, volatile uint32_t val);
-uint32_t atomic_add(volatile uint32_t *pw, volatile uint32_t val);
-uint32_t atomic_exchange_if_greater(volatile uint32_t *pw, volatile uint32_t val);
-
-uint64_t atomic_conditional_increment(volatile uint64_t *pw);
-uint64_t atomic_decrement(volatile uint64_t *pw);
-uint64_t atomic_increment(volatile uint64_t *pw);
-uint64_t atomic_sub(volatile uint64_t *pw, volatile uint64_t val);
-uint64_t atomic_add(volatile uint64_t *pw, volatile uint64_t val);
-uint64_t atomic_exchange_if_greater(volatile uint64_t *pw, volatile uint64_t val);
-#else
-//no threads supported?
-#error Must provide atomic functions for this platform or compiler!
-#endif
+ _ALWAYS_INLINE_ explicit SafeNumeric<T>(T p_value = static_cast<T>(0)) :
+ value(p_value) {
+ }
+};
-struct SafeRefCount {
- uint32_t count = 0;
+class SafeFlag {
+protected:
+ bool flag;
public:
- // destroy() is called when weak_count_ drops to zero.
-
- _ALWAYS_INLINE_ bool ref() { // true on success
+ _ALWAYS_INLINE_ bool is_set() const {
+ return flag;
+ }
- return atomic_conditional_increment(&count) != 0;
+ _ALWAYS_INLINE_ void set() {
+ flag = true;
}
- _ALWAYS_INLINE_ uint32_t refval() { // none-zero on success
+ _ALWAYS_INLINE_ void clear() {
+ flag = false;
+ }
- return atomic_conditional_increment(&count);
+ _ALWAYS_INLINE_ void set_to(bool p_value) {
+ flag = p_value;
}
- _ALWAYS_INLINE_ bool unref() { // true if must be disposed of
+ _ALWAYS_INLINE_ explicit SafeFlag(bool p_value = false) :
+ flag(p_value) {}
+};
+
+class SafeRefCount {
+ uint32_t count = 0;
- return atomic_decrement(&count) == 0;
+public:
+ _ALWAYS_INLINE_ bool ref() { // true on success
+ if (count != 0) {
+ ++count;
+ return true;
+ } else {
+ return false;
+ }
}
- _ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of
+ _ALWAYS_INLINE_ uint32_t refval() { // none-zero on success
+ if (count != 0) {
+ return ++count;
+ } else {
+ return 0;
+ }
+ }
- return atomic_decrement(&count);
+ _ALWAYS_INLINE_ bool unref() { // true if must be disposed of
+ return --count == 0;
}
- _ALWAYS_INLINE_ uint32_t get() const { // nothrow
+ _ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of
+ return --count;
+ }
+ _ALWAYS_INLINE_ uint32_t get() const {
return count;
}
@@ -200,4 +324,6 @@ public:
}
};
+#endif
+
#endif // SAFE_REFCOUNT_H
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 48916f941e..347c6cd82e 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -35,6 +35,7 @@
#include "core/object/script_language.h"
#include "core/templates/hashfuncs.h"
#include "core/templates/vector.h"
+#include "core/variant/callable.h"
#include "core/variant/variant.h"
class ArrayPrivate {
@@ -140,7 +141,7 @@ uint32_t Array::hash() const {
void Array::_assign(const Array &p_array) {
if (_p->typed.type != Variant::OBJECT && _p->typed.type == p_array._p->typed.type) {
- //same type or untyped, just reference, shuold be fine
+ //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;
@@ -371,25 +372,22 @@ void Array::sort() {
}
struct _ArrayVariantSortCustom {
- Object *obj = nullptr;
- StringName func;
+ Callable func;
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
const Variant *args[2] = { &p_l, &p_r };
Callable::CallError err;
- bool res = obj->call(func, args, 2, err);
- if (err.error != Callable::CallError::CALL_OK) {
- res = false;
- }
+ Variant res;
+ func.call(args, 2, res, err);
+ ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, false,
+ "Error calling sorting method: " + Variant::get_callable_error_text(func, args, 1, err));
return res;
}
};
-void Array::sort_custom(Object *p_obj, const StringName &p_function) {
- ERR_FAIL_NULL(p_obj);
+void Array::sort_custom(Callable p_callable) {
SortArray<Variant, _ArrayVariantSortCustom, true> avs;
- avs.compare.obj = p_obj;
- avs.compare.func = p_function;
+ avs.compare.func = p_callable;
avs.sort(_p->array.ptrw(), _p->array.size());
}
@@ -438,13 +436,11 @@ int Array::bsearch(const Variant &p_value, bool p_before) {
return bisect(_p->array, p_value, p_before, _ArrayVariantSort());
}
-int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before) {
+int Array::bsearch_custom(const Variant &p_value, Callable p_callable, bool p_before) {
ERR_FAIL_COND_V(!_p->typed.validate(p_value, "custom binary search"), -1);
- ERR_FAIL_NULL_V(p_obj, 0);
_ArrayVariantSortCustom less;
- less.obj = p_obj;
- less.func = p_function;
+ less.func = p_callable;
return bisect(_p->array, p_value, p_before, less);
}
diff --git a/core/variant/array.h b/core/variant/array.h
index 26de5477b4..d8f2402330 100644
--- a/core/variant/array.h
+++ b/core/variant/array.h
@@ -37,6 +37,7 @@ class Variant;
class ArrayPrivate;
class Object;
class StringName;
+class Callable;
class Array {
mutable ArrayPrivate *_p;
@@ -78,10 +79,10 @@ public:
Variant back() const;
void sort();
- void sort_custom(Object *p_obj, const StringName &p_function);
+ void sort_custom(Callable p_callable);
void shuffle();
int bsearch(const Variant &p_value, bool p_before = true);
- int bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before = true);
+ int bsearch_custom(const Variant &p_value, Callable p_callable, bool p_before = true);
void invert();
int find(const Variant &p_value, int p_from = 0) const;
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 9d8e262cc9..8c0b7907e3 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -88,6 +88,7 @@ VARIANT_ENUM_CAST(Vector3::Axis);
VARIANT_ENUM_CAST(Error);
VARIANT_ENUM_CAST(Side);
+VARIANT_ENUM_CAST(ClockDirection);
VARIANT_ENUM_CAST(Corner);
VARIANT_ENUM_CAST(Orientation);
VARIANT_ENUM_CAST(HAlign);
@@ -237,6 +238,16 @@ void call_with_ptr_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P..
PtrToArg<R>::encode(p_method(p_instance, PtrToArg<P>::convert(p_args[Is])...), r_ret);
}
+template <class R, class... P, size_t... Is>
+void call_with_ptr_args_static_method_ret_helper(R (*p_method)(P...), const void **p_args, void *r_ret, IndexSequence<Is...>) {
+ PtrToArg<R>::encode(p_method(PtrToArg<P>::convert(p_args[Is])...), r_ret);
+}
+
+template <class... P, size_t... Is>
+void call_with_ptr_args_static_method_helper(void (*p_method)(P...), const void **p_args, IndexSequence<Is...>) {
+ p_method(PtrToArg<P>::convert(p_args[Is])...);
+}
+
template <class T, class... P, size_t... Is>
void call_with_validated_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) {
(p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...);
@@ -262,6 +273,16 @@ void call_with_validated_variant_args_static_retc_helper(T *p_instance, R (*p_me
VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method(p_instance, (VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...));
}
+template <class R, class... P, size_t... Is>
+void call_with_validated_variant_args_static_method_ret_helper(R (*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) {
+ VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...));
+}
+
+template <class... P, size_t... Is>
+void call_with_validated_variant_args_static_method_helper(void (*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) {
+ p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...);
+}
+
template <class T, class... P>
void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
@@ -455,6 +476,16 @@ void call_with_ptr_args_static_retc(T *p_instance, R (*p_method)(T *, P...), con
call_with_ptr_args_static_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
+template <class R, class... P>
+void call_with_ptr_args_static_method_ret(R (*p_method)(P...), const void **p_args, void *r_ret) {
+ call_with_ptr_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+void call_with_ptr_args_static_method(void (*p_method)(P...), const void **p_args) {
+ call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
template <class T, class... P>
void call_with_validated_variant_args(Variant *base, void (T::*p_method)(P...), const Variant **p_args) {
call_with_validated_variant_args_helper<T, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
@@ -475,6 +506,16 @@ void call_with_validated_variant_args_static_retc(Variant *base, R (*p_method)(T
call_with_validated_variant_args_static_retc_helper<T, R, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
+template <class... P>
+void call_with_validated_variant_args_static_method(void (*p_method)(P...), const Variant **p_args) {
+ call_with_validated_variant_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class R, class... P>
+void call_with_validated_variant_args_static_method_ret(R (*p_method)(P...), const Variant **p_args, Variant *r_ret) {
+ call_with_validated_variant_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
+}
+
// GCC raises "parameter 'p_args' set but not used" when P = {},
// it's not clever enough to treat other P values as making this branch valid.
#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
@@ -565,6 +606,28 @@ void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), co
#endif
}
+template <class R, class... P, size_t... Is>
+void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) {
+ r_error.error = Callable::CallError::CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+ r_ret = (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+ r_ret = (p_method)(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+}
+
+template <class... P, size_t... Is>
+void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
+ r_error.error = Callable::CallError::CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+ (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+ (p_method)(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+}
+
template <class T, class R, class... P>
void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
@@ -595,6 +658,42 @@ void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) co
(void)p_args;
}
+template <class R, class... P>
+void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
+#ifdef DEBUG_METHODS_ENABLED
+ if ((size_t)p_argcount > sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+
+ if ((size_t)p_argcount < sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+ call_with_variant_args_static_ret<R, P...>(p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
+#ifdef DEBUG_METHODS_ENABLED
+ if ((size_t)p_argcount > sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+
+ if ((size_t)p_argcount < sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+ call_with_variant_args_static<P...>(p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
template <class T, class R, class... P>
void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
@@ -659,6 +758,72 @@ void call_with_variant_args_retc_static_helper_dv(T *p_instance, R (*p_method)(T
call_with_variant_args_retc_static_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
+template <class R, class... P>
+void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector<Variant> &default_values) {
+#ifdef DEBUG_ENABLED
+ if ((size_t)p_argcount > sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+
+ int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
+
+ int32_t dvs = default_values.size();
+#ifdef DEBUG_ENABLED
+ if (missing > dvs) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+
+ const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array
+ for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
+ if (i < p_argcount) {
+ args[i] = p_args[i];
+ } else {
+ args[i] = &default_values[i - p_argcount + (dvs - missing)];
+ }
+ }
+
+ call_with_variant_args_static_ret(p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+void call_with_variant_args_static_dv(void (*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector<Variant> &default_values) {
+#ifdef DEBUG_ENABLED
+ if ((size_t)p_argcount > sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+
+ int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
+
+ int32_t dvs = default_values.size();
+#ifdef DEBUG_ENABLED
+ if (missing > dvs) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+
+ const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array
+ for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
+ if (i < p_argcount) {
+ args[i] = p_args[i];
+ } else {
+ args[i] = &default_values[i - p_argcount + (dvs - missing)];
+ }
+ }
+
+ call_with_variant_args_static(p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index bd51e2dd1e..a1d9c5ed2f 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -126,7 +126,7 @@ bool Callable::operator==(const Callable &p_callable) const {
if (custom_a == custom_b) {
if (custom_a) {
if (custom == p_callable.custom) {
- return true; //same pointer, dont even compare
+ return true; //same pointer, don't even compare
}
CallableCustom::CompareEqualFunc eq_a = custom->get_compare_equal_func();
@@ -155,7 +155,7 @@ bool Callable::operator<(const Callable &p_callable) const {
if (custom_a == custom_b) {
if (custom_a) {
if (custom == p_callable.custom) {
- return false; //same pointer, dont even compare
+ return false; //same pointer, don't even compare
}
CallableCustom::CompareLessFunc less_a = custom->get_compare_less_func();
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 5050aa24ec..0acafc64fa 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -495,6 +495,7 @@ public:
static bool has_builtin_method_return_value(Variant::Type p_type, const StringName &p_method);
static Variant::Type get_builtin_method_return_type(Variant::Type p_type, const StringName &p_method);
static bool is_builtin_method_const(Variant::Type p_type, const StringName &p_method);
+ static bool is_builtin_method_static(Variant::Type p_type, const StringName &p_method);
static bool is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method);
static void get_builtin_method_list(Variant::Type p_type, List<StringName> *p_list);
static int get_builtin_method_count(Variant::Type p_type);
@@ -502,6 +503,8 @@ public:
void call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant());
+ static void call_static(Variant::Type p_type, const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
+
static String get_call_error_text(const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
static String get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
static String get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 2fd8134fbd..8c1d8066d6 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -42,6 +42,16 @@
typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args);
typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args);
+template <class R, class... P>
+static _FORCE_INLINE_ void vc_static_method_call(R (*method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ call_with_variant_args_static_ret_dv(method, p_args, p_argcount, r_ret, r_error, p_defvals);
+}
+
+template <class... P>
+static _FORCE_INLINE_ void vc_static_method_call(void (*method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ call_with_variant_args_static_dv(method, p_args, p_argcount, r_error, p_defvals);
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ void vc_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) {
call_with_variant_args_ret_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, p_defvals);
@@ -81,6 +91,16 @@ static _FORCE_INLINE_ void vc_validated_call(void (T::*method)(P...) const, Vari
call_with_validated_variant_argsc(base, method, p_args);
}
+template <class R, class... P>
+static _FORCE_INLINE_ void vc_validated_static_call(R (*method)(P...), const Variant **p_args, Variant *r_ret) {
+ call_with_validated_variant_args_static_method_ret(method, p_args, r_ret);
+}
+
+template <class... P>
+static _FORCE_INLINE_ void vc_validated_static_call(void (*method)(P...), const Variant **p_args, Variant *r_ret) {
+ call_with_validated_variant_args_static_method(method, p_args);
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ void vc_ptrcall(R (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) {
call_with_ptr_args_ret(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
@@ -150,6 +170,11 @@ static _FORCE_INLINE_ int vc_get_argument_count(R (*method)(T *, P...)) {
return sizeof...(P);
}
+template <class R, class... P>
+static _FORCE_INLINE_ int vc_get_argument_count_static(R (*method)(P...)) {
+ return sizeof...(P);
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (T::*method)(P...), int p_arg) {
return call_get_argument_type<P...>(p_arg);
@@ -174,6 +199,11 @@ static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (*method)(T *, P...),
return call_get_argument_type<P...>(p_arg);
}
+template <class R, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_argument_type_static(R (*method)(P...), int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ Variant::Type vc_get_return_type(R (T::*method)(P...)) {
return GetTypeInfo<R>::VARIANT_TYPE;
@@ -218,6 +248,16 @@ static _FORCE_INLINE_ bool vc_has_return_type(void (T::*method)(P...) const) {
return false;
}
+template <class... P>
+static _FORCE_INLINE_ bool vc_has_return_type_static(void (*method)(P...)) {
+ return false;
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ bool vc_has_return_type_static(R (*method)(P...)) {
+ return true;
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ bool vc_is_const(R (T::*method)(P...)) {
return false;
@@ -283,6 +323,9 @@ static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...) con
static bool is_const() { \
return vc_is_const(m_method_ptr); \
} \
+ static bool is_static() { \
+ return false; \
+ } \
static bool is_vararg() { \
return false; \
} \
@@ -294,6 +337,57 @@ static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...) con
} \
};
+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);
+}
+
+template <class... P>
+static _FORCE_INLINE_ void vc_static_ptrcall(void (*method)(P...), const void **p_args, void *r_ret) {
+ call_with_ptr_args_static_method<P...>(method, p_args);
+}
+
+#define STATIC_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_static_method_call(m_method_ptr, 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_change_return_type(m_method_ptr, r_ret); \
+ vc_validated_static_call(m_method_ptr, p_args, r_ret); \
+ } \
+ static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \
+ vc_static_ptrcall(m_method_ptr, p_args, r_ret); \
+ } \
+ static int get_argument_count() { \
+ return vc_get_argument_count_static(m_method_ptr); \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return vc_get_argument_type_static(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_static(m_method_ptr); \
+ } \
+ static bool is_const() { \
+ return false; \
+ } \
+ static bool is_static() { \
+ return true; \
+ } \
+ 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 T, class... P>
static _FORCE_INLINE_ void vc_ptrcall(R (*method)(T *, P...), void *p_base, const void **p_args, void *r_ret) {
call_with_ptr_args_static_retc<T, R, P...>(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
@@ -326,6 +420,9 @@ static _FORCE_INLINE_ void vc_ptrcall(R (*method)(T *, P...), void *p_base, cons
static bool is_const() { \
return true; \
} \
+ static bool is_static() { \
+ return false; \
+ } \
static bool is_vararg() { \
return false; \
} \
@@ -379,6 +476,9 @@ static _FORCE_INLINE_ void vc_ptrcall(R (*method)(T *, P...), void *p_base, cons
static bool is_const() { \
return true; \
} \
+ static bool is_static() { \
+ return false; \
+ } \
static bool is_vararg() { \
return true; \
} \
@@ -549,6 +649,7 @@ struct VariantBuiltInMethodInfo {
Vector<String> argument_names;
bool is_const;
+ bool is_static;
bool has_return_type;
bool is_vararg;
Variant::Type return_type;
@@ -580,6 +681,7 @@ static void register_builtin_method(const Vector<String> &p_argnames, const Vect
imi.argument_names = p_argnames;
imi.is_const = T::is_const();
+ imi.is_static = T::is_static();
imi.is_vararg = T::is_vararg();
imi.has_return_type = T::has_return_type();
imi.return_type = T::get_return_type();
@@ -625,6 +727,24 @@ void Variant::call(const StringName &p_method, const Variant **p_args, int p_arg
}
}
+void Variant::call_static(Variant::Type p_type, const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+
+ const VariantBuiltInMethodInfo *imf = builtin_method_info[p_type].lookup_ptr(p_method);
+
+ if (!imf) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ return;
+ }
+
+ if (!imf->is_static) {
+ r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
+ return;
+ }
+
+ imf->call(nullptr, p_args, p_argcount, r_ret, imf->default_arguments, r_error);
+}
+
bool Variant::has_method(const StringName &p_method) const {
if (type == OBJECT) {
Object *obj = get_validated_object();
@@ -724,6 +844,13 @@ bool Variant::is_builtin_method_const(Variant::Type p_type, const StringName &p_
return method->is_const;
}
+bool Variant::is_builtin_method_static(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, false);
+ return method->is_static;
+}
+
bool Variant::is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
@@ -759,7 +886,9 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const {
if (method->is_vararg) {
mi.flags |= METHOD_FLAG_VARARG;
}
-
+ if (method->is_static) {
+ mi.flags |= METHOD_FLAG_STATIC;
+ }
for (int i = 0; i < method->argument_count; i++) {
PropertyInfo pi;
#ifdef DEBUG_METHODS_ENABLED
@@ -855,6 +984,16 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va
#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);
+#else
+#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>(sarray(), m_default_args);
+#endif
+
+#ifdef DEBUG_METHODS_ENABLED
#define bind_methodv(m_type, m_name, m_method, m_arg_names, m_default_args) \
METHOD_CLASS(m_type, m_name, m_method); \
register_builtin_method<Method_##m_type##_##m_name>(m_arg_names, m_default_args);
@@ -956,6 +1095,8 @@ static void _register_variant_builtin_methods() {
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_integer, sarray(), varray());
bind_method(String, is_valid_float, sarray(), varray());
@@ -981,6 +1122,11 @@ static void _register_variant_builtin_methods() {
bind_method(String, to_utf16_buffer, sarray(), varray());
bind_method(String, to_utf32_buffer, sarray(), varray());
+ bind_static_method(String, num_scientific, sarray("number"), varray());
+ bind_static_method(String, num, sarray("number", "decimals"), varray(-1));
+ bind_static_method(String, chr, sarray("char"), varray());
+ bind_static_method(String, humanize_size, sarray("size"), varray());
+
/* Vector2 */
bind_method(Vector2, angle, sarray(), varray());
@@ -1059,6 +1205,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector3, min_axis, sarray(), varray());
bind_method(Vector3, max_axis, sarray(), varray());
bind_method(Vector3, angle_to, sarray("to"), varray());
+ bind_method(Vector3, signed_angle_to, sarray("to", "axis"), varray());
bind_method(Vector3, direction_to, sarray("b"), varray());
bind_method(Vector3, distance_to, sarray("b"), varray());
bind_method(Vector3, distance_squared_to, sarray("b"), varray());
@@ -1144,6 +1291,17 @@ static void _register_variant_builtin_methods() {
//ADDFUNC4R(COLOR, COLOR, Color, from_hsv, FLOAT, "h", FLOAT, "s", FLOAT, "v", FLOAT, "a", varray(1.0));
bind_method(Color, is_equal_approx, sarray("to"), varray());
+ bind_static_method(Color, hex, sarray("hex"), varray());
+ bind_static_method(Color, hex64, sarray("hex"), varray());
+ bind_static_method(Color, html, sarray("rgba"), varray());
+ bind_static_method(Color, html_is_valid, sarray("color"), varray());
+ bind_static_method(Color, find_named_color, sarray("name"), varray());
+ bind_static_method(Color, get_named_color_count, sarray(), varray());
+ bind_static_method(Color, get_named_color_name, sarray("idx"), varray());
+ bind_static_method(Color, get_named_color, sarray("idx"), varray());
+ bind_static_method(Color, from_string, sarray("str", "default"), varray());
+ bind_static_method(Color, from_rgbe9995, sarray("rgbe"), varray());
+
/* RID */
bind_method(RID, get_id, sarray(), varray());
@@ -1256,7 +1414,7 @@ static void _register_variant_builtin_methods() {
bind_method(Transform, rotated, sarray("axis", "phi"), varray());
bind_method(Transform, scaled, sarray("scale"), varray());
bind_method(Transform, translated, sarray("offset"), varray());
- bind_method(Transform, looking_at, sarray("target", "up"), varray());
+ bind_method(Transform, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0)));
bind_method(Transform, interpolate_with, sarray("xform", "weight"), varray());
bind_method(Transform, is_equal_approx, sarray("xform"), varray());
@@ -1298,10 +1456,10 @@ static void _register_variant_builtin_methods() {
bind_method(Array, pop_back, sarray(), varray());
bind_method(Array, pop_front, sarray(), varray());
bind_method(Array, sort, sarray(), varray());
- bind_method(Array, sort_custom, sarray("obj", "func"), varray());
+ bind_method(Array, sort_custom, sarray("func"), varray());
bind_method(Array, shuffle, sarray(), varray());
bind_method(Array, bsearch, sarray("value", "before"), varray(true));
- bind_method(Array, bsearch_custom, sarray("value", "obj", "func", "before"), varray(true));
+ bind_method(Array, bsearch_custom, sarray("value", "func", "before"), varray(true));
bind_method(Array, invert, sarray(), varray());
bind_method(Array, duplicate, sarray("deep"), varray(false));
bind_method(Array, slice, sarray("begin", "end", "step", "deep"), varray(1, false));
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index 52f9f6060e..f0c9e52b46 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -773,6 +773,7 @@ void Variant::_unregister_variant_constructors() {
}
void Variant::construct(Variant::Type p_type, Variant &base, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX);
uint32_t s = construct_data[p_type].size();
for (uint32_t i = 0; i < s; i++) {
int argc = construct_data[p_type][i].argument_count;
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index ed936c626b..edaeddbf27 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -381,7 +381,6 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
r_token.value = num.as_int();
}
return OK;
-
} else if ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_') {
StringBuffer<> id;
bool first = true;
@@ -508,8 +507,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
} else if (id == "nan") {
value = Math_NAN;
} else if (id == "Vector2") {
- Vector<float> args;
- Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
return err;
}
@@ -534,8 +533,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Vector2i(args[0], args[1]);
} else if (id == "Rect2") {
- Vector<float> args;
- Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
return err;
}
@@ -560,8 +559,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Rect2i(args[0], args[1], args[2], args[3]);
} else if (id == "Vector3") {
- Vector<float> args;
- Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
return err;
}
@@ -586,8 +585,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Vector3i(args[0], args[1], args[2]);
} else if (id == "Transform2D" || id == "Matrix32") { //compatibility
- Vector<float> args;
- Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
return err;
}
@@ -603,8 +602,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
m[2] = Vector2(args[4], args[5]);
value = m;
} else if (id == "Plane") {
- Vector<float> args;
- Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
return err;
}
@@ -616,8 +615,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Plane(args[0], args[1], args[2], args[3]);
} else if (id == "Quat") {
- Vector<float> args;
- Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
return err;
}
@@ -629,8 +628,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Quat(args[0], args[1], args[2], args[3]);
} else if (id == "AABB" || id == "Rect3") {
- Vector<float> args;
- Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
return err;
}
@@ -642,8 +641,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = AABB(Vector3(args[0], args[1], args[2]), Vector3(args[3], args[4], args[5]));
} else if (id == "Basis" || id == "Matrix3") { //compatibility
- Vector<float> args;
- Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
return err;
}
@@ -655,8 +654,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
} else if (id == "Transform") {
- Vector<float> args;
- Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
return err;
}
@@ -1006,8 +1005,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = arr;
} else if (id == "PackedVector2Array" || id == "PoolVector2Array" || id == "Vector2Array") {
- Vector<float> args;
- Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
return err;
}
@@ -1024,8 +1023,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = arr;
} else if (id == "PackedVector3Array" || id == "PoolVector3Array" || id == "Vector3Array") {
- Vector<float> args;
- Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
if (err) {
return err;
}
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index ea8263402a..f9cc7c4ff4 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -2198,7 +2198,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
}
return;
case STRING: {
- //this is pretty funny and bizarre, but artists like to use it for typewritter effects
+ //this is pretty funny and bizarre, but artists like to use it for typewriter effects
String sa = *reinterpret_cast<const String *>(a._data._mem);
String sb = *reinterpret_cast<const String *>(b._data._mem);
String dst;
diff --git a/doc/Makefile b/doc/Makefile
index 9534da9bd5..d4bc53bcf9 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -2,6 +2,7 @@ BASEDIR = $(CURDIR)
CLASSES = $(BASEDIR)/classes/ $(BASEDIR)/../modules/
OUTPUTDIR = $(BASEDIR)/_build
TOOLSDIR = $(BASEDIR)/tools
+JSDIR = $(BASEDIR)/../platform/javascript
.ONESHELL:
@@ -16,6 +17,10 @@ doxygen:
rst:
rm -rf $(OUTPUTDIR)/rst
mkdir -p $(OUTPUTDIR)/rst
- pushd $(OUTPUTDIR)/rst
- python3 $(TOOLSDIR)/makerst.py $(CLASSES)
- popd
+ python3 $(TOOLSDIR)/makerst.py -o $(OUTPUTDIR)/rst $(CLASSES)
+
+rstjs:
+ rm -rf $(OUTPUTDIR)/rstjs
+ mkdir -p $(OUTPUTDIR)/rstjs
+ npm --prefix $(JSDIR) ci
+ npm --prefix $(JSDIR) run docs -- --destination $(OUTPUTDIR)/rstjs/html5_shell_classref.rst
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index bf81362e79..25f8f22d44 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -50,7 +50,7 @@
<argument index="0" name="x" type="float">
</argument>
<description>
- Returns the arc cosine of [code]x[/code] in radians. Use to get the angle of cosine [code]x[/code].
+ Returns the arc cosine of [code]x[/code] in radians. Use to get the angle of cosine [code]x[/code]. [code]x[/code] must be between [code]-1.0[/code] and [code]1.0[/code] (inclusive), otherwise, [method acos] will return [constant @GDScript.NAN].
[codeblock]
# c is 0.523599 or 30 degrees if converted with rad2deg(c)
c = acos(0.866025)
@@ -63,7 +63,7 @@
<argument index="0" name="x" type="float">
</argument>
<description>
- Returns the arc sine of [code]x[/code] in radians. Use to get the angle of sine [code]x[/code].
+ Returns the arc sine of [code]x[/code] in radians. Use to get the angle of sine [code]x[/code]. [code]x[/code] must be between [code]-1.0[/code] and [code]1.0[/code] (inclusive), otherwise, [method asin] will return [constant @GDScript.NAN].
[codeblock]
# s is 0.523599 or 30 degrees if converted with rad2deg(s)
s = asin(0.5)
@@ -777,7 +777,7 @@
<return type="int">
</return>
<description>
- Returns a random unsigned 32 bit integer. Use remainder to obtain a random value in the interval [code][0, N - 1][/code] (where N is smaller than 2^32).
+ Returns a random unsigned 32-bit integer. Use remainder to obtain a random value in the interval [code][0, N - 1][/code] (where N is smaller than 2^32).
[codeblock]
randi() # Returns random integer between 0 and 2^32 - 1
randi() % 20 # Returns random integer between 0 and 19
@@ -935,7 +935,7 @@
<description>
Returns the result of smoothly interpolating the value of [code]x[/code] between [code]0[/code] and [code]1[/code], based on the where [code]x[/code] lies with respect to the edges [code]from[/code] and [code]to[/code].
The return value is [code]0[/code] if [code]x &lt;= from[/code], and [code]1[/code] if [code]x &gt;= to[/code]. If [code]x[/code] lies between [code]from[/code] and [code]to[/code], the returned value follows an S-shaped curve that maps [code]x[/code] between [code]0[/code] and [code]1[/code].
- This S-shaped curve is the cubic Hermite interpolator, given by [code]f(x) = 3*x^2 - 2*x^3[/code].
+ This S-shaped curve is the cubic Hermite interpolator, given by [code]f(y) = 3*y^2 - 2*y^3[/code] where [code]y = (x-from) / (to-from)[/code].
[codeblock]
smoothstep(0, 2, -5.0) # Returns 0.0
smoothstep(0, 2, 0.5) # Returns 0.15625
@@ -1280,6 +1280,10 @@
<constant name="HORIZONTAL" value="0" enum="Orientation">
General horizontal alignment, usually used for [Separator], [ScrollBar], [Slider], etc.
</constant>
+ <constant name="CLOCKWISE" value="0" enum="ClockDirection">
+ </constant>
+ <constant name="COUNTERCLOCKWISE" value="1" enum="ClockDirection">
+ </constant>
<constant name="HALIGN_LEFT" value="0" enum="HAlign">
Horizontal left alignment, usually for text-derived classes.
</constant>
@@ -1304,730 +1308,730 @@
<constant name="SPKEY" value="16777216">
Keycodes with this bit applied are non-printable.
</constant>
- <constant name="KEY_ESCAPE" value="16777217" enum="KeyList">
+ <constant name="KEY_ESCAPE" value="16777217" enum="Key">
Escape key.
</constant>
- <constant name="KEY_TAB" value="16777218" enum="KeyList">
+ <constant name="KEY_TAB" value="16777218" enum="Key">
Tab key.
</constant>
- <constant name="KEY_BACKTAB" value="16777219" enum="KeyList">
+ <constant name="KEY_BACKTAB" value="16777219" enum="Key">
Shift + Tab key.
</constant>
- <constant name="KEY_BACKSPACE" value="16777220" enum="KeyList">
+ <constant name="KEY_BACKSPACE" value="16777220" enum="Key">
Backspace key.
</constant>
- <constant name="KEY_ENTER" value="16777221" enum="KeyList">
+ <constant name="KEY_ENTER" value="16777221" enum="Key">
Return key (on the main keyboard).
</constant>
- <constant name="KEY_KP_ENTER" value="16777222" enum="KeyList">
+ <constant name="KEY_KP_ENTER" value="16777222" enum="Key">
Enter key on the numeric keypad.
</constant>
- <constant name="KEY_INSERT" value="16777223" enum="KeyList">
+ <constant name="KEY_INSERT" value="16777223" enum="Key">
Insert key.
</constant>
- <constant name="KEY_DELETE" value="16777224" enum="KeyList">
+ <constant name="KEY_DELETE" value="16777224" enum="Key">
Delete key.
</constant>
- <constant name="KEY_PAUSE" value="16777225" enum="KeyList">
+ <constant name="KEY_PAUSE" value="16777225" enum="Key">
Pause key.
</constant>
- <constant name="KEY_PRINT" value="16777226" enum="KeyList">
+ <constant name="KEY_PRINT" value="16777226" enum="Key">
Print Screen key.
</constant>
- <constant name="KEY_SYSREQ" value="16777227" enum="KeyList">
+ <constant name="KEY_SYSREQ" value="16777227" enum="Key">
System Request key.
</constant>
- <constant name="KEY_CLEAR" value="16777228" enum="KeyList">
+ <constant name="KEY_CLEAR" value="16777228" enum="Key">
Clear key.
</constant>
- <constant name="KEY_HOME" value="16777229" enum="KeyList">
+ <constant name="KEY_HOME" value="16777229" enum="Key">
Home key.
</constant>
- <constant name="KEY_END" value="16777230" enum="KeyList">
+ <constant name="KEY_END" value="16777230" enum="Key">
End key.
</constant>
- <constant name="KEY_LEFT" value="16777231" enum="KeyList">
+ <constant name="KEY_LEFT" value="16777231" enum="Key">
Left arrow key.
</constant>
- <constant name="KEY_UP" value="16777232" enum="KeyList">
+ <constant name="KEY_UP" value="16777232" enum="Key">
Up arrow key.
</constant>
- <constant name="KEY_RIGHT" value="16777233" enum="KeyList">
+ <constant name="KEY_RIGHT" value="16777233" enum="Key">
Right arrow key.
</constant>
- <constant name="KEY_DOWN" value="16777234" enum="KeyList">
+ <constant name="KEY_DOWN" value="16777234" enum="Key">
Down arrow key.
</constant>
- <constant name="KEY_PAGEUP" value="16777235" enum="KeyList">
+ <constant name="KEY_PAGEUP" value="16777235" enum="Key">
Page Up key.
</constant>
- <constant name="KEY_PAGEDOWN" value="16777236" enum="KeyList">
+ <constant name="KEY_PAGEDOWN" value="16777236" enum="Key">
Page Down key.
</constant>
- <constant name="KEY_SHIFT" value="16777237" enum="KeyList">
+ <constant name="KEY_SHIFT" value="16777237" enum="Key">
Shift key.
</constant>
- <constant name="KEY_CONTROL" value="16777238" enum="KeyList">
+ <constant name="KEY_CONTROL" value="16777238" enum="Key">
Control key.
</constant>
- <constant name="KEY_META" value="16777239" enum="KeyList">
+ <constant name="KEY_META" value="16777239" enum="Key">
Meta key.
</constant>
- <constant name="KEY_ALT" value="16777240" enum="KeyList">
+ <constant name="KEY_ALT" value="16777240" enum="Key">
Alt key.
</constant>
- <constant name="KEY_CAPSLOCK" value="16777241" enum="KeyList">
+ <constant name="KEY_CAPSLOCK" value="16777241" enum="Key">
Caps Lock key.
</constant>
- <constant name="KEY_NUMLOCK" value="16777242" enum="KeyList">
+ <constant name="KEY_NUMLOCK" value="16777242" enum="Key">
Num Lock key.
</constant>
- <constant name="KEY_SCROLLLOCK" value="16777243" enum="KeyList">
+ <constant name="KEY_SCROLLLOCK" value="16777243" enum="Key">
Scroll Lock key.
</constant>
- <constant name="KEY_F1" value="16777244" enum="KeyList">
+ <constant name="KEY_F1" value="16777244" enum="Key">
F1 key.
</constant>
- <constant name="KEY_F2" value="16777245" enum="KeyList">
+ <constant name="KEY_F2" value="16777245" enum="Key">
F2 key.
</constant>
- <constant name="KEY_F3" value="16777246" enum="KeyList">
+ <constant name="KEY_F3" value="16777246" enum="Key">
F3 key.
</constant>
- <constant name="KEY_F4" value="16777247" enum="KeyList">
+ <constant name="KEY_F4" value="16777247" enum="Key">
F4 key.
</constant>
- <constant name="KEY_F5" value="16777248" enum="KeyList">
+ <constant name="KEY_F5" value="16777248" enum="Key">
F5 key.
</constant>
- <constant name="KEY_F6" value="16777249" enum="KeyList">
+ <constant name="KEY_F6" value="16777249" enum="Key">
F6 key.
</constant>
- <constant name="KEY_F7" value="16777250" enum="KeyList">
+ <constant name="KEY_F7" value="16777250" enum="Key">
F7 key.
</constant>
- <constant name="KEY_F8" value="16777251" enum="KeyList">
+ <constant name="KEY_F8" value="16777251" enum="Key">
F8 key.
</constant>
- <constant name="KEY_F9" value="16777252" enum="KeyList">
+ <constant name="KEY_F9" value="16777252" enum="Key">
F9 key.
</constant>
- <constant name="KEY_F10" value="16777253" enum="KeyList">
+ <constant name="KEY_F10" value="16777253" enum="Key">
F10 key.
</constant>
- <constant name="KEY_F11" value="16777254" enum="KeyList">
+ <constant name="KEY_F11" value="16777254" enum="Key">
F11 key.
</constant>
- <constant name="KEY_F12" value="16777255" enum="KeyList">
+ <constant name="KEY_F12" value="16777255" enum="Key">
F12 key.
</constant>
- <constant name="KEY_F13" value="16777256" enum="KeyList">
+ <constant name="KEY_F13" value="16777256" enum="Key">
F13 key.
</constant>
- <constant name="KEY_F14" value="16777257" enum="KeyList">
+ <constant name="KEY_F14" value="16777257" enum="Key">
F14 key.
</constant>
- <constant name="KEY_F15" value="16777258" enum="KeyList">
+ <constant name="KEY_F15" value="16777258" enum="Key">
F15 key.
</constant>
- <constant name="KEY_F16" value="16777259" enum="KeyList">
+ <constant name="KEY_F16" value="16777259" enum="Key">
F16 key.
</constant>
- <constant name="KEY_KP_MULTIPLY" value="16777345" enum="KeyList">
+ <constant name="KEY_KP_MULTIPLY" value="16777345" enum="Key">
Multiply (*) key on the numeric keypad.
</constant>
- <constant name="KEY_KP_DIVIDE" value="16777346" enum="KeyList">
+ <constant name="KEY_KP_DIVIDE" value="16777346" enum="Key">
Divide (/) key on the numeric keypad.
</constant>
- <constant name="KEY_KP_SUBTRACT" value="16777347" enum="KeyList">
+ <constant name="KEY_KP_SUBTRACT" value="16777347" enum="Key">
Subtract (-) key on the numeric keypad.
</constant>
- <constant name="KEY_KP_PERIOD" value="16777348" enum="KeyList">
+ <constant name="KEY_KP_PERIOD" value="16777348" enum="Key">
Period (.) key on the numeric keypad.
</constant>
- <constant name="KEY_KP_ADD" value="16777349" enum="KeyList">
+ <constant name="KEY_KP_ADD" value="16777349" enum="Key">
Add (+) key on the numeric keypad.
</constant>
- <constant name="KEY_KP_0" value="16777350" enum="KeyList">
+ <constant name="KEY_KP_0" value="16777350" enum="Key">
Number 0 on the numeric keypad.
</constant>
- <constant name="KEY_KP_1" value="16777351" enum="KeyList">
+ <constant name="KEY_KP_1" value="16777351" enum="Key">
Number 1 on the numeric keypad.
</constant>
- <constant name="KEY_KP_2" value="16777352" enum="KeyList">
+ <constant name="KEY_KP_2" value="16777352" enum="Key">
Number 2 on the numeric keypad.
</constant>
- <constant name="KEY_KP_3" value="16777353" enum="KeyList">
+ <constant name="KEY_KP_3" value="16777353" enum="Key">
Number 3 on the numeric keypad.
</constant>
- <constant name="KEY_KP_4" value="16777354" enum="KeyList">
+ <constant name="KEY_KP_4" value="16777354" enum="Key">
Number 4 on the numeric keypad.
</constant>
- <constant name="KEY_KP_5" value="16777355" enum="KeyList">
+ <constant name="KEY_KP_5" value="16777355" enum="Key">
Number 5 on the numeric keypad.
</constant>
- <constant name="KEY_KP_6" value="16777356" enum="KeyList">
+ <constant name="KEY_KP_6" value="16777356" enum="Key">
Number 6 on the numeric keypad.
</constant>
- <constant name="KEY_KP_7" value="16777357" enum="KeyList">
+ <constant name="KEY_KP_7" value="16777357" enum="Key">
Number 7 on the numeric keypad.
</constant>
- <constant name="KEY_KP_8" value="16777358" enum="KeyList">
+ <constant name="KEY_KP_8" value="16777358" enum="Key">
Number 8 on the numeric keypad.
</constant>
- <constant name="KEY_KP_9" value="16777359" enum="KeyList">
+ <constant name="KEY_KP_9" value="16777359" enum="Key">
Number 9 on the numeric keypad.
</constant>
- <constant name="KEY_SUPER_L" value="16777260" enum="KeyList">
+ <constant name="KEY_SUPER_L" value="16777260" enum="Key">
Left Super key (Windows key).
</constant>
- <constant name="KEY_SUPER_R" value="16777261" enum="KeyList">
+ <constant name="KEY_SUPER_R" value="16777261" enum="Key">
Right Super key (Windows key).
</constant>
- <constant name="KEY_MENU" value="16777262" enum="KeyList">
+ <constant name="KEY_MENU" value="16777262" enum="Key">
Context menu key.
</constant>
- <constant name="KEY_HYPER_L" value="16777263" enum="KeyList">
+ <constant name="KEY_HYPER_L" value="16777263" enum="Key">
Left Hyper key.
</constant>
- <constant name="KEY_HYPER_R" value="16777264" enum="KeyList">
+ <constant name="KEY_HYPER_R" value="16777264" enum="Key">
Right Hyper key.
</constant>
- <constant name="KEY_HELP" value="16777265" enum="KeyList">
+ <constant name="KEY_HELP" value="16777265" enum="Key">
Help key.
</constant>
- <constant name="KEY_DIRECTION_L" value="16777266" enum="KeyList">
+ <constant name="KEY_DIRECTION_L" value="16777266" enum="Key">
Left Direction key.
</constant>
- <constant name="KEY_DIRECTION_R" value="16777267" enum="KeyList">
+ <constant name="KEY_DIRECTION_R" value="16777267" enum="Key">
Right Direction key.
</constant>
- <constant name="KEY_BACK" value="16777280" enum="KeyList">
+ <constant name="KEY_BACK" value="16777280" enum="Key">
Media back key. Not to be confused with the Back button on an Android device.
</constant>
- <constant name="KEY_FORWARD" value="16777281" enum="KeyList">
+ <constant name="KEY_FORWARD" value="16777281" enum="Key">
Media forward key.
</constant>
- <constant name="KEY_STOP" value="16777282" enum="KeyList">
+ <constant name="KEY_STOP" value="16777282" enum="Key">
Media stop key.
</constant>
- <constant name="KEY_REFRESH" value="16777283" enum="KeyList">
+ <constant name="KEY_REFRESH" value="16777283" enum="Key">
Media refresh key.
</constant>
- <constant name="KEY_VOLUMEDOWN" value="16777284" enum="KeyList">
+ <constant name="KEY_VOLUMEDOWN" value="16777284" enum="Key">
Volume down key.
</constant>
- <constant name="KEY_VOLUMEMUTE" value="16777285" enum="KeyList">
+ <constant name="KEY_VOLUMEMUTE" value="16777285" enum="Key">
Mute volume key.
</constant>
- <constant name="KEY_VOLUMEUP" value="16777286" enum="KeyList">
+ <constant name="KEY_VOLUMEUP" value="16777286" enum="Key">
Volume up key.
</constant>
- <constant name="KEY_BASSBOOST" value="16777287" enum="KeyList">
+ <constant name="KEY_BASSBOOST" value="16777287" enum="Key">
Bass Boost key.
</constant>
- <constant name="KEY_BASSUP" value="16777288" enum="KeyList">
+ <constant name="KEY_BASSUP" value="16777288" enum="Key">
Bass up key.
</constant>
- <constant name="KEY_BASSDOWN" value="16777289" enum="KeyList">
+ <constant name="KEY_BASSDOWN" value="16777289" enum="Key">
Bass down key.
</constant>
- <constant name="KEY_TREBLEUP" value="16777290" enum="KeyList">
+ <constant name="KEY_TREBLEUP" value="16777290" enum="Key">
Treble up key.
</constant>
- <constant name="KEY_TREBLEDOWN" value="16777291" enum="KeyList">
+ <constant name="KEY_TREBLEDOWN" value="16777291" enum="Key">
Treble down key.
</constant>
- <constant name="KEY_MEDIAPLAY" value="16777292" enum="KeyList">
+ <constant name="KEY_MEDIAPLAY" value="16777292" enum="Key">
Media play key.
</constant>
- <constant name="KEY_MEDIASTOP" value="16777293" enum="KeyList">
+ <constant name="KEY_MEDIASTOP" value="16777293" enum="Key">
Media stop key.
</constant>
- <constant name="KEY_MEDIAPREVIOUS" value="16777294" enum="KeyList">
+ <constant name="KEY_MEDIAPREVIOUS" value="16777294" enum="Key">
Previous song key.
</constant>
- <constant name="KEY_MEDIANEXT" value="16777295" enum="KeyList">
+ <constant name="KEY_MEDIANEXT" value="16777295" enum="Key">
Next song key.
</constant>
- <constant name="KEY_MEDIARECORD" value="16777296" enum="KeyList">
+ <constant name="KEY_MEDIARECORD" value="16777296" enum="Key">
Media record key.
</constant>
- <constant name="KEY_HOMEPAGE" value="16777297" enum="KeyList">
+ <constant name="KEY_HOMEPAGE" value="16777297" enum="Key">
Home page key.
</constant>
- <constant name="KEY_FAVORITES" value="16777298" enum="KeyList">
+ <constant name="KEY_FAVORITES" value="16777298" enum="Key">
Favorites key.
</constant>
- <constant name="KEY_SEARCH" value="16777299" enum="KeyList">
+ <constant name="KEY_SEARCH" value="16777299" enum="Key">
Search key.
</constant>
- <constant name="KEY_STANDBY" value="16777300" enum="KeyList">
+ <constant name="KEY_STANDBY" value="16777300" enum="Key">
Standby key.
</constant>
- <constant name="KEY_OPENURL" value="16777301" enum="KeyList">
+ <constant name="KEY_OPENURL" value="16777301" enum="Key">
Open URL / Launch Browser key.
</constant>
- <constant name="KEY_LAUNCHMAIL" value="16777302" enum="KeyList">
+ <constant name="KEY_LAUNCHMAIL" value="16777302" enum="Key">
Launch Mail key.
</constant>
- <constant name="KEY_LAUNCHMEDIA" value="16777303" enum="KeyList">
+ <constant name="KEY_LAUNCHMEDIA" value="16777303" enum="Key">
Launch Media key.
</constant>
- <constant name="KEY_LAUNCH0" value="16777304" enum="KeyList">
+ <constant name="KEY_LAUNCH0" value="16777304" enum="Key">
Launch Shortcut 0 key.
</constant>
- <constant name="KEY_LAUNCH1" value="16777305" enum="KeyList">
+ <constant name="KEY_LAUNCH1" value="16777305" enum="Key">
Launch Shortcut 1 key.
</constant>
- <constant name="KEY_LAUNCH2" value="16777306" enum="KeyList">
+ <constant name="KEY_LAUNCH2" value="16777306" enum="Key">
Launch Shortcut 2 key.
</constant>
- <constant name="KEY_LAUNCH3" value="16777307" enum="KeyList">
+ <constant name="KEY_LAUNCH3" value="16777307" enum="Key">
Launch Shortcut 3 key.
</constant>
- <constant name="KEY_LAUNCH4" value="16777308" enum="KeyList">
+ <constant name="KEY_LAUNCH4" value="16777308" enum="Key">
Launch Shortcut 4 key.
</constant>
- <constant name="KEY_LAUNCH5" value="16777309" enum="KeyList">
+ <constant name="KEY_LAUNCH5" value="16777309" enum="Key">
Launch Shortcut 5 key.
</constant>
- <constant name="KEY_LAUNCH6" value="16777310" enum="KeyList">
+ <constant name="KEY_LAUNCH6" value="16777310" enum="Key">
Launch Shortcut 6 key.
</constant>
- <constant name="KEY_LAUNCH7" value="16777311" enum="KeyList">
+ <constant name="KEY_LAUNCH7" value="16777311" enum="Key">
Launch Shortcut 7 key.
</constant>
- <constant name="KEY_LAUNCH8" value="16777312" enum="KeyList">
+ <constant name="KEY_LAUNCH8" value="16777312" enum="Key">
Launch Shortcut 8 key.
</constant>
- <constant name="KEY_LAUNCH9" value="16777313" enum="KeyList">
+ <constant name="KEY_LAUNCH9" value="16777313" enum="Key">
Launch Shortcut 9 key.
</constant>
- <constant name="KEY_LAUNCHA" value="16777314" enum="KeyList">
+ <constant name="KEY_LAUNCHA" value="16777314" enum="Key">
Launch Shortcut A key.
</constant>
- <constant name="KEY_LAUNCHB" value="16777315" enum="KeyList">
+ <constant name="KEY_LAUNCHB" value="16777315" enum="Key">
Launch Shortcut B key.
</constant>
- <constant name="KEY_LAUNCHC" value="16777316" enum="KeyList">
+ <constant name="KEY_LAUNCHC" value="16777316" enum="Key">
Launch Shortcut C key.
</constant>
- <constant name="KEY_LAUNCHD" value="16777317" enum="KeyList">
+ <constant name="KEY_LAUNCHD" value="16777317" enum="Key">
Launch Shortcut D key.
</constant>
- <constant name="KEY_LAUNCHE" value="16777318" enum="KeyList">
+ <constant name="KEY_LAUNCHE" value="16777318" enum="Key">
Launch Shortcut E key.
</constant>
- <constant name="KEY_LAUNCHF" value="16777319" enum="KeyList">
+ <constant name="KEY_LAUNCHF" value="16777319" enum="Key">
Launch Shortcut F key.
</constant>
- <constant name="KEY_UNKNOWN" value="33554431" enum="KeyList">
+ <constant name="KEY_UNKNOWN" value="33554431" enum="Key">
Unknown key.
</constant>
- <constant name="KEY_SPACE" value="32" enum="KeyList">
+ <constant name="KEY_SPACE" value="32" enum="Key">
Space key.
</constant>
- <constant name="KEY_EXCLAM" value="33" enum="KeyList">
+ <constant name="KEY_EXCLAM" value="33" enum="Key">
! key.
</constant>
- <constant name="KEY_QUOTEDBL" value="34" enum="KeyList">
+ <constant name="KEY_QUOTEDBL" value="34" enum="Key">
" key.
</constant>
- <constant name="KEY_NUMBERSIGN" value="35" enum="KeyList">
+ <constant name="KEY_NUMBERSIGN" value="35" enum="Key">
# key.
</constant>
- <constant name="KEY_DOLLAR" value="36" enum="KeyList">
+ <constant name="KEY_DOLLAR" value="36" enum="Key">
$ key.
</constant>
- <constant name="KEY_PERCENT" value="37" enum="KeyList">
+ <constant name="KEY_PERCENT" value="37" enum="Key">
% key.
</constant>
- <constant name="KEY_AMPERSAND" value="38" enum="KeyList">
+ <constant name="KEY_AMPERSAND" value="38" enum="Key">
&amp; key.
</constant>
- <constant name="KEY_APOSTROPHE" value="39" enum="KeyList">
+ <constant name="KEY_APOSTROPHE" value="39" enum="Key">
' key.
</constant>
- <constant name="KEY_PARENLEFT" value="40" enum="KeyList">
+ <constant name="KEY_PARENLEFT" value="40" enum="Key">
( key.
</constant>
- <constant name="KEY_PARENRIGHT" value="41" enum="KeyList">
+ <constant name="KEY_PARENRIGHT" value="41" enum="Key">
) key.
</constant>
- <constant name="KEY_ASTERISK" value="42" enum="KeyList">
+ <constant name="KEY_ASTERISK" value="42" enum="Key">
* key.
</constant>
- <constant name="KEY_PLUS" value="43" enum="KeyList">
+ <constant name="KEY_PLUS" value="43" enum="Key">
+ key.
</constant>
- <constant name="KEY_COMMA" value="44" enum="KeyList">
+ <constant name="KEY_COMMA" value="44" enum="Key">
, key.
</constant>
- <constant name="KEY_MINUS" value="45" enum="KeyList">
+ <constant name="KEY_MINUS" value="45" enum="Key">
- key.
</constant>
- <constant name="KEY_PERIOD" value="46" enum="KeyList">
+ <constant name="KEY_PERIOD" value="46" enum="Key">
. key.
</constant>
- <constant name="KEY_SLASH" value="47" enum="KeyList">
+ <constant name="KEY_SLASH" value="47" enum="Key">
/ key.
</constant>
- <constant name="KEY_0" value="48" enum="KeyList">
+ <constant name="KEY_0" value="48" enum="Key">
Number 0.
</constant>
- <constant name="KEY_1" value="49" enum="KeyList">
+ <constant name="KEY_1" value="49" enum="Key">
Number 1.
</constant>
- <constant name="KEY_2" value="50" enum="KeyList">
+ <constant name="KEY_2" value="50" enum="Key">
Number 2.
</constant>
- <constant name="KEY_3" value="51" enum="KeyList">
+ <constant name="KEY_3" value="51" enum="Key">
Number 3.
</constant>
- <constant name="KEY_4" value="52" enum="KeyList">
+ <constant name="KEY_4" value="52" enum="Key">
Number 4.
</constant>
- <constant name="KEY_5" value="53" enum="KeyList">
+ <constant name="KEY_5" value="53" enum="Key">
Number 5.
</constant>
- <constant name="KEY_6" value="54" enum="KeyList">
+ <constant name="KEY_6" value="54" enum="Key">
Number 6.
</constant>
- <constant name="KEY_7" value="55" enum="KeyList">
+ <constant name="KEY_7" value="55" enum="Key">
Number 7.
</constant>
- <constant name="KEY_8" value="56" enum="KeyList">
+ <constant name="KEY_8" value="56" enum="Key">
Number 8.
</constant>
- <constant name="KEY_9" value="57" enum="KeyList">
+ <constant name="KEY_9" value="57" enum="Key">
Number 9.
</constant>
- <constant name="KEY_COLON" value="58" enum="KeyList">
+ <constant name="KEY_COLON" value="58" enum="Key">
: key.
</constant>
- <constant name="KEY_SEMICOLON" value="59" enum="KeyList">
+ <constant name="KEY_SEMICOLON" value="59" enum="Key">
; key.
</constant>
- <constant name="KEY_LESS" value="60" enum="KeyList">
+ <constant name="KEY_LESS" value="60" enum="Key">
&lt; key.
</constant>
- <constant name="KEY_EQUAL" value="61" enum="KeyList">
+ <constant name="KEY_EQUAL" value="61" enum="Key">
= key.
</constant>
- <constant name="KEY_GREATER" value="62" enum="KeyList">
+ <constant name="KEY_GREATER" value="62" enum="Key">
&gt; key.
</constant>
- <constant name="KEY_QUESTION" value="63" enum="KeyList">
+ <constant name="KEY_QUESTION" value="63" enum="Key">
? key.
</constant>
- <constant name="KEY_AT" value="64" enum="KeyList">
+ <constant name="KEY_AT" value="64" enum="Key">
@ key.
</constant>
- <constant name="KEY_A" value="65" enum="KeyList">
+ <constant name="KEY_A" value="65" enum="Key">
A key.
</constant>
- <constant name="KEY_B" value="66" enum="KeyList">
+ <constant name="KEY_B" value="66" enum="Key">
B key.
</constant>
- <constant name="KEY_C" value="67" enum="KeyList">
+ <constant name="KEY_C" value="67" enum="Key">
C key.
</constant>
- <constant name="KEY_D" value="68" enum="KeyList">
+ <constant name="KEY_D" value="68" enum="Key">
D key.
</constant>
- <constant name="KEY_E" value="69" enum="KeyList">
+ <constant name="KEY_E" value="69" enum="Key">
E key.
</constant>
- <constant name="KEY_F" value="70" enum="KeyList">
+ <constant name="KEY_F" value="70" enum="Key">
F key.
</constant>
- <constant name="KEY_G" value="71" enum="KeyList">
+ <constant name="KEY_G" value="71" enum="Key">
G key.
</constant>
- <constant name="KEY_H" value="72" enum="KeyList">
+ <constant name="KEY_H" value="72" enum="Key">
H key.
</constant>
- <constant name="KEY_I" value="73" enum="KeyList">
+ <constant name="KEY_I" value="73" enum="Key">
I key.
</constant>
- <constant name="KEY_J" value="74" enum="KeyList">
+ <constant name="KEY_J" value="74" enum="Key">
J key.
</constant>
- <constant name="KEY_K" value="75" enum="KeyList">
+ <constant name="KEY_K" value="75" enum="Key">
K key.
</constant>
- <constant name="KEY_L" value="76" enum="KeyList">
+ <constant name="KEY_L" value="76" enum="Key">
L key.
</constant>
- <constant name="KEY_M" value="77" enum="KeyList">
+ <constant name="KEY_M" value="77" enum="Key">
M key.
</constant>
- <constant name="KEY_N" value="78" enum="KeyList">
+ <constant name="KEY_N" value="78" enum="Key">
N key.
</constant>
- <constant name="KEY_O" value="79" enum="KeyList">
+ <constant name="KEY_O" value="79" enum="Key">
O key.
</constant>
- <constant name="KEY_P" value="80" enum="KeyList">
+ <constant name="KEY_P" value="80" enum="Key">
P key.
</constant>
- <constant name="KEY_Q" value="81" enum="KeyList">
+ <constant name="KEY_Q" value="81" enum="Key">
Q key.
</constant>
- <constant name="KEY_R" value="82" enum="KeyList">
+ <constant name="KEY_R" value="82" enum="Key">
R key.
</constant>
- <constant name="KEY_S" value="83" enum="KeyList">
+ <constant name="KEY_S" value="83" enum="Key">
S key.
</constant>
- <constant name="KEY_T" value="84" enum="KeyList">
+ <constant name="KEY_T" value="84" enum="Key">
T key.
</constant>
- <constant name="KEY_U" value="85" enum="KeyList">
+ <constant name="KEY_U" value="85" enum="Key">
U key.
</constant>
- <constant name="KEY_V" value="86" enum="KeyList">
+ <constant name="KEY_V" value="86" enum="Key">
V key.
</constant>
- <constant name="KEY_W" value="87" enum="KeyList">
+ <constant name="KEY_W" value="87" enum="Key">
W key.
</constant>
- <constant name="KEY_X" value="88" enum="KeyList">
+ <constant name="KEY_X" value="88" enum="Key">
X key.
</constant>
- <constant name="KEY_Y" value="89" enum="KeyList">
+ <constant name="KEY_Y" value="89" enum="Key">
Y key.
</constant>
- <constant name="KEY_Z" value="90" enum="KeyList">
+ <constant name="KEY_Z" value="90" enum="Key">
Z key.
</constant>
- <constant name="KEY_BRACKETLEFT" value="91" enum="KeyList">
+ <constant name="KEY_BRACKETLEFT" value="91" enum="Key">
[ key.
</constant>
- <constant name="KEY_BACKSLASH" value="92" enum="KeyList">
+ <constant name="KEY_BACKSLASH" value="92" enum="Key">
\ key.
</constant>
- <constant name="KEY_BRACKETRIGHT" value="93" enum="KeyList">
+ <constant name="KEY_BRACKETRIGHT" value="93" enum="Key">
] key.
</constant>
- <constant name="KEY_ASCIICIRCUM" value="94" enum="KeyList">
+ <constant name="KEY_ASCIICIRCUM" value="94" enum="Key">
^ key.
</constant>
- <constant name="KEY_UNDERSCORE" value="95" enum="KeyList">
+ <constant name="KEY_UNDERSCORE" value="95" enum="Key">
_ key.
</constant>
- <constant name="KEY_QUOTELEFT" value="96" enum="KeyList">
+ <constant name="KEY_QUOTELEFT" value="96" enum="Key">
` key.
</constant>
- <constant name="KEY_BRACELEFT" value="123" enum="KeyList">
+ <constant name="KEY_BRACELEFT" value="123" enum="Key">
{ key.
</constant>
- <constant name="KEY_BAR" value="124" enum="KeyList">
+ <constant name="KEY_BAR" value="124" enum="Key">
| key.
</constant>
- <constant name="KEY_BRACERIGHT" value="125" enum="KeyList">
+ <constant name="KEY_BRACERIGHT" value="125" enum="Key">
} key.
</constant>
- <constant name="KEY_ASCIITILDE" value="126" enum="KeyList">
+ <constant name="KEY_ASCIITILDE" value="126" enum="Key">
~ key.
</constant>
- <constant name="KEY_NOBREAKSPACE" value="160" enum="KeyList">
+ <constant name="KEY_NOBREAKSPACE" value="160" enum="Key">
Non-breakable space key.
</constant>
- <constant name="KEY_EXCLAMDOWN" value="161" enum="KeyList">
+ <constant name="KEY_EXCLAMDOWN" value="161" enum="Key">
¡ key.
</constant>
- <constant name="KEY_CENT" value="162" enum="KeyList">
+ <constant name="KEY_CENT" value="162" enum="Key">
¢ key.
</constant>
- <constant name="KEY_STERLING" value="163" enum="KeyList">
+ <constant name="KEY_STERLING" value="163" enum="Key">
£ key.
</constant>
- <constant name="KEY_CURRENCY" value="164" enum="KeyList">
+ <constant name="KEY_CURRENCY" value="164" enum="Key">
¤ key.
</constant>
- <constant name="KEY_YEN" value="165" enum="KeyList">
+ <constant name="KEY_YEN" value="165" enum="Key">
¥ key.
</constant>
- <constant name="KEY_BROKENBAR" value="166" enum="KeyList">
+ <constant name="KEY_BROKENBAR" value="166" enum="Key">
¦ key.
</constant>
- <constant name="KEY_SECTION" value="167" enum="KeyList">
+ <constant name="KEY_SECTION" value="167" enum="Key">
§ key.
</constant>
- <constant name="KEY_DIAERESIS" value="168" enum="KeyList">
+ <constant name="KEY_DIAERESIS" value="168" enum="Key">
¨ key.
</constant>
- <constant name="KEY_COPYRIGHT" value="169" enum="KeyList">
+ <constant name="KEY_COPYRIGHT" value="169" enum="Key">
© key.
</constant>
- <constant name="KEY_ORDFEMININE" value="170" enum="KeyList">
+ <constant name="KEY_ORDFEMININE" value="170" enum="Key">
ª key.
</constant>
- <constant name="KEY_GUILLEMOTLEFT" value="171" enum="KeyList">
+ <constant name="KEY_GUILLEMOTLEFT" value="171" enum="Key">
« key.
</constant>
- <constant name="KEY_NOTSIGN" value="172" enum="KeyList">
+ <constant name="KEY_NOTSIGN" value="172" enum="Key">
¬ key.
</constant>
- <constant name="KEY_HYPHEN" value="173" enum="KeyList">
+ <constant name="KEY_HYPHEN" value="173" enum="Key">
Soft hyphen key.
</constant>
- <constant name="KEY_REGISTERED" value="174" enum="KeyList">
+ <constant name="KEY_REGISTERED" value="174" enum="Key">
® key.
</constant>
- <constant name="KEY_MACRON" value="175" enum="KeyList">
+ <constant name="KEY_MACRON" value="175" enum="Key">
¯ key.
</constant>
- <constant name="KEY_DEGREE" value="176" enum="KeyList">
+ <constant name="KEY_DEGREE" value="176" enum="Key">
° key.
</constant>
- <constant name="KEY_PLUSMINUS" value="177" enum="KeyList">
+ <constant name="KEY_PLUSMINUS" value="177" enum="Key">
± key.
</constant>
- <constant name="KEY_TWOSUPERIOR" value="178" enum="KeyList">
+ <constant name="KEY_TWOSUPERIOR" value="178" enum="Key">
² key.
</constant>
- <constant name="KEY_THREESUPERIOR" value="179" enum="KeyList">
+ <constant name="KEY_THREESUPERIOR" value="179" enum="Key">
³ key.
</constant>
- <constant name="KEY_ACUTE" value="180" enum="KeyList">
+ <constant name="KEY_ACUTE" value="180" enum="Key">
´ key.
</constant>
- <constant name="KEY_MU" value="181" enum="KeyList">
+ <constant name="KEY_MU" value="181" enum="Key">
µ key.
</constant>
- <constant name="KEY_PARAGRAPH" value="182" enum="KeyList">
+ <constant name="KEY_PARAGRAPH" value="182" enum="Key">
¶ key.
</constant>
- <constant name="KEY_PERIODCENTERED" value="183" enum="KeyList">
+ <constant name="KEY_PERIODCENTERED" value="183" enum="Key">
· key.
</constant>
- <constant name="KEY_CEDILLA" value="184" enum="KeyList">
+ <constant name="KEY_CEDILLA" value="184" enum="Key">
¸ key.
</constant>
- <constant name="KEY_ONESUPERIOR" value="185" enum="KeyList">
+ <constant name="KEY_ONESUPERIOR" value="185" enum="Key">
¹ key.
</constant>
- <constant name="KEY_MASCULINE" value="186" enum="KeyList">
+ <constant name="KEY_MASCULINE" value="186" enum="Key">
º key.
</constant>
- <constant name="KEY_GUILLEMOTRIGHT" value="187" enum="KeyList">
+ <constant name="KEY_GUILLEMOTRIGHT" value="187" enum="Key">
» key.
</constant>
- <constant name="KEY_ONEQUARTER" value="188" enum="KeyList">
+ <constant name="KEY_ONEQUARTER" value="188" enum="Key">
¼ key.
</constant>
- <constant name="KEY_ONEHALF" value="189" enum="KeyList">
+ <constant name="KEY_ONEHALF" value="189" enum="Key">
½ key.
</constant>
- <constant name="KEY_THREEQUARTERS" value="190" enum="KeyList">
+ <constant name="KEY_THREEQUARTERS" value="190" enum="Key">
¾ key.
</constant>
- <constant name="KEY_QUESTIONDOWN" value="191" enum="KeyList">
+ <constant name="KEY_QUESTIONDOWN" value="191" enum="Key">
¿ key.
</constant>
- <constant name="KEY_AGRAVE" value="192" enum="KeyList">
+ <constant name="KEY_AGRAVE" value="192" enum="Key">
À key.
</constant>
- <constant name="KEY_AACUTE" value="193" enum="KeyList">
+ <constant name="KEY_AACUTE" value="193" enum="Key">
Á key.
</constant>
- <constant name="KEY_ACIRCUMFLEX" value="194" enum="KeyList">
+ <constant name="KEY_ACIRCUMFLEX" value="194" enum="Key">
 key.
</constant>
- <constant name="KEY_ATILDE" value="195" enum="KeyList">
+ <constant name="KEY_ATILDE" value="195" enum="Key">
à key.
</constant>
- <constant name="KEY_ADIAERESIS" value="196" enum="KeyList">
+ <constant name="KEY_ADIAERESIS" value="196" enum="Key">
Ä key.
</constant>
- <constant name="KEY_ARING" value="197" enum="KeyList">
+ <constant name="KEY_ARING" value="197" enum="Key">
Å key.
</constant>
- <constant name="KEY_AE" value="198" enum="KeyList">
+ <constant name="KEY_AE" value="198" enum="Key">
Æ key.
</constant>
- <constant name="KEY_CCEDILLA" value="199" enum="KeyList">
+ <constant name="KEY_CCEDILLA" value="199" enum="Key">
Ç key.
</constant>
- <constant name="KEY_EGRAVE" value="200" enum="KeyList">
+ <constant name="KEY_EGRAVE" value="200" enum="Key">
È key.
</constant>
- <constant name="KEY_EACUTE" value="201" enum="KeyList">
+ <constant name="KEY_EACUTE" value="201" enum="Key">
É key.
</constant>
- <constant name="KEY_ECIRCUMFLEX" value="202" enum="KeyList">
+ <constant name="KEY_ECIRCUMFLEX" value="202" enum="Key">
Ê key.
</constant>
- <constant name="KEY_EDIAERESIS" value="203" enum="KeyList">
+ <constant name="KEY_EDIAERESIS" value="203" enum="Key">
Ë key.
</constant>
- <constant name="KEY_IGRAVE" value="204" enum="KeyList">
+ <constant name="KEY_IGRAVE" value="204" enum="Key">
Ì key.
</constant>
- <constant name="KEY_IACUTE" value="205" enum="KeyList">
+ <constant name="KEY_IACUTE" value="205" enum="Key">
Í key.
</constant>
- <constant name="KEY_ICIRCUMFLEX" value="206" enum="KeyList">
+ <constant name="KEY_ICIRCUMFLEX" value="206" enum="Key">
Î key.
</constant>
- <constant name="KEY_IDIAERESIS" value="207" enum="KeyList">
+ <constant name="KEY_IDIAERESIS" value="207" enum="Key">
Ï key.
</constant>
- <constant name="KEY_ETH" value="208" enum="KeyList">
+ <constant name="KEY_ETH" value="208" enum="Key">
Ð key.
</constant>
- <constant name="KEY_NTILDE" value="209" enum="KeyList">
+ <constant name="KEY_NTILDE" value="209" enum="Key">
Ñ key.
</constant>
- <constant name="KEY_OGRAVE" value="210" enum="KeyList">
+ <constant name="KEY_OGRAVE" value="210" enum="Key">
Ò key.
</constant>
- <constant name="KEY_OACUTE" value="211" enum="KeyList">
+ <constant name="KEY_OACUTE" value="211" enum="Key">
Ó key.
</constant>
- <constant name="KEY_OCIRCUMFLEX" value="212" enum="KeyList">
+ <constant name="KEY_OCIRCUMFLEX" value="212" enum="Key">
Ô key.
</constant>
- <constant name="KEY_OTILDE" value="213" enum="KeyList">
+ <constant name="KEY_OTILDE" value="213" enum="Key">
Õ key.
</constant>
- <constant name="KEY_ODIAERESIS" value="214" enum="KeyList">
+ <constant name="KEY_ODIAERESIS" value="214" enum="Key">
Ö key.
</constant>
- <constant name="KEY_MULTIPLY" value="215" enum="KeyList">
+ <constant name="KEY_MULTIPLY" value="215" enum="Key">
× key.
</constant>
- <constant name="KEY_OOBLIQUE" value="216" enum="KeyList">
+ <constant name="KEY_OOBLIQUE" value="216" enum="Key">
Ø key.
</constant>
- <constant name="KEY_UGRAVE" value="217" enum="KeyList">
+ <constant name="KEY_UGRAVE" value="217" enum="Key">
Ù key.
</constant>
- <constant name="KEY_UACUTE" value="218" enum="KeyList">
+ <constant name="KEY_UACUTE" value="218" enum="Key">
Ú key.
</constant>
- <constant name="KEY_UCIRCUMFLEX" value="219" enum="KeyList">
+ <constant name="KEY_UCIRCUMFLEX" value="219" enum="Key">
Û key.
</constant>
- <constant name="KEY_UDIAERESIS" value="220" enum="KeyList">
+ <constant name="KEY_UDIAERESIS" value="220" enum="Key">
Ü key.
</constant>
- <constant name="KEY_YACUTE" value="221" enum="KeyList">
+ <constant name="KEY_YACUTE" value="221" enum="Key">
Ý key.
</constant>
- <constant name="KEY_THORN" value="222" enum="KeyList">
+ <constant name="KEY_THORN" value="222" enum="Key">
Þ key.
</constant>
- <constant name="KEY_SSHARP" value="223" enum="KeyList">
+ <constant name="KEY_SSHARP" value="223" enum="Key">
ß key.
</constant>
- <constant name="KEY_DIVISION" value="247" enum="KeyList">
+ <constant name="KEY_DIVISION" value="247" enum="Key">
÷ key.
</constant>
- <constant name="KEY_YDIAERESIS" value="255" enum="KeyList">
+ <constant name="KEY_YDIAERESIS" value="255" enum="Key">
ÿ key.
</constant>
<constant name="KEY_CODE_MASK" value="33554431" enum="KeyModifierMask">
@@ -2057,148 +2061,166 @@
<constant name="KEY_MASK_GROUP_SWITCH" value="1073741824" enum="KeyModifierMask">
Group Switch key mask.
</constant>
- <constant name="BUTTON_LEFT" value="1" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_LEFT" value="1" enum="MouseButton">
Left mouse button.
</constant>
- <constant name="BUTTON_RIGHT" value="2" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_RIGHT" value="2" enum="MouseButton">
Right mouse button.
</constant>
- <constant name="BUTTON_MIDDLE" value="3" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_MIDDLE" value="3" enum="MouseButton">
Middle mouse button.
</constant>
- <constant name="BUTTON_XBUTTON1" value="8" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_XBUTTON1" value="8" enum="MouseButton">
Extra mouse button 1 (only present on some mice).
</constant>
- <constant name="BUTTON_XBUTTON2" value="9" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_XBUTTON2" value="9" enum="MouseButton">
Extra mouse button 2 (only present on some mice).
</constant>
- <constant name="BUTTON_WHEEL_UP" value="4" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_WHEEL_UP" value="4" enum="MouseButton">
Mouse wheel up.
</constant>
- <constant name="BUTTON_WHEEL_DOWN" value="5" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_WHEEL_DOWN" value="5" enum="MouseButton">
Mouse wheel down.
</constant>
- <constant name="BUTTON_WHEEL_LEFT" value="6" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_WHEEL_LEFT" value="6" enum="MouseButton">
Mouse wheel left button (only present on some mice).
</constant>
- <constant name="BUTTON_WHEEL_RIGHT" value="7" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_WHEEL_RIGHT" value="7" enum="MouseButton">
Mouse wheel right button (only present on some mice).
</constant>
- <constant name="BUTTON_MASK_LEFT" value="1" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_MASK_LEFT" value="1" enum="MouseButton">
Left mouse button mask.
</constant>
- <constant name="BUTTON_MASK_RIGHT" value="2" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_MASK_RIGHT" value="2" enum="MouseButton">
Right mouse button mask.
</constant>
- <constant name="BUTTON_MASK_MIDDLE" value="4" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_MASK_MIDDLE" value="4" enum="MouseButton">
Middle mouse button mask.
</constant>
- <constant name="BUTTON_MASK_XBUTTON1" value="128" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_MASK_XBUTTON1" value="128" enum="MouseButton">
Extra mouse button 1 mask.
</constant>
- <constant name="BUTTON_MASK_XBUTTON2" value="256" enum="ButtonList">
+ <constant name="MOUSE_BUTTON_MASK_XBUTTON2" value="256" enum="MouseButton">
Extra mouse button 2 mask.
</constant>
- <constant name="JOY_BUTTON_INVALID" value="-1" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_INVALID" value="-1" enum="JoyButton">
An invalid game controller button.
</constant>
- <constant name="JOY_BUTTON_A" value="0" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_A" value="0" enum="JoyButton">
Game controller SDL button A. Corresponds to the bottom action button: Sony Cross, Xbox A, Nintendo B.
</constant>
- <constant name="JOY_BUTTON_B" value="1" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_B" value="1" enum="JoyButton">
Game controller SDL button B. Corresponds to the right action button: Sony Circle, Xbox B, Nintendo A.
</constant>
- <constant name="JOY_BUTTON_X" value="2" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_X" value="2" enum="JoyButton">
Game controller SDL button X. Corresponds to the left action button: Sony Square, Xbox X, Nintendo Y.
</constant>
- <constant name="JOY_BUTTON_Y" value="3" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_Y" value="3" enum="JoyButton">
Game controller SDL button Y. Corresponds to the top action button: Sony Triangle, Xbox Y, Nintendo X.
</constant>
- <constant name="JOY_BUTTON_BACK" value="4" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_BACK" value="4" enum="JoyButton">
Game controller SDL back button. Corresponds to the Sony Select, Xbox Back, Nintendo - button.
</constant>
- <constant name="JOY_BUTTON_GUIDE" value="5" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_GUIDE" value="5" enum="JoyButton">
Game controller SDL guide button. Corresponds to the Sony PS, Xbox Home button.
</constant>
- <constant name="JOY_BUTTON_START" value="6" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_START" value="6" enum="JoyButton">
Game controller SDL start button. Corresponds to the Nintendo + button.
</constant>
- <constant name="JOY_BUTTON_LEFT_STICK" value="7" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_LEFT_STICK" value="7" enum="JoyButton">
Game controller SDL left stick button. Corresponds to the Sony L3, Xbox L/LS button.
</constant>
- <constant name="JOY_BUTTON_RIGHT_STICK" value="8" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_RIGHT_STICK" value="8" enum="JoyButton">
Game controller SDL right stick button. Corresponds to the Sony R3, Xbox R/RS button.
</constant>
- <constant name="JOY_BUTTON_LEFT_SHOULDER" value="9" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_LEFT_SHOULDER" value="9" enum="JoyButton">
Game controller SDL left shoulder button. Corresponds to the Sony L1, Xbox LB button.
</constant>
- <constant name="JOY_BUTTON_RIGHT_SHOULDER" value="10" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_RIGHT_SHOULDER" value="10" enum="JoyButton">
Game controller SDL right shoulder button. Corresponds to the Sony R1, Xbox RB button.
</constant>
- <constant name="JOY_BUTTON_DPAD_UP" value="11" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_DPAD_UP" value="11" enum="JoyButton">
Game controller D-pad up button.
</constant>
- <constant name="JOY_BUTTON_DPAD_DOWN" value="12" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_DPAD_DOWN" value="12" enum="JoyButton">
Game controller D-pad down button.
</constant>
- <constant name="JOY_BUTTON_DPAD_LEFT" value="13" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_DPAD_LEFT" value="13" enum="JoyButton">
Game controller D-pad left button.
</constant>
- <constant name="JOY_BUTTON_DPAD_RIGHT" value="14" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_DPAD_RIGHT" value="14" enum="JoyButton">
Game controller D-pad right button.
</constant>
- <constant name="JOY_BUTTON_SDL_MAX" value="15" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_MISC1" value="15" enum="JoyButton">
+ Game controller SDL miscellaneous button. Corresponds to Xbox share button, PS5 microphone button, Nintendo capture button.
+ </constant>
+ <constant name="JOY_BUTTON_PADDLE1" value="16" enum="JoyButton">
+ Game controller SDL paddle 1 button.
+ </constant>
+ <constant name="JOY_BUTTON_PADDLE2" value="17" enum="JoyButton">
+ Game controller SDL paddle 2 button.
+ </constant>
+ <constant name="JOY_BUTTON_PADDLE3" value="18" enum="JoyButton">
+ Game controller SDL paddle 3 button.
+ </constant>
+ <constant name="JOY_BUTTON_PADDLE4" value="19" enum="JoyButton">
+ Game controller SDL paddle 4 button.
+ </constant>
+ <constant name="JOY_BUTTON_TOUCHPAD" value="20" enum="JoyButton">
+ Game controller SDL touchpad button.
+ </constant>
+ <constant name="JOY_BUTTON_SDL_MAX" value="21" enum="JoyButton">
The number of SDL game controller buttons.
</constant>
- <constant name="JOY_BUTTON_MAX" value="36" enum="JoyButtonList">
+ <constant name="JOY_BUTTON_MAX" value="36" enum="JoyButton">
The maximum number of game controller buttons: Android supports up to 36 buttons.
</constant>
- <constant name="JOY_AXIS_INVALID" value="-1" enum="JoyAxisList">
+ <constant name="JOY_AXIS_INVALID" value="-1" enum="JoyAxis">
An invalid game controller axis.
</constant>
- <constant name="JOY_AXIS_LEFT_X" value="0" enum="JoyAxisList">
+ <constant name="JOY_AXIS_LEFT_X" value="0" enum="JoyAxis">
Game controller left joystick x-axis.
</constant>
- <constant name="JOY_AXIS_LEFT_Y" value="1" enum="JoyAxisList">
+ <constant name="JOY_AXIS_LEFT_Y" value="1" enum="JoyAxis">
Game controller left joystick y-axis.
</constant>
- <constant name="JOY_AXIS_RIGHT_X" value="2" enum="JoyAxisList">
+ <constant name="JOY_AXIS_RIGHT_X" value="2" enum="JoyAxis">
Game controller right joystick x-axis.
</constant>
- <constant name="JOY_AXIS_RIGHT_Y" value="3" enum="JoyAxisList">
+ <constant name="JOY_AXIS_RIGHT_Y" value="3" enum="JoyAxis">
Game controller right joystick y-axis.
</constant>
- <constant name="JOY_AXIS_TRIGGER_LEFT" value="4" enum="JoyAxisList">
+ <constant name="JOY_AXIS_TRIGGER_LEFT" value="4" enum="JoyAxis">
Game controller left trigger axis.
</constant>
- <constant name="JOY_AXIS_TRIGGER_RIGHT" value="5" enum="JoyAxisList">
+ <constant name="JOY_AXIS_TRIGGER_RIGHT" value="5" enum="JoyAxis">
Game controller right trigger axis.
</constant>
- <constant name="JOY_AXIS_SDL_MAX" value="6" enum="JoyAxisList">
+ <constant name="JOY_AXIS_SDL_MAX" value="6" enum="JoyAxis">
The number of SDL game controller axes.
</constant>
- <constant name="JOY_AXIS_MAX" value="10" enum="JoyAxisList">
+ <constant name="JOY_AXIS_MAX" value="10" enum="JoyAxis">
The maximum number of game controller axes: OpenVR supports up to 5 Joysticks making a total of 10 axes.
</constant>
- <constant name="MIDI_MESSAGE_NOTE_OFF" value="8" enum="MidiMessageList">
+ <constant name="MIDI_MESSAGE_NOTE_OFF" value="8" enum="MIDIMessage">
MIDI note OFF message.
</constant>
- <constant name="MIDI_MESSAGE_NOTE_ON" value="9" enum="MidiMessageList">
+ <constant name="MIDI_MESSAGE_NOTE_ON" value="9" enum="MIDIMessage">
MIDI note ON message.
</constant>
- <constant name="MIDI_MESSAGE_AFTERTOUCH" value="10" enum="MidiMessageList">
+ <constant name="MIDI_MESSAGE_AFTERTOUCH" value="10" enum="MIDIMessage">
MIDI aftertouch message.
</constant>
- <constant name="MIDI_MESSAGE_CONTROL_CHANGE" value="11" enum="MidiMessageList">
+ <constant name="MIDI_MESSAGE_CONTROL_CHANGE" value="11" enum="MIDIMessage">
MIDI control change message.
</constant>
- <constant name="MIDI_MESSAGE_PROGRAM_CHANGE" value="12" enum="MidiMessageList">
+ <constant name="MIDI_MESSAGE_PROGRAM_CHANGE" value="12" enum="MIDIMessage">
MIDI program change message.
</constant>
- <constant name="MIDI_MESSAGE_CHANNEL_PRESSURE" value="13" enum="MidiMessageList">
+ <constant name="MIDI_MESSAGE_CHANNEL_PRESSURE" value="13" enum="MIDIMessage">
MIDI channel pressure message.
</constant>
- <constant name="MIDI_MESSAGE_PITCH_BEND" value="14" enum="MidiMessageList">
+ <constant name="MIDI_MESSAGE_PITCH_BEND" value="14" enum="MIDIMessage">
MIDI pitch bend message.
</constant>
<constant name="OK" value="0" enum="Error">
@@ -2387,43 +2409,49 @@
<constant name="PROPERTY_HINT_LAYERS_2D_PHYSICS" value="9" enum="PropertyHint">
Hints that an integer property is a bitmask using the optionally named 2D physics layers.
</constant>
- <constant name="PROPERTY_HINT_LAYERS_3D_RENDER" value="10" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LAYERS_2D_NAVIGATION" value="10" enum="PropertyHint">
+ Hints that an integer property is a bitmask using the optionally named 2D navigation layers.
+ </constant>
+ <constant name="PROPERTY_HINT_LAYERS_3D_RENDER" value="11" enum="PropertyHint">
Hints that an integer property is a bitmask using the optionally named 3D render layers.
</constant>
- <constant name="PROPERTY_HINT_LAYERS_3D_PHYSICS" value="11" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LAYERS_3D_PHYSICS" value="12" enum="PropertyHint">
Hints that an integer property is a bitmask using the optionally named 3D physics layers.
</constant>
- <constant name="PROPERTY_HINT_FILE" value="12" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LAYERS_3D_NAVIGATION" value="13" enum="PropertyHint">
+ Hints that an integer property is a bitmask using the optionally named 2D navigation layers.
+ </constant>
+ <constant name="PROPERTY_HINT_FILE" value="14" enum="PropertyHint">
Hints that a string property is a path to a file. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code].
</constant>
- <constant name="PROPERTY_HINT_DIR" value="13" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_DIR" value="15" enum="PropertyHint">
Hints that a string property is a path to a directory. Editing it will show a file dialog for picking the path.
</constant>
- <constant name="PROPERTY_HINT_GLOBAL_FILE" value="14" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_GLOBAL_FILE" value="16" enum="PropertyHint">
Hints that a string property is an absolute path to a file outside the project folder. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code].
</constant>
- <constant name="PROPERTY_HINT_GLOBAL_DIR" value="15" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_GLOBAL_DIR" value="17" enum="PropertyHint">
Hints that a string property is an absolute path to a directory outside the project folder. Editing it will show a file dialog for picking the path.
</constant>
- <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="16" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="18" enum="PropertyHint">
Hints that a property is an instance of a [Resource]-derived type, optionally specified via the hint string (e.g. [code]"Texture2D"[/code]). Editing it will show a popup menu of valid resource types to instantiate.
</constant>
- <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="17" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="19" enum="PropertyHint">
Hints that a string property is text with line breaks. Editing it will show a text input field where line breaks can be typed.
</constant>
- <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="18" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="20" enum="PropertyHint">
Hints that a string property should have a placeholder text visible on its input field, whenever the property is empty. The hint string is the placeholder text to use.
</constant>
- <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="19" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="21" enum="PropertyHint">
Hints that a color property should be edited without changing its alpha component, i.e. only R, G and B channels are edited.
</constant>
- <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="20" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="22" enum="PropertyHint">
Hints that an image is compressed using lossy compression.
</constant>
- <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="21" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="23" enum="PropertyHint">
Hints that an image is compressed using lossless compression.
</constant>
- <constant name="PROPERTY_HINT_TYPE_STRING" value="23" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_TYPE_STRING" value="25" enum="PropertyHint">
Hint that a property represents a particular type. If a property is [constant TYPE_STRING], allows to set a type from the create dialog. If you need to create an [Array] to contain elements of a specific type, the [code]hint_string[/code] must encode nested types using [code]":"[/code] and [code]"/"[/code] for specifying [Resource] types. For instance:
[codeblock]
hint_string = "%s:" % [TYPE_INT] # Array of inteters.
@@ -2502,6 +2530,8 @@
<constant name="METHOD_FLAG_FROM_SCRIPT" value="64" enum="MethodFlags">
Deprecated method flag, unused.
</constant>
+ <constant name="METHOD_FLAG_STATIC" value="256" enum="MethodFlags">
+ </constant>
<constant name="METHOD_FLAGS_DEFAULT" value="1" enum="MethodFlags">
Default method flags.
</constant>
diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml
index 8cd7e6f5fa..a28bde9946 100644
--- a/doc/classes/AABB.xml
+++ b/doc/classes/AABB.xml
@@ -41,14 +41,14 @@
Constructs an [AABB] from a position and size.
</description>
</method>
- <method name="abs">
+ <method name="abs" qualifiers="const">
<return type="AABB">
</return>
<description>
Returns an AABB with equivalent position and size, modified so that the most-negative corner is the origin and the size is positive.
</description>
</method>
- <method name="encloses">
+ <method name="encloses" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="with" type="AABB">
@@ -57,7 +57,7 @@
Returns [code]true[/code] if this [AABB] completely encloses another one.
</description>
</method>
- <method name="expand">
+ <method name="expand" qualifiers="const">
<return type="AABB">
</return>
<argument index="0" name="to_point" type="Vector3">
@@ -66,14 +66,14 @@
Returns this [AABB] expanded to include a given point.
</description>
</method>
- <method name="get_area">
+ <method name="get_area" qualifiers="const">
<return type="float">
</return>
<description>
Returns the volume of the [AABB].
</description>
</method>
- <method name="get_endpoint">
+ <method name="get_endpoint" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="idx" type="int">
@@ -82,49 +82,49 @@
Gets the position of the 8 endpoints of the [AABB] in space.
</description>
</method>
- <method name="get_longest_axis">
+ <method name="get_longest_axis" qualifiers="const">
<return type="Vector3">
</return>
<description>
Returns the normalized longest axis of the [AABB].
</description>
</method>
- <method name="get_longest_axis_index">
+ <method name="get_longest_axis_index" qualifiers="const">
<return type="int">
</return>
<description>
Returns the index of the longest axis of the [AABB] (according to [Vector3]'s [code]AXIS_*[/code] constants).
</description>
</method>
- <method name="get_longest_axis_size">
+ <method name="get_longest_axis_size" qualifiers="const">
<return type="float">
</return>
<description>
Returns the scalar length of the longest axis of the [AABB].
</description>
</method>
- <method name="get_shortest_axis">
+ <method name="get_shortest_axis" qualifiers="const">
<return type="Vector3">
</return>
<description>
Returns the normalized shortest axis of the [AABB].
</description>
</method>
- <method name="get_shortest_axis_index">
+ <method name="get_shortest_axis_index" qualifiers="const">
<return type="int">
</return>
<description>
Returns the index of the shortest axis of the [AABB] (according to [Vector3]::AXIS* enum).
</description>
</method>
- <method name="get_shortest_axis_size">
+ <method name="get_shortest_axis_size" qualifiers="const">
<return type="float">
</return>
<description>
Returns the scalar length of the shortest axis of the [AABB].
</description>
</method>
- <method name="get_support">
+ <method name="get_support" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="dir" type="Vector3">
@@ -133,7 +133,7 @@
Returns the support point in a given direction. This is useful for collision detection algorithms.
</description>
</method>
- <method name="grow">
+ <method name="grow" qualifiers="const">
<return type="AABB">
</return>
<argument index="0" name="by" type="float">
@@ -142,21 +142,21 @@
Returns a copy of the [AABB] grown a given amount of units towards all the sides.
</description>
</method>
- <method name="has_no_area">
+ <method name="has_no_area" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the [AABB] is flat or empty.
</description>
</method>
- <method name="has_no_surface">
+ <method name="has_no_surface" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the [AABB] is empty.
</description>
</method>
- <method name="has_point">
+ <method name="has_point" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="point" type="Vector3">
@@ -165,7 +165,7 @@
Returns [code]true[/code] if the [AABB] contains a point.
</description>
</method>
- <method name="intersection">
+ <method name="intersection" qualifiers="const">
<return type="AABB">
</return>
<argument index="0" name="with" type="AABB">
@@ -174,7 +174,7 @@
Returns the intersection between two [AABB]. An empty AABB (size 0,0,0) is returned on failure.
</description>
</method>
- <method name="intersects">
+ <method name="intersects" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="with" type="AABB">
@@ -183,7 +183,7 @@
Returns [code]true[/code] if the [AABB] overlaps with another.
</description>
</method>
- <method name="intersects_plane">
+ <method name="intersects_plane" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="plane" type="Plane">
@@ -192,7 +192,7 @@
Returns [code]true[/code] if the [AABB] is on both sides of a plane.
</description>
</method>
- <method name="intersects_ray">
+ <method name="intersects_ray" qualifiers="const">
<return type="Variant">
</return>
<argument index="0" name="from" type="Vector3">
@@ -202,7 +202,7 @@
<description>
</description>
</method>
- <method name="intersects_segment">
+ <method name="intersects_segment" qualifiers="const">
<return type="Variant">
</return>
<argument index="0" name="from" type="Vector3">
@@ -213,7 +213,7 @@
Returns [code]true[/code] if the [AABB] intersects the line segment between [code]from[/code] and [code]to[/code].
</description>
</method>
- <method name="is_equal_approx">
+ <method name="is_equal_approx" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="aabb" type="AABB">
@@ -222,7 +222,7 @@
Returns [code]true[/code] if this [AABB] and [code]aabb[/code] are approximately equal, by calling [method @GlobalScope.is_equal_approx] on each component.
</description>
</method>
- <method name="merge">
+ <method name="merge" qualifiers="const">
<return type="AABB">
</return>
<argument index="0" name="with" type="AABB">
@@ -264,7 +264,7 @@
Beginning corner. Typically has values lower than [member end].
</member>
<member name="size" type="Vector3" setter="" getter="" default="Vector3( 0, 0, 0 )">
- Size from [member position] to [member end]. Typically all components are positive.
+ Size from [member position] to [member end]. Typically, all components are positive.
If the size is negative, you can use [method abs] to fix it.
</member>
</members>
diff --git a/doc/classes/AStar.xml b/doc/classes/AStar.xml
index bfdc66623d..e975b8ed28 100644
--- a/doc/classes/AStar.xml
+++ b/doc/classes/AStar.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AStar" inherits="Reference" version="4.0">
<brief_description>
- An implementation of A* to find shortest paths among connected points in space.
+ An implementation of A* to find the shortest paths among connected points in space.
</brief_description>
<description>
A* (A star) is a computer algorithm that is widely used in pathfinding and graph traversal, the process of plotting short paths among vertices (points), passing through a given set of edges (segments). It enjoys widespread use due to its performance and accuracy. Godot's A* implementation uses points in three-dimensional space and Euclidean distances by default.
diff --git a/doc/classes/AnimatedSprite3D.xml b/doc/classes/AnimatedSprite3D.xml
index e1fb78e5b5..02ccab4e05 100644
--- a/doc/classes/AnimatedSprite3D.xml
+++ b/doc/classes/AnimatedSprite3D.xml
@@ -49,6 +49,11 @@
</member>
</members>
<signals>
+ <signal name="animation_finished">
+ <description>
+ Emitted when the animation is finished (when it plays the last frame). If the animation is looping, this signal is emitted every time the last frame is drawn.
+ </description>
+ </signal>
<signal name="frame_changed">
<description>
Emitted when [member frame] changed.
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index 9720405ffd..7ceb21d22e 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -710,7 +710,7 @@
[b]Note:[/b] Length is not delimited by the last key, as this one may be before or after the end to ensure correct interpolation and looping.
</member>
<member name="loop" type="bool" setter="set_loop" getter="has_loop" default="false">
- A flag indicating that the animation must loop. This is uses for correct interpolation of animation cycles, and for hinting the player that it must restart the animation.
+ A flag indicating that the animation must loop. This is used for correct interpolation of animation cycles, and for hinting the player that it must restart the animation.
</member>
<member name="step" type="float" setter="set_step" getter="get_step" default="0.1">
The animation step value.
diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml
index bebff61671..7696f36009 100644
--- a/doc/classes/AnimationPlayer.xml
+++ b/doc/classes/AnimationPlayer.xml
@@ -237,7 +237,7 @@
</member>
<member name="current_animation" type="String" setter="set_current_animation" getter="get_current_animation" default="&quot;&quot;">
The name of the currently playing animation. If no animation is playing, the property's value is an empty string. Changing this value does not restart the animation. See [method play] for more information on playing animations.
- [b]Note[/b]: while this property appears in the inspector, it's not meant to be edited and it's not saved in the scene. This property is mainly used to get the currently playing animation, and internally for animation playback tracks. For more information, see [Animation].
+ [b]Note[/b]: while this property appears in the inspector, it's not meant to be edited, and it's not saved in the scene. This property is mainly used to get the currently playing animation, and internally for animation playback tracks. For more information, see [Animation].
</member>
<member name="current_animation_length" type="float" setter="" getter="get_current_animation_length">
The length (in seconds) of the currently being played animation.
@@ -254,7 +254,7 @@
<member name="playback_default_blend_time" type="float" setter="set_default_blend_time" getter="get_default_blend_time" default="0.0">
The default time in which to blend animations. Ranges from 0 to 4096 with 0.01 precision.
</member>
- <member name="playback_process_mode" type="int" setter="set_animation_process_mode" getter="get_animation_process_mode" enum="AnimationPlayer.AnimationProcessMode" default="1">
+ <member name="playback_process_mode" type="int" setter="set_process_callback" getter="get_process_callback" enum="AnimationPlayer.AnimationProcessCallback" default="1">
The process notification in which to update animations.
</member>
<member name="playback_speed" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0">
@@ -299,13 +299,13 @@
</signal>
</signals>
<constants>
- <constant name="ANIMATION_PROCESS_PHYSICS" value="0" enum="AnimationProcessMode">
+ <constant name="ANIMATION_PROCESS_PHYSICS" value="0" enum="AnimationProcessCallback">
Process animation during the physics process. This is especially useful when animating physics bodies.
</constant>
- <constant name="ANIMATION_PROCESS_IDLE" value="1" enum="AnimationProcessMode">
+ <constant name="ANIMATION_PROCESS_IDLE" value="1" enum="AnimationProcessCallback">
Process animation during the idle process.
</constant>
- <constant name="ANIMATION_PROCESS_MANUAL" value="2" enum="AnimationProcessMode">
+ <constant name="ANIMATION_PROCESS_MANUAL" value="2" enum="AnimationProcessCallback">
Do not process animation. Use [method advance] to process the animation manually.
</constant>
<constant name="ANIMATION_METHOD_CALL_DEFERRED" value="0" enum="AnimationMethodCallMode">
diff --git a/doc/classes/AnimationTree.xml b/doc/classes/AnimationTree.xml
index 262b5addb7..2517941133 100644
--- a/doc/classes/AnimationTree.xml
+++ b/doc/classes/AnimationTree.xml
@@ -45,8 +45,8 @@
<member name="anim_player" type="NodePath" setter="set_animation_player" getter="get_animation_player" default="NodePath(&quot;&quot;)">
The path to the [AnimationPlayer] used for animating.
</member>
- <member name="process_mode" type="int" setter="set_process_mode" getter="get_process_mode" enum="AnimationTree.AnimationProcessMode" default="1">
- The process mode of this [AnimationTree]. See [enum AnimationProcessMode] for available modes.
+ <member name="process_callback" type="int" setter="set_process_callback" getter="get_process_callback" enum="AnimationTree.AnimationProcessCallback" default="1">
+ The process mode of this [AnimationTree]. See [enum AnimationProcessCallback] for available modes.
</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].
@@ -57,13 +57,13 @@
</member>
</members>
<constants>
- <constant name="ANIMATION_PROCESS_PHYSICS" value="0" enum="AnimationProcessMode">
+ <constant name="ANIMATION_PROCESS_PHYSICS" value="0" enum="AnimationProcessCallback">
The animations will progress during the physics frame (i.e. [method Node._physics_process]).
</constant>
- <constant name="ANIMATION_PROCESS_IDLE" value="1" enum="AnimationProcessMode">
+ <constant name="ANIMATION_PROCESS_IDLE" value="1" enum="AnimationProcessCallback">
The animations will progress during the idle frame (i.e. [method Node._process]).
</constant>
- <constant name="ANIMATION_PROCESS_MANUAL" value="2" enum="AnimationProcessMode">
+ <constant name="ANIMATION_PROCESS_MANUAL" value="2" enum="AnimationProcessCallback">
The animations will only progress manually (see [method advance]).
</constant>
</constants>
diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml
index a02f077cf7..9711a2a35b 100644
--- a/doc/classes/Area2D.xml
+++ b/doc/classes/Area2D.xml
@@ -187,7 +187,7 @@
</description>
</signal>
<signal name="body_entered">
- <argument index="0" name="body" type="Node">
+ <argument index="0" name="body" type="Node2D">
</argument>
<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.
@@ -195,7 +195,7 @@
</description>
</signal>
<signal name="body_exited">
- <argument index="0" name="body" type="Node">
+ <argument index="0" name="body" type="Node2D">
</argument>
<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.
@@ -205,7 +205,7 @@
<signal name="body_shape_entered">
<argument index="0" name="body_id" type="int">
</argument>
- <argument index="1" name="body" type="Node">
+ <argument index="1" name="body" type="Node2D">
</argument>
<argument index="2" name="body_shape" type="int">
</argument>
@@ -222,7 +222,7 @@
<signal name="body_shape_exited">
<argument index="0" name="body_id" type="int">
</argument>
- <argument index="1" name="body" type="Node">
+ <argument index="1" name="body" type="Node2D">
</argument>
<argument index="2" name="body_shape" type="int">
</argument>
diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml
index bd43d619dd..4271769155 100644
--- a/doc/classes/Area3D.xml
+++ b/doc/classes/Area3D.xml
@@ -197,7 +197,7 @@
</description>
</signal>
<signal name="body_entered">
- <argument index="0" name="body" type="Node">
+ <argument index="0" name="body" type="Node3D">
</argument>
<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.
@@ -205,7 +205,7 @@
</description>
</signal>
<signal name="body_exited">
- <argument index="0" name="body" type="Node">
+ <argument index="0" name="body" type="Node3D">
</argument>
<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.
@@ -215,7 +215,7 @@
<signal name="body_shape_entered">
<argument index="0" name="body_id" type="int">
</argument>
- <argument index="1" name="body" type="Node">
+ <argument index="1" name="body" type="Node3D">
</argument>
<argument index="2" name="body_shape" type="int">
</argument>
@@ -232,7 +232,7 @@
<signal name="body_shape_exited">
<argument index="0" name="body_id" type="int">
</argument>
- <argument index="1" name="body" type="Node">
+ <argument index="1" name="body" type="Node3D">
</argument>
<argument index="2" name="body_shape" type="int">
</argument>
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index de3d89ee0f..dcfb91eb61 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -166,7 +166,7 @@
[/codeblock]
</description>
</method>
- <method name="back">
+ <method name="back" qualifiers="const">
<return type="Variant">
</return>
<description>
@@ -191,15 +191,13 @@
</return>
<argument index="0" name="value" type="Variant">
</argument>
- <argument index="1" name="obj" type="Object">
+ <argument index="1" name="func" type="Callable">
</argument>
- <argument index="2" name="func" type="StringName">
- </argument>
- <argument index="3" name="before" type="bool" default="true">
+ <argument index="2" name="before" type="bool" default="true">
</argument>
<description>
Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search and a custom comparison method. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array. The custom method receives two arguments (an element from the array and the value searched for) and must return [code]true[/code] if the first argument is less than the second, and return [code]false[/code] otherwise.
- [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ [b]Note:[/b] Calling [method bsearch_custom] on an unsorted array results in unexpected behavior.
</description>
</method>
<method name="clear">
@@ -209,7 +207,7 @@
Clears the array. This is equivalent to using [method resize] with a size of [code]0[/code].
</description>
</method>
- <method name="count">
+ <method name="count" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="value" type="Variant">
@@ -218,7 +216,7 @@
Returns the number of times an element is in the array.
</description>
</method>
- <method name="duplicate">
+ <method name="duplicate" qualifiers="const">
<return type="Array">
</return>
<argument index="0" name="deep" type="bool" default="false">
@@ -239,7 +237,7 @@
[b]Note:[/b] On large arrays, this method will be slower if the removed element is close to the beginning of the array (index 0). This is because all elements placed after the removed element have to be reindexed.
</description>
</method>
- <method name="find">
+ <method name="find" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="what" type="Variant">
@@ -250,7 +248,7 @@
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">
+ <method name="find_last" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="value" type="Variant">
@@ -259,7 +257,7 @@
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">
+ <method name="front" qualifiers="const">
<return type="Variant">
</return>
<description>
@@ -267,7 +265,7 @@
[b]Note:[/b] Calling this function is not the same as writing [code]array[0][/code]. If the array is empty, accessing by index will pause project execution when running from the editor.
</description>
</method>
- <method name="has">
+ <method name="has" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="value" type="Variant">
@@ -309,7 +307,7 @@
[/codeblocks]
</description>
</method>
- <method name="hash">
+ <method name="hash" qualifiers="const">
<return type="int">
</return>
<description>
@@ -337,21 +335,21 @@
Reverses the order of the elements in the array.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the array is empty.
</description>
</method>
- <method name="max">
+ <method name="max" qualifiers="const">
<return type="Variant">
</return>
<description>
Returns the maximum value contained in the array if all elements are of comparable types. If the elements can't be compared, [code]null[/code] is returned.
</description>
</method>
- <method name="min">
+ <method name="min" qualifiers="const">
<return type="Variant">
</return>
<description>
@@ -476,7 +474,7 @@
Resizes the array to contain a different number of elements. If the array size is smaller, elements are cleared, if bigger, new elements are [code]null[/code].
</description>
</method>
- <method name="rfind">
+ <method name="rfind" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="what" type="Variant">
@@ -494,14 +492,14 @@
Shuffles the array such that the items will have a random order. This method uses the global random number generator common to methods such as [method @GlobalScope.randi]. Call [method @GlobalScope.randomize] to ensure that a new seed will be used each time if you want non-reproducible shuffling.
</description>
</method>
- <method name="size">
+ <method name="size" qualifiers="const">
<return type="int">
</return>
<description>
Returns the number of elements in the array.
</description>
</method>
- <method name="slice">
+ <method name="slice" qualifiers="const">
<return type="Array">
</return>
<argument index="0" name="begin" type="int">
@@ -537,12 +535,10 @@
<method name="sort_custom">
<return type="void">
</return>
- <argument index="0" name="obj" type="Object">
- </argument>
- <argument index="1" name="func" type="StringName">
+ <argument index="0" name="func" type="Callable">
</argument>
<description>
- 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 arguments (a pair of elements from the array) and must return either [code]true[/code] or [code]false[/code].
+ Sorts the array using a custom method. The custom method receives two arguments (a pair of elements from the array) and must return either [code]true[/code] or [code]false[/code].
[b]Note:[/b] you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior.
[codeblocks]
[gdscript]
@@ -553,7 +549,7 @@
return false
var my_items = [[5, "Potato"], [9, "Rice"], [4, "Tomato"]]
- my_items.sort_custom(MyCustomSorter, "sort_ascending")
+ my_items.sort_custom(MyCustomSorter.sort_ascending)
print(my_items) # Prints [[4, Tomato], [5, Potato], [9, Rice]].
[/gdscript]
[csharp]
diff --git a/doc/classes/AtlasTexture.xml b/doc/classes/AtlasTexture.xml
index 5bc077ef49..9865319419 100644
--- a/doc/classes/AtlasTexture.xml
+++ b/doc/classes/AtlasTexture.xml
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AtlasTexture" inherits="Texture2D" version="4.0">
<brief_description>
- Packs multiple small textures in a single, bigger one. Helps to optimize video memory costs and render calls.
+ Crops out one part of a texture, such as a texture from a texture atlas.
</brief_description>
<description>
- [Texture2D] resource aimed at managing big textures files that pack multiple smaller textures. Consists of a [Texture2D], a margin that defines the border width, and a region that defines the actual area of the AtlasTexture.
+ [Texture2D] resource that crops out one part of the [member atlas] texture, defined by [member region]. The main use case is cropping out textures from a texture atlas, which is a big texture file that packs multiple smaller textures. Consists of a [Texture2D] for the [member atlas], a [member region] that defines the area of [member atlas] to use, and a [member margin] that defines the border width.
+ [AtlasTexture] cannot be used in an [AnimatedTexture], cannot be tiled in nodes such as [TextureRect], and does not work properly if used inside of other [AtlasTexture] resources. Multiple [AtlasTexture] resources can be used to crop multiple textures from the atlas. Using a texture atlas helps to optimize video memory costs and render calls compared to using multiple small files.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AudioEffectCapture.xml b/doc/classes/AudioEffectCapture.xml
index cf3d87c2e4..c7ee621ca6 100644
--- a/doc/classes/AudioEffectCapture.xml
+++ b/doc/classes/AudioEffectCapture.xml
@@ -67,7 +67,7 @@
</methods>
<members>
<member name="buffer_length" type="float" setter="set_buffer_length" getter="get_buffer_length" default="0.1">
- Length of the internal ring buffer, in seconds.
+ Length of the internal ring buffer, in seconds. Setting the buffer length will have no effect if already initialized.
</member>
</members>
<constants>
diff --git a/doc/classes/BackBufferCopy.xml b/doc/classes/BackBufferCopy.xml
index 7cc6a5613b..9a70b8f20c 100644
--- a/doc/classes/BackBufferCopy.xml
+++ b/doc/classes/BackBufferCopy.xml
@@ -4,7 +4,7 @@
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 bufferized 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.
+ 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>
diff --git a/doc/classes/BakedLightmapData.xml b/doc/classes/BakedLightmapData.xml
index 026477782a..904555c48e 100644
--- a/doc/classes/BakedLightmapData.xml
+++ b/doc/classes/BakedLightmapData.xml
@@ -12,11 +12,11 @@
</return>
<argument index="0" name="path" type="NodePath">
</argument>
- <argument index="1" name="lightmap" type="Rect2">
+ <argument index="1" name="uv_scale" type="Rect2">
</argument>
- <argument index="2" name="offset" type="int">
+ <argument index="2" name="slice_index" type="int">
</argument>
- <argument index="3" name="arg3" type="int">
+ <argument index="3" name="sub_instance" type="int">
</argument>
<description>
</description>
diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml
index 45ef4cb14c..f7e31f5f9c 100644
--- a/doc/classes/BaseButton.xml
+++ b/doc/classes/BaseButton.xml
@@ -49,7 +49,7 @@
</member>
<member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" default="1">
Binary mask to choose which mouse buttons this button will respond to.
- To allow both left-click and right-click, use [code]BUTTON_MASK_LEFT | BUTTON_MASK_RIGHT[/code].
+ To allow both left-click and right-click, use [code]MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT[/code].
</member>
<member name="disabled" type="bool" setter="set_disabled" getter="is_disabled" default="false">
If [code]true[/code], the button is in disabled state and can't be clicked or toggled.
diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index 31e6ea5e54..c87398ac8f 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -82,7 +82,7 @@
Texture to multiply by [member albedo_color]. Used for basic texturing of objects.
</member>
<member name="alpha_antialiasing_edge" type="float" setter="set_alpha_antialiasing_edge" getter="get_alpha_antialiasing_edge">
- Threshold at which antialiasing will by applied on the alpha channel.
+ Threshold at which antialiasing will be applied on the alpha channel.
</member>
<member name="alpha_antialiasing_mode" type="int" setter="set_alpha_antialiasing" getter="get_alpha_antialiasing" enum="BaseMaterial3D.AlphaAntiAliasing">
The type of alpha antialiasing to apply. See [enum AlphaAntiAliasing].
@@ -93,7 +93,7 @@
<member name="alpha_scissor_threshold" type="float" setter="set_alpha_scissor_threshold" getter="get_alpha_scissor_threshold">
Threshold at which the alpha scissor will discard values.
</member>
- <member name="anisotropy" type="float" setter="set_anisotropy" getter="get_anisotropy">
+ <member name="anisotropy" type="float" setter="set_anisotropy" getter="get_anisotropy" default="0.0">
The strength of the anisotropy effect.
</member>
<member name="anisotropy_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
@@ -105,19 +105,19 @@
<member name="ao_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
If [code]true[/code], ambient occlusion is enabled. Ambient occlusion darkens areas based on the [member ao_texture].
</member>
- <member name="ao_light_affect" type="float" setter="set_ao_light_affect" getter="get_ao_light_affect">
+ <member name="ao_light_affect" type="float" setter="set_ao_light_affect" getter="get_ao_light_affect" default="0.0">
Amount that ambient occlusion affects lighting from lights. If [code]0[/code], ambient occlusion only affects ambient light. If [code]1[/code], ambient occlusion affects lights just as much as it affects ambient light. This can be used to impact the strength of the ambient occlusion effect, but typically looks unrealistic.
</member>
- <member name="ao_on_uv2" type="bool" setter="set_flag" getter="get_flag">
+ <member name="ao_on_uv2" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], use [code]UV2[/code] coordinates to look up from the [member ao_texture].
</member>
<member name="ao_texture" type="Texture2D" setter="set_texture" getter="get_texture">
Texture that defines the amount of ambient occlusion for a given point on the object.
</member>
- <member name="ao_texture_channel" type="int" setter="set_ao_texture_channel" getter="get_ao_texture_channel" enum="BaseMaterial3D.TextureChannel">
+ <member name="ao_texture_channel" type="int" setter="set_ao_texture_channel" getter="get_ao_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.
</member>
- <member name="backlight" type="Color" setter="set_backlight" getter="get_backlight">
+ <member name="backlight" type="Color" setter="set_backlight" getter="get_backlight" default="Color( 0, 0, 0, 1 )">
The color used by the backlight effect. Represents the light passing through an object.
</member>
<member name="backlight_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
@@ -127,7 +127,7 @@
Texture used to control the backlight effect per-pixel. Added to [member backlight].
</member>
<member name="billboard_keep_scale" type="bool" setter="set_flag" getter="get_flag" default="false">
- If [code]true[/code], the shader will keep the scale set for the mesh. Otherwise the scale is lost when billboarding. Only applies when [member billboard_mode] is [constant BILLBOARD_ENABLED].
+ If [code]true[/code], the shader will keep the scale set for the mesh. Otherwise, the scale is lost when billboarding. Only applies when [member billboard_mode] is [constant BILLBOARD_ENABLED].
</member>
<member name="billboard_mode" type="int" setter="set_billboard_mode" getter="get_billboard_mode" enum="BaseMaterial3D.BillboardMode" default="0">
Controls how the object faces the camera. See [enum BillboardMode].
@@ -137,13 +137,13 @@
The material's blend mode.
[b]Note:[/b] Values other than [code]Mix[/code] force the object into the transparent pipeline. See [enum BlendMode].
</member>
- <member name="clearcoat" type="float" setter="set_clearcoat" getter="get_clearcoat">
+ <member name="clearcoat" type="float" setter="set_clearcoat" getter="get_clearcoat" default="1.0">
Sets the strength of the clearcoat effect. Setting to [code]0[/code] looks the same as disabling the clearcoat effect.
</member>
<member name="clearcoat_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
If [code]true[/code], clearcoat rendering is enabled. Adds a secondary transparent pass to the lighting calculation resulting in an added specular blob. This makes materials appear as if they have a clear layer on them that can be either glossy or rough.
</member>
- <member name="clearcoat_gloss" type="float" setter="set_clearcoat_gloss" getter="get_clearcoat_gloss">
+ <member name="clearcoat_gloss" type="float" setter="set_clearcoat_gloss" getter="get_clearcoat_gloss" default="0.5">
Sets the roughness of the clearcoat pass. A higher value results in a smoother clearcoat while a lower value results in a rougher clearcoat.
</member>
<member name="clearcoat_texture" type="Texture2D" setter="set_texture" getter="get_texture">
@@ -158,7 +158,7 @@
<member name="detail_albedo" type="Texture2D" setter="set_texture" getter="get_texture">
Texture that specifies the color of the detail overlay.
</member>
- <member name="detail_blend_mode" type="int" setter="set_detail_blend_mode" getter="get_detail_blend_mode" enum="BaseMaterial3D.BlendMode">
+ <member name="detail_blend_mode" type="int" setter="set_detail_blend_mode" getter="get_detail_blend_mode" enum="BaseMaterial3D.BlendMode" default="0">
Specifies how the [member detail_albedo] should blend with the current [code]ALBEDO[/code]. See [enum BlendMode] for options.
</member>
<member name="detail_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
@@ -171,7 +171,7 @@
Texture that specifies the per-pixel normal of the detail overlay.
[b]Note:[/b] Godot expects the normal map to use X+, Y-, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
</member>
- <member name="detail_uv_layer" type="int" setter="set_detail_uv" getter="get_detail_uv" enum="BaseMaterial3D.DetailUV">
+ <member name="detail_uv_layer" type="int" setter="set_detail_uv" getter="get_detail_uv" enum="BaseMaterial3D.DetailUV" default="0">
Specifies whether to use [code]UV[/code] or [code]UV2[/code] for the detail layer. See [enum DetailUV] for options.
</member>
<member name="diffuse_mode" type="int" setter="set_diffuse_mode" getter="get_diffuse_mode" enum="BaseMaterial3D.DiffuseMode" default="0">
@@ -183,30 +183,30 @@
<member name="disable_receive_shadows" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], the object receives no shadow that would otherwise be cast onto it.
</member>
- <member name="distance_fade_max_distance" type="float" setter="set_distance_fade_max_distance" getter="get_distance_fade_max_distance">
+ <member name="distance_fade_max_distance" type="float" setter="set_distance_fade_max_distance" getter="get_distance_fade_max_distance" default="10.0">
Distance at which the object appears fully opaque.
[b]Note:[/b] If [code]distance_fade_max_distance[/code] is less than [code]distance_fade_min_distance[/code], the behavior will be reversed. The object will start to fade away at [code]distance_fade_max_distance[/code] and will fully disappear once it reaches [code]distance_fade_min_distance[/code].
</member>
- <member name="distance_fade_min_distance" type="float" setter="set_distance_fade_min_distance" getter="get_distance_fade_min_distance">
+ <member name="distance_fade_min_distance" type="float" setter="set_distance_fade_min_distance" getter="get_distance_fade_min_distance" default="0.0">
Distance at which the object starts to become visible. If the object is less than this distance away, it will be invisible.
[b]Note:[/b] If [code]distance_fade_min_distance[/code] is greater than [code]distance_fade_max_distance[/code], the behavior will be reversed. The object will start to fade away at [code]distance_fade_max_distance[/code] and will fully disappear once it reaches [code]distance_fade_min_distance[/code].
</member>
<member name="distance_fade_mode" type="int" setter="set_distance_fade" getter="get_distance_fade" enum="BaseMaterial3D.DistanceFadeMode" default="0">
Specifies which type of fade to use. Can be any of the [enum DistanceFadeMode]s.
</member>
- <member name="emission" type="Color" setter="set_emission" getter="get_emission">
+ <member name="emission" type="Color" setter="set_emission" getter="get_emission" default="Color( 0, 0, 0, 1 )">
The emitted light's color. See [member emission_enabled].
</member>
<member name="emission_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
If [code]true[/code], the body emits light. Emitting light makes the object appear brighter. The object can also cast light on other objects if a [GIProbe] is used and this object is used in baked lighting.
</member>
- <member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy">
+ <member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy" default="1.0">
The emitted light's strength. See [member emission_enabled].
</member>
- <member name="emission_on_uv2" type="bool" setter="set_flag" getter="get_flag">
+ <member name="emission_on_uv2" type="bool" setter="set_flag" getter="get_flag" default="false">
Use [code]UV2[/code] to read from the [member emission_texture].
</member>
- <member name="emission_operator" type="int" setter="set_emission_operator" getter="get_emission_operator" enum="BaseMaterial3D.EmissionOperator">
+ <member name="emission_operator" type="int" setter="set_emission_operator" getter="get_emission_operator" enum="BaseMaterial3D.EmissionOperator" default="0">
Sets how [member emission] interacts with [member emission_texture]. Can either add or multiply. See [enum EmissionOperator] for options.
</member>
<member name="emission_texture" type="Texture2D" setter="set_texture" getter="get_texture">
@@ -221,21 +221,23 @@
<member name="grow_amount" type="float" setter="set_grow" getter="get_grow" default="0.0">
Grows object vertices in the direction of their normals.
</member>
- <member name="heightmap_deep_parallax" type="bool" setter="set_heightmap_deep_parallax" getter="is_heightmap_deep_parallax_enabled">
+ <member name="heightmap_deep_parallax" type="bool" setter="set_heightmap_deep_parallax" getter="is_heightmap_deep_parallax_enabled" default="false">
</member>
<member name="heightmap_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
+ If [code]true[/code], height mapping is enabled (also called "parallax mapping" or "depth mapping"). See also [member normal_enabled].
+ [b]Note:[/b] Height mapping is not supported if triplanar mapping is used on the same material. The value of [member heightmap_enabled] will be ignored if [member uv1_triplanar] is enabled.
</member>
- <member name="heightmap_flip_binormal" type="bool" setter="set_heightmap_deep_parallax_flip_binormal" getter="get_heightmap_deep_parallax_flip_binormal">
+ <member name="heightmap_flip_binormal" type="bool" setter="set_heightmap_deep_parallax_flip_binormal" getter="get_heightmap_deep_parallax_flip_binormal" default="false">
</member>
- <member name="heightmap_flip_tangent" type="bool" setter="set_heightmap_deep_parallax_flip_tangent" getter="get_heightmap_deep_parallax_flip_tangent">
+ <member name="heightmap_flip_tangent" type="bool" setter="set_heightmap_deep_parallax_flip_tangent" getter="get_heightmap_deep_parallax_flip_tangent" default="false">
</member>
- <member name="heightmap_flip_texture" type="bool" setter="set_flag" getter="get_flag">
+ <member name="heightmap_flip_texture" type="bool" setter="set_flag" getter="get_flag" default="false">
</member>
<member name="heightmap_max_layers" type="int" setter="set_heightmap_deep_parallax_max_layers" getter="get_heightmap_deep_parallax_max_layers">
</member>
<member name="heightmap_min_layers" type="int" setter="set_heightmap_deep_parallax_min_layers" getter="get_heightmap_deep_parallax_min_layers">
</member>
- <member name="heightmap_scale" type="float" setter="set_heightmap_scale" getter="get_heightmap_scale">
+ <member name="heightmap_scale" type="float" setter="set_heightmap_scale" getter="get_heightmap_scale" default="0.05">
</member>
<member name="heightmap_texture" type="Texture2D" setter="set_texture" getter="get_texture">
</member>
@@ -258,7 +260,7 @@
<member name="normal_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
If [code]true[/code], normal mapping is enabled.
</member>
- <member name="normal_scale" type="float" setter="set_normal_scale" getter="get_normal_scale">
+ <member name="normal_scale" type="float" setter="set_normal_scale" getter="get_normal_scale" default="1.0">
The strength of the normal map's effect.
</member>
<member name="normal_texture" type="Texture2D" setter="set_texture" getter="get_texture">
@@ -279,7 +281,7 @@
<member name="point_size" type="float" setter="set_point_size" getter="get_point_size" default="1.0">
The point size in pixels. See [member use_point_size].
</member>
- <member name="proximity_fade_distance" type="float" setter="set_proximity_fade_distance" getter="get_proximity_fade_distance">
+ <member name="proximity_fade_distance" type="float" setter="set_proximity_fade_distance" getter="get_proximity_fade_distance" default="1.0">
Distance over which the fade effect takes place. The larger the distance the longer it takes for an object to fade.
</member>
<member name="proximity_fade_enable" type="bool" setter="set_proximity_fade" getter="is_proximity_fade_enabled" default="false">
@@ -288,16 +290,16 @@
<member name="refraction_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
If [code]true[/code], the refraction effect is enabled. Distorts transparency based on light from behind the object.
</member>
- <member name="refraction_scale" type="float" setter="set_refraction" getter="get_refraction">
+ <member name="refraction_scale" type="float" setter="set_refraction" getter="get_refraction" default="0.05">
The strength of the refraction effect.
</member>
<member name="refraction_texture" type="Texture2D" setter="set_texture" getter="get_texture">
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">
+ <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.
</member>
- <member name="rim" type="float" setter="set_rim" getter="get_rim">
+ <member name="rim" type="float" setter="set_rim" getter="get_rim" default="1.0">
Sets the strength of the rim lighting effect.
</member>
<member name="rim_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
@@ -306,7 +308,7 @@
<member name="rim_texture" type="Texture2D" setter="set_texture" getter="get_texture">
Texture used to set the strength of the rim lighting effect per-pixel. Multiplied by [member rim].
</member>
- <member name="rim_tint" type="float" setter="set_rim_tint" getter="get_rim_tint">
+ <member name="rim_tint" type="float" setter="set_rim_tint" getter="get_rim_tint" default="0.5">
The amount of to blend light and albedo color when rendering rim effect. If [code]0[/code] the light color is used, while [code]1[/code] means albedo color is used. An intermediate value generally works best.
</member>
<member name="roughness" type="float" setter="set_roughness" getter="get_roughness" default="1.0">
@@ -330,24 +332,24 @@
<member name="subsurf_scatter_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
If [code]true[/code], subsurface scattering is enabled. Emulates light that penetrates an object's surface, is scattered, and then emerges.
</member>
- <member name="subsurf_scatter_skin_mode" type="bool" setter="set_flag" getter="get_flag">
+ <member name="subsurf_scatter_skin_mode" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], subsurface scattering will use a special mode optimized for the color and density of human skin.
</member>
- <member name="subsurf_scatter_strength" type="float" setter="set_subsurface_scattering_strength" getter="get_subsurface_scattering_strength">
+ <member name="subsurf_scatter_strength" type="float" setter="set_subsurface_scattering_strength" getter="get_subsurface_scattering_strength" default="0.0">
The strength of the subsurface scattering effect.
</member>
<member name="subsurf_scatter_texture" type="Texture2D" setter="set_texture" getter="get_texture">
Texture used to control the subsurface scattering strength. Stored in the red texture channel. Multiplied by [member subsurf_scatter_strength].
</member>
- <member name="subsurf_scatter_transmittance_boost" type="float" setter="set_transmittance_boost" getter="get_transmittance_boost">
+ <member name="subsurf_scatter_transmittance_boost" type="float" setter="set_transmittance_boost" getter="get_transmittance_boost" default="0.0">
</member>
- <member name="subsurf_scatter_transmittance_color" type="Color" setter="set_transmittance_color" getter="get_transmittance_color">
+ <member name="subsurf_scatter_transmittance_color" type="Color" setter="set_transmittance_color" getter="get_transmittance_color" default="Color( 1, 1, 1, 1 )">
</member>
- <member name="subsurf_scatter_transmittance_curve" type="float" setter="set_transmittance_curve" getter="get_transmittance_curve">
+ <member name="subsurf_scatter_transmittance_curve" type="float" setter="set_transmittance_curve" getter="get_transmittance_curve" default="1.0">
</member>
- <member name="subsurf_scatter_transmittance_depth" type="float" setter="set_transmittance_depth" getter="get_transmittance_depth">
+ <member name="subsurf_scatter_transmittance_depth" type="float" setter="set_transmittance_depth" getter="get_transmittance_depth" default="0.1">
</member>
- <member name="subsurf_scatter_transmittance_enabled" type="bool" setter="set_feature" getter="get_feature">
+ <member name="subsurf_scatter_transmittance_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
</member>
<member name="subsurf_scatter_transmittance_texture" type="Texture2D" setter="set_texture" getter="get_texture">
</member>
diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml
index 4c9cd5702e..55ae58ee3a 100644
--- a/doc/classes/Basis.xml
+++ b/doc/classes/Basis.xml
@@ -78,7 +78,7 @@
Constructs a basis matrix from 3 axis vectors (matrix columns).
</description>
</method>
- <method name="determinant">
+ <method name="determinant" qualifiers="const">
<return type="float">
</return>
<description>
@@ -86,7 +86,7 @@
A negative determinant means the basis has a negative scale. A zero determinant means the basis isn't invertible, and is usually considered invalid.
</description>
</method>
- <method name="get_euler">
+ <method name="get_euler" qualifiers="const">
<return type="Vector3">
</return>
<description>
@@ -94,35 +94,35 @@
Consider using the [method get_rotation_quat] method instead, which returns a [Quat] quaternion instead of Euler angles.
</description>
</method>
- <method name="get_orthogonal_index">
+ <method name="get_orthogonal_index" qualifiers="const">
<return type="int">
</return>
<description>
This function considers a discretization of rotations into 24 points on unit sphere, lying along the vectors (x,y,z) with each component being either -1, 0, or 1, and returns the index of the point best representing the orientation of the object. It is mainly used by the [GridMap] editor. For further details, refer to the Godot source code.
</description>
</method>
- <method name="get_rotation_quat">
+ <method name="get_rotation_quat" qualifiers="const">
<return type="Quat">
</return>
<description>
Returns the basis's rotation in the form of a quaternion. See [method get_euler] if you need Euler angles, but keep in mind quaternions should generally be preferred to Euler angles.
</description>
</method>
- <method name="get_scale">
+ <method name="get_scale" qualifiers="const">
<return type="Vector3">
</return>
<description>
Assuming that the matrix is the combination of a rotation and scaling, return the absolute value of scaling factors along each axis.
</description>
</method>
- <method name="inverse">
+ <method name="inverse" qualifiers="const">
<return type="Basis">
</return>
<description>
Returns the inverse of the matrix.
</description>
</method>
- <method name="is_equal_approx">
+ <method name="is_equal_approx" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="b" type="Basis">
@@ -171,14 +171,14 @@
<description>
</description>
</method>
- <method name="orthonormalized">
+ <method name="orthonormalized" qualifiers="const">
<return type="Basis">
</return>
<description>
Returns the orthonormalized version of the matrix (useful to call from time to time to avoid rounding error for orthogonal matrices). This performs a Gram-Schmidt orthonormalization on the basis of the matrix.
</description>
</method>
- <method name="rotated">
+ <method name="rotated" qualifiers="const">
<return type="Basis">
</return>
<argument index="0" name="axis" type="Vector3">
@@ -189,7 +189,7 @@
Introduce an additional rotation around the given axis by phi (radians). The axis must be a normalized vector.
</description>
</method>
- <method name="scaled">
+ <method name="scaled" qualifiers="const">
<return type="Basis">
</return>
<argument index="0" name="scale" type="Vector3">
@@ -198,7 +198,7 @@
Introduce an additional scaling specified by the given 3D scaling factor.
</description>
</method>
- <method name="slerp">
+ <method name="slerp" qualifiers="const">
<return type="Basis">
</return>
<argument index="0" name="to" type="Basis">
@@ -209,7 +209,7 @@
Assuming that the matrix is a proper rotation matrix, slerp performs a spherical-linear interpolation with another rotation matrix.
</description>
</method>
- <method name="tdotx">
+ <method name="tdotx" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="with" type="Vector3">
@@ -218,7 +218,7 @@
Transposed dot product with the X axis of the matrix.
</description>
</method>
- <method name="tdoty">
+ <method name="tdoty" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="with" type="Vector3">
@@ -227,7 +227,7 @@
Transposed dot product with the Y axis of the matrix.
</description>
</method>
- <method name="tdotz">
+ <method name="tdotz" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="with" type="Vector3">
@@ -236,7 +236,7 @@
Transposed dot product with the Z axis of the matrix.
</description>
</method>
- <method name="transposed">
+ <method name="transposed" qualifiers="const">
<return type="Basis">
</return>
<description>
diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml
index 8908c5f830..51c35b15ce 100644
--- a/doc/classes/Button.xml
+++ b/doc/classes/Button.xml
@@ -34,6 +34,7 @@
[/codeblocks]
Buttons (like all Control nodes) can also be created in the editor, but some situations may require creating them from code.
See also [BaseButton] which contains common properties and methods associated with this node.
+ [b]Note:[/b] Buttons do not interpret touch input and therefore don't support multitouch, since mouse emulation can only press one button at a given time. Use [TouchScreenButton] for buttons that trigger gameplay movement or actions, as [TouchScreenButton] supports multitouch.
</description>
<tutorials>
<link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link>
@@ -128,7 +129,7 @@
Text [Color] used when the [Button] is being hovered and pressed.
</theme_item>
<theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
- Text outline [Color] of the [Button].
+ The tint of text outline of the [Button].
</theme_item>
<theme_item name="font_pressed_color" type="Color" default="Color( 1, 1, 1, 1 )">
Text [Color] used when the [Button] is being pressed.
@@ -161,7 +162,7 @@
Default [StyleBox] for the [Button].
</theme_item>
<theme_item name="outline_size" type="int" default="0">
- Size of the [Button]'s text outline.
+ The size of the text outline.
</theme_item>
<theme_item name="pressed" type="StyleBox">
[StyleBox] used when the [Button] is being pressed.
diff --git a/doc/classes/Callable.xml b/doc/classes/Callable.xml
index f137ede90f..0cfbd0270c 100644
--- a/doc/classes/Callable.xml
+++ b/doc/classes/Callable.xml
@@ -8,26 +8,26 @@
[b]Example:[/b]
[codeblocks]
[gdscript]
- var callable = Callable(self, "print_args")
func print_args(arg1, arg2, arg3 = ""):
prints(arg1, arg2, arg3)
func test():
- callable.call("hello", "world") # Prints "hello world".
+ var callable = Callable(self, "print_args")
+ callable.call("hello", "world") # Prints "hello world ".
callable.call(Vector2.UP, 42, callable) # Prints "(0, -1) 42 Node(Node.gd)::print_args".
callable.call("invalid") # Invalid call, should have at least 2 arguments.
[/gdscript]
[csharp]
- Callable callable = new Callable(this, "print_args");
- public void PrintArgs(object arg1, object arg2, object arg3 = "")
+ public void PrintArgs(object arg1, object arg2, object arg3 = null)
{
GD.PrintS(arg1, arg2, arg3);
}
public void Test()
{
- callable.Call("hello", "world"); // Prints "hello world".
- callable.Call(Vector2.Up, 42, callable); // Prints "(0, -1) 42 Node(Node.gd)::print_args".
+ Callable callable = new Callable(this, nameof(PrintArgs));
+ callable.Call("hello", "world"); // Prints "hello world null".
+ callable.Call(Vector2.Up, 42, callable); // Prints "(0, -1) 42 Node(Node.cs)::PrintArgs".
callable.Call("invalid"); // Invalid call, should have at least 2 arguments.
}
[/csharp]
@@ -63,69 +63,74 @@
Creates a new [Callable] for the method called [code]method[/code] in the specified [code]object[/code].
</description>
</method>
- <method name="bind" qualifiers="vararg">
+ <method name="bind" qualifiers="vararg const">
<return type="Callable">
</return>
<description>
+ Returns a copy of this [Callable] with the arguments bound. Bound arguments are passed after the arguments supplied by [method call].
</description>
</method>
- <method name="call" qualifiers="vararg">
+ <method name="call" qualifiers="vararg const">
<return type="Variant">
</return>
<description>
Calls the method represented by this [Callable]. Arguments can be passed and should match the method's signature.
</description>
</method>
- <method name="call_deferred" qualifiers="vararg">
+ <method name="call_deferred" qualifiers="vararg const">
<return type="void">
</return>
<description>
Calls the method represented by this [Callable] in deferred mode, i.e. during the idle frame. Arguments can be passed and should match the method's signature.
</description>
</method>
- <method name="get_method">
+ <method name="get_method" qualifiers="const">
<return type="StringName">
</return>
<description>
Returns the name of the method represented by this [Callable].
</description>
</method>
- <method name="get_object">
+ <method name="get_object" qualifiers="const">
<return type="Object">
</return>
<description>
Returns the object on which this [Callable] is called.
</description>
</method>
- <method name="get_object_id">
+ <method name="get_object_id" qualifiers="const">
<return type="int">
</return>
<description>
Returns the ID of this [Callable]'s object (see [method Object.get_instance_id]).
</description>
</method>
- <method name="hash">
+ <method name="hash" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the hash value of this [Callable]'s object.
</description>
</method>
- <method name="is_custom">
+ <method name="is_custom" qualifiers="const">
<return type="bool">
</return>
<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].
</description>
</method>
- <method name="is_null">
+ <method name="is_null" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if this [Callable] has no target to call the method on.
</description>
</method>
- <method name="is_standard">
+ <method name="is_standard" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if this [Callable] is a standard callable, referencing an object and a method using a [StringName].
</description>
</method>
<method name="operator !=" qualifiers="operator">
@@ -134,6 +139,7 @@
<argument index="0" name="right" type="Callable">
</argument>
<description>
+ Returns [code]true[/code] if both [Callable]s invoke different targets.
</description>
</method>
<method name="operator ==" qualifiers="operator">
@@ -142,14 +148,16 @@
<argument index="0" name="right" type="Callable">
</argument>
<description>
+ Returns [code]true[/code] if both [Callable]s invoke the same custom target.
</description>
</method>
- <method name="unbind">
+ <method name="unbind" qualifiers="const">
<return type="Callable">
</return>
<argument index="0" name="argcount" type="int">
</argument>
<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.
</description>
</method>
</methods>
diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml
index 2a4e726d43..d40567bdcb 100644
--- a/doc/classes/Camera2D.xml
+++ b/doc/classes/Camera2D.xml
@@ -168,8 +168,8 @@
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2( 0, 0 )">
The camera's offset, useful for looking around or camera shake animations.
</member>
- <member name="process_mode" type="int" setter="set_process_mode" getter="get_process_mode" enum="Camera2D.Camera2DProcessMode" default="1">
- The camera's process callback. See [enum Camera2DProcessMode].
+ <member name="process_callback" type="int" setter="set_process_callback" getter="get_process_callback" enum="Camera2D.Camera2DProcessCallback" default="1">
+ The camera's process callback. See [enum Camera2DProcessCallback].
</member>
<member name="rotating" type="bool" setter="set_rotating" getter="is_rotating" default="false">
If [code]true[/code], the camera rotates with the target.
@@ -191,10 +191,10 @@
<constant name="ANCHOR_MODE_DRAG_CENTER" value="1" enum="AnchorMode">
The camera's position takes into account vertical/horizontal offsets and the screen size.
</constant>
- <constant name="CAMERA2D_PROCESS_PHYSICS" value="0" enum="Camera2DProcessMode">
+ <constant name="CAMERA2D_PROCESS_PHYSICS" value="0" enum="Camera2DProcessCallback">
The camera updates with the [code]_physics_process[/code] callback.
</constant>
- <constant name="CAMERA2D_PROCESS_IDLE" value="1" enum="Camera2DProcessMode">
+ <constant name="CAMERA2D_PROCESS_IDLE" value="1" enum="Camera2DProcessCallback">
The camera updates with the [code]_process[/code] callback.
</constant>
</constants>
diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml
index 034b2e9629..9f1d6d8e31 100644
--- a/doc/classes/Camera3D.xml
+++ b/doc/classes/Camera3D.xml
@@ -194,7 +194,7 @@
</member>
<member name="fov" type="float" setter="set_fov" getter="get_fov" default="75.0">
The camera's field of view angle (in degrees). Only applicable in perspective mode. Since [member keep_aspect] locks one axis, [code]fov[/code] sets the other axis' field of view angle.
- For reference, the default vertical field of view value ([code]75.0[/code]) is equivalent to an horizontal FOV of:
+ For reference, the default vertical field of view value ([code]75.0[/code]) is equivalent to a horizontal FOV of:
- ~91.31 degrees in a 4:3 viewport
- ~101.67 degrees in a 16:10 viewport
- ~107.51 degrees in a 16:9 viewport
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index d13f431a16..87b157db4e 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -318,7 +318,7 @@
<argument index="9" name="flags" type="int" default="3">
</argument>
<description>
- Draws [code]text[/code] using the specified [code]font[/code] at the [code]position[/code] (top-left corner). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width.
+ Draws [code]text[/code] using the specified [code]font[/code] at the [code]position[/code] (bottom-left corner using the baseline of the font). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width.
[b]Example using the default project font:[/b]
[codeblocks]
[gdscript]
diff --git a/doc/classes/CharFXTransform.xml b/doc/classes/CharFXTransform.xml
index b4cb110337..850098f741 100644
--- a/doc/classes/CharFXTransform.xml
+++ b/doc/classes/CharFXTransform.xml
@@ -17,7 +17,7 @@
The color the character will be drawn with.
</member>
<member name="elapsed_time" type="float" setter="set_elapsed_time" getter="get_elapsed_time" default="0.0">
- The time elapsed since the [RichTextLabel] was added to the scene tree (in seconds). Time stops when the project is paused, unless the [RichTextLabel]'s [member Node.pause_mode] is set to [constant Node.PAUSE_MODE_PROCESS].
+ The time elapsed since the [RichTextLabel] was added to the scene tree (in seconds). Time stops when the project is paused depending on the value of the [RichTextLabel]'s [member Node.process_mode].
[b]Note:[/b] Time still passes while the [RichTextLabel] is hidden.
</member>
<member name="env" type="Dictionary" setter="set_environment" getter="get_environment" default="{}">
diff --git a/doc/classes/CheckBox.xml b/doc/classes/CheckBox.xml
index bd91f9ed06..80febfbfe7 100644
--- a/doc/classes/CheckBox.xml
+++ b/doc/classes/CheckBox.xml
@@ -45,6 +45,9 @@
<theme_item name="font_hover_pressed_color" type="Color" default="Color( 1, 1, 1, 1 )">
The [CheckBox] text's font color when it's hovered and pressed.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the [CheckBox].
+ </theme_item>
<theme_item name="font_pressed_color" type="Color" default="Color( 1, 1, 1, 1 )">
The [CheckBox] text's font color when it's pressed.
</theme_item>
@@ -63,6 +66,9 @@
<theme_item name="normal" type="StyleBox">
The [StyleBox] to display as a background.
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
<theme_item name="pressed" type="StyleBox">
The [StyleBox] to display as a background when the [CheckBox] is pressed.
</theme_item>
diff --git a/doc/classes/CheckButton.xml b/doc/classes/CheckButton.xml
index a05e532d4a..46e590a115 100644
--- a/doc/classes/CheckButton.xml
+++ b/doc/classes/CheckButton.xml
@@ -42,6 +42,9 @@
<theme_item name="font_hover_pressed_color" type="Color" default="Color( 1, 1, 1, 1 )">
The [CheckButton] text's font color when it's hovered and pressed.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the [CheckButton].
+ </theme_item>
<theme_item name="font_pressed_color" type="Color" default="Color( 1, 1, 1, 1 )">
The [CheckButton] text's font color when it's pressed.
</theme_item>
@@ -84,6 +87,9 @@
<theme_item name="on_mirrored" type="Texture2D">
The icon to display when the [CheckButton] is checked (for right-to-left layouts).
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
<theme_item name="pressed" type="StyleBox">
The [StyleBox] to display as a background when the [CheckButton] is pressed.
</theme_item>
diff --git a/doc/classes/ClippedCamera3D.xml b/doc/classes/ClippedCamera3D.xml
index de90247536..9116af19c3 100644
--- a/doc/classes/ClippedCamera3D.xml
+++ b/doc/classes/ClippedCamera3D.xml
@@ -95,15 +95,15 @@
<member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.0">
The camera's collision margin. The camera can't get closer than this distance to a colliding object.
</member>
- <member name="process_mode" type="int" setter="set_process_mode" getter="get_process_mode" enum="ClippedCamera3D.ProcessMode" default="0">
- The camera's process callback. See [enum ProcessMode].
+ <member name="process_callback" type="int" setter="set_process_callback" getter="get_process_callback" enum="ClippedCamera3D.ClipProcessCallback" default="0">
+ The camera's process callback. See [enum ClipProcessCallback].
</member>
</members>
<constants>
- <constant name="CLIP_PROCESS_PHYSICS" value="0" enum="ProcessMode">
+ <constant name="CLIP_PROCESS_PHYSICS" value="0" enum="ClipProcessCallback">
The camera updates with the [code]_physics_process[/code] callback.
</constant>
- <constant name="CLIP_PROCESS_IDLE" value="1" enum="ProcessMode">
+ <constant name="CLIP_PROCESS_IDLE" value="1" enum="ClipProcessCallback">
The camera updates with the [code]_process[/code] callback.
</constant>
</constants>
diff --git a/doc/classes/CodeEdit.xml b/doc/classes/CodeEdit.xml
index f897f2405b..81795abcdd 100644
--- a/doc/classes/CodeEdit.xml
+++ b/doc/classes/CodeEdit.xml
@@ -3,7 +3,7 @@
<brief_description>
</brief_description>
<description>
- [b]Note[/b]: By default [CodeEdit] always use left-to-right text direction to correcly display source code.
+ [b]Note[/b]: By default [CodeEdit] always use left-to-right text direction to correctly display source code.
</description>
<tutorials>
</tutorials>
@@ -179,6 +179,9 @@
</theme_item>
<theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the [CodeEdit].
+ </theme_item>
<theme_item name="font_readonly_color" type="Color" default="Color( 0.88, 0.88, 0.88, 0.5 )">
</theme_item>
<theme_item name="font_selected_color" type="Color" default="Color( 0, 0, 0, 1 )">
@@ -194,6 +197,9 @@
</theme_item>
<theme_item name="normal" type="StyleBox">
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
<theme_item name="read_only" type="StyleBox">
</theme_item>
<theme_item name="safe_line_number_color" type="Color" default="Color( 0.67, 0.78, 0.67, 0.6 )">
diff --git a/doc/classes/CodeHighlighter.xml b/doc/classes/CodeHighlighter.xml
index 7a1dad547b..f078e4e5b0 100644
--- a/doc/classes/CodeHighlighter.xml
+++ b/doc/classes/CodeHighlighter.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CodeHighlighter" inherits="SyntaxHighlighter" version="4.0">
<brief_description>
+ A syntax highlighter for code.
</brief_description>
<description>
+ A syntax highlighter for code.
</description>
<tutorials>
</tutorials>
@@ -10,15 +12,18 @@
<method name="add_color_region">
<return type="void">
</return>
- <argument index="0" name="p_start_key" type="String">
+ <argument index="0" name="start_key" type="String">
</argument>
- <argument index="1" name="p_end_key" type="String">
+ <argument index="1" name="end_key" type="String">
</argument>
- <argument index="2" name="p_color" type="Color">
+ <argument index="2" name="color" type="Color">
</argument>
- <argument index="3" name="p_line_only" type="bool" default="false">
+ <argument index="3" name="line_only" type="bool" default="false">
</argument>
<description>
+ Adds a color region such as comments or strings.
+ Both the start and end keys must be symbols. Only the start key has to be unique.
+ Line only denotes if the region should continue until the end of the line or carry over on to the next line. If the end key is blank this is automatically set to [code]true[/code].
</description>
</method>
<method name="add_keyword_color">
@@ -29,6 +34,8 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Sets the color for a keyword.
+ The keyword cannot contain any symbols except '_'.
</description>
</method>
<method name="add_member_keyword_color">
@@ -39,24 +46,30 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Sets the color for a member keyword.
+ The member keyword cannot contain any symbols except '_'.
+ It will not be highlighted if preceded by a '.'.
</description>
</method>
<method name="clear_color_regions">
<return type="void">
</return>
<description>
+ Removes all color regions.
</description>
</method>
<method name="clear_keyword_colors">
<return type="void">
</return>
<description>
+ Removes all keywords.
</description>
</method>
<method name="clear_member_keyword_colors">
<return type="void">
</return>
<description>
+ Removes all member keywords.
</description>
</method>
<method name="get_keyword_color" qualifiers="const">
@@ -65,6 +78,7 @@
<argument index="0" name="keyword" type="String">
</argument>
<description>
+ Returns the color for a keyword.
</description>
</method>
<method name="get_member_keyword_color" qualifiers="const">
@@ -73,14 +87,16 @@
<argument index="0" name="member_keyword" type="String">
</argument>
<description>
+ Returns the color for a member keyword.
</description>
</method>
<method name="has_color_region" qualifiers="const">
<return type="bool">
</return>
- <argument index="0" name="p_start_key" type="String">
+ <argument index="0" name="start_key" type="String">
</argument>
<description>
+ Return [code]true[/code] if the start key exists, else [code]false[/code].
</description>
</method>
<method name="has_keyword_color" qualifiers="const">
@@ -89,6 +105,7 @@
<argument index="0" name="keyword" type="String">
</argument>
<description>
+ Return [code]true[/code] if the keyword exists, else [code]false[/code].
</description>
</method>
<method name="has_member_keyword_color" qualifiers="const">
@@ -97,14 +114,16 @@
<argument index="0" name="member_keyword" type="String">
</argument>
<description>
+ Return [code]true[/code] if the member keyword exists, else [code]false[/code].
</description>
</method>
<method name="remove_color_region">
<return type="void">
</return>
- <argument index="0" name="p_start_key" type="String">
+ <argument index="0" name="start_key" type="String">
</argument>
<description>
+ Removes the color region that uses that start key.
</description>
</method>
<method name="remove_keyword_color">
@@ -113,6 +132,7 @@
<argument index="0" name="keyword" type="String">
</argument>
<description>
+ Removes the keyword.
</description>
</method>
<method name="remove_member_keyword_color">
@@ -121,23 +141,31 @@
<argument index="0" name="member_keyword" type="String">
</argument>
<description>
+ Removes the member keyword.
</description>
</method>
</methods>
<members>
<member name="color_regions" type="Dictionary" setter="set_color_regions" getter="get_color_regions" default="{}">
+ Sets the color regions. All existing regions will be removed. The [Dictionary] key is the region start and end key, separated by a space. The value is the region color.
</member>
<member name="function_color" type="Color" setter="set_function_color" getter="get_function_color" default="Color( 0, 0, 0, 1 )">
+ Sets color for functions. A function is a non-keyword string followed by a '('.
</member>
<member name="keyword_colors" type="Dictionary" setter="set_keyword_colors" getter="get_keyword_colors" default="{}">
+ Sets the keyword colors. All existing keywords will be removed. The [Dictionary] key is the keyword. The value is the keyword color.
</member>
<member name="member_keyword_colors" type="Dictionary" setter="set_member_keyword_colors" getter="get_member_keyword_colors" default="{}">
+ Sets the member keyword colors. All existing member keyword will be removed. The [Dictionary] key is the member keyword. The value is the member keyword color.
</member>
<member name="member_variable_color" type="Color" setter="set_member_variable_color" getter="get_member_variable_color" default="Color( 0, 0, 0, 1 )">
+ Sets color for member variables. A member variable is non-keyword, non-function string proceeded with a '.'.
</member>
<member name="number_color" type="Color" setter="set_number_color" getter="get_number_color" default="Color( 0, 0, 0, 1 )">
+ Sets the color for numbers.
</member>
<member name="symbol_color" type="Color" setter="set_symbol_color" getter="get_symbol_color" default="Color( 0, 0, 0, 1 )">
+ Sets the color for symbols.
</member>
</members>
<constants>
diff --git a/doc/classes/CollisionPolygon3D.xml b/doc/classes/CollisionPolygon3D.xml
index dd3c57d1d0..38f4c5fe5c 100644
--- a/doc/classes/CollisionPolygon3D.xml
+++ b/doc/classes/CollisionPolygon3D.xml
@@ -17,6 +17,9 @@
<member name="disabled" type="bool" setter="set_disabled" getter="is_disabled" default="false">
If [code]true[/code], no collision will be produced.
</member>
+ <member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.04">
+ The collision margin for the generated [Shape3D]. See [member Shape3D.margin] for more details.
+ </member>
<member name="polygon" type="PackedVector2Array" setter="set_polygon" getter="get_polygon" default="PackedVector2Array( )">
Array of vertices which define the polygon.
[b]Note:[/b] The returned value is a copy of the original. Methods which mutate the size or properties of the return value will not impact the original polygon. To change properties of the polygon, assign it to a temporary variable and make changes before reassigning the [code]polygon[/code] member.
diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml
index ce88e0ae88..c33d007735 100644
--- a/doc/classes/Color.xml
+++ b/doc/classes/Color.xml
@@ -56,10 +56,8 @@
</return>
<argument index="0" name="code" type="String">
</argument>
- <argument index="1" name="alpha" type="float">
- </argument>
<description>
- Constructs a [Color] either from an HTML color code or from a standardized color name, with [code]alpha[/code] 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. Supported color names are the same as the constants.
</description>
</method>
<method name="Color" qualifiers="constructor">
@@ -67,8 +65,10 @@
</return>
<argument index="0" name="code" type="String">
</argument>
+ <argument index="1" name="alpha" type="float">
+ </argument>
<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, with [code]alpha[/code] on the range of 0 to 1. Supported color names are the same as the constants.
</description>
</method>
<method name="Color" qualifiers="constructor">
@@ -80,16 +80,14 @@
</argument>
<argument index="2" name="b" type="float">
</argument>
- <argument index="3" name="a" type="float">
- </argument>
<description>
- Constructs a [Color] from RGBA values, typically between 0 and 1.
+ Constructs a [Color] from RGB values, typically between 0 and 1. Alpha will be 1.
[codeblocks]
[gdscript]
- var color = Color(0.2, 1.0, 0.7, 0.8) # Similar to `Color8(51, 255, 178, 204)`
+ var color = Color(0.2, 1.0, 0.7) # Similar to `Color8(51, 255, 178, 255)`
[/gdscript]
[csharp]
- var color = new Color(0.2f, 1.0f, 0.7f, 0.8f); // Similar to `Color.Color8(51, 255, 178, 255, 204)`
+ var color = new Color(0.2f, 1.0f, 0.7f); // Similar to `Color.Color8(51, 255, 178, 255)`
[/csharp]
[/codeblocks]
</description>
@@ -103,19 +101,21 @@
</argument>
<argument index="2" name="b" type="float">
</argument>
+ <argument index="3" name="a" type="float">
+ </argument>
<description>
- Constructs a [Color] from RGB values, typically between 0 and 1. Alpha will be 1.
+ Constructs a [Color] from RGBA values, typically between 0 and 1.
[codeblocks]
[gdscript]
- var color = Color(0.2, 1.0, 0.7) # Similar to `Color8(51, 255, 178, 255)`
+ var color = Color(0.2, 1.0, 0.7, 0.8) # Similar to `Color8(51, 255, 178, 204)`
[/gdscript]
[csharp]
- var color = new Color(0.2f, 1.0f, 0.7f); // Similar to `Color.Color8(51, 255, 178, 255)`
+ var color = new Color(0.2f, 1.0f, 0.7f, 0.8f); // Similar to `Color.Color8(51, 255, 178, 255, 204)`
[/csharp]
[/codeblocks]
</description>
</method>
- <method name="blend">
+ <method name="blend" qualifiers="const">
<return type="Color">
</return>
<argument index="0" name="over" type="Color">
@@ -136,7 +136,7 @@
[/codeblocks]
</description>
</method>
- <method name="darkened">
+ <method name="darkened" qualifiers="const">
<return type="Color">
</return>
<argument index="0" name="amount" type="float">
@@ -155,7 +155,87 @@
[/codeblocks]
</description>
</method>
- <method name="inverted">
+ <method name="find_named_color" qualifiers="static">
+ <return type="int">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="from_rgbe9995" qualifiers="static">
+ <return type="Color">
+ </return>
+ <argument index="0" name="rgbe" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="from_string" qualifiers="static">
+ <return type="Color">
+ </return>
+ <argument index="0" name="str" type="String">
+ </argument>
+ <argument index="1" name="default" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_named_color" qualifiers="static">
+ <return type="Color">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_named_color_count" qualifiers="static">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_named_color_name" qualifiers="static">
+ <return type="String">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="hex" qualifiers="static">
+ <return type="Color">
+ </return>
+ <argument index="0" name="hex" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="hex64" qualifiers="static">
+ <return type="Color">
+ </return>
+ <argument index="0" name="hex" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="html" qualifiers="static">
+ <return type="Color">
+ </return>
+ <argument index="0" name="rgba" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="html_is_valid" qualifiers="static">
+ <return type="bool">
+ </return>
+ <argument index="0" name="color" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="inverted" qualifiers="const">
<return type="Color">
</return>
<description>
@@ -172,7 +252,7 @@
[/codeblocks]
</description>
</method>
- <method name="is_equal_approx">
+ <method name="is_equal_approx" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="to" type="Color">
@@ -181,7 +261,7 @@
Returns [code]true[/code] if this color and [code]color[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component.
</description>
</method>
- <method name="lerp">
+ <method name="lerp" qualifiers="const">
<return type="Color">
</return>
<argument index="0" name="to" type="Color">
@@ -204,7 +284,7 @@
[/codeblocks]
</description>
</method>
- <method name="lightened">
+ <method name="lightened" qualifiers="const">
<return type="Color">
</return>
<argument index="0" name="amount" type="float">
@@ -323,7 +403,7 @@
<description>
</description>
</method>
- <method name="to_abgr32">
+ <method name="to_abgr32" qualifiers="const">
<return type="int">
</return>
<description>
@@ -340,7 +420,7 @@
[/codeblocks]
</description>
</method>
- <method name="to_abgr64">
+ <method name="to_abgr64" qualifiers="const">
<return type="int">
</return>
<description>
@@ -357,7 +437,7 @@
[/codeblocks]
</description>
</method>
- <method name="to_argb32">
+ <method name="to_argb32" qualifiers="const">
<return type="int">
</return>
<description>
@@ -374,7 +454,7 @@
[/codeblocks]
</description>
</method>
- <method name="to_argb64">
+ <method name="to_argb64" qualifiers="const">
<return type="int">
</return>
<description>
@@ -391,7 +471,7 @@
[/codeblocks]
</description>
</method>
- <method name="to_html">
+ <method name="to_html" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="with_alpha" type="bool" default="true">
@@ -413,7 +493,7 @@
[/codeblocks]
</description>
</method>
- <method name="to_rgba32">
+ <method name="to_rgba32" qualifiers="const">
<return type="int">
</return>
<description>
@@ -430,7 +510,7 @@
[/codeblocks]
</description>
</method>
- <method name="to_rgba64">
+ <method name="to_rgba64" qualifiers="const">
<return type="int">
</return>
<description>
diff --git a/doc/classes/ColorPicker.xml b/doc/classes/ColorPicker.xml
index aea3542867..2fc4313e47 100644
--- a/doc/classes/ColorPicker.xml
+++ b/doc/classes/ColorPicker.xml
@@ -91,6 +91,9 @@
<theme_item name="add_preset" type="Texture2D">
The icon for the "Add Preset" button.
</theme_item>
+ <theme_item name="bar_arrow" type="Texture2D">
+ The texture for the arrow grabber.
+ </theme_item>
<theme_item name="color_hue" type="Texture2D">
Custom texture for the hue selection slider on the right.
</theme_item>
diff --git a/doc/classes/ColorPickerButton.xml b/doc/classes/ColorPickerButton.xml
index b351faf9ca..e49027e61d 100644
--- a/doc/classes/ColorPickerButton.xml
+++ b/doc/classes/ColorPickerButton.xml
@@ -79,6 +79,9 @@
<theme_item name="font_hover_color" type="Color" default="Color( 1, 1, 1, 1 )">
Text [Color] used when the [ColorPickerButton] is being hovered.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the [ColorPickerButton].
+ </theme_item>
<theme_item name="font_pressed_color" type="Color" default="Color( 0.8, 0.8, 0.8, 1 )">
Text [Color] used when the [ColorPickerButton] is being pressed.
</theme_item>
@@ -94,6 +97,9 @@
<theme_item name="normal" type="StyleBox">
Default [StyleBox] for the [ColorPickerButton].
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
<theme_item name="pressed" type="StyleBox">
[StyleBox] used when the [ColorPickerButton] is being pressed.
</theme_item>
diff --git a/doc/classes/ConcavePolygonShape3D.xml b/doc/classes/ConcavePolygonShape3D.xml
index 3e83202472..a9687abedc 100644
--- a/doc/classes/ConcavePolygonShape3D.xml
+++ b/doc/classes/ConcavePolygonShape3D.xml
@@ -28,6 +28,11 @@
</description>
</method>
</methods>
+ <members>
+ <member name="backface_collision" type="bool" setter="set_backface_collision_enabled" getter="is_backface_collision_enabled" default="false">
+ If set to [code]true[/code], collisions occur on both sides of the concave shape faces. Otherwise they occur only along the face normals.
+ </member>
+ </members>
<constants>
</constants>
</class>
diff --git a/doc/classes/ConfigFile.xml b/doc/classes/ConfigFile.xml
index da17d993e3..2cac424f2e 100644
--- a/doc/classes/ConfigFile.xml
+++ b/doc/classes/ConfigFile.xml
@@ -158,7 +158,7 @@
<argument index="0" name="data" type="String">
</argument>
<description>
- Parses the the passed string as the contents of a config file. The string is parsed and loaded in the ConfigFile object which the method was called on.
+ Parses the passed string as the contents of a config file. The string is parsed and loaded in the ConfigFile object which the method was called on.
Returns one of the [enum Error] code constants ([code]OK[/code] on success).
</description>
</method>
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index e5285587eb..b22878e56a 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -50,7 +50,7 @@
[gdscript]
func _gui_input(event):
if event is InputEventMouseButton:
- if event.button_index == BUTTON_LEFT and event.pressed:
+ if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
print("I've been clicked D:")
[/gdscript]
[csharp]
@@ -869,7 +869,7 @@
<argument index="0" name="control" type="Control">
</argument>
<description>
- Shows the given control at the mouse pointer. A good time to call this method is in [method get_drag_data]. The control must not be in the scene tree.
+ Shows the given control at the mouse pointer. A good time to call this method is in [method get_drag_data]. The control must not be in the scene tree. You should not free the control, and you should not keep a reference to the control beyond the duration of the drag. It will be deleted automatically after the drag has ended.
[codeblocks]
[gdscript]
export (Color, RGBA) var color = Color(1, 0, 0, 1)
diff --git a/doc/classes/CryptoKey.xml b/doc/classes/CryptoKey.xml
index 410c2262f9..26b3087b21 100644
--- a/doc/classes/CryptoKey.xml
+++ b/doc/classes/CryptoKey.xml
@@ -27,7 +27,7 @@
</argument>
<description>
Loads a key from [code]path[/code]. If [code]public_only[/code] is [code]true[/code], only the public key will be loaded.
- [b]Note[/b]: [code]path[/code] should should be a "*.pub" file if [code]public_only[/code] is [code]true[/code], a "*.key" file otherwise.
+ [b]Note[/b]: [code]path[/code] should be a "*.pub" file if [code]public_only[/code] is [code]true[/code], a "*.key" file otherwise.
</description>
</method>
<method name="load_from_string">
@@ -50,7 +50,7 @@
</argument>
<description>
Saves a key to the given [code]path[/code]. If [code]public_only[/code] is [code]true[/code], only the public key will be saved.
- [b]Note[/b]: [code]path[/code] should should be a "*.pub" file if [code]public_only[/code] is [code]true[/code], a "*.key" file otherwise.
+ [b]Note[/b]: [code]path[/code] should be a "*.pub" file if [code]public_only[/code] is [code]true[/code], a "*.key" file otherwise.
</description>
</method>
<method name="save_to_string">
diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml
index 2d50d98a74..b33f3b4ffc 100644
--- a/doc/classes/Curve2D.xml
+++ b/doc/classes/Curve2D.xml
@@ -63,7 +63,7 @@
<argument index="0" name="to_point" type="Vector2">
</argument>
<description>
- Returns the closest point (in curve's local space) to [code]to_point[/code].
+ Returns the closest baked point (in curve's local space) to [code]to_point[/code].
[code]to_point[/code] must be in this curve's local space.
</description>
</method>
diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml
index bda04f010b..fcd150ad57 100644
--- a/doc/classes/Curve3D.xml
+++ b/doc/classes/Curve3D.xml
@@ -78,7 +78,7 @@
<argument index="0" name="to_point" type="Vector3">
</argument>
<description>
- Returns the closest point (in curve's local space) to [code]to_point[/code].
+ Returns the closest baked point (in curve's local space) to [code]to_point[/code].
[code]to_point[/code] must be in this curve's local space.
</description>
</method>
diff --git a/doc/classes/Decal.xml b/doc/classes/Decal.xml
index ca36b2400c..14c35ae6d3 100644
--- a/doc/classes/Decal.xml
+++ b/doc/classes/Decal.xml
@@ -6,7 +6,7 @@
<description>
[Decal]s are used to project a texture onto a [Mesh] in the scene. Use Decals to add detail to a scene without affecting the underlying [Mesh]. They are often used to add weathering to building, add dirt or mud to the ground, or add variety to props. Decals can be moved at any time, making them suitable for things like blob shadows or laser sight dots.
They are made of an [AABB] and a group of [Texture2D]s specifying [Color], normal, ORM (ambient occlusion, roughness, metallic), and emission. Decals are projected within their [AABB] so altering the orientation of the Decal affects the direction in which they are projected. By default, Decals are projected down (i.e. from positive Y to negative Y).
- The [Texture2D]s associated with the Decal are automatically stored in a texture atlas which is used for drawing the decals so all decals can be drawn at once. Godot uses clustered decals, meaning they are stored in cluster data and drawn when the mesh is drawn, they are not drawn as a postprocessing effect after.
+ The [Texture2D]s associated with the Decal are automatically stored in a texture atlas which is used for drawing the decals so all decals can be drawn at once. Godot uses clustered decals, meaning they are stored in cluster data and drawn when the mesh is drawn, they are not drawn as a post-processing effect after.
</description>
<tutorials>
</tutorials>
@@ -65,7 +65,7 @@
Blends the albedo [Color] of the decal with albedo [Color] of the underlying mesh.
</member>
<member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="1048575">
- Specifies which [member VisualInstance3D.layers] this decal will project on. By default, Decals affect all layers. This is used so you can specify which types of objects receive the Decal and which do not. This is especially useful so you an ensure that dynamic objects don't accidentally receive a Decal intended for the terrain under them.
+ Specifies which [member VisualInstance3D.layers] this decal will project on. By default, Decals affect all layers. This is used so you can specify which types of objects receive the Decal and which do not. This is especially useful so you can ensure that dynamic objects don't accidentally receive a Decal intended for the terrain under them.
</member>
<member name="distance_fade_begin" type="float" setter="set_distance_fade_begin" getter="get_distance_fade_begin" default="10.0">
Distance from the camera at which the Decal begins to fade away.
diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml
index d3fcbc9f64..16c4348994 100644
--- a/doc/classes/Dictionary.xml
+++ b/doc/classes/Dictionary.xml
@@ -4,7 +4,7 @@
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, even though this may not be reflected when printing the dictionary. In other programming languages, this data structure is sometimes referred to as an 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 elements, even though this may not be reflected when printing the dictionary. 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].
@@ -206,7 +206,7 @@
Clear the dictionary, removing all key/value pairs.
</description>
</method>
- <method name="duplicate">
+ <method name="duplicate" qualifiers="const">
<return type="Dictionary">
</return>
<argument index="0" name="deep" type="bool" default="false">
@@ -224,7 +224,7 @@
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. Does not erase elements while iterating over the dictionary.
</description>
</method>
- <method name="get">
+ <method name="get" qualifiers="const">
<return type="Variant">
</return>
<argument index="0" name="key" type="Variant">
@@ -235,7 +235,7 @@
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.
</description>
</method>
- <method name="has">
+ <method name="has" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="key" type="Variant">
@@ -260,16 +260,16 @@
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].
</description>
</method>
- <method name="has_all">
+ <method name="has_all" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="keys" type="Array">
</argument>
<description>
- Returns [code]true[/code] if the dictionary has all of the keys in the given array.
+ Returns [code]true[/code] if the dictionary has all the keys in the given array.
</description>
</method>
- <method name="hash">
+ <method name="hash" qualifiers="const">
<return type="int">
</return>
<description>
@@ -292,14 +292,14 @@
[b]Note:[/b] Dictionaries with the same keys/values but in a different order will have a different hash.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the dictionary is empty.
</description>
</method>
- <method name="keys">
+ <method name="keys" qualifiers="const">
<return type="Array">
</return>
<description>
@@ -330,14 +330,14 @@
<description>
</description>
</method>
- <method name="size">
+ <method name="size" qualifiers="const">
<return type="int">
</return>
<description>
Returns the number of keys in the dictionary.
</description>
</method>
- <method name="values">
+ <method name="values" qualifiers="const">
<return type="Array">
</return>
<description>
diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml
index 2d7292717d..6a126204c6 100644
--- a/doc/classes/Directory.xml
+++ b/doc/classes/Directory.xml
@@ -125,7 +125,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- On Windows, returns the name of the drive (partition) passed as an argument (e.g. [code]C:[/code]). On other platforms, or if the requested drive does not existed, the method returns an empty String.
+ On Windows, returns the name of the drive (partition) passed as an argument (e.g. [code]C:[/code]). On other platforms, or if the requested drive does not exist, the method returns an empty String.
</description>
</method>
<method name="get_drive_count">
@@ -167,7 +167,7 @@
<return type="void">
</return>
<description>
- Closes the current stream opened with [method list_dir_begin] (whether it has been fully processed with [method get_next] or not does not matter).
+ Closes the current stream opened with [method list_dir_begin] (whether it has been fully processed with [method get_next] does not matter).
</description>
</method>
<method name="make_dir">
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index d91ea6528a..91e90d051d 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -492,7 +492,7 @@
</argument>
<argument index="3" name="subtitle_track" type="String">
</argument>
- <argument index="4" name="arg4" type="int">
+ <argument index="4" name="screen" type="int">
</argument>
<description>
</description>
@@ -635,6 +635,42 @@
<description>
</description>
</method>
+ <method name="tablet_get_current_driver" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ Returns current active tablet driver name.
+ [b]Note:[/b] This method is implemented on Windows.
+ </description>
+ </method>
+ <method name="tablet_get_driver_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the total number of available tablet drivers.
+ [b]Note:[/b] This method is implemented on Windows.
+ </description>
+ </method>
+ <method name="tablet_get_driver_name" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ Returns the tablet driver name for the given index.
+ [b]Note:[/b] This method is implemented on Windows.
+ </description>
+ </method>
+ <method name="tablet_set_current_driver">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ Set active tablet driver name.
+ [b]Note:[/b] This method is implemented on Windows.
+ </description>
+ </method>
<method name="virtual_keyboard_get_height" qualifiers="const">
<return type="int">
</return>
diff --git a/doc/classes/EditorFileSystem.xml b/doc/classes/EditorFileSystem.xml
index 5461dccd27..3a045817c2 100644
--- a/doc/classes/EditorFileSystem.xml
+++ b/doc/classes/EditorFileSystem.xml
@@ -90,7 +90,7 @@
<argument index="0" name="resources" type="PackedStringArray">
</argument>
<description>
- Remitted if a resource is reimported.
+ Emitted if a resource is reimported.
</description>
</signal>
<signal name="resources_reload">
diff --git a/doc/classes/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml
index e5401134bf..aa64ab4043 100644
--- a/doc/classes/EditorImportPlugin.xml
+++ b/doc/classes/EditorImportPlugin.xml
@@ -16,7 +16,7 @@
return "my.special.plugin"
func get_visible_name():
- return "Special Mesh Importer"
+ return "Special Mesh"
func get_recognized_extensions():
return ["special", "spec"]
@@ -44,8 +44,7 @@
# Fill the Mesh with data read in "file", left as an exercise to the reader.
var filename = save_path + "." + get_save_extension()
- ResourceSaver.save(filename, mesh)
- return OK
+ return ResourceSaver.save(filename, mesh)
[/gdscript]
[csharp]
using Godot;
@@ -60,7 +59,7 @@
public override String GetVisibleName()
{
- return "Special Mesh Importer";
+ return "Special Mesh";
}
public override Godot.Collections.Array GetRecognizedExtensions()
@@ -104,8 +103,7 @@
var mesh = new ArrayMesh();
// Fill the Mesh with data read in "file", left as an exercise to the reader.
String filename = savePath + "." + GetSaveExtension();
- ResourceSaver.Save(filename, mesh);
- return (int)Error.Ok;
+ return (int)ResourceSaver.Save(filename, mesh);
}
}
[/csharp]
@@ -220,7 +218,7 @@
<return type="String">
</return>
<description>
- Gets the name to display in the import window.
+ Gets the name to display in the import window. You should choose this name as a continuation to "Import as", e.g. "Import as Special Mesh".
</description>
</method>
<method name="import" qualifiers="virtual">
diff --git a/doc/classes/EditorInspector.xml b/doc/classes/EditorInspector.xml
index 6f03165a97..d85f95baff 100644
--- a/doc/classes/EditorInspector.xml
+++ b/doc/classes/EditorInspector.xml
@@ -10,14 +10,6 @@
<tutorials>
</tutorials>
<methods>
- <method name="refresh">
- <return type="void">
- </return>
- <description>
- Refreshes the inspector.
- [b]Note:[/b] To save on CPU resources, calling this method will do nothing if the time specified in [code]docks/property_editor/auto_refresh_interval[/code] editor setting hasn't passed yet since this method was last called. (By default, this interval is set to 0.3 seconds.)
- </description>
- </method>
</methods>
<members>
<member name="scroll_horizontal_enabled" type="bool" setter="set_enable_h_scroll" getter="is_h_scroll_enabled" override="true" default="false" />
diff --git a/doc/classes/EditorInspectorPlugin.xml b/doc/classes/EditorInspectorPlugin.xml
index 3cc624f49b..8204dc931e 100644
--- a/doc/classes/EditorInspectorPlugin.xml
+++ b/doc/classes/EditorInspectorPlugin.xml
@@ -4,12 +4,12 @@
Plugin for adding custom property editors on inspector.
</brief_description>
<description>
- This plugins allows adding custom property editors to [EditorInspector].
+ These plugins allow adding custom property editors to [EditorInspector].
Plugins are registered via [method EditorPlugin.add_inspector_plugin].
When an object is edited, the [method can_handle] function is called and must return [code]true[/code] if the object type is supported.
If supported, the function [method parse_begin] will be called, allowing to place custom controls at the beginning of the class.
Subsequently, the [method parse_category] and [method parse_property] are called for every category and property. They offer the ability to add custom controls to the inspector too.
- Finally [method parse_end] will be called.
+ Finally, [method parse_end] will be called.
On each of these calls, the "add" functions can be called.
</description>
<tutorials>
diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml
index 322cff4e43..34657a1c08 100644
--- a/doc/classes/EditorNode3DGizmoPlugin.xml
+++ b/doc/classes/EditorNode3DGizmoPlugin.xml
@@ -98,6 +98,13 @@
Creates an unshaded material with its variants (selected and/or editable) and adds them to the internal material list. They can then be accessed with [method get_material] and used in [method EditorNode3DGizmo.add_mesh] and [method EditorNode3DGizmo.add_lines]. Should not be overridden.
</description>
</method>
+ <method name="get_gizmo_name" qualifiers="virtual">
+ <return type="String">
+ </return>
+ <description>
+ Override this method to provide the name that will appear in the gizmo visibility menu.
+ </description>
+ </method>
<method name="get_handle_name" qualifiers="virtual">
<return type="String">
</return>
@@ -131,13 +138,6 @@
Gets material from the internal list of materials. If an [EditorNode3DGizmo] is provided, it will try to get the corresponding variant (selected and/or editable).
</description>
</method>
- <method name="get_name" qualifiers="virtual">
- <return type="String">
- </return>
- <description>
- Override this method to provide the name that will appear in the gizmo visibility menu.
- </description>
- </method>
<method name="get_priority" qualifiers="virtual">
<return type="int">
</return>
@@ -170,7 +170,7 @@
<return type="bool">
</return>
<description>
- Override this method to define whether Node3D with this gizmo should be selecteble even when the gizmo is hidden.
+ Override this method to define whether Node3D with this gizmo should be selectable even when the gizmo is hidden.
</description>
</method>
<method name="redraw" qualifiers="virtual">
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index be21ad65c5..8dcffb0b74 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -169,6 +169,8 @@
<return type="bool">
</return>
<description>
+ This method is called when the editor is about to run the project. The plugin can then perform required operations before the project runs.
+ This method must return a boolean. If this method returns [code]false[/code], the project will not run. The run is aborted immediately, so this also prevents all other plugins' [method build] methods from running.
</description>
</method>
<method name="clear" qualifiers="virtual">
@@ -559,7 +561,7 @@
<argument index="0" name="script" type="Script">
</argument>
<description>
- Removes the debugger plugin with given script fromm the Debugger.
+ Removes the debugger plugin with given script from the Debugger.
</description>
</method>
<method name="remove_export_plugin">
@@ -675,6 +677,10 @@
Emitted when user changes the workspace ([b]2D[/b], [b]3D[/b], [b]Script[/b], [b]AssetLib[/b]). Also works with custom screens defined by plugins.
</description>
</signal>
+ <signal name="project_settings_changed">
+ <description>
+ </description>
+ </signal>
<signal name="resource_saved">
<argument index="0" name="resource" type="Resource">
</argument>
diff --git a/doc/classes/EditorSceneImporterMesh.xml b/doc/classes/EditorSceneImporterMesh.xml
index 1c903bd889..58b7104667 100644
--- a/doc/classes/EditorSceneImporterMesh.xml
+++ b/doc/classes/EditorSceneImporterMesh.xml
@@ -29,7 +29,7 @@
</argument>
<argument index="4" name="material" type="Material" default="null">
</argument>
- <argument index="5" name="arg5" type="String" default="&quot;&quot;">
+ <argument index="5" name="name" type="String" default="&quot;&quot;">
</argument>
<description>
</description>
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index 6088ae7a43..016d0128eb 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -160,6 +160,16 @@
Returns the default value of the setting specified by [code]name[/code]. This is the value that would be applied when clicking the Revert button in the Editor Settings.
</description>
</method>
+ <method name="set_builtin_action_override">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="actions_list" type="Array">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_favorites">
<return type="void">
</return>
diff --git a/doc/classes/EditorSyntaxHighlighter.xml b/doc/classes/EditorSyntaxHighlighter.xml
index 103d95e1d6..b80e81928f 100644
--- a/doc/classes/EditorSyntaxHighlighter.xml
+++ b/doc/classes/EditorSyntaxHighlighter.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorSyntaxHighlighter" inherits="SyntaxHighlighter" version="4.0">
<brief_description>
+ Base Syntax highlighter resource for the [ScriptEditor].
</brief_description>
<description>
+ Base syntax highlighter resource all editor syntax highlighters extend from, it is used in the [ScriptEditor].
+ Add a syntax highlighter to an individual script by calling [method ScriptEditorBase.add_syntax_highlighter]. To apply to all scripts on open, call [method ScriptEditor.register_syntax_highlighter]
</description>
<tutorials>
</tutorials>
@@ -11,18 +14,21 @@
<return type="String">
</return>
<description>
+ Virtual method which can be overridden to return the syntax highlighter name.
</description>
</method>
<method name="_get_supported_extentions" qualifiers="virtual">
<return type="Array">
</return>
<description>
+ Virtual method which can be overridden to return the supported file extensions.
</description>
</method>
<method name="_get_supported_languages" qualifiers="virtual">
<return type="Array">
</return>
<description>
+ Virtual method which can be overridden to return the supported language names.
</description>
</method>
</methods>
diff --git a/doc/classes/EditorVCSInterface.xml b/doc/classes/EditorVCSInterface.xml
index bb356c2183..0056b5ce16 100644
--- a/doc/classes/EditorVCSInterface.xml
+++ b/doc/classes/EditorVCSInterface.xml
@@ -38,7 +38,7 @@
<return type="Dictionary">
</return>
<description>
- Returns a [Dictionary] containing the path of the detected file change mapped to an integer signifying what kind of a change the corresponding file has experienced.
+ Returns a [Dictionary] containing the path of the detected file change mapped to an integer signifying what kind of change the corresponding file has experienced.
The following integer values are being used to signify that the detected file is:
- [code]0[/code]: New to the VCS working directory
- [code]1[/code]: Modified
diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml
index 02b81ee9b7..f9d8cf574a 100644
--- a/doc/classes/Engine.xml
+++ b/doc/classes/Engine.xml
@@ -162,7 +162,7 @@
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 tunneling issues, but keep in mind doing so will increase CPU usage.
</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 in-game clock and real clock, but allows to 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.
+ 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.
</member>
<member name="target_fps" type="int" setter="set_target_fps" getter="get_target_fps" default="0">
The desired frames per second. If the hardware cannot keep up, this setting may not be respected. A value of 0 means no limit.
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index 9dd4ecc37b..821aa91d21 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -169,6 +169,8 @@
</member>
<member name="reflected_light_source" type="int" setter="set_reflection_source" getter="get_reflection_source" enum="Environment.ReflectionSource" default="0">
</member>
+ <member name="sdfgi_bounce_feedback" type="float" setter="set_sdfgi_bounce_feedback" getter="get_sdfgi_bounce_feedback" default="0.0">
+ </member>
<member name="sdfgi_cascade0_distance" type="float" setter="set_sdfgi_cascade0_distance" getter="get_sdfgi_cascade0_distance" default="12.8">
</member>
<member name="sdfgi_cascades" type="int" setter="set_sdfgi_cascades" getter="get_sdfgi_cascades" enum="Environment.SDFGICascades" default="1">
@@ -187,8 +189,6 @@
</member>
<member name="sdfgi_read_sky_light" type="bool" setter="set_sdfgi_read_sky_light" getter="is_sdfgi_reading_sky_light" default="false">
</member>
- <member name="sdfgi_use_multi_bounce" type="bool" setter="set_sdfgi_use_multi_bounce" getter="is_sdfgi_using_multi_bounce" default="false">
- </member>
<member name="sdfgi_use_occlusion" type="bool" setter="set_sdfgi_use_occlusion" getter="is_sdfgi_using_occlusion" default="false">
</member>
<member name="sdfgi_y_scale" type="int" setter="set_sdfgi_y_scale" getter="get_sdfgi_y_scale" enum="Environment.SDFGIYScale" default="0">
@@ -265,12 +265,14 @@
</member>
<member name="volumetric_fog_light_energy" type="float" setter="set_volumetric_fog_light_energy" getter="get_volumetric_fog_light_energy" default="1.0">
</member>
- <member name="volumetric_fog_shadow_filter" type="int" setter="set_volumetric_fog_shadow_filter" getter="get_volumetric_fog_shadow_filter" enum="Environment.VolumetricFogShadowFilter" default="1">
+ <member name="volumetric_fog_temporal_reprojection_amount" type="float" setter="set_volumetric_fog_temporal_reprojection_amount" getter="get_volumetric_fog_temporal_reprojection_amount" default="0.9">
+ </member>
+ <member name="volumetric_fog_temporal_reprojection_enabled" type="bool" setter="set_volumetric_fog_temporal_reprojection_enabled" getter="is_volumetric_fog_temporal_reprojection_enabled" default="true">
</member>
</members>
<constants>
<constant name="BG_CLEAR_COLOR" value="0" enum="BGMode">
- Clears the background using the clear color defined in [member ProjectSettings.rendering/environment/default_clear_color].
+ Clears the background using the clear color defined in [member ProjectSettings.rendering/environment/defaults/default_clear_color].
</constant>
<constant name="BG_COLOR" value="1" enum="BGMode">
Clears the background using a custom clear color.
diff --git a/doc/classes/File.xml b/doc/classes/File.xml
index ff03f44789..e0781e807f 100644
--- a/doc/classes/File.xml
+++ b/doc/classes/File.xml
@@ -42,6 +42,7 @@
[/codeblocks]
In the example above, the file will be saved in the user data folder as specified in the [url=https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html]Data paths[/url] documentation.
[b]Note:[/b] To access project resources once exported, it is recommended to use [ResourceLoader] instead of the [File] API, as some files are converted to engine-specific formats and their original source files might not be present in the exported PCK package.
+ [b]Note:[/b] Files are automatically closed only if the process exits "normally" (such as by clicking the window manager's close button or pressing [b]Alt + F4[/b]). If you stop the project execution by pressing [b]F8[/b] while the project is running, the file won't be closed as the game process will be killed. You can work around this by calling [method flush] at regular intervals.
</description>
<tutorials>
<link title="File system">https://docs.godotengine.org/en/latest/getting_started/step_by_step/filesystem.html</link>
@@ -52,7 +53,7 @@
<return type="void">
</return>
<description>
- Closes the currently opened file.
+ Closes the currently opened file and prevents subsequent read/write operations. Use [method flush] to persist the data to disk without closing the file.
</description>
</method>
<method name="eof_reached" qualifiers="const">
@@ -73,6 +74,14 @@
[b]Note:[/b] Many resources types are imported (e.g. textures or sound files), and their source asset will not be included in the exported game, as only the imported version is used. See [method ResourceLoader.exists] for an alternative approach that takes resource remapping into account.
</description>
</method>
+ <method name="flush">
+ <return type="void">
+ </return>
+ <description>
+ Writes the file's buffer to disk. Flushing is automatically performed when the file is closed. This means you don't need to call [method flush] manually before closing a file using [method close]. Still, calling [method flush] can be used to ensure the data is safe even if the project crashes instead of being closed gracefully.
+ [b]Note:[/b] Only call [method flush] when you actually need it. Otherwise, it will decrease performance due to constant disk writes.
+ </description>
+ </method>
<method name="get_16" qualifiers="const">
<return type="int">
</return>
diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml
index edd2bd137f..20d5b6ce9b 100644
--- a/doc/classes/Font.xml
+++ b/doc/classes/Font.xml
@@ -175,7 +175,7 @@
</argument>
<description>
Returns the size of a character, optionally taking kerning into account if the next character is provided.
- [b]Note:[/b] Do not use this function to calculate width of the string character by character, use [method get_string_size] or [TextLine] instead.
+ [b]Note:[/b] Do not use this function to calculate width of the string character by character, use [method get_string_size] or [TextLine] instead. The height returned is the font height (see also [method get_height]) and has no relation to the glyph height.
</description>
</method>
<method name="get_data" qualifiers="const">
@@ -247,7 +247,8 @@
<argument index="1" name="size" type="int" default="-1">
</argument>
<description>
- Returns the size size of a bounding box of a string, taking kerning and advance into account.
+ Returns the size of a bounding box of a string, taking kerning and advance into account.
+ [b]Note:[/b] Real height of the string is context-dependent and can be significantly different from the value returned by [method get_height].
See also [method draw_string].
</description>
</method>
@@ -329,10 +330,10 @@
</methods>
<members>
<member name="extra_spacing_bottom" type="int" setter="set_spacing" getter="get_spacing" default="0">
- Extra spacing at the bottom in pixels.
+ Extra spacing at the bottom of the line in pixels.
</member>
<member name="extra_spacing_top" type="int" setter="set_spacing" getter="get_spacing" default="0">
- Extra character spacing in pixels.
+ Extra spacing at the top of the line in pixels.
</member>
</members>
<constants>
diff --git a/doc/classes/FontData.xml b/doc/classes/FontData.xml
index e2c35f9ce7..e426c8fb36 100644
--- a/doc/classes/FontData.xml
+++ b/doc/classes/FontData.xml
@@ -11,6 +11,45 @@
<tutorials>
</tutorials>
<methods>
+ <method name="bitmap_add_char">
+ <return type="void">
+ </return>
+ <argument index="0" name="char" type="int">
+ </argument>
+ <argument index="1" name="texture_idx" type="int">
+ </argument>
+ <argument index="2" name="rect" type="Rect2">
+ </argument>
+ <argument index="3" name="align" type="Vector2">
+ </argument>
+ <argument index="4" name="advance" type="float">
+ </argument>
+ <description>
+ Adds a character to the font, where [code]character[/code] is the Unicode value, [code]texture[/code] is the texture index, [code]rect[/code] is the region in the texture (in pixels!), [code]align[/code] is the (optional) alignment for the character and [code]advance[/code] is the (optional) advance.
+ </description>
+ </method>
+ <method name="bitmap_add_kerning_pair">
+ <return type="void">
+ </return>
+ <argument index="0" name="A" type="int">
+ </argument>
+ <argument index="1" name="B" type="int">
+ </argument>
+ <argument index="2" name="kerning" type="int">
+ </argument>
+ <description>
+ Adds a kerning pair to the bitmap font as a difference. Kerning pairs are special cases where a typeface advance is determined by the next character.
+ </description>
+ </method>
+ <method name="bitmap_add_texture">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="Texture">
+ </argument>
+ <description>
+ Adds a texture to the bitmap font.
+ </description>
+ </method>
<method name="draw_glyph" qualifiers="const">
<return type="Vector2">
</return>
@@ -154,6 +193,15 @@
Returns list of script support overrides.
</description>
</method>
+ <method name="get_spacing" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="type" type="int">
+ </argument>
+ <description>
+ Returns the spacing for the given [code]type[/code] (see [enum SpacingType]).
+ </description>
+ </method>
<method name="get_supported_chars" qualifiers="const">
<return type="String">
</return>
@@ -256,6 +304,19 @@
Note: For non-scalable fonts [code]base_size[/code] is ignored, use [method get_base_size] to check actual font size.
</description>
</method>
+ <method name="new_bitmap">
+ <return type="void">
+ </return>
+ <argument index="0" name="height" type="float">
+ </argument>
+ <argument index="1" name="ascent" type="float">
+ </argument>
+ <argument index="2" name="base_size" type="int">
+ </argument>
+ <description>
+ Creates new, empty bitmap font.
+ </description>
+ </method>
<method name="remove_language_support_override">
<return type="void">
</return>
@@ -296,6 +357,17 @@
Adds override for [method is_script_supported].
</description>
</method>
+ <method name="set_spacing">
+ <return type="void">
+ </return>
+ <argument index="0" name="type" type="int">
+ </argument>
+ <argument index="1" name="value" type="int">
+ </argument>
+ <description>
+ Sets the spacing for [code]type[/code] (see [enum SpacingType]) to [code]value[/code] in pixels (not relative to the font size).
+ </description>
+ </method>
<method name="set_variation">
<return type="void">
</return>
@@ -318,6 +390,14 @@
<member name="distance_field_hint" type="bool" setter="set_distance_field_hint" getter="get_distance_field_hint" default="false">
If [code]true[/code], distance field hint is enabled.
</member>
+ <member name="extra_spacing_glyph" type="int" setter="set_spacing" getter="get_spacing" default="0">
+ Extra spacing for each glyph in pixels.
+ This can be a negative number to make the distance between glyphs smaller.
+ </member>
+ <member name="extra_spacing_space" type="int" setter="set_spacing" getter="get_spacing" default="0">
+ Extra spacing for the space character in pixels.
+ This can be a negative number to make the distance between words smaller.
+ </member>
<member name="force_autohinter" type="bool" setter="set_force_autohinter" getter="get_force_autohinter" default="false">
If [code]true[/code], default autohinter is used for font hinting.
</member>
@@ -326,5 +406,11 @@
</member>
</members>
<constants>
+ <constant name="SPACING_GLYPH" value="0" enum="SpacingType">
+ Spacing for each glyph.
+ </constant>
+ <constant name="SPACING_SPACE" value="1" enum="SpacingType">
+ Spacing for the space character.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/GIProbe.xml b/doc/classes/GIProbe.xml
index 52d3698201..dd51248fd9 100644
--- a/doc/classes/GIProbe.xml
+++ b/doc/classes/GIProbe.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
[GIProbe]s are used to provide high-quality real-time indirect light to scenes. They precompute the effect of objects that emit light and the effect of static geometry to simulate the behavior of complex light in real-time. [GIProbe]s need to be baked before using, however, once baked, dynamic objects will receive light from them. Further, lights can be fully dynamic or baked.
- Having [GIProbe]s in a scene can be expensive, the quality of the probe can be turned down in exchange for better performance in the [ProjectSettings] using [member ProjectSettings.rendering/quality/gi_probes/quality].
+ Having [GIProbe]s in a scene can be expensive, the quality of the probe can be turned down in exchange for better performance in the [ProjectSettings] using [member ProjectSettings.rendering/global_illumination/gi_probes/quality].
</description>
<tutorials>
<link title="GI probes">https://docs.godotengine.org/en/latest/tutorials/3d/gi_probes.html</link>
diff --git a/doc/classes/Geometry3D.xml b/doc/classes/Geometry3D.xml
index d0b930defb..9f012008e3 100644
--- a/doc/classes/Geometry3D.xml
+++ b/doc/classes/Geometry3D.xml
@@ -129,7 +129,7 @@
<argument index="2" name="planes" type="Array">
</argument>
<description>
- Given a convex hull defined though the [Plane]s in the array [code]planes[/code], tests if the segment ([code]from[/code], [code]to[/code]) intersects with that hull. If an intersection is found, returns a [PackedVector3Array] containing the point the intersection and the hull's normal. If no intersecion is found, an the returned array is empty.
+ Given a convex hull defined though the [Plane]s in the array [code]planes[/code], tests if the segment ([code]from[/code], [code]to[/code]) intersects with that hull. If an intersection is found, returns a [PackedVector3Array] containing the point the intersection and the hull's normal. Otherwise, returns an empty array.
</description>
</method>
<method name="segment_intersects_cylinder">
diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml
index 10afa4c339..b4536c0589 100644
--- a/doc/classes/GraphEdit.xml
+++ b/doc/classes/GraphEdit.xml
@@ -88,7 +88,7 @@
</return>
<description>
Gets the [HBoxContainer] that contains the zooming and grid snap controls in the top left of the graph.
- Warning: The intended usage of this function is to allow you to reposition or add your own custom controls to the container. This is an internal control and as such should not be freed. If you wish to hide this or any of it's children use their [member CanvasItem.visible] property instead.
+ Warning: The intended usage of this function is to allow you to reposition or add your own custom controls to the container. This is an internal control and as such should not be freed. If you wish to hide this or any of its children, use their [member CanvasItem.visible] property instead.
</description>
</method>
<method name="is_node_connected">
diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml
index 4b0ea4dcb1..aae3126c0f 100644
--- a/doc/classes/GraphNode.xml
+++ b/doc/classes/GraphNode.xml
@@ -6,7 +6,7 @@
<description>
A GraphNode is a container. Each GraphNode can have several input and output slots, sometimes referred to as ports, allowing connections between GraphNodes. To add a slot to GraphNode, add any [Control]-derived child node to it.
After adding at least one child to GraphNode new sections will be automatically created in the Inspector called 'Slot'. When 'Slot' is expanded you will see list with index number for each slot. You can click on each of them to expand further.
- In the Inspector you can enable (show) or disable (hide) slots. By default all slots are disabled so you may not see any slots on your GraphNode initially. You can assign a type to each slot. Only slots of the same type will be able to connect to each other. You can also assign colors to slots. A tuple of input and output slots is defined for each GUI element included in the GraphNode. Input connections are on the left and output connections are on the right side of GraphNode. Only enabled slots are counted as connections.
+ In the Inspector you can enable (show) or disable (hide) slots. By default, all slots are disabled so you may not see any slots on your GraphNode initially. You can assign a type to each slot. Only slots of the same type will be able to connect to each other. You can also assign colors to slots. A tuple of input and output slots is defined for each GUI element included in the GraphNode. Input connections are on the left and output connections are on the right side of GraphNode. Only enabled slots are counted as connections.
</description>
<tutorials>
</tutorials>
@@ -272,6 +272,13 @@
Emitted when the GraphNode is requested to be resized. Happens on dragging the resizer handle (see [member resizable]).
</description>
</signal>
+ <signal name="slot_updated">
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ Emitted when any GraphNode's slot is updated.
+ </description>
+ </signal>
</signals>
<constants>
<constant name="OVERLAY_DISABLED" value="0" enum="Overlay">
diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml
index 9ff682f79d..ddfcdf7724 100644
--- a/doc/classes/HTTPClient.xml
+++ b/doc/classes/HTTPClient.xml
@@ -4,7 +4,7 @@
Low-level hyper-text transfer protocol client.
</brief_description>
<description>
- Hyper-text transfer protocol client (sometimes called "User Agent"). Used to make HTTP requests to download web content, upload files and other data or to communicate with various services, among other use cases. [b]See the [HTTPRequest] node for an higher-level alternative.[/b]
+ Hyper-text transfer protocol client (sometimes called "User Agent"). Used to make HTTP requests to download web content, upload files and other data or to communicate with various services, among other use cases. [b]See the [HTTPRequest] node for a higher-level alternative.[/b]
[b]Note:[/b] This client only needs to connect to a host once (see [method connect_to_host]) to send multiple requests. Because of this, methods that take URLs usually take just the part after the host instead of the full URL, as the client is already connected to a host. See [method request] for a full example and to get started.
A [HTTPClient] should be reused between multiple requests or to connect to different hosts instead of creating one client per request. Supports SSL and SSL server certificate verification. HTTP status codes in the 2xx range indicate success, 3xx redirection (i.e. "try again, but over here"), 4xx something was wrong with the request, and 5xx something went wrong on the server's side.
For more information on HTTP, see https://developer.mozilla.org/en-US/docs/Web/HTTP (or read RFC 2616 to get it straight from the source: https://tools.ietf.org/html/rfc2616).
diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml
index a65f66c72a..25667d8f79 100644
--- a/doc/classes/HTTPRequest.xml
+++ b/doc/classes/HTTPRequest.xml
@@ -229,7 +229,7 @@
<member name="accept_gzip" type="bool" setter="set_accept_gzip" getter="is_accepting_gzip" default="true">
If [code]true[/code], this header will be added to each request: [code]Accept-Encoding: gzip, deflate[/code] telling servers that it's okay to compress response bodies.
Any Response body declaring a [code]Content-Encoding[/code] of either [code]gzip[/code] or [code]deflate[/code] will then be automatically decompressed, and the uncompressed bytes will be delivered via [code]request_completed[/code].
- If the user has specified their own [code]Accept-Encoding[/code] header, then no header will be added regaurdless of [code]accept_gzip[/code].
+ If the user has specified their own [code]Accept-Encoding[/code] header, then no header will be added regardless of [code]accept_gzip[/code].
If [code]false[/code] no header will be added, and no decompression will be performed on response bodies. The raw bytes of the response body will be returned via [code]request_completed[/code].
</member>
<member name="body_size_limit" type="int" setter="set_body_size_limit" getter="get_body_size_limit" default="-1">
diff --git a/doc/classes/IP.xml b/doc/classes/IP.xml
index 152f381a83..849f036bbd 100644
--- a/doc/classes/IP.xml
+++ b/doc/classes/IP.xml
@@ -31,7 +31,7 @@
<return type="Array">
</return>
<description>
- Returns all of the user's current IPv4 and IPv6 addresses as an array.
+ Returns all the user's current IPv4 and IPv6 addresses as an array.
</description>
</method>
<method name="get_local_interfaces" qualifiers="const">
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 3dba5d13aa..9d87c9bf9a 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -12,6 +12,18 @@
<link title="Importing images">https://docs.godotengine.org/en/latest/getting_started/workflow/assets/importing_images.html</link>
</tutorials>
<methods>
+ <method name="adjust_bcs">
+ <return type="void">
+ </return>
+ <argument index="0" name="brightness" type="float">
+ </argument>
+ <argument index="1" name="contrast" type="float">
+ </argument>
+ <argument index="2" name="saturation" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="blend_rect">
<return type="void">
</return>
@@ -228,7 +240,7 @@
<argument index="0" name="renormalize" type="bool" default="false">
</argument>
<description>
- Generates mipmaps for the image. Mipmaps are pre-calculated and lower resolution copies of the image. Mipmaps are automatically used if the image needs to be scaled down when rendered. This improves image quality and the performance of the rendering. Returns an error if the image is compressed, in a custom format or if the image's width/height is 0.
+ Generates mipmaps for the image. Mipmaps are precalculated and lower resolution copies of the image. Mipmaps are automatically used if the image needs to be scaled down when rendered. This improves image quality and the performance of the rendering. Returns an error if the image is compressed, in a custom format or if the image's width/height is 0.
</description>
</method>
<method name="get_data" qualifiers="const">
@@ -548,7 +560,7 @@
</methods>
<members>
<member name="data" type="Dictionary" setter="_set_data" getter="_get_data" default="{&quot;data&quot;: PackedByteArray( ),&quot;format&quot;: &quot;Lum8&quot;,&quot;height&quot;: 0,&quot;mipmaps&quot;: false,&quot;width&quot;: 0}">
- Holds all of the image's color data in a given format. See [enum Format] constants.
+ Holds all the image's color data in a given format. See [enum Format] constants.
</member>
</members>
<constants>
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index cfb3e8d981..d7408cd0ff 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -49,7 +49,7 @@
<return type="Vector3">
</return>
<description>
- Returns the acceleration of the device's accelerometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO].
+ Returns the acceleration in m/s² of the device's accelerometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO].
Note this method returns an empty [Vector3] when running from the editor even when your device has an accelerometer. You must export your project to a supported device to read values from the accelerometer.
[b]Note:[/b] This method only works on iOS, Android, and UWP. On other platforms, it always returns [constant Vector3.ZERO].
</description>
@@ -59,6 +59,8 @@
</return>
<argument index="0" name="action" type="StringName">
</argument>
+ <argument index="1" name="exact_match" type="bool" default="false">
+ </argument>
<description>
Returns a value between 0 and 1 representing the raw intensity of the given action, ignoring the action's deadzone. In most cases, you should use [method get_action_strength] instead.
</description>
@@ -68,6 +70,8 @@
</return>
<argument index="0" name="action" type="StringName">
</argument>
+ <argument index="1" name="exact_match" type="bool" default="false">
+ </argument>
<description>
Returns a value between 0 and 1 representing the intensity of the given action. In a joypad, for example, the further away the axis (analog sticks or L2, R2 triggers) is from the dead zone, the closer the value will be to 1. If the action is mapped to a control that has no axis as the keyboard, the value returned will be 0 or 1.
</description>
@@ -81,7 +85,7 @@
</argument>
<description>
Get axis input by specifying two actions, one negative and one positive.
- This is a horthand for writing [code]Input.get_action_strength("positive_action") - Input.get_action_strength("negative_action")[/code].
+ This is a shorthand for writing [code]Input.get_action_strength("positive_action") - Input.get_action_strength("negative_action")[/code].
</description>
</method>
<method name="get_connected_joypads">
@@ -102,7 +106,7 @@
<return type="Vector3">
</return>
<description>
- Returns the gravity of the device's accelerometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO].
+ Returns the gravity in m/s² of the device's accelerometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO].
[b]Note:[/b] This method only works on Android and iOS. On other platforms, it always returns [constant Vector3.ZERO].
</description>
</method>
@@ -122,7 +126,7 @@
<argument index="1" name="axis" type="int">
</argument>
<description>
- Returns the current value of the joypad axis at given index (see [enum JoyAxisList]).
+ Returns the current value of the joypad axis at given index (see [enum JoyAxis]).
</description>
</method>
<method name="get_joy_guid" qualifiers="const">
@@ -172,7 +176,7 @@
<return type="Vector3">
</return>
<description>
- Returns the the magnetic field strength in micro-Tesla for all axes of the device's magnetometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO].
+ Returns the magnetic field strength in micro-Tesla for all axes of the device's magnetometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO].
[b]Note:[/b] This method only works on Android, iOS and UWP. On other platforms, it always returns [constant Vector3.ZERO].
</description>
</method>
@@ -214,6 +218,8 @@
</return>
<argument index="0" name="action" type="StringName">
</argument>
+ <argument index="1" name="exact_match" type="bool" default="false">
+ </argument>
<description>
Returns [code]true[/code] when the user starts pressing the action event, meaning it's [code]true[/code] only on the frame that the user pressed down the button.
This is useful for code that needs to run only once when an action is pressed, instead of every frame while it's pressed.
@@ -224,6 +230,8 @@
</return>
<argument index="0" name="action" type="StringName">
</argument>
+ <argument index="1" name="exact_match" type="bool" default="false">
+ </argument>
<description>
Returns [code]true[/code] when the user stops pressing the action event, meaning it's [code]true[/code] only on the frame that the user released the button.
</description>
@@ -233,6 +241,8 @@
</return>
<argument index="0" name="action" type="StringName">
</argument>
+ <argument index="1" name="exact_match" type="bool" default="false">
+ </argument>
<description>
Returns [code]true[/code] if you are pressing the action event. Note that if an action has multiple buttons assigned and more than one of them is pressed, releasing one button will release the action, even if some other button assigned to this action is still pressed.
</description>
@@ -245,7 +255,7 @@
<argument index="1" name="button" type="int">
</argument>
<description>
- Returns [code]true[/code] if you are pressing the joypad button (see [enum JoyButtonList]).
+ Returns [code]true[/code] if you are pressing the joypad button (see [enum JoyButton]).
</description>
</method>
<method name="is_joy_known">
@@ -263,7 +273,7 @@
<argument index="0" name="keycode" type="int">
</argument>
<description>
- Returns [code]true[/code] if you are pressing the key in the current keyboard layout. You can pass a [enum KeyList] constant.
+ Returns [code]true[/code] if you are pressing the key in the current keyboard layout. You can pass a [enum Key] constant.
</description>
</method>
<method name="is_mouse_button_pressed" qualifiers="const">
@@ -272,7 +282,7 @@
<argument index="0" name="button" type="int">
</argument>
<description>
- Returns [code]true[/code] if you are pressing the mouse button specified with [enum ButtonList].
+ Returns [code]true[/code] if you are pressing the mouse button specified with [enum MouseButton].
</description>
</method>
<method name="joy_connection_changed">
diff --git a/doc/classes/InputEvent.xml b/doc/classes/InputEvent.xml
index 8c6063bd67..28c4773f51 100644
--- a/doc/classes/InputEvent.xml
+++ b/doc/classes/InputEvent.xml
@@ -35,6 +35,8 @@
</return>
<argument index="0" name="action" type="StringName">
</argument>
+ <argument index="1" name="exact_match" type="bool" default="false">
+ </argument>
<description>
Returns a value between 0.0 and 1.0 depending on the given actions' state. Useful for getting the value of events of type [InputEventJoypadMotion].
</description>
@@ -44,6 +46,8 @@
</return>
<argument index="0" name="action" type="StringName">
</argument>
+ <argument index="1" name="exact_match" type="bool" default="false">
+ </argument>
<description>
Returns [code]true[/code] if this input event matches a pre-defined action of any type.
</description>
@@ -55,6 +59,8 @@
</argument>
<argument index="1" name="allow_echo" type="bool" default="false">
</argument>
+ <argument index="2" name="exact_match" type="bool" default="false">
+ </argument>
<description>
Returns [code]true[/code] if the given action is being pressed (and is not an echo event for [InputEventKey] events, unless [code]allow_echo[/code] is [code]true[/code]). Not relevant for events of type [InputEventMouseMotion] or [InputEventScreenDrag].
</description>
@@ -64,6 +70,8 @@
</return>
<argument index="0" name="action" type="StringName">
</argument>
+ <argument index="1" name="exact_match" type="bool" default="false">
+ </argument>
<description>
Returns [code]true[/code] if the given action is released (i.e. not pressed). Not relevant for events of type [InputEventMouseMotion] or [InputEventScreenDrag].
</description>
diff --git a/doc/classes/InputEventAction.xml b/doc/classes/InputEventAction.xml
index 1fe85a5ae8..ed290fc7e2 100644
--- a/doc/classes/InputEventAction.xml
+++ b/doc/classes/InputEventAction.xml
@@ -21,7 +21,7 @@
If [code]true[/code], the action's state is pressed. If [code]false[/code], the action's state is released.
</member>
<member name="strength" type="float" setter="set_strength" getter="get_strength" default="1.0">
- The action's strength between 0 and 1. This value is considered as equal to 0 if pressed is [code]false[/code]. The event strength allows faking analog joypad motion events, by precising how strongly is the joypad axis bent or pressed.
+ The action's strength between 0 and 1. This value is considered as equal to 0 if pressed is [code]false[/code]. The event strength allows faking analog joypad motion events, by specifying how strongly the joypad axis is bent or pressed.
</member>
</members>
<constants>
diff --git a/doc/classes/InputEventJoypadButton.xml b/doc/classes/InputEventJoypadButton.xml
index 6ab4942f85..b1f4836f6e 100644
--- a/doc/classes/InputEventJoypadButton.xml
+++ b/doc/classes/InputEventJoypadButton.xml
@@ -13,7 +13,7 @@
</methods>
<members>
<member name="button_index" type="int" setter="set_button_index" getter="get_button_index" default="0">
- Button identifier. One of the [enum JoyButtonList] button constants.
+ Button identifier. One of the [enum JoyButton] button constants.
</member>
<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false">
If [code]true[/code], the button's state is pressed. If [code]false[/code], the button's state is released.
diff --git a/doc/classes/InputEventJoypadMotion.xml b/doc/classes/InputEventJoypadMotion.xml
index 2d7787b568..39fdb14016 100644
--- a/doc/classes/InputEventJoypadMotion.xml
+++ b/doc/classes/InputEventJoypadMotion.xml
@@ -13,7 +13,7 @@
</methods>
<members>
<member name="axis" type="int" setter="set_axis" getter="get_axis" default="0">
- Axis identifier. Use one of the [enum JoyAxisList] axis constants.
+ Axis identifier. Use one of the [enum JoyAxis] axis constants.
</member>
<member name="axis_value" type="float" setter="set_axis_value" getter="get_axis_value" default="0.0">
Current position of the joystick on the given axis. The value ranges from [code]-1.0[/code] to [code]1.0[/code]. A value of [code]0[/code] means the axis is in its resting position.
diff --git a/doc/classes/InputEventKey.xml b/doc/classes/InputEventKey.xml
index fe91b9c13e..9f2b829823 100644
--- a/doc/classes/InputEventKey.xml
+++ b/doc/classes/InputEventKey.xml
@@ -32,11 +32,11 @@
If [code]true[/code], the key was already pressed before this event. It means the user is holding the key down.
</member>
<member name="keycode" type="int" setter="set_keycode" getter="get_keycode" default="0">
- The key keycode, which corresponds to one of the [enum KeyList] constants. Represent key in the current keyboard layout.
+ The key keycode, which corresponds to one of the [enum Key] constants. Represent key in the current keyboard layout.
To get a human-readable representation of the [InputEventKey], use [code]OS.get_keycode_string(event.keycode)[/code] where [code]event[/code] is the [InputEventKey].
</member>
<member name="physical_keycode" type="int" setter="set_physical_keycode" getter="get_physical_keycode" default="0">
- Key physical keycode, which corresponds to one of the [enum KeyList] constants. Represent the physical location of a key on the 101/102-key US QWERTY keyboard.
+ Key physical keycode, which corresponds to one of the [enum Key] constants. Represent the physical location of a key on the 101/102-key US QWERTY keyboard.
To get a human-readable representation of the [InputEventKey], use [code]OS.get_keycode_string(event.keycode)[/code] where [code]event[/code] is the [InputEventKey].
</member>
<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false">
diff --git a/doc/classes/InputEventMouse.xml b/doc/classes/InputEventMouse.xml
index 31e82bbaed..e54c3224da 100644
--- a/doc/classes/InputEventMouse.xml
+++ b/doc/classes/InputEventMouse.xml
@@ -13,7 +13,7 @@
</methods>
<members>
<member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" default="0">
- The mouse button mask identifier, one of or a bitwise combination of the [enum ButtonList] button masks.
+ The mouse button mask identifier, one of or a bitwise combination of the [enum MouseButton] button masks.
</member>
<member name="global_position" type="Vector2" setter="set_global_position" getter="get_global_position" default="Vector2( 0, 0 )">
The global mouse position relative to the current [Viewport] when used in [method Control._gui_input], otherwise is at 0,0.
diff --git a/doc/classes/InputEventMouseButton.xml b/doc/classes/InputEventMouseButton.xml
index d7b64a9a2d..d7e92f8bca 100644
--- a/doc/classes/InputEventMouseButton.xml
+++ b/doc/classes/InputEventMouseButton.xml
@@ -13,7 +13,7 @@
</methods>
<members>
<member name="button_index" type="int" setter="set_button_index" getter="get_button_index" default="0">
- The mouse button identifier, one of the [enum ButtonList] button or button wheel constants.
+ The mouse button identifier, one of the [enum MouseButton] button or button wheel constants.
</member>
<member name="doubleclick" type="bool" setter="set_doubleclick" getter="is_doubleclick" default="false">
If [code]true[/code], the mouse button's state is a double-click.
diff --git a/doc/classes/InputMap.xml b/doc/classes/InputMap.xml
index 49d29b3a53..0fb18d8e81 100644
--- a/doc/classes/InputMap.xml
+++ b/doc/classes/InputMap.xml
@@ -100,6 +100,8 @@
</argument>
<argument index="1" name="action" type="StringName">
</argument>
+ <argument index="2" name="exact_match" type="bool" default="false">
+ </argument>
<description>
Returns [code]true[/code] if the given event is part of an existing action. This method ignores keyboard modifiers if the given [InputEvent] is not pressed (for proper release detection). See [method action_has_event] if you don't want this behavior.
</description>
diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml
index abc327e8bb..0020cbf242 100644
--- a/doc/classes/ItemList.xml
+++ b/doc/classes/ItemList.xml
@@ -302,16 +302,7 @@
<argument index="1" name="custom_bg_color" type="Color">
</argument>
<description>
- [codeblocks]
- [gdscript]
- var itemList = ItemList.new()
- some_string.set_item_custom_bg_color(0, Color.red) # This will set the background color of the first item of the control to red.
- [/gdscript]
- [csharp]
- var itemList = new ItemList();
- itemList.SetItemCustomBgColor(0, Colors.Red); // This will set the background color of the first item of the control to red.
- [/csharp]
- [/codeblocks]
+ Sets the background color of the item specified by [code]idx[/code] index to the specified [Color].
</description>
</method>
<method name="set_item_custom_fg_color">
@@ -323,16 +314,6 @@
</argument>
<description>
Sets the foreground color of the item specified by [code]idx[/code] index to the specified [Color].
- [codeblocks]
- [gdscript]
- var item_list = ItemList.new()
- item_list.set_item_custom_fg_color(0, Color.red) # This will set the foreground color of the first item of the control to red.
- [/gdscript]
- [csharp]
- var itemList = new ItemList();
- itemList.SetItemCustomFgColor(0, Colors.Red); // This will set the foreground color of the first item of the control to red.
- [/csharp]
- [/codeblocks]
</description>
</method>
<method name="set_item_disabled">
@@ -615,6 +596,9 @@
<theme_item name="font_color" type="Color" default="Color( 0.63, 0.63, 0.63, 1 )">
Default text [Color] of the item.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the item.
+ </theme_item>
<theme_item name="font_selected_color" type="Color" default="Color( 1, 1, 1, 1 )">
Text [Color] used when the item is selected.
</theme_item>
@@ -633,6 +617,9 @@
<theme_item name="line_separation" type="int" default="2">
The vertical spacing between each line of text.
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the item text outline.
+ </theme_item>
<theme_item name="selected" type="StyleBox">
[StyleBox] for the selected items, used when the [ItemList] is not being focused.
</theme_item>
diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml
index 476b64a336..fdd4db6115 100644
--- a/doc/classes/KinematicBody2D.xml
+++ b/doc/classes/KinematicBody2D.xml
@@ -162,7 +162,10 @@
</methods>
<members>
<member name="collision/safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.08">
- If the body is at least this close to another body, this body will consider them to be colliding.
+ Extra margin used for collision recovery in motion functions (see [method move_and_collide], [method move_and_slide], [method move_and_slide_with_snap]).
+ If the body is at least this close to another body, it will consider them to be colliding and will be pushed away before performing the actual motion.
+ A higher value means it's more flexible for detecting collision, which helps with consistently detecting walls and floors.
+ A lower value forces the collision algorithm to use more exact detection, so it can be used in cases that specifically require precision, e.g at very low scale to avoid visible jittering, or for stability with a stack of kinematic bodies.
</member>
<member name="motion/sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
If [code]true[/code], the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method move_and_slide] or [method move_and_collide] functions.
diff --git a/doc/classes/KinematicBody3D.xml b/doc/classes/KinematicBody3D.xml
index a21496de54..efd3f58f88 100644
--- a/doc/classes/KinematicBody3D.xml
+++ b/doc/classes/KinematicBody3D.xml
@@ -177,7 +177,10 @@
Lock the body's Z axis movement.
</member>
<member name="collision/safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.001">
- If the body is at least this close to another body, this body will consider them to be colliding.
+ Extra margin used for collision recovery in motion functions (see [method move_and_collide], [method move_and_slide], [method move_and_slide_with_snap]).
+ If the body is at least this close to another body, it will consider them to be colliding and will be pushed away before performing the actual motion.
+ A higher value means it's more flexible for detecting collision, which helps with consistently detecting walls and floors.
+ A lower value forces the collision algorithm to use more exact detection, so it can be used in cases that specifically require precision, e.g at very low scale to avoid visible jittering, or for stability with a stack of kinematic bodies.
</member>
</members>
<constants>
diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml
index 8574ff9836..76b9686393 100644
--- a/doc/classes/Label.xml
+++ b/doc/classes/Label.xml
@@ -32,7 +32,7 @@
</argument>
<description>
Returns the height of the line [code]line[/code].
- If [code]line[/code] is set to [code]-1[/code], returns biggest line height.
+ If [code]line[/code] is set to [code]-1[/code], returns the biggest line height.
If there're no lines returns font size in pixels.
</description>
</method>
diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml
index 6c008e4f7e..6bae612c9f 100644
--- a/doc/classes/Light3D.xml
+++ b/doc/classes/Light3D.xml
@@ -58,7 +58,7 @@
If [code]true[/code], the light's effect is reversed, darkening areas and casting bright shadows.
</member>
<member name="light_projector" type="Texture2D" setter="set_projector" getter="get_projector">
- [Texture2D] projected by light. [member shadow_enabled] must be on for the projector to work. Light projectors make the light appear as if it is shining through a colored but transparent object, almost like light shining through stained glass.
+ [Texture2D] projected by light. [member shadow_enabled] must be on for the projector to work. Light projectors make the light appear as if it is shining through a colored but transparent object, almost like light shining through stained-glass.
</member>
<member name="light_size" type="float" setter="set_param" getter="get_param" default="0.0">
The size of the light in Godot units. Only available for [OmniLight3D]s and [SpotLight3D]s. Increasing this value will make the light fade out slower and shadows appear blurrier. This can be used to simulate area lights to an extent.
@@ -78,7 +78,7 @@
<member name="shadow_enabled" type="bool" setter="set_shadow" getter="has_shadow" default="false">
If [code]true[/code], the light will cast shadows.
</member>
- <member name="shadow_fog_fade" type="float" setter="set_param" getter="get_param" default="1.0">
+ <member name="shadow_fog_fade" type="float" setter="set_param" getter="get_param" default="0.1">
</member>
<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.
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index 61ecff52e3..360f5c451e 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -380,6 +380,9 @@
<theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
Default font color.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the [LineEdit].
+ </theme_item>
<theme_item name="font_selected_color" type="Color" default="Color( 0, 0, 0, 1 )">
Font color for selected text (inside the selection rectangle).
</theme_item>
@@ -389,12 +392,15 @@
<theme_item name="font_uneditable_color" type="Color" default="Color( 0.88, 0.88, 0.88, 0.5 )">
Font color when editing is disabled.
</theme_item>
- <theme_item name="minimum_spaces" type="int" default="12">
- Minimum horizontal space for the text (not counting the clear button and content margins). This value is measured in count of space characters (i.e. this amount of space characters can be displayed without scrolling).
+ <theme_item name="minimum_character_width" type="int" default="4">
+ Minimum horizontal space for the text (not counting the clear button and content margins). This value is measured in count of 'M' characters (i.e. this amount of 'M' characters can be displayed without scrolling).
</theme_item>
<theme_item name="normal" type="StyleBox">
Default background for the [LineEdit].
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
<theme_item name="read_only" type="StyleBox">
Background used when [LineEdit] is in read-only mode ([member editable] is set to [code]false[/code]).
</theme_item>
diff --git a/doc/classes/LinkButton.xml b/doc/classes/LinkButton.xml
index 0227870152..6e2f4399b3 100644
--- a/doc/classes/LinkButton.xml
+++ b/doc/classes/LinkButton.xml
@@ -84,12 +84,18 @@
<theme_item name="font_hover_color" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
Text [Color] used when the [LinkButton] is being hovered.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the [LinkButton].
+ </theme_item>
<theme_item name="font_pressed_color" type="Color" default="Color( 1, 1, 1, 1 )">
Text [Color] used when the [LinkButton] is being pressed.
</theme_item>
<theme_item name="font_size" type="int">
Font size of the [LinkButton]'s text.
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
<theme_item name="underline_spacing" type="int" default="2">
The vertical space between the baseline of text and the underline.
</theme_item>
diff --git a/doc/classes/MarginContainer.xml b/doc/classes/MarginContainer.xml
index c8eebd4677..a51632d5f1 100644
--- a/doc/classes/MarginContainer.xml
+++ b/doc/classes/MarginContainer.xml
@@ -5,21 +5,23 @@
</brief_description>
<description>
Adds a top, left, bottom, and right margin to all [Control] nodes that are direct children of the container. To control the [MarginContainer]'s margin, use the [code]margin_*[/code] theme properties listed below.
- [b]Note:[/b] Be careful, [Control] margin values are different than the constant margin values. If you want to change the custom margin values of the [MarginContainer] by code, you should use the following examples:
+ [b]Note:[/b] Be careful, [Control] margin values are different from the constant margin values. If you want to change the custom margin values of the [MarginContainer] by code, you should use the following examples:
[codeblocks]
[gdscript]
+ # This code sample assumes the current script is extending MarginContainer.
var margin_value = 100
- set("custom_constants/margin_top", margin_value)
- set("custom_constants/margin_left", margin_value)
- set("custom_constants/margin_bottom", margin_value)
- set("custom_constants/margin_right", margin_value)
+ add_theme_constant_override("margin_top", margin_value)
+ add_theme_constant_override("margin_left", margin_value)
+ add_theme_constant_override("margin_bottom", margin_value)
+ add_theme_constant_override("margin_right", margin_value)
[/gdscript]
[csharp]
+ // This code sample assumes the current script is extending MarginContainer.
int marginValue = 100;
- Set("custom_constants/margin_top", marginValue);
- Set("custom_constants/margin_left", marginValue);
- Set("custom_constants/margin_bottom", marginValue);
- Set("custom_constants/margin_right", marginValue);
+ AddThemeConstantOverride("margin_top", marginValue);
+ AddThemeConstantOverride("margin_left", marginValue);
+ AddThemeConstantOverride("margin_bottom", marginValue);
+ AddThemeConstantOverride("margin_right", marginValue);
[/csharp]
[/codeblocks]
</description>
diff --git a/doc/classes/MenuButton.xml b/doc/classes/MenuButton.xml
index 1e8874fdc5..7cbf9d3dfe 100644
--- a/doc/classes/MenuButton.xml
+++ b/doc/classes/MenuButton.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
Special button that brings up a [PopupMenu] when clicked.
- New items can be created inside this [PopupMenu] using [code]get_popup().add_item("My Item Name")[/code]. You can also create them directly from the editor. To do so, select the [MenuButton] node, then in the toolbar at the top of the 2D editor, click [b]Items[/b] then click [b]Add[/b] in the popup. You will be able to give each items new properties.
+ New items can be created inside this [PopupMenu] using [code]get_popup().add_item("My Item Name")[/code]. You can also create them directly from the editor. To do so, select the [MenuButton] node, then in the toolbar at the top of the 2D editor, click [b]Items[/b] then click [b]Add[/b] in the popup. You will be able to give each item new properties.
See also [BaseButton] which contains common properties and methods associated with this node.
</description>
<tutorials>
@@ -65,6 +65,9 @@
<theme_item name="font_hover_color" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
Text [Color] used when the [MenuButton] is being hovered.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the [MenuButton].
+ </theme_item>
<theme_item name="font_pressed_color" type="Color" default="Color( 1, 1, 1, 1 )">
Text [Color] used when the [MenuButton] is being pressed.
</theme_item>
@@ -80,6 +83,9 @@
<theme_item name="normal" type="StyleBox">
Default [StyleBox] for the [MenuButton].
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
<theme_item name="pressed" type="StyleBox">
[StyleBox] used when the [MenuButton] is being pressed.
</theme_item>
diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml
index 6ebfc946dc..2adebdb306 100644
--- a/doc/classes/MultiMesh.xml
+++ b/doc/classes/MultiMesh.xml
@@ -6,7 +6,7 @@
<description>
MultiMesh provides low-level mesh instancing. Drawing thousands of [MeshInstance3D] nodes can be slow, since each object is submitted to the GPU then drawn individually.
MultiMesh is much faster as it can draw thousands of instances with a single draw call, resulting in less API overhead.
- As a drawback, if the instances are too far away of each other, performance may be reduced as every single instance will always rendered (they are spatially indexed as one, for the whole object).
+ As a drawback, if the instances are too far away of each other, performance may be reduced as every single instance will always render (they are spatially indexed as one, for the whole object).
Since instances may have any behavior, the AABB used for visibility must be provided by the user.
</description>
<tutorials>
diff --git a/doc/classes/Navigation2D.xml b/doc/classes/Navigation2D.xml
deleted file mode 100644
index abac29bdb7..0000000000
--- a/doc/classes/Navigation2D.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Navigation2D" inherits="Node2D" version="4.0">
- <brief_description>
- 2D navigation and pathfinding node.
- </brief_description>
- <description>
- Navigation2D provides navigation and pathfinding within a 2D area, specified as a collection of [NavigationPolygon] resources. These are automatically collected from child [NavigationRegion2D] nodes.
- </description>
- <tutorials>
- <link title="2D Navigation Demo">https://godotengine.org/asset-library/asset/117</link>
- </tutorials>
- <methods>
- <method name="get_closest_point" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="to_point" type="Vector2">
- </argument>
- <description>
- Returns the point closest to the provided [code]to_point[/code] on the navigation mesh surface.
- </description>
- </method>
- <method name="get_closest_point_owner" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="to_point" type="Vector2">
- </argument>
- <description>
- Returns the owner region RID for the point returned by [method get_closest_point].
- </description>
- </method>
- <method name="get_rid" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="get_simple_path" qualifiers="const">
- <return type="PackedVector2Array">
- </return>
- <argument index="0" name="start" type="Vector2">
- </argument>
- <argument index="1" name="end" type="Vector2">
- </argument>
- <argument index="2" name="optimize" type="bool" default="true">
- </argument>
- <description>
- Returns the path between two given points. Points are in local coordinate space. If [code]optimize[/code] is [code]true[/code] (the default), the path is smoothed by merging path segments where possible.
- </description>
- </method>
- </methods>
- <members>
- <member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size" default="10.0">
- </member>
- <member name="edge_connection_margin" type="float" setter="set_edge_connection_margin" getter="get_edge_connection_margin" default="100.0">
- </member>
- </members>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/Navigation3D.xml b/doc/classes/Navigation3D.xml
deleted file mode 100644
index e7a4fe3c43..0000000000
--- a/doc/classes/Navigation3D.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Navigation3D" inherits="Node3D" version="4.0">
- <brief_description>
- Mesh-based navigation and pathfinding node.
- </brief_description>
- <description>
- Provides navigation and pathfinding within a collection of [NavigationMesh]es. These will be automatically collected from child [NavigationRegion3D] nodes. In addition to basic pathfinding, this class also assists with aligning navigation agents with the meshes they are navigating on.
- </description>
- <tutorials>
- <link title="3D Navmesh Demo">https://godotengine.org/asset-library/asset/124</link>
- </tutorials>
- <methods>
- <method name="get_closest_point" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="to_point" type="Vector3">
- </argument>
- <description>
- Returns the point closest to the provided [code]to_point[/code] on the navigation mesh surface.
- </description>
- </method>
- <method name="get_closest_point_normal" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="to_point" type="Vector3">
- </argument>
- <description>
- Returns the normal for the point returned by [method get_closest_point].
- </description>
- </method>
- <method name="get_closest_point_owner" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="to_point" type="Vector3">
- </argument>
- <description>
- Returns the owner region RID for the point returned by [method get_closest_point].
- </description>
- </method>
- <method name="get_closest_point_to_segment" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="start" type="Vector3">
- </argument>
- <argument index="1" name="end" type="Vector3">
- </argument>
- <argument index="2" name="use_collision" type="bool" default="false">
- </argument>
- <description>
- Returns the closest point between the navigation surface and the segment.
- </description>
- </method>
- <method name="get_rid" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="get_simple_path" qualifiers="const">
- <return type="PackedVector3Array">
- </return>
- <argument index="0" name="start" type="Vector3">
- </argument>
- <argument index="1" name="end" type="Vector3">
- </argument>
- <argument index="2" name="optimize" type="bool" default="true">
- </argument>
- <description>
- Returns the path between two given points. Points are in local coordinate space. If [code]optimize[/code] is [code]true[/code] (the default), the agent properties associated with each [NavigationMesh] (radius, height, etc.) are considered in the path calculation, otherwise they are ignored.
- </description>
- </method>
- </methods>
- <members>
- <member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size" default="0.3">
- </member>
- <member name="edge_connection_margin" type="float" setter="set_edge_connection_margin" getter="get_edge_connection_margin" default="5.0">
- </member>
- <member name="up_vector" type="Vector3" setter="set_up_vector" getter="get_up_vector" default="Vector3( 0, 1, 0 )">
- Defines which direction is up. By default, this is [code](0, 1, 0)[/code], which is the world's "up" direction.
- </member>
- </members>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml
index 5a9c31ef67..1060e2de41 100644
--- a/doc/classes/NavigationAgent2D.xml
+++ b/doc/classes/NavigationAgent2D.xml
@@ -4,7 +4,7 @@
2D Agent used in navigation for collision avoidance.
</brief_description>
<description>
- 2D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. This can be done by having the agent as a child of a [Navigation2D] node, or using [method set_navigation]. [NavigationAgent2D] is physics safe.
+ 2D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. [NavigationAgent2D] is physics safe.
</description>
<tutorials>
</tutorials>
@@ -37,13 +37,6 @@
Returns which index the agent is currently on in the navigation path's [PackedVector2Array].
</description>
</method>
- <method name="get_navigation" qualifiers="const">
- <return type="Node">
- </return>
- <description>
- Returns the [Navigation2D] node that the agent is using for its navigation system.
- </description>
- </method>
<method name="get_next_location">
<return type="Vector2">
</return>
@@ -79,15 +72,6 @@
Returns true if the target location is reached. The target location is set using [method set_target_location]. It may not always be possible to reach the target location. It should always be possible to reach the final location though. See [method get_final_location].
</description>
</method>
- <method name="set_navigation">
- <return type="void">
- </return>
- <argument index="0" name="navigation" type="Node">
- </argument>
- <description>
- Sets the [Navigation2D] node used by the agent. Useful when you don't want to make the agent a child of a [Navigation2D] node.
- </description>
- </method>
<method name="set_target_location">
<return type="void">
</return>
@@ -127,7 +111,7 @@
The distance threshold before a target is considered to be reached. This will allow an agent to not have to hit a point on the path exactly, but in the area.
</member>
<member name="time_horizon" type="float" setter="set_time_horizon" getter="get_time_horizon" default="20.0">
- The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithim, are safe with respect to other agents. The larger the number, the sooner the agent will respond to other agents, but less freedom in choosing its velocities. Must be positive.
+ The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithm, are safe with respect to other agents. The larger the number, the sooner the agent will respond to other agents, but less freedom in choosing its velocities. Must be positive.
</member>
</members>
<signals>
diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml
index f9df1d390b..00e9db0a33 100644
--- a/doc/classes/NavigationAgent3D.xml
+++ b/doc/classes/NavigationAgent3D.xml
@@ -4,7 +4,7 @@
3D Agent used in navigation for collision avoidance.
</brief_description>
<description>
- 3D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. This can be done by having the agent as a child of a [Navigation3D] node, or using [method set_navigation]. [NavigationAgent3D] is physics safe.
+ 3D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. [NavigationAgent3D] is physics safe.
</description>
<tutorials>
</tutorials>
@@ -37,13 +37,6 @@
Returns which index the agent is currently on in the navigation path's [PackedVector3Array].
</description>
</method>
- <method name="get_navigation" qualifiers="const">
- <return type="Node">
- </return>
- <description>
- Returns the [Navigation3D] node that the agent is using for its navigation system.
- </description>
- </method>
<method name="get_next_location">
<return type="Vector3">
</return>
@@ -79,15 +72,6 @@
Returns true if the target location is reached. The target location is set using [method set_target_location]. It may not always be possible to reach the target location. It should always be possible to reach the final location though. See [method get_final_location].
</description>
</method>
- <method name="set_navigation">
- <return type="void">
- </return>
- <argument index="0" name="navigation" type="Node">
- </argument>
- <description>
- Sets the [Navigation3D] node used by the agent. Useful when you don't want to make the agent a child of a [Navigation3D] node.
- </description>
- </method>
<method name="set_target_location">
<return type="void">
</return>
@@ -133,7 +117,7 @@
The distance threshold before a target is considered to be reached. This will allow an agent to not have to hit a point on the path exactly, but in the area.
</member>
<member name="time_horizon" type="float" setter="set_time_horizon" getter="get_time_horizon" default="5.0">
- The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithim, are safe with respect to other agents. The larger the number, the sooner the agent will respond to other agents, but less freedom in choosing its velocities. Must be positive.
+ The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithm, are safe with respect to other agents. The larger the number, the sooner the agent will respond to other agents, but less freedom in choosing its velocities. Must be positive.
</member>
</members>
<signals>
diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml
index dd7464ac0e..1f6e582731 100644
--- a/doc/classes/NavigationMesh.xml
+++ b/doc/classes/NavigationMesh.xml
@@ -111,7 +111,7 @@
The physics layers used to generate the [NavigationMesh].
</member>
<member name="geometry/parsed_geometry_type" type="int" setter="set_parsed_geometry_type" getter="get_parsed_geometry_type" default="0">
- What kind of geomerty is used to generate the [NavigationMesh].
+ What kind of geometry is used to generate the [NavigationMesh].
</member>
<member name="geometry/source_geometry_mode" type="int" setter="set_source_geometry_mode" getter="get_source_geometry_mode" default="0">
Which geometry is used to generate the [NavigationMesh].
diff --git a/doc/classes/NavigationObstacle2D.xml b/doc/classes/NavigationObstacle2D.xml
index ddd96975f1..2e94eb0bba 100644
--- a/doc/classes/NavigationObstacle2D.xml
+++ b/doc/classes/NavigationObstacle2D.xml
@@ -4,27 +4,11 @@
2D Obstacle used in navigation for collision avoidance.
</brief_description>
<description>
- 2D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. This can be done by having the obstacle as a child of a [Navigation2D] node, or using [method set_navigation]. [NavigationObstacle2D] is physics safe.
+ 2D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. [NavigationObstacle2D] is physics safe.
</description>
<tutorials>
</tutorials>
<methods>
- <method name="get_navigation" qualifiers="const">
- <return type="Node">
- </return>
- <description>
- Returns the [Navigation2D] node that the obstacle is using for its navigation system.
- </description>
- </method>
- <method name="set_navigation">
- <return type="void">
- </return>
- <argument index="0" name="navigation" type="Node">
- </argument>
- <description>
- Sets the [Navigation2D] node used by the obstacle. Useful when you don't want to make the obstacle a child of a [Navigation2D] node.
- </description>
- </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/NavigationObstacle3D.xml b/doc/classes/NavigationObstacle3D.xml
index e01a40ed73..d7454a7bea 100644
--- a/doc/classes/NavigationObstacle3D.xml
+++ b/doc/classes/NavigationObstacle3D.xml
@@ -4,27 +4,11 @@
3D Obstacle used in navigation for collision avoidance.
</brief_description>
<description>
- 3D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. This can be done by having the obstacle as a child of a [Navigation3D] node, or using [method set_navigation]. [NavigationObstacle3D] is physics safe.
+ 3D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. [NavigationObstacle3D] is physics safe.
</description>
<tutorials>
</tutorials>
<methods>
- <method name="get_navigation" qualifiers="const">
- <return type="Node">
- </return>
- <description>
- Returns the [Navigation3D] node that the obstacle is using for its navigation system.
- </description>
- </method>
- <method name="set_navigation">
- <return type="void">
- </return>
- <argument index="0" name="navigation" type="Node">
- </argument>
- <description>
- Sets the [Navigation3D] node used by the obstacle. Useful when you don't want to make the obstacle a child of a [Navigation3D] node.
- </description>
- </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/NavigationRegion2D.xml b/doc/classes/NavigationRegion2D.xml
index aef114e1db..33a3f04c3d 100644
--- a/doc/classes/NavigationRegion2D.xml
+++ b/doc/classes/NavigationRegion2D.xml
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="NavigationRegion2D" inherits="Node2D" version="4.0">
<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.
</description>
<tutorials>
</tutorials>
@@ -10,8 +14,13 @@
</methods>
<members>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true">
+ Determines if the [NavigationRegion2D] is enabled or disabled.
+ </member>
+ <member name="layers" type="int" setter="set_layers" getter="get_layers" default="1">
+ A bitfield determining all layers the region belongs to. These 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">
+ The [NavigationPolygon] resource to use.
</member>
</members>
<constants>
diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml
index b70bfb6596..2904ba4200 100644
--- a/doc/classes/NavigationRegion3D.xml
+++ b/doc/classes/NavigationRegion3D.xml
@@ -4,7 +4,8 @@
A region of the navigation map.
</brief_description>
<description>
- A region of the navigation map. It tells the [Navigation3D] node what can be navigated and what cannot, based on the [NavigationMesh] resource. This should be a child of a [Navigation3D] node (even not a direct child).
+ 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].
</description>
<tutorials>
</tutorials>
@@ -21,6 +22,9 @@
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true">
Determines if the [NavigationRegion3D] is enabled or disabled.
</member>
+ <member name="layers" type="int" setter="set_layers" getter="get_layers" default="1">
+ A bitfield determining all layers the region belongs to. These 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">
The [NavigationMesh] resource to use.
</member>
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index 5f0b04487e..b0a57ed227 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -4,7 +4,12 @@
Server interface for low-level 2D navigation access
</brief_description>
<description>
- NavigationServer2D is the server responsible for all 2D navigation. It creates the agents, maps, and regions for navigation to work as expected. This 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.
+ NavigationServer2D is the server responsible for all 2D navigation. It handles several objects, namely maps, regions and agents.
+ Maps are made up of regions, which are made of navigation polygons. Together, they define the navigable areas in the 2D world. For two regions to be connected to each other, they must share a similar edge. An edge is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex.
+ You may assign navigation layers to regions with [method NavigationServer2D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer2D.map_get_path]. This allows allowing or forbidding some areas to 2D objects.
+ To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity.
+ [b]Note:[/b] the collision avoidance system ignores regions. Using the 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.
+ 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.
</description>
<tutorials>
<link title="2D Navigation Demo">https://godotengine.org/asset-library/asset/117</link>
@@ -207,8 +212,10 @@
</argument>
<argument index="3" name="optimize" type="bool">
</argument>
+ <argument index="4" name="layers" type="int" default="1">
+ </argument>
<description>
- Returns the navigation path to reach the destination from the origin, while avoiding static obstacles.
+ Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path.
</description>
</method>
<method name="map_is_active" qualifiers="const">
@@ -260,6 +267,57 @@
Creates a new region.
</description>
</method>
+ <method name="region_get_connection_pathway_end" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <argument index="1" name="connection" type="int">
+ </argument>
+ <description>
+ Returns the ending point of a connection door. [code]connection[/code] is an index between 0 and the return value of [method region_get_connections_count].
+ </description>
+ </method>
+ <method name="region_get_connection_pathway_start" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <argument index="1" name="connection" type="int">
+ </argument>
+ <description>
+ Returns the starting point of a connection door. [code]connection[/code] is an index between 0 and the return value of [method region_get_connections_count].
+ </description>
+ </method>
+ <method name="region_get_connections_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <description>
+ Returns how many connections this [code]region[/code] has with other regions in the map.
+ </description>
+ </method>
+ <method name="region_get_layers" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <description>
+ Returns the region's layers.
+ </description>
+ </method>
+ <method name="region_set_layers" qualifiers="const">
+ <return type="void">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <argument index="1" name="layers" type="int">
+ </argument>
+ <description>
+ Set the region's layers. This allows selecting regions from a path request (when using [method NavigationServer2D.map_get_path]).
+ </description>
+ </method>
<method name="region_set_map" qualifiers="const">
<return type="void">
</return>
@@ -294,6 +352,15 @@
</description>
</method>
</methods>
+ <signals>
+ <signal name="map_changed">
+ <argument index="0" name="map" type="RID">
+ </argument>
+ <description>
+ Emitted when a navigation map is updated, when a region moves or is modified.
+ </description>
+ </signal>
+ </signals>
<constants>
</constants>
</class>
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index 95890c4b4c..b098a7fc20 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -4,7 +4,12 @@
Server interface for low-level 3D navigation access
</brief_description>
<description>
- NavigationServer3D is the server responsible for all 3D navigation. It creates the agents, maps, and regions for navigation to work as expected. This 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.
+ NavigationServer3D is the server responsible for all 3D navigation. It handles several objects, namely maps, regions and agents.
+ Maps are made up of regions, which are made of navigation meshes. Together, they define the navigable areas in the 3D world. For two regions to be connected to each other, they must share a similar edge. An edge is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex.
+ You may assign navigation layers to regions with [method NavigationServer3D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer3D.map_get_path]. This allows allowing or forbidding some areas to 3D objects.
+ To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity.
+ [b]Note:[/b] the collision avoidance system ignores regions. Using the 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.
+ 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.
</description>
<tutorials>
<link title="3D Navmesh Demo">https://godotengine.org/asset-library/asset/124</link>
@@ -219,7 +224,7 @@
<argument index="0" name="map" type="RID">
</argument>
<description>
- Returns the edge connection margin of the map.
+ Returns the edge connection margin of the map. This distance is the minimum vertex distance needed to connect two edges from different regions.
</description>
</method>
<method name="map_get_path" qualifiers="const">
@@ -233,8 +238,10 @@
</argument>
<argument index="3" name="optimize" type="bool">
</argument>
+ <argument index="4" name="layers" type="int" default="1">
+ </argument>
<description>
- Returns the navigation path to reach the destination from the origin.
+ Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path.
</description>
</method>
<method name="map_get_up" qualifiers="const">
@@ -285,7 +292,7 @@
<argument index="1" name="margin" type="float">
</argument>
<description>
- Set the map edge connection margein used to weld the compatible region edges.
+ Set the map edge connection margin used to weld the compatible region edges.
</description>
</method>
<method name="map_set_up" qualifiers="const">
@@ -328,6 +335,57 @@
Creates a new region.
</description>
</method>
+ <method name="region_get_connection_pathway_end" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <argument index="1" name="connection" type="int">
+ </argument>
+ <description>
+ Returns the ending point of a connection door. [code]connection[/code] is an index between 0 and the return value of [method region_get_connections_count].
+ </description>
+ </method>
+ <method name="region_get_connection_pathway_start" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <argument index="1" name="connection" type="int">
+ </argument>
+ <description>
+ Returns the starting point of a connection door. [code]connection[/code] is an index between 0 and the return value of [method region_get_connections_count].
+ </description>
+ </method>
+ <method name="region_get_connections_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <description>
+ Returns how many connections this [code]region[/code] has with other regions in the map.
+ </description>
+ </method>
+ <method name="region_get_layers" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <description>
+ Returns the region's layers.
+ </description>
+ </method>
+ <method name="region_set_layers" qualifiers="const">
+ <return type="void">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <argument index="1" name="layers" type="int">
+ </argument>
+ <description>
+ Set the region's layers. This allows selecting regions from a path request (when using [method NavigationServer3D.map_get_path]).
+ </description>
+ </method>
<method name="region_set_map" qualifiers="const">
<return type="void">
</return>
@@ -371,6 +429,15 @@
</description>
</method>
</methods>
+ <signals>
+ <signal name="map_changed">
+ <argument index="0" name="map" type="RID">
+ </argument>
+ <description>
+ Emitted when a navigation map is updated, when a region moves or is modified.
+ </description>
+ </signal>
+ </signals>
<constants>
</constants>
</class>
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 5f0d6462e2..7750d45226 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -128,7 +128,7 @@
</argument>
<description>
Adds a child node. Nodes can have any number of children, but every child must have a unique name. Child nodes are automatically deleted when the parent node is deleted, so an entire scene can be removed by deleting its topmost node.
- If [code]legible_unique_name[/code] is [code]true[/code], the child node will have an human-readable name based on the name of the node being instanced instead of its type.
+ If [code]legible_unique_name[/code] is [code]true[/code], the child node will have a human-readable name based on the name of the node being instanced instead of its type.
[b]Note:[/b] If the child node already has a parent, the function will fail. Use [method remove_child] first to remove the node from its current parent. For example:
[codeblocks]
[gdscript]
@@ -158,8 +158,8 @@
<argument index="1" name="legible_unique_name" type="bool" default="false">
</argument>
<description>
- Adds a [code]sibling[/code] node to current's node parent, at the the same level as that node, right below it.
- If [code]legible_unique_name[/code] is [code]true[/code], the child node will have an human-readable name based on the name of the node being instanced instead of its type.
+ Adds a [code]sibling[/code] node to current's node parent, at the same level as that node, right below it.
+ If [code]legible_unique_name[/code] is [code]true[/code], the child node will have a human-readable name based on the name of the node being instanced instead of its type.
Use [method add_child] instead of this method if you don't need the child node to be added below a specific node in the list of children.
</description>
</method>
@@ -179,7 +179,7 @@
<return type="bool">
</return>
<description>
- Returns [code]true[/code] if the node can process while the scene tree is paused (see [member pause_mode]). Always returns [code]true[/code] if the scene tree is not paused, and [code]false[/code] if the node is not in the tree.
+ Returns [code]true[/code] if the node can process while the scene tree is paused (see [member process_mode]). Always returns [code]true[/code] if the scene tree is not paused, and [code]false[/code] if the node is not in the tree.
</description>
</method>
<method name="duplicate" qualifiers="const">
@@ -245,6 +245,12 @@
Returns an array of references to node's children.
</description>
</method>
+ <method name="get_editor_description" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_groups" qualifiers="const">
<return type="Array">
</return>
@@ -757,6 +763,14 @@
Sets the folded state of the node in the Scene dock.
</description>
</method>
+ <method name="set_editor_description">
+ <return type="void">
+ </return>
+ <argument index="0" name="editor_description" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_network_master">
<return type="void">
</return>
@@ -868,8 +882,8 @@
<member name="owner" type="Node" setter="set_owner" getter="get_owner">
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 (using [PackedScene]), all the nodes it owns will be saved with it. This allows for the creation of complex [SceneTree]s, with instancing and subinstancing.
</member>
- <member name="pause_mode" type="int" setter="set_pause_mode" getter="get_pause_mode" enum="Node.PauseMode" default="0">
- Pause mode. How the node will behave if the [SceneTree] is paused.
+ <member name="process_mode" type="int" setter="set_process_mode" getter="get_process_mode" enum="Node.ProcessMode" default="0">
+ Can be used to pause or unpause the node, or make the node paused based on the [SceneTree], or make it inherit the process mode from its parent (default).
</member>
<member name="process_priority" type="int" setter="set_process_priority" getter="get_process_priority" default="0">
The node's priority in the execution order of the enabled processing callbacks (i.e. [constant NOTIFICATION_PROCESS], [constant NOTIFICATION_PHYSICS_PROCESS] and their internal counterparts). Nodes whose process priority value is [i]lower[/i] will have their processing callbacks executed first.
@@ -1017,14 +1031,20 @@
<constant name="NOTIFICATION_TEXT_SERVER_CHANGED" value="2018">
Notification received when text server is changed.
</constant>
- <constant name="PAUSE_MODE_INHERIT" value="0" enum="PauseMode">
- Inherits pause mode from the node's parent. For the root node, it is equivalent to [constant PAUSE_MODE_STOP]. Default.
+ <constant name="PROCESS_MODE_INHERIT" value="0" enum="ProcessMode">
+ Inherits process mode from the node's parent. For the root node, it is equivalent to [constant PROCESS_MODE_PAUSABLE]. Default.
+ </constant>
+ <constant name="PROCESS_MODE_PAUSABLE" value="1" enum="ProcessMode">
+ Stops processing when the [SceneTree] is paused (process when unpaused). This is the inverse of [constant PROCESS_MODE_WHEN_PAUSED].
+ </constant>
+ <constant name="PROCESS_MODE_WHEN_PAUSED" value="2" enum="ProcessMode">
+ Only process when the [SceneTree] is paused (don't process when unpaused). This is the inverse of [constant PROCESS_MODE_PAUSABLE].
</constant>
- <constant name="PAUSE_MODE_STOP" value="1" enum="PauseMode">
- Stops processing when the [SceneTree] is paused.
+ <constant name="PROCESS_MODE_ALWAYS" value="3" enum="ProcessMode">
+ Always process. Continue processing always, ignoring the [SceneTree]'s paused property. This is the inverse of [constant PROCESS_MODE_DISABLED].
</constant>
- <constant name="PAUSE_MODE_PROCESS" value="2" enum="PauseMode">
- Continue to process regardless of the [SceneTree] pause state.
+ <constant name="PROCESS_MODE_DISABLED" value="4" enum="ProcessMode">
+ Never process. Completely disables processing, ignoring the [SceneTree]'s paused property. This is the inverse of [constant PROCESS_MODE_ALWAYS].
</constant>
<constant name="DUPLICATE_SIGNALS" value="1" enum="DuplicateFlags">
Duplicate the node's signals.
diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml
index 8b56050058..5c29c0d48f 100644
--- a/doc/classes/Node3D.xml
+++ b/doc/classes/Node3D.xml
@@ -103,7 +103,7 @@
</return>
<argument index="0" name="target" type="Vector3">
</argument>
- <argument index="1" name="up" type="Vector3">
+ <argument index="1" name="up" type="Vector3" default="Vector3( 0, 1, 0 )">
</argument>
<description>
Rotates itself so that the local -Z axis points towards the [code]target[/code] position.
@@ -118,7 +118,7 @@
</argument>
<argument index="1" name="target" type="Vector3">
</argument>
- <argument index="2" name="up" type="Vector3">
+ <argument index="2" name="up" type="Vector3" default="Vector3( 0, 1, 0 )">
</argument>
<description>
Moves the node to the specified [code]position[/code], and then rotates itself to point toward the [code]target[/code] as per [method look_at]. Operations take place in global space.
diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml
index 36835d9e94..817ccd5160 100644
--- a/doc/classes/NodePath.xml
+++ b/doc/classes/NodePath.xml
@@ -66,11 +66,11 @@
[/codeblock]
</description>
</method>
- <method name="get_as_property_path">
+ <method name="get_as_property_path" qualifiers="const">
<return type="NodePath">
</return>
<description>
- Returns a node path with a colon character ([code]:[/code]) prepended, transforming it to a pure property path with no node name (defaults to resolving from the from the current node).
+ Returns a node path with a colon character ([code]:[/code]) prepended, transforming it to a pure property path with no node name (defaults to resolving from the current node).
[codeblocks]
[gdscript]
# This will be parsed as a node path to the "x" property in the "position" node.
@@ -89,7 +89,7 @@
[/codeblocks]
</description>
</method>
- <method name="get_concatenated_subnames">
+ <method name="get_concatenated_subnames" qualifiers="const">
<return type="StringName">
</return>
<description>
@@ -106,7 +106,7 @@
[/codeblocks]
</description>
</method>
- <method name="get_name">
+ <method name="get_name" qualifiers="const">
<return type="StringName">
</return>
<argument index="0" name="idx" type="int">
@@ -129,7 +129,7 @@
[/codeblocks]
</description>
</method>
- <method name="get_name_count">
+ <method name="get_name_count" qualifiers="const">
<return type="int">
</return>
<description>
@@ -137,7 +137,7 @@
For example, [code]"Path2D/PathFollow2D/Sprite2D"[/code] has 3 names.
</description>
</method>
- <method name="get_subname">
+ <method name="get_subname" qualifiers="const">
<return type="StringName">
</return>
<argument index="0" name="idx" type="int">
@@ -158,7 +158,7 @@
[/codeblocks]
</description>
</method>
- <method name="get_subname_count">
+ <method name="get_subname_count" qualifiers="const">
<return type="int">
</return>
<description>
@@ -166,14 +166,14 @@
For example, [code]"Path2D/PathFollow2D/Sprite2D:texture:load_path"[/code] has 2 subnames.
</description>
</method>
- <method name="is_absolute">
+ <method name="is_absolute" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the node path is absolute (as opposed to relative), which means that it starts with a slash character ([code]/[/code]). Absolute node paths can be used to access the root node ([code]"/root"[/code]) or autoloads (e.g. [code]"/global"[/code] if a "global" autoload was registered).
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 8620de1378..a76ea5868c 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -54,7 +54,7 @@
<argument index="0" name="msec" type="int">
</argument>
<description>
- Delay execution of the current thread by [code]msec[/code] milliseconds.
+ Delay execution of the current thread by [code]msec[/code] milliseconds. [code]usec[/code] must be greater than or equal to [code]0[/code]. Otherwise, [method delay_msec] will do nothing and will print an error message.
</description>
</method>
<method name="delay_usec" qualifiers="const">
@@ -63,7 +63,7 @@
<argument index="0" name="usec" type="int">
</argument>
<description>
- Delay execution of the current thread by [code]usec[/code] microseconds.
+ Delay execution of the current thread by [code]usec[/code] microseconds. [code]usec[/code] must be greater than or equal to [code]0[/code]. Otherwise, [method delay_usec] will do nothing and will print an error message.
</description>
</method>
<method name="dump_memory_to_file">
@@ -207,10 +207,11 @@
<method name="get_environment" qualifiers="const">
<return type="String">
</return>
- <argument index="0" name="environment" type="String">
+ <argument index="0" name="variable" type="String">
</argument>
<description>
- Returns an environment variable.
+ Returns the value of an environment variable. Returns an empty string if the environment variable doesn't exist.
+ [b]Note:[/b] Double-check the casing of [code]variable[/code]. Environment variable names are case-sensitive on all platforms except Windows.
</description>
</method>
<method name="get_executable_path" qualifiers="const">
@@ -243,9 +244,9 @@
</return>
<description>
Returns the host OS locale as a string of the form [code]language_Script_COUNTRY_VARIANT@extra[/code].
- [code]language[/code] - 2 or 3 letter [url=https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes]language code[/url], in lower case.
- [code]Script[/code] - optional, 4 letter [url=https://en.wikipedia.org/wiki/ISO_15924]script code[/url], in title case.
- [code]COUNTRY[/code] - optional, 2 or 3 letter [url=https://en.wikipedia.org/wiki/ISO_3166-1]country code[/url], in upper case.
+ [code]language[/code] - 2 or 3-letter [url=https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes]language code[/url], in lower case.
+ [code]Script[/code] - optional, 4-letter [url=https://en.wikipedia.org/wiki/ISO_15924]script code[/url], in title case.
+ [code]COUNTRY[/code] - optional, 2 or 3-letter [url=https://en.wikipedia.org/wiki/ISO_3166-1]country code[/url], in upper case.
[code]VARIANT[/code] - optional, language variant, region and sort order. Variant can have any number of underscored key words.
[code]extra[/code] - optional, semicolon separated list of additional key words. Currency, calendar, sort order and numbering system information.
</description>
@@ -304,24 +305,6 @@
[b]Note:[/b] This method is implemented on Android, Linux, macOS and Windows.
</description>
</method>
- <method name="get_tablet_driver_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the total number of available tablet drivers.
- [b]Note:[/b] This method is implemented on Windows.
- </description>
- </method>
- <method name="get_tablet_driver_name" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Returns the tablet driver name for the given index.
- [b]Note:[/b] This method is implemented on Windows.
- </description>
- </method>
<method name="get_thread_caller_id" qualifiers="const">
<return type="int">
</return>
@@ -384,6 +367,7 @@
<description>
Gets an epoch time value from a dictionary of time values.
[code]datetime[/code] must be populated with the following keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]hour[/code], [code]minute[/code], [code]second[/code].
+ If the dictionary is empty [code]0[/code] is returned.
You can pass the output from [method get_datetime_from_unix_time] directly into this function. Daylight Savings Time ([code]dst[/code]), if present, is ignored.
</description>
</method>
@@ -401,10 +385,11 @@
<method name="has_environment" qualifiers="const">
<return type="bool">
</return>
- <argument index="0" name="environment" type="String">
+ <argument index="0" name="variable" type="String">
</argument>
<description>
- Returns [code]true[/code] if an environment variable exists.
+ Returns [code]true[/code] if the environment variable with the name [code]variable[/code] exists.
+ [b]Note:[/b] Double-check the casing of [code]variable[/code]. Environment variable names are case-sensitive on all platforms except Windows.
</description>
</method>
<method name="has_feature" qualifiers="const">
@@ -519,6 +504,18 @@
[b]Note:[/b] This method is implemented on Android.
</description>
</method>
+ <method name="set_environment" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="variable" type="String">
+ </argument>
+ <argument index="1" name="value" type="String">
+ </argument>
+ <description>
+ Sets the value of the environment variable [code]variable[/code] to [code]value[/code]. The environment variable will be set for the Godot process and any process executed with [method execute] after running [method set_environment]. The environment variable will [i]not[/i] persist to processes run after the Godot process was terminated.
+ [b]Note:[/b] Double-check the casing of [code]variable[/code]. Environment variable names are case-sensitive on all platforms except Windows.
+ </description>
+ </method>
<method name="set_thread_name">
<return type="int" enum="Error">
</return>
@@ -553,19 +550,12 @@
</method>
</methods>
<members>
- <member name="exit_code" type="int" setter="set_exit_code" getter="get_exit_code" default="0">
- The exit code passed to the OS when the main loop exits. By convention, an exit code of [code]0[/code] indicates success whereas a non-zero exit code indicates an error. For portability reasons, the exit code should be set between 0 and 125 (inclusive).
- [b]Note:[/b] This value will be ignored if using [method SceneTree.quit] with an [code]exit_code[/code] argument passed.
- </member>
<member name="low_processor_usage_mode" type="bool" setter="set_low_processor_usage_mode" getter="is_in_low_processor_usage_mode" default="false">
If [code]true[/code], the engine optimizes for low processor usage by only refreshing the screen if needed. Can improve battery consumption on mobile.
</member>
<member name="low_processor_usage_mode_sleep_usec" type="int" setter="set_low_processor_usage_mode_sleep_usec" getter="get_low_processor_usage_mode_sleep_usec" default="6900">
The amount of sleeping between frames when the low-processor usage mode is enabled (in microseconds). Higher values will result in lower CPU usage.
</member>
- <member name="tablet_driver" type="String" setter="set_current_tablet_driver" getter="get_current_tablet_driver" default="&quot;&quot;">
- The current tablet driver in use.
- </member>
</members>
<constants>
<constant name="VIDEO_DRIVER_GLES2" value="0" enum="VideoDriver">
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index 6ff7e34194..7da9c1ac38 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Object" version="4.0">
<brief_description>
- Base class for all non built-in types.
+ Base class for all non-built-in types.
</brief_description>
<description>
Every class which is not a built-in type inherits from this class.
@@ -10,11 +10,20 @@
Some classes that extend Object add memory management. This is the case of [Reference], 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]:
- [codeblock]
+ [codeblocks]
+ [gdscript]
var n = Node2D.new()
print("position" in n) # Prints "True".
print("other_property" in n) # Prints "False".
- [/codeblock]
+ [/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 [Reference], references to an Object stored in a variable can become invalid without warning. Therefore, it's recommended to use [Reference] for data classes instead of [Object].
@@ -96,9 +105,16 @@
</argument>
<description>
Calls the [code]method[/code] on the object and returns the result. This method supports a variable number of arguments, so parameters are passed as a comma separated list. Example:
- [codeblock]
- call("set", "position", Vector2(42.0, 0.0))
- [/codeblock]
+ [codeblocks]
+ [gdscript]
+ var node = Node2D.new()
+ node.call("set", "position", Vector2(42, 0))
+ [/gdscript]
+ [csharp]
+ var node = new Node2D();
+ node.Call("set", "position", new Vector2(42, 0));
+ [/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).
</description>
</method>
@@ -109,9 +125,16 @@
</argument>
<description>
Calls the [code]method[/code] on the object during idle time. This method supports a variable number of arguments, so parameters are passed as a comma separated list. Example:
- [codeblock]
- call_deferred("set", "position", Vector2(42.0, 0.0))
- [/codeblock]
+ [codeblocks]
+ [gdscript]
+ var node = Node2D.new()
+ node.call_deferred("set", "position", Vector2(42, 0))
+ [/gdscript]
+ [csharp]
+ var node = new Node2D();
+ node.CallDeferred("set", "position", new Vector2(42, 0));
+ [/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).
</description>
</method>
@@ -124,9 +147,16 @@
</argument>
<description>
Calls the [code]method[/code] 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].
- [codeblock]
- callv("set", [ "position", Vector2(42.0, 0.0) ])
- [/codeblock]
+ [codeblocks]
+ [gdscript]
+ var node = Node2D.new()
+ node.callv("set", ["position", Vector2(42, 0)])
+ [/gdscript]
+ [csharp]
+ var node = new Node2D();
+ node.Callv("set", new Godot.Collections.Array { "position", new Vector2(42, 0) });
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="can_translate_messages" qualifiers="const">
@@ -148,23 +178,140 @@
<argument index="3" name="flags" type="int" default="0">
</argument>
<description>
- [b]FIXME:[/b] The syntax changed with the addition of [Callable], this should be updated.
- Connects a [code]signal[/code] to a [code]method[/code] on a [code]target[/code] object. Pass optional [code]binds[/code] to the call as an [Array] of parameters. These parameters will be passed to the method after any parameter used in the call to [method emit_signal]. Use [code]flags[/code] to set deferred or one-shot connections. See [enum ConnectFlags] constants.
- A [code]signal[/code] can only be connected once to a [code]method[/code]. It will throw 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 [code]target[/code] is destroyed in the game's lifecycle, the connection will be lost.
- Examples:
- [codeblock]
- connect("pressed", self, "_on_Button_pressed") # BaseButton signal
- connect("text_entered", self, "_on_LineEdit_text_entered") # LineEdit signal
- connect("hit", self, "_on_Player_hit", [ weapon_type, damage ]) # User-defined signal
- [/codeblock]
- An example of the relationship between [code]binds[/code] passed to [method connect] and parameters used when calling [method emit_signal]:
- [codeblock]
- connect("hit", self, "_on_Player_hit", [ weapon_type, damage ]) # weapon_type and damage are passed last
- emit_signal("hit", "Dark lord", 5) # "Dark lord" and 5 are passed first
- func _on_Player_hit(hit_by, level, weapon_type, damage):
- print("Hit by %s (lvl %d) with weapon %s for %d damage" % [hit_by, level, weapon_type, damage])
- [/codeblock]
+ Connects a [code]signal[/code] to a [code]callable[/code]. Pass optional [code]binds[/code] to the call as an [Array] of parameters. These parameters will be passed to the [Callable]'s method after any parameter used in the call to [method emit_signal]. Use [code]flags[/code] to set deferred or one-shot connections. See [enum ConnectFlags] constants.
+ [b]Note:[/b] This method is the legacy implementation for connecting signals. The recommended modern approach is to use [method Signal.connect] and to use [method Callable.bind] to add and validate parameter binds. Both syntaxes are shown below.
+ A signal can only be connected once to a [Callable]. It will throw an error if already connected, unless the signal was connected with [constant CONNECT_REFERENCE_COUNTED]. To avoid this, first, use [method is_connected] to check for existing connections.
+ If the callable's target is destroyed in the game's lifecycle, the connection will be lost.
+ [b]Examples with recommended syntax:[/b]
+ 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#.
+ [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.button_down.connect(_on_button_down)
+
+ # 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.
+ player.hit.connect(_on_player_hit.bind("sword", 100))
+
+ func _on_button_down():
+ print("Button down!")
+
+ func _on_player_hit(weapon_type, damage):
+ print("Hit with weapon %s for %d damage." % [weapon_type, damage])
+ [/gdscript]
+ [csharp]
+ public override void _Ready()
+ {
+ var button = new Button();
+ // 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.
+ 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 });
+ }
+
+ private void OnButtonDown()
+ {
+ GD.Print("Button down!");
+ }
+
+ private void OnPlayerHit(string weaponType, int damage)
+ {
+ GD.Print(String.Format("Hit with weapon {0} for {1} damage.", weaponType, damage));
+ }
+ [/csharp]
+ [/codeblocks]
+ [b][code]Object.connect()[/code] or [code]Signal.connect()[/code]?[/b]
+ As seen above, the recommended method to connect signals is not [method Object.connect]. The code block below shows the four options for connecting signals, using either this legacy method or the recommended [method Signal.connect], and using either an implicit [Callable] or a manually defined one.
+ [codeblocks]
+ [gdscript]
+ func _ready():
+ var button = Button.new()
+ # Option 1: Object.connect() with an implicit Callable for the defined function.
+ button.connect("button_down", _on_button_down)
+ # Option 2: Object.connect() with a constructed Callable using a target object and method name.
+ button.connect("button_down", Callable(self, "_on_button_down"))
+ # Option 3: Signal.connect() with an implicit Callable for the defined function.
+ button.button_down.connect(_on_button_down)
+ # Option 4: Signal.connect() with a constructed Callable using a target object and method name.
+ button.button_down.connect(Callable(self, "_on_button_down"))
+
+ func _on_button_down():
+ print("Button down!")
+ [/gdscript]
+ [csharp]
+ public override void _Ready()
+ {
+ var button = new Button();
+ // Option 1: Object.Connect() with an implicit Callable for the defined function.
+ button.Connect("button_down", OnButtonDown);
+ // Option 2: Object.connect() with a constructed Callable using a target object and method name.
+ button.Connect("button_down", new Callable(self, nameof(OnButtonDown)));
+ // Option 3: Signal.connect() with an implicit Callable for the defined function.
+ button.ButtonDown.Connect(OnButtonDown);
+ // Option 3b: In C#, we can use signals as events and connect with this more idiomatic syntax:
+ button.ButtonDown += OnButtonDown;
+ // Option 4: Signal.connect() with a constructed Callable using a target object and method name.
+ button.ButtonDown.Connect(new Callable(self, nameof(OnButtonDown)));
+ }
+
+ private void OnButtonDown()
+ {
+ GD.Print("Button down!");
+ }
+ [/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 throw 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 throw 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.
+ [codeblocks]
+ [gdscript]
+ func _ready():
+ # 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).
+ 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.
+ 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()).
+ 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).
+ 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));
+ }
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="disconnect">
@@ -175,8 +322,7 @@
<argument index="1" name="callable" type="Callable">
</argument>
<description>
- [b]FIXME:[/b] The syntax changed with the addition of [Callable], this should be updated.
- Disconnects a [code]signal[/code] from a [code]method[/code] on the given [code]target[/code].
+ Disconnects a [code]signal[/code] from a given [code]callable[/code].
If you try to disconnect a connection that does not exist, the method will throw an error. Use [method is_connected] to ensure that the connection exists.
</description>
</method>
@@ -187,10 +333,16 @@
</argument>
<description>
Emits the given [code]signal[/code]. 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. Example:
- [codeblock]
- emit_signal("hit", weapon_type, damage)
+ [codeblocks]
+ [gdscript]
+ emit_signal("hit", "sword", 100)
emit_signal("game_over")
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ EmitSignal("hit", "sword", 100);
+ EmitSignal("game_over");
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="free">
@@ -359,8 +511,7 @@
<argument index="1" name="callable" type="Callable">
</argument>
<description>
- [b]FIXME:[/b] The syntax changed with the addition of [Callable], this should be updated.
- Returns [code]true[/code] if a connection exists for a given [code]signal[/code], [code]target[/code], and [code]method[/code].
+ Returns [code]true[/code] if a connection exists for a given [code]signal[/code] and [code]callable[/code].
</description>
</method>
<method name="is_queued_for_deletion" qualifiers="const">
@@ -382,11 +533,11 @@
If [code]reversed[/code] is [code]true[/code], [method _notification] is called first on the object's own class, and then up to its successive parent classes. If [code]reversed[/code] is [code]false[/code], [method _notification] is called first on the highest ancestor ([Object] itself), and then down to its successive inheriting classes.
</description>
</method>
- <method name="property_list_changed_notify">
+ <method name="notify_property_list_changed">
<return type="void">
</return>
<description>
- Notify the editor that the property list has changed, so that editor plugins can take the new values into account. Does nothing on export builds.
+ 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.
</description>
</method>
<method name="remove_meta">
@@ -440,11 +591,20 @@
</argument>
<description>
Assigns a new value to the property identified by the [NodePath]. The node path should be relative to the current object and can use the colon character ([code]:[/code]) to access nested properties. Example:
- [codeblock]
- set_indexed("position", Vector2(42, 0))
- set_indexed("position:y", -10)
- print(position) # (42, -10)
- [/codeblock]
+ [codeblocks]
+ [gdscript]
+ var node = Node2D.new()
+ node.set_indexed("position", Vector2(42, 0))
+ node.set_indexed("position:y", -10)
+ print(node.position) # (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)
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="set_message_translation">
@@ -520,6 +680,10 @@
</method>
</methods>
<signals>
+ <signal name="property_list_changed">
+ <description>
+ </description>
+ </signal>
<signal name="script_changed">
<description>
Emitted whenever the object's script is changed.
diff --git a/doc/classes/PHashTranslation.xml b/doc/classes/OptimizedTranslation.xml
index 30194e9495..a5ca93c7ff 100644
--- a/doc/classes/PHashTranslation.xml
+++ b/doc/classes/OptimizedTranslation.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PHashTranslation" inherits="Translation" version="4.0">
+<class name="OptimizedTranslation" inherits="Translation" version="4.0">
<brief_description>
Optimized translation.
</brief_description>
diff --git a/doc/classes/OptionButton.xml b/doc/classes/OptionButton.xml
index 1a80962751..52da08c02f 100644
--- a/doc/classes/OptionButton.xml
+++ b/doc/classes/OptionButton.xml
@@ -259,6 +259,9 @@
<theme_item name="font_hover_color" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
Text [Color] used when the [OptionButton] is being hovered.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the [OptionButton].
+ </theme_item>
<theme_item name="font_pressed_color" type="Color" default="Color( 1, 1, 1, 1 )">
Text [Color] used when the [OptionButton] is being pressed.
</theme_item>
@@ -280,6 +283,9 @@
<theme_item name="normal_mirrored" type="StyleBox">
Default [StyleBox] for the [OptionButton] (for right-to-left layouts).
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
<theme_item name="pressed" type="StyleBox">
[StyleBox] used when the [OptionButton] is being pressed (for left-to-right layouts).
</theme_item>
diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml
index 75fb7c1465..3c7f0f4fad 100644
--- a/doc/classes/PackedByteArray.xml
+++ b/doc/classes/PackedByteArray.xml
@@ -52,7 +52,7 @@
Appends a [PackedByteArray] at the end of this array.
</description>
</method>
- <method name="compress">
+ <method name="compress" qualifiers="const">
<return type="PackedByteArray">
</return>
<argument index="0" name="compression_mode" type="int" default="0">
@@ -61,7 +61,7 @@
Returns a new [PackedByteArray] with the data compressed. Set the compression mode using one of [enum File.CompressionMode]'s constants.
</description>
</method>
- <method name="decompress">
+ <method name="decompress" qualifiers="const">
<return type="PackedByteArray">
</return>
<argument index="0" name="buffer_size" type="int">
@@ -72,7 +72,7 @@
Returns a new [PackedByteArray] with the data decompressed. Set [code]buffer_size[/code] to the size of the uncompressed data. Set the compression mode using one of [enum File.CompressionMode]'s constants.
</description>
</method>
- <method name="decompress_dynamic">
+ <method name="decompress_dynamic" qualifiers="const">
<return type="PackedByteArray">
</return>
<argument index="0" name="max_output_size" type="int">
@@ -81,7 +81,7 @@
</argument>
<description>
Returns a new [PackedByteArray] with the data decompressed. Set the compression mode using one of [enum File.CompressionMode]'s constants. [b]This method only accepts gzip and deflate compression modes.[/b]
- This method is potentially slower than [code]decompress[/code], as it may have to re-allocate it's output buffer multiple times while decompressing, where as [code]decompress[/code] knows it's output buffer size from the beginning.
+ This method is potentially slower than [code]decompress[/code], as it may have to re-allocate its output buffer multiple times while decompressing, whereas [code]decompress[/code] knows it's output buffer size from the beginning.
GZIP has a maximal compression ratio of 1032:1, meaning it's very possible for a small compressed payload to decompress to a potentially very large output. To guard against this, you may provide a maximum size this function is allowed to allocate in bytes via [code]max_output_size[/code]. Passing -1 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.
</description>
</method>
@@ -92,28 +92,28 @@
Creates a copy of the array, and returns it.
</description>
</method>
- <method name="get_string_from_ascii">
+ <method name="get_string_from_ascii" qualifiers="const">
<return type="String">
</return>
<description>
Converts ASCII/Latin-1 encoded array to [String]. Fast alternative to [method get_string_from_utf8] if the content is ASCII/Latin-1 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 use [method get_string_from_utf8].
</description>
</method>
- <method name="get_string_from_utf16">
+ <method name="get_string_from_utf16" qualifiers="const">
<return type="String">
</return>
<description>
Converts UTF-16 encoded array to [String]. If the BOM is missing, system endianness is assumed. Returns empty string if source array is not valid UTF-16 string.
</description>
</method>
- <method name="get_string_from_utf32">
+ <method name="get_string_from_utf32" qualifiers="const">
<return type="String">
</return>
<description>
Converts UTF-32 encoded array to [String]. System endianness is assumed. Returns empty string if source array is not valid UTF-32 string.
</description>
</method>
- <method name="get_string_from_utf8">
+ <method name="get_string_from_utf8" qualifiers="const">
<return type="String">
</return>
<description>
@@ -129,7 +129,7 @@
Returns [code]true[/code] if the array contains [code]value[/code].
</description>
</method>
- <method name="hex_encode">
+ <method name="hex_encode" qualifiers="const">
<return type="String">
</return>
<description>
@@ -164,7 +164,7 @@
Reverses the order of the elements in the array.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -241,7 +241,7 @@
Changes the byte at the given index.
</description>
</method>
- <method name="size">
+ <method name="size" qualifiers="const">
<return type="int">
</return>
<description>
@@ -255,7 +255,7 @@
Sorts the elements of the array in ascending order.
</description>
</method>
- <method name="subarray">
+ <method name="subarray" qualifiers="const">
<return type="PackedByteArray">
</return>
<argument index="0" name="from" type="int">
diff --git a/doc/classes/PackedColorArray.xml b/doc/classes/PackedColorArray.xml
index 48d5822f7c..abfedc84cc 100644
--- a/doc/classes/PackedColorArray.xml
+++ b/doc/classes/PackedColorArray.xml
@@ -86,7 +86,7 @@
Reverses the order of the elements in the array.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -163,7 +163,7 @@
Changes the [Color] at the given index.
</description>
</method>
- <method name="size">
+ <method name="size" qualifiers="const">
<return type="int">
</return>
<description>
@@ -177,7 +177,7 @@
Sorts the elements of the array in ascending order.
</description>
</method>
- <method name="subarray">
+ <method name="subarray" qualifiers="const">
<return type="PackedColorArray">
</return>
<argument index="0" name="from" type="int">
@@ -187,7 +187,7 @@
<description>
</description>
</method>
- <method name="to_byte_array">
+ <method name="to_byte_array" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml
index 6598828089..8918312dc7 100644
--- a/doc/classes/PackedFloat32Array.xml
+++ b/doc/classes/PackedFloat32Array.xml
@@ -87,7 +87,7 @@
Reverses the order of the elements in the array.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -156,7 +156,7 @@
Changes the float at the given index.
</description>
</method>
- <method name="size">
+ <method name="size" qualifiers="const">
<return type="int">
</return>
<description>
@@ -170,7 +170,7 @@
Sorts the elements of the array in ascending order.
</description>
</method>
- <method name="subarray">
+ <method name="subarray" qualifiers="const">
<return type="PackedFloat32Array">
</return>
<argument index="0" name="from" type="int">
@@ -180,7 +180,7 @@
<description>
</description>
</method>
- <method name="to_byte_array">
+ <method name="to_byte_array" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml
index d116c6756b..fbb832299e 100644
--- a/doc/classes/PackedFloat64Array.xml
+++ b/doc/classes/PackedFloat64Array.xml
@@ -87,7 +87,7 @@
Reverses the order of the elements in the array.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -164,7 +164,7 @@
Changes the float at the given index.
</description>
</method>
- <method name="size">
+ <method name="size" qualifiers="const">
<return type="int">
</return>
<description>
@@ -178,7 +178,7 @@
Sorts the elements of the array in ascending order.
</description>
</method>
- <method name="subarray">
+ <method name="subarray" qualifiers="const">
<return type="PackedFloat64Array">
</return>
<argument index="0" name="from" type="int">
@@ -188,7 +188,7 @@
<description>
</description>
</method>
- <method name="to_byte_array">
+ <method name="to_byte_array" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml
index 2ac7a67b4b..ecef2d508b 100644
--- a/doc/classes/PackedInt32Array.xml
+++ b/doc/classes/PackedInt32Array.xml
@@ -87,7 +87,7 @@
Reverses the order of the elements in the array.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -164,7 +164,7 @@
Changes the integer at the given index.
</description>
</method>
- <method name="size">
+ <method name="size" qualifiers="const">
<return type="int">
</return>
<description>
@@ -178,7 +178,7 @@
Sorts the elements of the array in ascending order.
</description>
</method>
- <method name="subarray">
+ <method name="subarray" qualifiers="const">
<return type="PackedInt32Array">
</return>
<argument index="0" name="from" type="int">
@@ -188,7 +188,7 @@
<description>
</description>
</method>
- <method name="to_byte_array">
+ <method name="to_byte_array" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml
index a7b6bf0a0f..19619d60cf 100644
--- a/doc/classes/PackedInt64Array.xml
+++ b/doc/classes/PackedInt64Array.xml
@@ -87,7 +87,7 @@
Reverses the order of the elements in the array.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -164,7 +164,7 @@
Changes the integer at the given index.
</description>
</method>
- <method name="size">
+ <method name="size" qualifiers="const">
<return type="int">
</return>
<description>
@@ -178,7 +178,7 @@
Sorts the elements of the array in ascending order.
</description>
</method>
- <method name="subarray">
+ <method name="subarray" qualifiers="const">
<return type="PackedInt64Array">
</return>
<argument index="0" name="from" type="int">
@@ -188,7 +188,7 @@
<description>
</description>
</method>
- <method name="to_byte_array">
+ <method name="to_byte_array" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml
index d15bcfd114..1d9be7f165 100644
--- a/doc/classes/PackedScene.xml
+++ b/doc/classes/PackedScene.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
A simplified interface to a scene file. Provides access to operations and checks that can be performed on the scene resource itself.
- Can be used to save a node to a file. When saving, the node as well as all the node it owns get saved (see [code]owner[/code] property on [Node]).
+ Can be used to save a node to a file. When saving, the node as well as all the nodes it owns get saved (see [code]owner[/code] property on [Node]).
[b]Note:[/b] The node doesn't need to own itself.
[b]Example of loading a saved scene:[/b]
[codeblocks]
diff --git a/doc/classes/PackedStringArray.xml b/doc/classes/PackedStringArray.xml
index fb7ed2a906..c241573b93 100644
--- a/doc/classes/PackedStringArray.xml
+++ b/doc/classes/PackedStringArray.xml
@@ -87,7 +87,7 @@
Reverses the order of the elements in the array.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -164,7 +164,7 @@
Changes the [String] at the given index.
</description>
</method>
- <method name="size">
+ <method name="size" qualifiers="const">
<return type="int">
</return>
<description>
@@ -178,7 +178,7 @@
Sorts the elements of the array in ascending order.
</description>
</method>
- <method name="subarray">
+ <method name="subarray" qualifiers="const">
<return type="PackedStringArray">
</return>
<argument index="0" name="from" type="int">
@@ -188,7 +188,7 @@
<description>
</description>
</method>
- <method name="to_byte_array">
+ <method name="to_byte_array" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml
index eb364ddb18..9138dc68e1 100644
--- a/doc/classes/PackedVector2Array.xml
+++ b/doc/classes/PackedVector2Array.xml
@@ -87,7 +87,7 @@
Reverses the order of the elements in the array.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -172,7 +172,7 @@
Changes the [Vector2] at the given index.
</description>
</method>
- <method name="size">
+ <method name="size" qualifiers="const">
<return type="int">
</return>
<description>
@@ -186,7 +186,7 @@
Sorts the elements of the array in ascending order.
</description>
</method>
- <method name="subarray">
+ <method name="subarray" qualifiers="const">
<return type="PackedVector2Array">
</return>
<argument index="0" name="from" type="int">
@@ -196,7 +196,7 @@
<description>
</description>
</method>
- <method name="to_byte_array">
+ <method name="to_byte_array" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml
index 08ce187b5c..0a3b0cf2c0 100644
--- a/doc/classes/PackedVector3Array.xml
+++ b/doc/classes/PackedVector3Array.xml
@@ -86,7 +86,7 @@
Reverses the order of the elements in the array.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -171,7 +171,7 @@
Changes the [Vector3] at the given index.
</description>
</method>
- <method name="size">
+ <method name="size" qualifiers="const">
<return type="int">
</return>
<description>
@@ -185,7 +185,7 @@
Sorts the elements of the array in ascending order.
</description>
</method>
- <method name="subarray">
+ <method name="subarray" qualifiers="const">
<return type="PackedVector3Array">
</return>
<argument index="0" name="from" type="int">
@@ -195,7 +195,7 @@
<description>
</description>
</method>
- <method name="to_byte_array">
+ <method name="to_byte_array" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
diff --git a/doc/classes/PhysicalBone3D.xml b/doc/classes/PhysicalBone3D.xml
index dcf24c1d32..38d9f722b1 100644
--- a/doc/classes/PhysicalBone3D.xml
+++ b/doc/classes/PhysicalBone3D.xml
@@ -91,7 +91,7 @@
The body's bounciness. Values range from [code]0[/code] (no bounce) to [code]1[/code] (full bounciness).
</member>
<member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep" default="true">
- If [code]true[/code], the body is deactivated when there is no movement, so it will not take part in the simulation until it is awaken by an external force.
+ If [code]true[/code], the body is deactivated when there is no movement, so it will not take part in the simulation until it is awakened by an external force.
</member>
<member name="friction" type="float" setter="set_friction" getter="get_friction" default="1.0">
The body's friction, from [code]0[/code] (frictionless) to [code]1[/code] (max friction).
diff --git a/doc/classes/PhysicalSkyMaterial.xml b/doc/classes/PhysicalSkyMaterial.xml
index 2e0f9c52f2..381371b973 100644
--- a/doc/classes/PhysicalSkyMaterial.xml
+++ b/doc/classes/PhysicalSkyMaterial.xml
@@ -23,22 +23,22 @@
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 whiteish color around the sun and horizon.
+ 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.
</member>
<member name="mie_color" type="Color" setter="set_mie_color" getter="get_mie_color" default="Color( 0.36, 0.56, 0.82, 1 )">
Controls the [Color] of the mie scattering 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 passing through straight forward. A value of [code]-1[/code] means that all light is scatter backwards.
+ 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.
</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 Rayleigh scattering. 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.056, 0.14, 0.3, 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 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.
</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/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml
index 6a1508b0e3..701a430538 100644
--- a/doc/classes/PhysicsServer2D.xml
+++ b/doc/classes/PhysicsServer2D.xml
@@ -58,7 +58,7 @@
<return type="RID">
</return>
<description>
- Creates an [Area2D].
+ Creates an [Area2D]. After creating an [Area2D] with this method, assign it to a space using [method area_set_space] to use the created [Area2D] in the physics world.
</description>
</method>
<method name="area_get_canvas_instance_id" qualifiers="const">
@@ -850,21 +850,6 @@
<description>
</description>
</method>
- <method name="damped_spring_joint_create">
- <return type="RID">
- </return>
- <argument index="0" name="anchor_a" type="Vector2">
- </argument>
- <argument index="1" name="anchor_b" type="Vector2">
- </argument>
- <argument index="2" name="body_a" type="RID">
- </argument>
- <argument index="3" name="body_b" type="RID">
- </argument>
- <description>
- Creates a damped spring joint between two bodies. If not specified, the second body is assumed to be the joint itself.
- </description>
- </method>
<method name="damped_spring_joint_get_param" qualifiers="const">
<return type="float">
</return>
@@ -907,21 +892,18 @@
Returns information about the current state of the 2D physics engine. See [enum ProcessInfo] for a list of available states.
</description>
</method>
- <method name="groove_joint_create">
- <return type="RID">
+ <method name="joint_clear">
+ <return type="void">
</return>
- <argument index="0" name="groove1_a" type="Vector2">
- </argument>
- <argument index="1" name="groove2_a" type="Vector2">
- </argument>
- <argument index="2" name="anchor_b" type="Vector2">
- </argument>
- <argument index="3" name="body_a" type="RID">
- </argument>
- <argument index="4" name="body_b" type="RID">
+ <argument index="0" name="joint" type="RID">
</argument>
<description>
- Creates a groove joint between two bodies. If not specified, the bodies are assumed to be the joint itself.
+ </description>
+ </method>
+ <method name="joint_create">
+ <return type="RID">
+ </return>
+ <description>
</description>
</method>
<method name="joint_get_param" qualifiers="const">
@@ -944,36 +926,71 @@
Returns a joint's type (see [enum JointType]).
</description>
</method>
- <method name="joint_set_param">
+ <method name="joint_make_damped_spring">
<return type="void">
</return>
<argument index="0" name="joint" type="RID">
</argument>
- <argument index="1" name="param" type="int" enum="PhysicsServer2D.JointParam">
+ <argument index="1" name="anchor_a" type="Vector2">
</argument>
- <argument index="2" name="value" type="float">
+ <argument index="2" name="anchor_b" type="Vector2">
+ </argument>
+ <argument index="3" name="body_a" type="RID">
+ </argument>
+ <argument index="4" name="body_b" type="RID">
</argument>
<description>
- Sets a joint parameter. See [enum JointParam] for a list of available parameters.
</description>
</method>
- <method name="line_shape_create">
- <return type="RID">
+ <method name="joint_make_groove">
+ <return type="void">
</return>
+ <argument index="0" name="joint" type="RID">
+ </argument>
+ <argument index="1" name="groove1_a" type="Vector2">
+ </argument>
+ <argument index="2" name="groove2_a" type="Vector2">
+ </argument>
+ <argument index="3" name="anchor_b" type="Vector2">
+ </argument>
+ <argument index="4" name="body_a" type="RID">
+ </argument>
+ <argument index="5" name="body_b" type="RID">
+ </argument>
<description>
</description>
</method>
- <method name="pin_joint_create">
- <return type="RID">
+ <method name="joint_make_pin">
+ <return type="void">
</return>
- <argument index="0" name="anchor" type="Vector2">
+ <argument index="0" name="joint" type="RID">
</argument>
- <argument index="1" name="body_a" type="RID">
+ <argument index="1" name="anchor" type="Vector2">
</argument>
- <argument index="2" name="body_b" type="RID">
+ <argument index="2" name="body_a" type="RID">
+ </argument>
+ <argument index="3" name="body_b" type="RID">
</argument>
<description>
- Creates a pin joint between two bodies. If not specified, the second body is assumed to be the joint itself.
+ </description>
+ </method>
+ <method name="joint_set_param">
+ <return type="void">
+ </return>
+ <argument index="0" name="joint" type="RID">
+ </argument>
+ <argument index="1" name="param" type="int" enum="PhysicsServer2D.JointParam">
+ </argument>
+ <argument index="2" name="value" type="float">
+ </argument>
+ <description>
+ Sets a joint parameter. See [enum JointParam] for a list of available parameters.
+ </description>
+ </method>
+ <method name="line_shape_create">
+ <return type="RID">
+ </return>
+ <description>
</description>
</method>
<method name="ray_shape_create">
@@ -1233,15 +1250,18 @@
<constant name="BODY_STATE_CAN_SLEEP" value="4" enum="BodyState">
Constant to set/get whether the body can sleep.
</constant>
- <constant name="JOINT_PIN" value="0" enum="JointType">
+ <constant name="JOINT_TYPE_PIN" value="0" enum="JointType">
Constant to create pin joints.
</constant>
- <constant name="JOINT_GROOVE" value="1" enum="JointType">
+ <constant name="JOINT_TYPE_GROOVE" value="1" enum="JointType">
Constant to create groove joints.
</constant>
- <constant name="JOINT_DAMPED_SPRING" value="2" enum="JointType">
+ <constant name="JOINT_TYPE_DAMPED_SPRING" value="2" enum="JointType">
Constant to create damped spring joints.
</constant>
+ <constant name="JOINT_TYPE_MAX" value="3" enum="JointType">
+ Represents the size of the [enum JointType] enum.
+ </constant>
<constant name="JOINT_PARAM_BIAS" value="0" enum="JointParam">
</constant>
<constant name="JOINT_PARAM_MAX_BIAS" value="1" enum="JointParam">
diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml
index 5fd3ef5db2..9a7926e937 100644
--- a/doc/classes/PhysicsServer3D.xml
+++ b/doc/classes/PhysicsServer3D.xml
@@ -129,15 +129,6 @@
Returns the transform matrix for an area.
</description>
</method>
- <method name="area_is_ray_pickable" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- If [code]true[/code], area collides with rays.
- </description>
- </method>
<method name="area_remove_shape">
<return type="void">
</return>
@@ -421,12 +412,7 @@
<method name="body_create">
<return type="RID">
</return>
- <argument index="0" name="mode" type="int" enum="PhysicsServer3D.BodyMode" default="2">
- </argument>
- <argument index="1" name="init_sleeping" type="bool" default="false">
- </argument>
<description>
- Creates a physics body. The first parameter can be any value from [enum BodyMode] constants, for the type of body created. Additionally, the body can be created in sleeping state to save processing time.
</description>
</method>
<method name="body_get_collision_layer" qualifiers="const">
@@ -582,15 +568,6 @@
Returns whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]).
</description>
</method>
- <method name="body_is_ray_pickable" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- If [code]true[/code], the body can be detected by rays.
- </description>
- </method>
<method name="body_remove_collision_exception">
<return type="void">
</return>
@@ -815,6 +792,24 @@
Sets a body state (see [enum BodyState] constants).
</description>
</method>
+ <method name="box_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="capsule_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="concave_polygon_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="cone_twist_joint_get_param" qualifiers="const">
<return type="float">
</return>
@@ -839,6 +834,24 @@
Sets a cone_twist_joint parameter (see [enum ConeTwistJointParam] constants).
</description>
</method>
+ <method name="convex_polygon_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="custom_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="cylinder_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="free_rid">
<return type="void">
</return>
@@ -848,7 +861,7 @@
Destroys any of the objects created by PhysicsServer3D. If the [RID] passed is not one of the objects that can be created by PhysicsServer3D, an error will be sent to the console.
</description>
</method>
- <method name="generic_6dof_joint_get_flag">
+ <method name="generic_6dof_joint_get_flag" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="joint" type="RID">
@@ -861,7 +874,7 @@
Gets a generic_6_DOF_joint flag (see [enum G6DOFJointAxisFlag] constants).
</description>
</method>
- <method name="generic_6dof_joint_get_param">
+ <method name="generic_6dof_joint_get_param" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="joint" type="RID">
@@ -913,6 +926,12 @@
Returns an Info defined by the [enum ProcessInfo] input given.
</description>
</method>
+ <method name="heightmap_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="hinge_joint_get_flag" qualifiers="const">
<return type="bool">
</return>
@@ -961,97 +980,116 @@
Sets a hinge_joint parameter (see [enum HingeJointParam] constants).
</description>
</method>
- <method name="joint_create_cone_twist">
- <return type="RID">
+ <method name="joint_clear">
+ <return type="void">
</return>
- <argument index="0" name="body_A" type="RID">
- </argument>
- <argument index="1" name="local_ref_A" type="Transform">
- </argument>
- <argument index="2" name="body_B" type="RID">
- </argument>
- <argument index="3" name="local_ref_B" type="Transform">
+ <argument index="0" name="joint" type="RID">
</argument>
<description>
- Creates a [ConeTwistJoint3D].
</description>
</method>
- <method name="joint_create_generic_6dof">
+ <method name="joint_create">
<return type="RID">
</return>
- <argument index="0" name="body_A" type="RID">
- </argument>
- <argument index="1" name="local_ref_A" type="Transform">
- </argument>
- <argument index="2" name="body_B" type="RID">
+ <description>
+ </description>
+ </method>
+ <method name="joint_get_solver_priority" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="joint" type="RID">
</argument>
- <argument index="3" name="local_ref_B" type="Transform">
+ <description>
+ Gets the priority value of the Joint3D.
+ </description>
+ </method>
+ <method name="joint_get_type" qualifiers="const">
+ <return type="int" enum="PhysicsServer3D.JointType">
+ </return>
+ <argument index="0" name="joint" type="RID">
</argument>
<description>
- Creates a [Generic6DOFJoint3D].
+ Returns the type of the Joint3D.
</description>
</method>
- <method name="joint_create_hinge">
- <return type="RID">
+ <method name="joint_make_cone_twist">
+ <return type="void">
</return>
- <argument index="0" name="body_A" type="RID">
+ <argument index="0" name="joint" type="RID">
</argument>
- <argument index="1" name="hinge_A" type="Transform">
+ <argument index="1" name="body_A" type="RID">
</argument>
- <argument index="2" name="body_B" type="RID">
+ <argument index="2" name="local_ref_A" type="Transform">
</argument>
- <argument index="3" name="hinge_B" type="Transform">
+ <argument index="3" name="body_B" type="RID">
+ </argument>
+ <argument index="4" name="local_ref_B" type="Transform">
</argument>
<description>
- Creates a [HingeJoint3D].
</description>
</method>
- <method name="joint_create_pin">
- <return type="RID">
+ <method name="joint_make_generic_6dof">
+ <return type="void">
</return>
- <argument index="0" name="body_A" type="RID">
+ <argument index="0" name="joint" type="RID">
</argument>
- <argument index="1" name="local_A" type="Vector3">
+ <argument index="1" name="body_A" type="RID">
+ </argument>
+ <argument index="2" name="local_ref_A" type="Transform">
</argument>
- <argument index="2" name="body_B" type="RID">
+ <argument index="3" name="body_B" type="RID">
</argument>
- <argument index="3" name="local_B" type="Vector3">
+ <argument index="4" name="local_ref_B" type="Transform">
</argument>
<description>
- Creates a [PinJoint3D].
</description>
</method>
- <method name="joint_create_slider">
- <return type="RID">
+ <method name="joint_make_hinge">
+ <return type="void">
</return>
- <argument index="0" name="body_A" type="RID">
+ <argument index="0" name="joint" type="RID">
+ </argument>
+ <argument index="1" name="body_A" type="RID">
</argument>
- <argument index="1" name="local_ref_A" type="Transform">
+ <argument index="2" name="hinge_A" type="Transform">
</argument>
- <argument index="2" name="body_B" type="RID">
+ <argument index="3" name="body_B" type="RID">
</argument>
- <argument index="3" name="local_ref_B" type="Transform">
+ <argument index="4" name="hinge_B" type="Transform">
</argument>
<description>
- Creates a [SliderJoint3D].
</description>
</method>
- <method name="joint_get_solver_priority" qualifiers="const">
- <return type="int">
+ <method name="joint_make_pin">
+ <return type="void">
</return>
<argument index="0" name="joint" type="RID">
</argument>
+ <argument index="1" name="body_A" type="RID">
+ </argument>
+ <argument index="2" name="local_A" type="Vector3">
+ </argument>
+ <argument index="3" name="body_B" type="RID">
+ </argument>
+ <argument index="4" name="local_B" type="Vector3">
+ </argument>
<description>
- Gets the priority value of the Joint3D.
</description>
</method>
- <method name="joint_get_type" qualifiers="const">
- <return type="int" enum="PhysicsServer3D.JointType">
+ <method name="joint_make_slider">
+ <return type="void">
</return>
<argument index="0" name="joint" type="RID">
</argument>
+ <argument index="1" name="body_A" type="RID">
+ </argument>
+ <argument index="2" name="local_ref_A" type="Transform">
+ </argument>
+ <argument index="3" name="body_B" type="RID">
+ </argument>
+ <argument index="4" name="local_ref_B" type="Transform">
+ </argument>
<description>
- Returns the type of the Joint3D.
</description>
</method>
<method name="joint_set_solver_priority">
@@ -1129,22 +1167,25 @@
Sets a pin_joint parameter (see [enum PinJointParam] constants).
</description>
</method>
- <method name="set_active">
- <return type="void">
+ <method name="plane_shape_create">
+ <return type="RID">
</return>
- <argument index="0" name="active" type="bool">
- </argument>
<description>
- Activates or deactivates the 3D physics engine.
</description>
</method>
- <method name="shape_create">
+ <method name="ray_shape_create">
<return type="RID">
</return>
- <argument index="0" name="type" type="int" enum="PhysicsServer3D.ShapeType">
+ <description>
+ </description>
+ </method>
+ <method name="set_active">
+ <return type="void">
+ </return>
+ <argument index="0" name="active" type="bool">
</argument>
<description>
- Creates a shape of a type from [enum ShapeType]. Does not assign it to a body or an area. To do so, you must use [method area_set_shape] or [method body_set_shape].
+ Activates or deactivates the 3D physics engine.
</description>
</method>
<method name="shape_get_data" qualifiers="const">
@@ -1260,23 +1301,32 @@
Sets the value for a space parameter. A list of available parameters is on the [enum SpaceParameter] constants.
</description>
</method>
+ <method name="sphere_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
- <constant name="JOINT_PIN" value="0" enum="JointType">
+ <constant name="JOINT_TYPE_PIN" value="0" enum="JointType">
The [Joint3D] is a [PinJoint3D].
</constant>
- <constant name="JOINT_HINGE" value="1" enum="JointType">
+ <constant name="JOINT_TYPE_HINGE" value="1" enum="JointType">
The [Joint3D] is a [HingeJoint3D].
</constant>
- <constant name="JOINT_SLIDER" value="2" enum="JointType">
+ <constant name="JOINT_TYPE_SLIDER" value="2" enum="JointType">
The [Joint3D] is a [SliderJoint3D].
</constant>
- <constant name="JOINT_CONE_TWIST" value="3" enum="JointType">
+ <constant name="JOINT_TYPE_CONE_TWIST" value="3" enum="JointType">
The [Joint3D] is a [ConeTwistJoint3D].
</constant>
- <constant name="JOINT_6DOF" value="4" enum="JointType">
+ <constant name="JOINT_TYPE_6DOF" value="4" enum="JointType">
The [Joint3D] is a [Generic6DOFJoint3D].
</constant>
+ <constant name="JOINT_TYPE_MAX" value="5" enum="JointType">
+ Represents the size of the [enum JointType] enum.
+ </constant>
<constant name="PIN_JOINT_BIAS" value="0" enum="PinJointParam">
The strength with which the pinned objects try to stay in positional relation to each other.
The higher, the stronger.
diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml
index ed96f753c2..2342f00631 100644
--- a/doc/classes/Plane.xml
+++ b/doc/classes/Plane.xml
@@ -76,14 +76,14 @@
Creates a plane from the three points, given in clockwise order.
</description>
</method>
- <method name="center">
+ <method name="center" qualifiers="const">
<return type="Vector3">
</return>
<description>
Returns the center of the plane.
</description>
</method>
- <method name="distance_to">
+ <method name="distance_to" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="point" type="Vector3">
@@ -92,7 +92,7 @@
Returns the shortest distance from the plane to the position [code]point[/code].
</description>
</method>
- <method name="has_point">
+ <method name="has_point" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="point" type="Vector3">
@@ -103,7 +103,7 @@
Returns [code]true[/code] if [code]point[/code] is inside the plane. Comparison uses a custom minimum [code]epsilon[/code] threshold.
</description>
</method>
- <method name="intersect_3">
+ <method name="intersect_3" qualifiers="const">
<return type="Variant">
</return>
<argument index="0" name="b" type="Plane">
@@ -114,7 +114,7 @@
Returns the intersection point of the three planes [code]b[/code], [code]c[/code] and this plane. If no intersection is found, [code]null[/code] is returned.
</description>
</method>
- <method name="intersects_ray">
+ <method name="intersects_ray" qualifiers="const">
<return type="Variant">
</return>
<argument index="0" name="from" type="Vector3">
@@ -125,7 +125,7 @@
Returns the intersection point of a ray consisting of the position [code]from[/code] and the direction normal [code]dir[/code] with this plane. If no intersection is found, [code]null[/code] is returned.
</description>
</method>
- <method name="intersects_segment">
+ <method name="intersects_segment" qualifiers="const">
<return type="Variant">
</return>
<argument index="0" name="from" type="Vector3">
@@ -136,7 +136,7 @@
Returns the intersection point of a segment from position [code]begin[/code] to position [code]end[/code] with this plane. If no intersection is found, [code]null[/code] is returned.
</description>
</method>
- <method name="is_equal_approx">
+ <method name="is_equal_approx" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="to_plane" type="Plane">
@@ -145,7 +145,7 @@
Returns [code]true[/code] if this plane and [code]plane[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component.
</description>
</method>
- <method name="is_point_over">
+ <method name="is_point_over" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="plane" type="Vector3">
@@ -154,7 +154,7 @@
Returns [code]true[/code] if [code]point[/code] is located above the plane.
</description>
</method>
- <method name="normalized">
+ <method name="normalized" qualifiers="const">
<return type="Plane">
</return>
<description>
@@ -189,7 +189,7 @@
<description>
</description>
</method>
- <method name="project">
+ <method name="project" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="point" type="Vector3">
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 47e8e57a4e..418785222e 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -565,7 +565,7 @@
<argument index="1" name="state" type="int">
</argument>
<description>
- Sets the state of an multistate item. See [method add_multistate_item] for details.
+ Sets the state of a multistate item. See [method add_multistate_item] for details.
</description>
</method>
<method name="set_item_opentype_feature">
@@ -664,13 +664,13 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Cycle to the next state of an multistate item. See [method add_multistate_item] for details.
+ Cycle to the next state of a multistate item. See [method add_multistate_item] for details.
</description>
</method>
</methods>
<members>
<member name="allow_search" type="bool" setter="set_allow_search" getter="get_allow_search" default="true">
- If [code]true[/code], allows to navigate [PopupMenu] with letter keys.
+ If [code]true[/code], allows navigating [PopupMenu] with letter keys.
</member>
<member name="hide_on_checkable_item_selection" type="bool" setter="set_hide_on_checkable_item_selection" getter="is_hide_on_checkable_item_selection" default="true">
If [code]true[/code], hides the [PopupMenu] when a checkbox or radio button is selected.
@@ -729,6 +729,9 @@
<theme_item name="font_hover_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
[Color] used for the hovered text.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the menu item.
+ </theme_item>
<theme_item name="font_separator_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
[Color] used for labeled separators' text. See [method add_separator].
</theme_item>
@@ -741,12 +744,19 @@
<theme_item name="hseparation" type="int" default="4">
The horizontal space between the item's name and the shortcut text/submenu arrow.
</theme_item>
+ <theme_item name="item_end_padding" type="int" default="2">
+ </theme_item>
+ <theme_item name="item_start_padding" type="int" default="2">
+ </theme_item>
<theme_item name="labeled_separator_left" type="StyleBox">
[StyleBox] for the left side of labeled separator. See [method add_separator].
</theme_item>
<theme_item name="labeled_separator_right" type="StyleBox">
[StyleBox] for the right side of labeled separator. See [method add_separator].
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the item text outline.
+ </theme_item>
<theme_item name="panel" type="StyleBox">
Default [StyleBox] of the [PopupMenu] items.
</theme_item>
diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml
index 25943f6d47..8b73bcb9c1 100644
--- a/doc/classes/PrimitiveMesh.xml
+++ b/doc/classes/PrimitiveMesh.xml
@@ -31,7 +31,7 @@
</methods>
<members>
<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 unnexpected culling when using a shader to offset vertices.
+ 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>
<member name="flip_faces" type="bool" setter="set_flip_faces" getter="get_flip_faces" default="false">
If set, the order of the vertices in each triangle are reversed resulting in the backside of the mesh being drawn.
diff --git a/doc/classes/ProgressBar.xml b/doc/classes/ProgressBar.xml
index bb7fd31ee8..160b61c720 100644
--- a/doc/classes/ProgressBar.xml
+++ b/doc/classes/ProgressBar.xml
@@ -32,11 +32,17 @@
<theme_item name="font_color" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
The color of the text.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the [ProgressBar].
+ </theme_item>
<theme_item name="font_shadow_color" type="Color" default="Color( 0, 0, 0, 1 )">
The color of the text's shadow.
</theme_item>
<theme_item name="font_size" type="int">
Font size used to draw the fill percentage if [member percent_visible] is [code]true[/code].
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
</theme_items>
</class>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index fc618206ed..5b9150ab04 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -169,6 +169,7 @@
</return>
<description>
Saves the configuration to the [code]project.godot[/code] file.
+ [b]Note:[/b] This method is intended to be used by editor plugins, as modified [ProjectSettings] can't be loaded back in the running app. If you want to change project settings in exported projects, use [method save_custom] to save [code]override.cfg[/code] file.
</description>
</method>
<method name="save_custom">
@@ -177,7 +178,7 @@
<argument index="0" name="file" type="String">
</argument>
<description>
- Saves the configuration to a custom file. The file extension must be [code].godot[/code] (to save in text-based [ConfigFile] format) or [code].binary[/code] (to save in binary format).
+ Saves the configuration to a custom file. The file extension must be [code].godot[/code] (to save in text-based [ConfigFile] format) or [code].binary[/code] (to save in binary format). You can also save [code]override.cfg[/code] file, which is also text, but can be used in exported projects unlike other formats.
</description>
</method>
<method name="set_initial_value">
@@ -273,9 +274,11 @@
If [code]true[/code], flushes the standard output stream every time a line is printed. This affects both terminal logging and file logging.
When running a project, this setting must be enabled if you want logs to be collected by service managers such as systemd/journalctl. This setting is disabled by default on release builds, since flushing on every printed line will negatively affect performance if lots of lines are printed in a rapid succession. Also, if this setting is enabled, logged files will still be written successfully if the application crashes or is otherwise killed by the user (without being closed "normally").
[b]Note:[/b] Regardless of this setting, the standard error stream ([code]stderr[/code]) is always flushed when a line is printed to it.
+ Changes to this setting will only be applied upon restarting the application.
</member>
<member name="application/run/flush_stdout_on_print.debug" type="bool" setter="" getter="" default="true">
Debug build override for [member application/run/flush_stdout_on_print], as performance is less important during debugging.
+ Changes to this setting will only be applied upon restarting the application.
</member>
<member name="application/run/frame_delay_msec" type="int" setter="" getter="" default="0">
Forces a delay between frames in the main loop (in milliseconds). This may be useful if you plan to disable vertical synchronization.
@@ -289,31 +292,31 @@
<member name="application/run/main_scene" type="String" setter="" getter="" default="&quot;&quot;">
Path to the main scene file that will be loaded when the project runs.
</member>
- <member name="audio/channel_disable_threshold_db" type="float" setter="" getter="" default="-60.0">
+ <member name="audio/buses/channel_disable_threshold_db" type="float" setter="" getter="" default="-60.0">
Audio buses will disable automatically when sound goes below a given dB threshold for a given time. This saves CPU as effects assigned to that bus will no longer do any processing.
</member>
- <member name="audio/channel_disable_time" type="float" setter="" getter="" default="2.0">
+ <member name="audio/buses/channel_disable_time" type="float" setter="" getter="" default="2.0">
Audio buses will disable automatically when sound goes below a given dB threshold for a given time. This saves CPU as effects assigned to that bus will no longer do any processing.
</member>
- <member name="audio/default_bus_layout" type="String" setter="" getter="" default="&quot;res://default_bus_layout.tres&quot;">
+ <member name="audio/buses/default_bus_layout" type="String" setter="" getter="" default="&quot;res://default_bus_layout.tres&quot;">
Default [AudioBusLayout] resource file to use in the project, unless overridden by the scene.
</member>
- <member name="audio/driver" type="String" setter="" getter="">
+ <member name="audio/driver/driver" type="String" setter="" getter="">
Specifies the audio driver to use. This setting is platform-dependent as each platform supports different audio drivers. If left empty, the default audio driver will be used.
</member>
- <member name="audio/enable_audio_input" type="bool" setter="" getter="" default="false">
+ <member name="audio/driver/enable_input" type="bool" setter="" getter="" default="false">
If [code]true[/code], microphone input will be allowed. This requires appropriate permissions to be set when exporting to Android or iOS.
</member>
- <member name="audio/mix_rate" type="int" setter="" getter="" default="44100">
+ <member name="audio/driver/mix_rate" type="int" setter="" getter="" default="44100">
Mixing rate used for audio. In general, it's better to not touch this and leave it to the host operating system.
</member>
- <member name="audio/output_latency" type="int" setter="" getter="" default="15">
+ <member name="audio/driver/output_latency" type="int" setter="" getter="" default="15">
Output latency in milliseconds for audio. Lower values will result in lower audio latency at the cost of increased CPU usage. Low values may result in audible cracking on slower hardware.
</member>
- <member name="audio/output_latency.web" type="int" setter="" getter="" default="50">
- Safer override for [member audio/output_latency] in the Web platform, to avoid audio issues especially on mobile devices.
+ <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/video_delay_compensation_ms" type="int" setter="" getter="" default="0">
+ <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.
</member>
<member name="compression/formats/gzip/compression_level" type="int" setter="" getter="" default="-1">
@@ -331,6 +334,18 @@
<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/file_logging/enable_file_logging" type="bool" setter="" getter="" default="false">
+ If [code]true[/code], logs all output to files.
+ </member>
+ <member name="debug/file_logging/enable_file_logging.pc" type="bool" setter="" getter="" default="true">
+ Desktop override for [member debug/file_logging/enable_file_logging], as log files are not readily accessible on mobile/Web platforms.
+ </member>
+ <member name="debug/file_logging/log_path" type="String" setter="" getter="" default="&quot;user://logs/godot.log&quot;">
+ Path to logs within the project. Using an [code]user://[/code] path is recommended.
+ </member>
+ <member name="debug/file_logging/max_log_files" type="int" setter="" getter="" default="5">
+ Specifies the maximum amount of log files allowed (used for rotation).
+ </member>
<member name="debug/gdscript/completion/autocomplete_setters_and_getters" type="bool" setter="" getter="" default="false">
If [code]true[/code], displays getters and setters in autocompletion results in the script editor. This setting is meant to be used when porting old projects (Godot 2), as using member variables is the preferred style from Godot 3 onwards.
</member>
@@ -428,7 +443,7 @@
<member name="debug/settings/fps/force_fps" type="int" setter="" getter="" default="0">
Maximum number of frames per second allowed. The actual number of frames per second may still be below this value if the game is lagging.
If [member display/window/vsync/use_vsync] is enabled, it takes precedence and the forced FPS number cannot exceed the monitor's refresh rate.
- This setting is therefore mostly relevant for lowering the maximum FPS below VSync, e.g. to perform non real-time rendering of static frames, or test the project under lag conditions.
+ This setting is therefore mostly relevant for lowering the maximum FPS below VSync, e.g. to perform non-real-time rendering of static frames, or test the project under lag conditions.
</member>
<member name="debug/settings/gdscript/max_call_stack" type="int" setter="" getter="" default="1024">
Maximum call stack allowed for debugging GDScript.
@@ -448,10 +463,13 @@
<member name="debug/shapes/collision/contact_color" type="Color" setter="" getter="" default="Color( 1, 0.2, 0.1, 0.8 )">
Color of the contact points between collision shapes, visible when "Visible Collision Shapes" is enabled in the Debug menu.
</member>
+ <member name="debug/shapes/collision/draw_2d_outlines" type="bool" setter="" getter="" default="true">
+ Sets whether 2D physics will display collision outlines in game when "Visible Collision Shapes" is enabled in the Debug menu.
+ </member>
<member name="debug/shapes/collision/max_contacts_displayed" type="int" setter="" getter="" default="10000">
Maximum number of contact points between collision shapes to display when "Visible Collision Shapes" is enabled in the Debug menu.
</member>
- <member name="debug/shapes/collision/shape_color" type="Color" setter="" getter="" default="Color( 0, 0.6, 0.7, 0.5 )">
+ <member name="debug/shapes/collision/shape_color" type="Color" setter="" getter="" default="Color( 0, 0.6, 0.7, 0.42 )">
Color of the collision shapes, visible when "Visible Collision Shapes" is enabled in the Debug menu.
</member>
<member name="debug/shapes/navigation/disabled_geometry_color" type="Color" setter="" getter="" default="Color( 1, 0.7, 0.1, 0.4 )">
@@ -470,14 +488,11 @@
Position offset for tooltips, relative to the mouse cursor's hotspot.
</member>
<member name="display/window/dpi/allow_hidpi" type="bool" setter="" getter="" default="false">
- If [code]true[/code], allows HiDPI display on Windows and macOS. This setting has no effect on desktop Linux, as DPI-awareness fallbacks are not supported there.
+ If [code]true[/code], allows HiDPI display on Windows, macOS, and the HTML5 platform. This setting has no effect on desktop 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">
If [code]true[/code], keeps the screen on (even in case of inactivity), so the screensaver does not take over. Works on desktop and mobile platforms.
</member>
- <member name="display/window/force_right_to_left_layout_direction" type="bool" setter="" getter="" default="false">
- Force layout direction and text writing direction to RTL for all locales.
- </member>
<member name="display/window/handheld/orientation" type="String" setter="" getter="" default="&quot;landscape&quot;">
Default orientation on mobile devices.
</member>
@@ -513,12 +528,6 @@
<member name="display/window/size/width" type="int" setter="" getter="" default="1024">
Sets the game's main viewport width. On desktop platforms, this is the default window size. Stretch mode settings also use this as a reference when enabled.
</member>
- <member name="display/window/tablet_driver" type="String" setter="" getter="">
- Specifies the tablet driver to use. If left empty, the default driver will be used.
- </member>
- <member name="display/window/text_name" type="String" setter="" getter="" default="&quot;&quot;">
- Specifies the [TextServer] to use. If left empty, the default will be used.
- </member>
<member name="display/window/vsync/use_vsync" type="bool" setter="" getter="" default="true">
If [code]true[/code], enables vertical synchronization. This eliminates tearing that may appear in moving scenes, at the cost of higher input latency and stuttering at lower framerates. If [code]false[/code], vertical synchronization will be disabled, however, many platforms will enforce it regardless (such as mobile platforms and HTML5).
</member>
@@ -526,12 +535,18 @@
If [code]Use Vsync[/code] is enabled and this setting is [code]true[/code], enables vertical synchronization via the operating system's window compositor when in windowed mode and the compositor is enabled. This will prevent stutter in certain situations. (Windows only.)
[b]Note:[/b] This option is experimental and meant to alleviate stutter experienced by some users. However, some users have experienced a Vsync framerate halving (e.g. from 60 FPS to 30 FPS) when using it.
</member>
- <member name="editor/script_templates_search_path" type="String" setter="" getter="" default="&quot;res://script_templates&quot;">
- Search path for project-specific script templates. Godot will search for script templates both in the editor-specific path and in this project-specific path.
+ <member name="editor/node_naming/name_casing" type="int" setter="" getter="" default="0">
+ When creating node names automatically, set the type of casing in this project. This is mostly an editor setting.
</member>
- <member name="editor/search_in_file_extensions" type="PackedStringArray" setter="" getter="" default="PackedStringArray( &quot;gd&quot;, &quot;shader&quot; )">
+ <member name="editor/node_naming/name_num_separator" type="int" setter="" getter="" default="0">
+ What to use to separate node name from number. This is mostly an editor setting.
+ </member>
+ <member name="editor/script/search_in_file_extensions" type="PackedStringArray" setter="" getter="" default="PackedStringArray( &quot;gd&quot;, &quot;shader&quot; )">
Text-based file extensions to include in the script editor's "Find in Files" feature. You can add e.g. [code]tscn[/code] if you wish to also parse your scene files, especially if you use built-in scripts which are serialized in the scene files.
</member>
+ <member name="editor/script/templates_search_path" type="String" setter="" getter="" default="&quot;res://script_templates&quot;">
+ Search path for project-specific script templates. Godot will search for script templates both in the editor-specific path and in this project-specific path.
+ </member>
<member name="gui/common/default_scroll_deadzone" type="int" setter="" getter="" default="0">
Default value for [member ScrollContainer.scroll_deadzone], which will be used for all [ScrollContainer]s unless overridden.
</member>
@@ -566,6 +581,10 @@
Default [InputEventAction] to discard a modal or pending input.
[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_copy" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_cut" type="Dictionary" setter="" getter="">
+ </member>
<member name="input/ui_down" type="Dictionary" setter="" getter="">
Default [InputEventAction] to move down in the UI.
[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.
@@ -574,6 +593,12 @@
Default [InputEventAction] to go to the end position of a [Control] (e.g. last item in an [ItemList] or a [Tree]), matching the behavior of [constant KEY_END] on typical desktop UI systems.
[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_filedialog_refresh" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_filedialog_show_hidden" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_filedialog_up_one_level" type="Dictionary" setter="" getter="">
+ </member>
<member name="input/ui_focus_next" type="Dictionary" setter="" getter="">
Default [InputEventAction] to focus the next [Control] in the scene. The focus behavior can be configured via [member Control.focus_next].
[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.
@@ -582,6 +607,10 @@
Default [InputEventAction] to focus the previous [Control] in the scene. The focus behavior can be configured via [member Control.focus_previous].
[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_graph_delete" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_graph_duplicate" type="Dictionary" setter="" getter="">
+ </member>
<member name="input/ui_home" type="Dictionary" setter="" getter="">
Default [InputEventAction] to go to the start position of a [Control] (e.g. first item in an [ItemList] or a [Tree]), matching the behavior of [constant KEY_HOME] on typical desktop UI systems.
[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.
@@ -590,6 +619,8 @@
Default [InputEventAction] to move left in the UI.
[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_menu" type="Dictionary" setter="" getter="">
+ </member>
<member name="input/ui_page_down" type="Dictionary" setter="" getter="">
Default [InputEventAction] to go down a page in a [Control] (e.g. in an [ItemList] or a [Tree]), matching the behavior of [constant KEY_PAGEDOWN] on typical desktop UI systems.
[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.
@@ -598,6 +629,10 @@
Default [InputEventAction] to go up a page in a [Control] (e.g. in an [ItemList] or a [Tree]), matching the behavior of [constant KEY_PAGEUP] on typical desktop UI systems.
[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_paste" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_redo" type="Dictionary" setter="" getter="">
+ </member>
<member name="input/ui_right" type="Dictionary" setter="" getter="">
Default [InputEventAction] to move right in the UI.
[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.
@@ -606,10 +641,102 @@
Default [InputEventAction] to select an item in a [Control] (e.g. in an [ItemList] or a [Tree]).
[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="">
+ </member>
+ <member name="input/ui_text_backspace" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_backspace_all_to_left" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_backspace_all_to_left.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_backspace_word" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_backspace_word.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_document_end" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_document_end.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_document_start" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_document_start.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_down" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_left" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_line_end" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_line_end.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_line_start" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_line_start.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_page_down" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_page_up" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_right" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_up" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_word_left" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_word_left.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_word_right" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_caret_word_right.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_completion_accept" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_completion_query" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_dedent" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_delete" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_delete_all_to_right" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_delete_all_to_right.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_delete_word" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_delete_word.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_indent" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_newline" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_newline_above" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_newline_blank" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_scroll_down" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_scroll_down.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_scroll_up" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_scroll_up.OSX" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_select_all" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_text_toggle_insert_mode" type="Dictionary" setter="" getter="">
+ </member>
+ <member name="input/ui_undo" type="Dictionary" setter="" getter="">
+ </member>
<member name="input/ui_up" type="Dictionary" setter="" getter="">
Default [InputEventAction] to move up in the UI.
[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_devices/pen_tablet/driver" type="String" setter="" getter="">
+ Specifies the tablet driver to use. If left empty, the default driver will be used.
+ </member>
+ <member name="input_devices/pen_tablet/driver.Windows" type="String" setter="" getter="">
+ Override for [member input_devices/pen_tablet/driver] on Windows.
+ </member>
<member name="input_devices/pointing/emulate_mouse_from_touch" type="bool" setter="" getter="" default="true">
If [code]true[/code], sends mouse input events when tapping or swiping on the touchscreen.
</member>
@@ -619,6 +746,78 @@
<member name="input_devices/pointing/ios/touch_delay" type="float" setter="" getter="" default="0.15">
Default delay for touch events. This only affects iOS devices.
</member>
+ <member name="internationalization/locale/fallback" type="String" setter="" getter="" default="&quot;en&quot;">
+ The locale to fall back to if a translation isn't available in a given language. If left empty, [code]en[/code] (English) will be used.
+ </member>
+ <member name="internationalization/locale/test" type="String" setter="" getter="" default="&quot;&quot;">
+ If non-empty, this locale will be used when running the project from the editor.
+ </member>
+ <member name="internationalization/rendering/force_right_to_left_layout_direction" type="bool" setter="" getter="" default="false">
+ Force layout direction and text writing direction to RTL for all locales.
+ </member>
+ <member name="internationalization/rendering/text_driver" type="String" setter="" getter="" default="&quot;&quot;">
+ Specifies the [TextServer] to use. If left empty, the default will be used.
+ </member>
+ <member name="layer_names/2d_navigation/layer_0" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 0. If left empty, the layer will display as "Layer 0".
+ </member>
+ <member name="layer_names/2d_navigation/layer_1" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 1. If left empty, the layer will display as "Layer 1".
+ </member>
+ <member name="layer_names/2d_navigation/layer_10" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 10. If left empty, the layer will display as "Layer 10".
+ </member>
+ <member name="layer_names/2d_navigation/layer_11" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 11. If left empty, the layer will display as "Layer 11".
+ </member>
+ <member name="layer_names/2d_navigation/layer_12" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 12. If left empty, the layer will display as "Layer 12".
+ </member>
+ <member name="layer_names/2d_navigation/layer_13" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 13. If left empty, the layer will display as "Layer 13".
+ </member>
+ <member name="layer_names/2d_navigation/layer_14" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 14. If left empty, the layer will display as "Layer 14".
+ </member>
+ <member name="layer_names/2d_navigation/layer_15" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 15. If left empty, the layer will display as "Layer 15".
+ </member>
+ <member name="layer_names/2d_navigation/layer_16" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 16. If left empty, the layer will display as "Layer 16".
+ </member>
+ <member name="layer_names/2d_navigation/layer_17" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 17. If left empty, the layer will display as "Layer 17".
+ </member>
+ <member name="layer_names/2d_navigation/layer_18" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 18. If left empty, the layer will display as "Layer 18".
+ </member>
+ <member name="layer_names/2d_navigation/layer_19" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 19. If left empty, the layer will display as "Layer 19".
+ </member>
+ <member name="layer_names/2d_navigation/layer_2" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 2. If left empty, the layer will display as "Layer 2".
+ </member>
+ <member name="layer_names/2d_navigation/layer_3" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 3. If left empty, the layer will display as "Layer 3".
+ </member>
+ <member name="layer_names/2d_navigation/layer_4" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 4. If left empty, the layer will display as "Layer 4".
+ </member>
+ <member name="layer_names/2d_navigation/layer_5" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 5. If left empty, the layer will display as "Layer 5".
+ </member>
+ <member name="layer_names/2d_navigation/layer_6" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 6. If left empty, the layer will display as "Layer 6".
+ </member>
+ <member name="layer_names/2d_navigation/layer_7" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 7. If left empty, the layer will display as "Layer 7".
+ </member>
+ <member name="layer_names/2d_navigation/layer_8" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 8. If left empty, the layer will display as "Layer 8".
+ </member>
+ <member name="layer_names/2d_navigation/layer_9" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 2D navigation layer 9. If left empty, the layer will display as "Layer 9".
+ </member>
<member name="layer_names/2d_physics/layer_0" type="String" setter="" getter="" default="&quot;&quot;">
Optional name for the 2D physics layer 0. If left empty, the layer will display as "Layer 0".
</member>
@@ -739,6 +938,66 @@
<member name="layer_names/2d_render/layer_9" type="String" setter="" getter="" default="&quot;&quot;">
Optional name for the 2D render layer 9. If left empty, the layer will display as "Layer 9".
</member>
+ <member name="layer_names/3d_navigation/layer_0" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 0. If left empty, the layer will display as "Layer 0".
+ </member>
+ <member name="layer_names/3d_navigation/layer_1" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 1. If left empty, the layer will display as "Layer 1".
+ </member>
+ <member name="layer_names/3d_navigation/layer_10" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 10. If left empty, the layer will display as "Layer 10".
+ </member>
+ <member name="layer_names/3d_navigation/layer_11" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 11. If left empty, the layer will display as "Layer 11".
+ </member>
+ <member name="layer_names/3d_navigation/layer_12" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 12. If left empty, the layer will display as "Layer 12".
+ </member>
+ <member name="layer_names/3d_navigation/layer_13" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 13. If left empty, the layer will display as "Layer 13".
+ </member>
+ <member name="layer_names/3d_navigation/layer_14" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 14. If left empty, the layer will display as "Layer 14".
+ </member>
+ <member name="layer_names/3d_navigation/layer_15" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 15. If left empty, the layer will display as "Layer 15".
+ </member>
+ <member name="layer_names/3d_navigation/layer_16" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 16. If left empty, the layer will display as "Layer 16".
+ </member>
+ <member name="layer_names/3d_navigation/layer_17" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 17. If left empty, the layer will display as "Layer 17".
+ </member>
+ <member name="layer_names/3d_navigation/layer_18" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 18. If left empty, the layer will display as "Layer 18".
+ </member>
+ <member name="layer_names/3d_navigation/layer_19" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 19. If left empty, the layer will display as "Layer 19".
+ </member>
+ <member name="layer_names/3d_navigation/layer_2" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 2. If left empty, the layer will display as "Layer 2".
+ </member>
+ <member name="layer_names/3d_navigation/layer_3" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 3. If left empty, the layer will display as "Layer 3".
+ </member>
+ <member name="layer_names/3d_navigation/layer_4" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 4. If left empty, the layer will display as "Layer 4".
+ </member>
+ <member name="layer_names/3d_navigation/layer_5" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 5. If left empty, the layer will display as "Layer 5".
+ </member>
+ <member name="layer_names/3d_navigation/layer_6" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 6. If left empty, the layer will display as "Layer 6".
+ </member>
+ <member name="layer_names/3d_navigation/layer_7" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 7. If left empty, the layer will display as "Layer 7".
+ </member>
+ <member name="layer_names/3d_navigation/layer_8" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 8. If left empty, the layer will display as "Layer 8".
+ </member>
+ <member name="layer_names/3d_navigation/layer_9" type="String" setter="" getter="" default="&quot;&quot;">
+ Optional name for the 3D navigation layer 9. If left empty, the layer will display as "Layer 9".
+ </member>
<member name="layer_names/3d_physics/layer_0" type="String" setter="" getter="" default="&quot;&quot;">
Optional name for the 3D physics layer 0. If left empty, the layer will display as "Layer 0".
</member>
@@ -859,24 +1118,6 @@
<member name="layer_names/3d_render/layer_9" type="String" setter="" getter="" default="&quot;&quot;">
Optional name for the 3D render layer 9. If left empty, the layer will display as "Layer 9".
</member>
- <member name="locale/fallback" type="String" setter="" getter="" default="&quot;en&quot;">
- The locale to fall back to if a translation isn't available in a given language. If left empty, [code]en[/code] (English) will be used.
- </member>
- <member name="locale/test" type="String" setter="" getter="" default="&quot;&quot;">
- If non-empty, this locale will be used when running the project from the editor.
- </member>
- <member name="logging/file_logging/enable_file_logging" type="bool" setter="" getter="" default="false">
- If [code]true[/code], logs all output to files.
- </member>
- <member name="logging/file_logging/enable_file_logging.pc" type="bool" setter="" getter="" default="true">
- Desktop override for [member logging/file_logging/enable_file_logging], as log files are not readily accessible on mobile/Web platforms.
- </member>
- <member name="logging/file_logging/log_path" type="String" setter="" getter="" default="&quot;user://logs/godot.log&quot;">
- Path to logs within the project. Using an [code]user://[/code] path is recommended.
- </member>
- <member name="logging/file_logging/max_log_files" type="int" setter="" getter="" default="5">
- Specifies the maximum amount of log files allowed (used for rotation).
- </member>
<member name="memory/limits/command_queue/multithreading_queue_size_kb" type="int" setter="" getter="" default="256">
</member>
<member name="memory/limits/message_queue/max_size_kb" type="int" setter="" getter="" default="4096">
@@ -899,6 +1140,18 @@
</member>
<member name="mono/unhandled_exception_policy" type="int" setter="" getter="" default="0">
</member>
+ <member name="navigation/2d/default_cell_size" type="int" setter="" getter="" default="10">
+ Default cell size for 2D navigation maps. See [method NavigationServer2D.map_set_cell_size].
+ </member>
+ <member name="navigation/2d/default_edge_connection_margin" type="int" setter="" getter="" default="5">
+ Default edge connection margin for 2D navigation maps. See [method NavigationServer2D.map_set_edge_connection_margin].
+ </member>
+ <member name="navigation/3d/default_cell_size" type="float" setter="" getter="" default="0.3">
+ Default cell size for 3D navigation maps. See [method NavigationServer3D.map_set_cell_size].
+ </member>
+ <member name="navigation/3d/default_edge_connection_margin" type="float" setter="" getter="" default="5.0">
+ Default edge connection margin for 3D navigation maps. See [method NavigationServer3D.map_set_edge_connection_margin].
+ </member>
<member name="network/limits/debugger/max_chars_per_second" type="int" setter="" getter="" default="32768">
Maximum amount of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
</member>
@@ -930,12 +1183,6 @@
The CA certificates bundle to use for SSL connections. If this is set to a non-empty value, this will [i]override[/i] Godot's default [url=https://github.com/godotengine/godot/blob/master/thirdparty/certs/ca-certificates.crt]Mozilla certificate bundle[/url]. If left empty, the default certificate bundle will be used.
If in doubt, leave this setting empty.
</member>
- <member name="node/name_casing" type="int" setter="" getter="" default="0">
- When creating node names automatically, set the type of casing in this project. This is mostly an editor setting.
- </member>
- <member name="node/name_num_separator" type="int" setter="" getter="" default="0">
- What to use to separate node name from number. This is mostly an editor setting.
- </member>
<member name="physics/2d/bp_hash_table_size" type="int" setter="" getter="" default="4096">
Size of the hash table used for the broad-phase 2D hash grid algorithm.
</member>
@@ -985,22 +1232,18 @@
Sets which physics engine to use for 2D physics.
"DEFAULT" and "GodotPhysics2D" are the same, as there is currently no alternative 2D physics server implemented.
</member>
+ <member name="physics/2d/run_on_thread" type="bool" setter="" getter="" default="false">
+ Sets whether 2D physics is run on the main thread or a separate one. Running the server on a thread increases performance, but restricts API access to only physics process.
+ </member>
<member name="physics/2d/sleep_threshold_angular" type="float" setter="" getter="" default="0.139626">
Threshold angular velocity under which a 2D physics body will be considered inactive. See [constant PhysicsServer2D.SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD].
</member>
<member name="physics/2d/sleep_threshold_linear" type="float" setter="" getter="" default="2.0">
Threshold linear velocity under which a 2D physics body will be considered inactive. See [constant PhysicsServer2D.SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD].
</member>
- <member name="physics/2d/thread_model" type="int" setter="" getter="" default="1">
- Sets whether physics is run on the main thread or a separate one. Running the server on a thread increases performance, but restricts API access to only physics process.
- [b]Warning:[/b] As of Godot 3.2, there are mixed reports about the use of a Multi-Threaded thread model for physics. Be sure to assess whether it does give you extra performance and no regressions when using it.
- </member>
<member name="physics/2d/time_before_sleep" type="float" setter="" getter="" default="0.5">
Time (in seconds) of inactivity before which a 2D physics body will put to sleep. See [constant PhysicsServer2D.SPACE_PARAM_BODY_TIME_TO_SLEEP].
</member>
- <member name="physics/3d/active_soft_world" type="bool" setter="" getter="" default="true">
- Sets whether the 3D physics world will be created with support for [SoftBody3D] physics. Only applies to the Bullet physics engine.
- </member>
<member name="physics/3d/default_angular_damp" type="float" setter="" getter="" default="0.1">
The default angular damp in 3D.
[b]Note:[/b] Good values are in the range [code]0[/code] to [code]1[/code]. At value [code]0[/code] objects will keep moving with the same velocity. Values greater than [code]1[/code] will aim to reduce the velocity to [code]0[/code] in less than a second e.g. a value of [code]2[/code] will aim to reduce the velocity to [code]0[/code] in half a second. A value equal to or greater than the physics frame rate ([member ProjectSettings.physics/common/physics_fps], [code]60[/code] by default) will bring the object to a stop in one iteration.
@@ -1041,6 +1284,15 @@
Sets which physics engine to use for 3D physics.
"DEFAULT" is currently the [url=https://bulletphysics.org]Bullet[/url] physics engine. The "GodotPhysics3D" engine is still supported as an alternative.
</member>
+ <member name="physics/3d/run_on_thread" type="bool" setter="" getter="" default="false">
+ Sets whether 3D physics is run on the main thread or a separate one. Running the server on a thread increases performance, but restricts API access to only physics process.
+ </member>
+ <member name="physics/3d/sleep_threshold_angular" type="float" setter="" getter="" default="0.139626">
+ </member>
+ <member name="physics/3d/sleep_threshold_linear" type="float" setter="" getter="" default="0.1">
+ </member>
+ <member name="physics/3d/time_before_sleep" type="float" setter="" getter="" default="0.5">
+ </member>
<member name="physics/common/enable_object_picking" type="bool" setter="" getter="" default="true">
Enables [member Viewport.physics_object_picking] on the root viewport.
</member>
@@ -1052,283 +1304,269 @@
Fix to improve physics jitter, specially on monitors where refresh rate is different than the physics FPS.
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.physics_jitter_fix] instead.
</member>
- <member name="rendering/cluster_builder/max_clustered_elements" type="float" setter="" getter="" default="512">
+ <member name="rendering/2d/sdf/oversize" type="int" setter="" getter="" default="1">
</member>
- <member name="rendering/environment/default_clear_color" type="Color" setter="" getter="" default="Color( 0.3, 0.3, 0.3, 1 )">
- Default background clear color. Overridable per [Viewport] using its [Environment]. See [member Environment.background_mode] and [member Environment.background_color] in particular. To change this default color programmatically, use [method RenderingServer.set_default_clear_color].
- </member>
- <member name="rendering/environment/default_environment" type="String" setter="" getter="" default="&quot;&quot;">
- [Environment] that will be used as a fallback environment in case a scene does not specify its own environment. The default environment is loaded in at scene load time regardless of whether you have set an environment or not. If you do not rely on the fallback environment, it is best to delete [code]default_env.tres[/code], or to specify a different default environment here.
+ <member name="rendering/2d/sdf/scale" type="int" setter="" getter="" default="1">
</member>
- <member name="rendering/forward_renderer/threaded_render_minimum_instances" type="int" setter="" getter="" default="500">
+ <member name="rendering/2d/shadow_atlas/size" type="int" setter="" getter="" default="2048">
</member>
- <member name="rendering/gpu_lightmapper/performance/max_rays_per_pass" type="int" setter="" getter="" default="32">
+ <member name="rendering/2d/snap/snap_2d_transforms_to_pixel" type="bool" setter="" getter="" default="false">
</member>
- <member name="rendering/gpu_lightmapper/performance/max_rays_per_probe_pass" type="int" setter="" getter="" default="64">
+ <member name="rendering/2d/snap/snap_2d_vertices_to_pixel" type="bool" setter="" getter="" default="false">
</member>
- <member name="rendering/gpu_lightmapper/performance/region_size" type="int" setter="" getter="" default="512">
- </member>
- <member name="rendering/gpu_lightmapper/quality/high_quality_probe_ray_count" type="int" setter="" getter="" default="512">
- </member>
- <member name="rendering/gpu_lightmapper/quality/high_quality_ray_count" type="int" setter="" getter="" default="256">
- </member>
- <member name="rendering/gpu_lightmapper/quality/low_quality_probe_ray_count" type="int" setter="" getter="" default="64">
- </member>
- <member name="rendering/gpu_lightmapper/quality/low_quality_ray_count" type="int" setter="" getter="" default="16">
+ <member name="rendering/anti_aliasing/quality/msaa" type="int" setter="" getter="" default="0">
+ Sets the number of MSAA samples to use (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware.
</member>
- <member name="rendering/gpu_lightmapper/quality/medium_quality_probe_ray_count" type="int" setter="" getter="" default="256">
+ <member name="rendering/anti_aliasing/quality/screen_space_aa" type="int" setter="" getter="" default="0">
+ Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry.
+ Another way to combat specular aliasing is to enable [member rendering/anti_aliasing/screen_space_roughness_limiter/enabled].
</member>
- <member name="rendering/gpu_lightmapper/quality/medium_quality_ray_count" type="int" setter="" getter="" default="64">
+ <member name="rendering/anti_aliasing/quality/use_debanding" type="bool" setter="" getter="" default="false">
</member>
- <member name="rendering/gpu_lightmapper/quality/ultra_quality_probe_ray_count" type="int" setter="" getter="" default="2048">
+ <member name="rendering/anti_aliasing/screen_space_roughness_limiter/amount" type="float" setter="" getter="" default="0.25">
</member>
- <member name="rendering/gpu_lightmapper/quality/ultra_quality_ray_count" type="int" setter="" getter="" default="1024">
+ <member name="rendering/anti_aliasing/screen_space_roughness_limiter/enabled" type="bool" setter="" getter="" default="true">
</member>
- <member name="rendering/high_end/global_shader_variables_buffer_size" type="int" setter="" getter="" default="65536">
+ <member name="rendering/anti_aliasing/screen_space_roughness_limiter/limit" type="float" setter="" getter="" default="0.18">
</member>
- <member name="rendering/lightmapper/probe_capture_update_speed" type="float" setter="" getter="" default="15">
+ <member name="rendering/camera/depth_of_field/depth_of_field_bokeh_quality" type="int" setter="" getter="" default="2">
+ Sets the quality of the depth of field effect. Higher quality takes more samples, which is slower but looks smoother.
</member>
- <member name="rendering/limits/rendering/max_renderable_elements" type="int" setter="" getter="" default="128000">
- Max amount of elements renderable in a frame. If more than this are visible per frame, they will be dropped. Keep in mind elements refer to mesh surfaces and not meshes themselves.
+ <member name="rendering/camera/depth_of_field/depth_of_field_bokeh_shape" type="int" setter="" getter="" default="1">
+ Sets the depth of field shape. Can be Box, Hexagon, or Circle. Box is the fastest. Circle is the most realistic, but also the most expensive to compute.
</member>
- <member name="rendering/limits/time/time_rollover_secs" type="float" setter="" getter="" default="3600">
+ <member name="rendering/camera/depth_of_field/depth_of_field_use_jitter" type="bool" setter="" getter="" default="false">
+ If [code]true[/code], jitters DOF samples to make effect slightly blurrier and hide lines created from low sample rates. This can result in a slightly grainy appearance when used with a low number of samples.
</member>
- <member name="rendering/quality/2d/snap_2d_transforms_to_pixel" type="bool" setter="" getter="" default="false">
+ <member name="rendering/driver/depth_prepass/disable_for_vendors" type="String" setter="" getter="" default="&quot;PowerVR,Mali,Adreno,Apple&quot;">
+ Disables depth pre-pass for some GPU vendors (usually mobile), as their architecture already does this.
</member>
- <member name="rendering/quality/2d/snap_2d_vertices_to_pixel" type="bool" setter="" getter="" default="false">
+ <member name="rendering/driver/depth_prepass/enable" type="bool" setter="" getter="" default="true">
+ If [code]true[/code], performs a previous depth pass before rendering materials. This increases performance in scenes with high overdraw, when complex materials and lighting are used.
</member>
- <member name="rendering/quality/2d_sdf/oversize" type="int" setter="" getter="" default="1">
+ <member name="rendering/driver/driver_name" type="String" setter="" getter="" default="&quot;Vulkan&quot;">
+ The video driver to use (currently only "Vulkan" is implemented).
+ [b]Note:[/b] The backend in use can be overridden at runtime via the [code]--rendering-driver[/code] command line argument.
+ [b]FIXME:[/b] No longer valid after DisplayServer split:
+ In such cases, this property is not updated, so use [code]OS.get_current_video_driver[/code] to query it at run-time.
</member>
- <member name="rendering/quality/2d_sdf/scale" type="int" setter="" getter="" default="1">
+ <member name="rendering/driver/rd_renderer/use_low_end_renderer" type="bool" setter="" getter="" default="false">
</member>
- <member name="rendering/quality/2d_shadow_atlas/size" type="int" setter="" getter="" default="2048">
+ <member name="rendering/driver/rd_renderer/use_low_end_renderer.mobile" type="bool" setter="" getter="" default="true">
</member>
- <member name="rendering/quality/depth_of_field/depth_of_field_bokeh_quality" type="int" setter="" getter="" default="2">
- Sets the quality of the depth of field effect. Higher quality takes more samples, which is slower but looks smoother.
+ <member name="rendering/driver/threads/thread_model" type="int" setter="" getter="" default="1">
+ Thread model for rendering. Rendering on a thread can vastly improve performance, but synchronizing to the main thread can cause a bit more jitter.
</member>
- <member name="rendering/quality/depth_of_field/depth_of_field_bokeh_shape" type="int" setter="" getter="" default="1">
- Sets the depth of field shape. Can be Box, Hexagon, or Circle. Box is the fastest. Circle is the most realistic, but also the most expensive to compute.
+ <member name="rendering/environment/defaults/default_clear_color" type="Color" setter="" getter="" default="Color( 0.3, 0.3, 0.3, 1 )">
+ Default background clear color. Overridable per [Viewport] using its [Environment]. See [member Environment.background_mode] and [member Environment.background_color] in particular. To change this default color programmatically, use [method RenderingServer.set_default_clear_color].
</member>
- <member name="rendering/quality/depth_of_field/depth_of_field_use_jitter" type="bool" setter="" getter="" default="false">
- If [code]true[/code], jitters DOF samples to make effect slightly blurrier and hide lines created from low sample rates. This can result in a slightly grainy appearance when used with a low number of samples.
+ <member name="rendering/environment/defaults/default_environment" type="String" setter="" getter="" default="&quot;&quot;">
+ [Environment] that will be used as a fallback environment in case a scene does not specify its own environment. The default environment is loaded in at scene load time regardless of whether you have set an environment or not. If you do not rely on the fallback environment, it is best to delete [code]default_env.tres[/code], or to specify a different default environment here.
</member>
- <member name="rendering/quality/depth_prepass/disable_for_vendors" type="String" setter="" getter="" default="&quot;PowerVR,Mali,Adreno,Apple&quot;">
- Disables depth pre-pass for some GPU vendors (usually mobile), as their architecture already does this.
+ <member name="rendering/environment/glow/upscale_mode" type="int" setter="" getter="" default="1">
+ Sets how the glow effect is upscaled before being copied onto the screen. Linear is faster, but looks blocky. Bicubic is slower but looks smooth.
</member>
- <member name="rendering/quality/depth_prepass/enable" type="bool" setter="" getter="" default="true">
- If [code]true[/code], performs a previous depth pass before rendering materials. This increases performance in scenes with high overdraw, when complex materials and lighting are used.
+ <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/quality/directional_shadow/16_bits" type="bool" setter="" getter="" default="true">
+ <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/quality/directional_shadow/size" type="int" setter="" getter="" default="4096">
- The directional shadow's size in pixels. Higher values will result in sharper shadows, at the cost of performance. The value will be rounded up to the nearest power of 2.
+ <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>
- <member name="rendering/quality/directional_shadow/size.mobile" type="int" setter="" getter="" default="2048">
- Lower-end override for [member rendering/quality/directional_shadow/size] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/environment/ssao/adaptive_target" type="float" setter="" getter="" default="0.5">
+ Quality target to use when [member rendering/environment/ssao/quality] is set to [code]ULTRA[/code]. A value of [code]0.0[/code] provides a quality and speed similar to [code]MEDIUM[/code] while a value of [code]1.0[/code] provides much higher quality than any of the other settings at the cost of performance.
</member>
- <member name="rendering/quality/directional_shadow/soft_shadow_quality" type="int" setter="" getter="" default="2">
- Quality setting for shadows cast by [DirectionalLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
+ <member name="rendering/environment/ssao/blur_passes" type="int" setter="" getter="" default="2">
+ Number of blur passes to use when computing screen-space ambient occlusion. A higher number will result in a smoother look, but will be slower to compute and will have less high-frequency detail.
</member>
- <member name="rendering/quality/directional_shadow/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0">
- Lower-end override for [member rendering/quality/directional_shadow/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/environment/ssao/fadeout_from" type="float" setter="" getter="" default="50.0">
+ Distance at which the screen-space ambient occlusion effect starts to fade out. Use this hide ambient occlusion at great distances.
</member>
- <member name="rendering/quality/driver/driver_name" type="String" setter="" getter="" default="&quot;Vulkan&quot;">
- The video driver to use ("GLES2" or "Vulkan").
- [b]Note:[/b] The backend in use can be overridden at runtime via the [code]--rendering-driver[/code] command line argument.
- [b]FIXME:[/b] No longer valid after DisplayServer split:
- In such cases, this property is not updated, so use [code]OS.get_current_video_driver[/code] to query it at run-time.
+ <member name="rendering/environment/ssao/fadeout_to" type="float" setter="" getter="" default="300.0">
+ Distance at which the screen-space ambient occlusion is fully faded out. Use this hide ambient occlusion at great distances.
</member>
- <member name="rendering/quality/gi/use_half_resolution" type="bool" setter="" getter="" default="false">
+ <member name="rendering/environment/ssao/half_size" type="bool" setter="" getter="" default="false">
+ If [code]true[/code], screen-space ambient occlusion will be rendered at half size and then upscaled before being added to the scene. This is significantly faster but may miss small details.
</member>
- <member name="rendering/quality/gi_probes/anisotropic" type="bool" setter="" getter="" default="false">
- If [code]true[/code], take additional samples when rendering objects affected by a [GIProbe] to reduce artifacts from only sampling in one direction.
+ <member name="rendering/environment/ssao/half_size.mobile" type="bool" setter="" getter="" default="true">
+ Lower-end override for [member rendering/environment/ssao/half_size] on mobile devices, due to performance concerns.
</member>
- <member name="rendering/quality/gi_probes/quality" type="int" setter="" getter="" default="1">
- Sets the number of cone samples taken when rendering objects affected by [GIProbe]s.
+ <member name="rendering/environment/ssao/quality" type="int" setter="" getter="" default="2">
+ Sets the quality of the screen-space ambient occlusion effect. Higher values take more samples and so will result in better quality, at the cost of performance. Setting to [code]ULTRA[/code] will use the [member rendering/environment/ssao/adaptive_target] setting.
</member>
- <member name="rendering/quality/glow/upscale_mode" type="int" setter="" getter="" default="1">
- Sets how the glow effect is upscaled before being copied onto the screen. Linear is faster, but looks blocky. Bicubic is slower but looks smooth.
+ <member name="rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale" type="float" setter="" getter="" default="0.01">
+ Scales the depth over which the subsurface scattering effect is applied. A high value may allow light to scatter into a part of the mesh or another mesh that is close in screen space but far in depth.
</member>
- <member name="rendering/quality/glow/upscale_mode.mobile" type="int" setter="" getter="" default="0">
- Lower-end override for [member rendering/quality/glow/upscale_mode] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/environment/subsurface_scattering/subsurface_scattering_quality" type="int" setter="" getter="" default="1">
+ Sets the quality of the subsurface scattering effect. Higher values are slower but look nicer.
</member>
- <member name="rendering/quality/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 name="rendering/environment/subsurface_scattering/subsurface_scattering_scale" type="float" setter="" getter="" default="0.05">
+ Scales the distance over which samples are taken for subsurface scattering effect. Changing this does not impact performance, but higher values will result in significant artifacts as the samples will become obviously spread out. A lower value results in a smaller spread of scattered light.
</member>
- <member name="rendering/quality/intended_usage/framebuffer_allocation" type="int" setter="" getter="" default="2">
- Strategy used for framebuffer allocation. The simpler it is, the less resources it uses (but the less features it supports). If set to "2D Without Sampling" or "3D Without Effects", sample buffers will not be allocated. This means [code]SCREEN_TEXTURE[/code] and [code]DEPTH_TEXTURE[/code] will not be available in shaders and post-processing effects will not be available in the [Environment].
+ <member name="rendering/environment/volumetric_fog/use_filter" type="int" setter="" getter="" default="1">
</member>
- <member name="rendering/quality/intended_usage/framebuffer_allocation.mobile" type="int" setter="" getter="" default="3">
- Lower-end override for [member rendering/quality/intended_usage/framebuffer_allocation] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/environment/volumetric_fog/volume_depth" type="int" setter="" getter="" default="128">
</member>
- <member name="rendering/quality/mesh_lod/threshold_pixels" type="float" setter="" getter="" default="1.0">
+ <member name="rendering/environment/volumetric_fog/volume_size" type="int" setter="" getter="" default="64">
</member>
- <member name="rendering/quality/rd_renderer/use_low_end_renderer" type="bool" setter="" getter="" default="false">
+ <member name="rendering/global_illumination/gi/use_half_resolution" type="bool" setter="" getter="" default="false">
</member>
- <member name="rendering/quality/rd_renderer/use_low_end_renderer.mobile" type="bool" setter="" getter="" default="true">
+ <member name="rendering/global_illumination/gi_probes/anisotropic" type="bool" setter="" getter="" default="false">
+ If [code]true[/code], take additional samples when rendering objects affected by a [GIProbe] to reduce artifacts from only sampling in one direction.
</member>
- <member name="rendering/quality/reflection_atlas/reflection_count" type="int" setter="" getter="" default="64">
- Number of cubemaps to store in the reflection atlas. The number of [ReflectionProbe]s in a scene will be limited by this amount. A higher number requires more VRAM.
+ <member name="rendering/global_illumination/gi_probes/quality" type="int" setter="" getter="" default="1">
+ Sets the number of cone samples taken when rendering objects affected by [GIProbe]s.
</member>
- <member name="rendering/quality/reflection_atlas/reflection_size" type="int" setter="" getter="" default="256">
- Size of cubemap faces for [ReflectionProbe]s. A higher number requires more VRAM and may make reflection probe updating slower.
+ <member name="rendering/global_illumination/sdfgi/frames_to_converge" type="int" setter="" getter="" default="4">
</member>
- <member name="rendering/quality/reflection_atlas/reflection_size.mobile" type="int" setter="" getter="" default="128">
- Lower-end override for [member rendering/quality/reflection_atlas/reflection_size] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/global_illumination/sdfgi/frames_to_update_lights" type="int" setter="" getter="" default="2">
</member>
- <member name="rendering/quality/reflections/fast_filter_high_quality" type="bool" setter="" getter="" default="false">
- Use a higher quality variant of the fast filtering algorithm. Significantly slower than using default quality, but results in smoother reflections. Should only be used when the scene is especially detailed.
+ <member name="rendering/global_illumination/sdfgi/probe_ray_count" type="int" setter="" getter="" default="1">
</member>
- <member name="rendering/quality/reflections/ggx_samples" type="int" setter="" getter="" default="1024">
- Sets the number of samples to take when using importance sampling for [Sky]s and [ReflectionProbe]s. A higher value will result in smoother, higher quality reflections, but increases time to calculate radiance maps. In general, fewer samples are needed for simpler, low dynamic range environments while more samples are needed for HDR environments and environments with a high level of detail.
+ <member name="rendering/lightmapping/bake_performance/max_rays_per_pass" type="int" setter="" getter="" default="32">
</member>
- <member name="rendering/quality/reflections/ggx_samples.mobile" type="int" setter="" getter="" default="128">
- Lower-end override for [member rendering/quality/reflections/ggx_samples] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/lightmapping/bake_performance/max_rays_per_probe_pass" type="int" setter="" getter="" default="64">
</member>
- <member name="rendering/quality/reflections/roughness_layers" type="int" setter="" getter="" default="8">
- Limits the number of layers to use in radiance maps when using importance sampling. A lower number will be slightly faster and take up less VRAM.
+ <member name="rendering/lightmapping/bake_performance/region_size" type="int" setter="" getter="" default="512">
</member>
- <member name="rendering/quality/reflections/texture_array_reflections" type="bool" setter="" getter="" default="true">
- If [code]true[/code], uses texture arrays instead of mipmaps for reflection probes and panorama backgrounds (sky). This reduces jitter noise and upscaling artifacts on reflections, but is significantly slower to compute and uses [member rendering/quality/reflections/roughness_layers] times more memory.
+ <member name="rendering/lightmapping/bake_quality/high_quality_probe_ray_count" type="int" setter="" getter="" default="512">
</member>
- <member name="rendering/quality/reflections/texture_array_reflections.mobile" type="bool" setter="" getter="" default="false">
- Lower-end override for [member rendering/quality/reflections/texture_array_reflections] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/lightmapping/bake_quality/high_quality_ray_count" type="int" setter="" getter="" default="256">
</member>
- <member name="rendering/quality/screen_filters/msaa" type="int" setter="" getter="" default="0">
- Sets the number of MSAA samples to use (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware.
- [b]Note:[/b] MSAA is not available on HTML5 export using the GLES2 backend.
+ <member name="rendering/lightmapping/bake_quality/low_quality_probe_ray_count" type="int" setter="" getter="" default="64">
</member>
- <member name="rendering/quality/screen_filters/screen_space_aa" type="int" setter="" getter="" default="0">
- Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry.
- Another way to combat specular aliasing is to enable [member rendering/quality/screen_filters/screen_space_roughness_limiter_enabled].
+ <member name="rendering/lightmapping/bake_quality/low_quality_ray_count" type="int" setter="" getter="" default="16">
</member>
- <member name="rendering/quality/screen_filters/screen_space_roughness_limiter_amount" type="float" setter="" getter="" default="0.25">
+ <member name="rendering/lightmapping/bake_quality/medium_quality_probe_ray_count" type="int" setter="" getter="" default="256">
</member>
- <member name="rendering/quality/screen_filters/screen_space_roughness_limiter_enabled" type="bool" setter="" getter="" default="true">
+ <member name="rendering/lightmapping/bake_quality/medium_quality_ray_count" type="int" setter="" getter="" default="64">
</member>
- <member name="rendering/quality/screen_filters/screen_space_roughness_limiter_limit" type="float" setter="" getter="" default="0.18">
+ <member name="rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count" type="int" setter="" getter="" default="2048">
</member>
- <member name="rendering/quality/screen_filters/use_debanding" type="bool" setter="" getter="" default="false">
+ <member name="rendering/lightmapping/bake_quality/ultra_quality_ray_count" type="int" setter="" getter="" default="1024">
</member>
- <member name="rendering/quality/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 name="rendering/lightmapping/probe_capture/update_speed" type="float" setter="" getter="" default="15">
</member>
- <member name="rendering/quality/shading/force_blinn_over_ggx" type="bool" setter="" getter="" default="false">
- If [code]true[/code], uses faster but lower-quality Blinn model to generate blurred reflections instead of the GGX model.
+ <member name="rendering/limits/cluster_builder/max_clustered_elements" type="float" setter="" getter="" default="512">
</member>
- <member name="rendering/quality/shading/force_blinn_over_ggx.mobile" type="bool" setter="" getter="" default="true">
- Lower-end override for [member rendering/quality/shading/force_blinn_over_ggx] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/limits/forward_renderer/threaded_render_minimum_instances" type="int" setter="" getter="" default="500">
</member>
- <member name="rendering/quality/shading/force_lambert_over_burley" type="bool" setter="" getter="" default="false">
- If [code]true[/code], uses faster but lower-quality Lambert material lighting model instead of Burley.
+ <member name="rendering/limits/global_shader_variables/buffer_size" type="int" setter="" getter="" default="65536">
</member>
- <member name="rendering/quality/shading/force_lambert_over_burley.mobile" type="bool" setter="" getter="" default="true">
- Lower-end override for [member rendering/quality/shading/force_lambert_over_burley] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/limits/spatial_indexer/threaded_cull_minimum_instances" type="int" setter="" getter="" default="1000">
</member>
- <member name="rendering/quality/shading/force_vertex_shading" type="bool" setter="" getter="" default="false">
- If [code]true[/code], forces vertex shading for all rendering. This can increase performance a lot, but also reduces quality immensely. Can be used to optimize performance on low-end mobile devices.
+ <member name="rendering/limits/spatial_indexer/update_iterations_per_frame" type="int" setter="" getter="" default="10">
</member>
- <member name="rendering/quality/shading/force_vertex_shading.mobile" type="bool" setter="" getter="" default="true">
- Lower-end override for [member rendering/quality/shading/force_vertex_shading] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/limits/time/time_rollover_secs" type="float" setter="" getter="" default="3600">
</member>
- <member name="rendering/quality/shadow_atlas/16_bits" type="bool" setter="" getter="" default="true">
+ <member name="rendering/mesh_lod/lod_change/threshold_pixels" type="float" setter="" getter="" default="1.0">
</member>
- <member name="rendering/quality/shadow_atlas/quadrant_0_subdiv" type="int" setter="" getter="" default="2">
- Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
+ <member name="rendering/reflections/reflection_atlas/reflection_count" type="int" setter="" getter="" default="64">
+ Number of cubemaps to store in the reflection atlas. The number of [ReflectionProbe]s in a scene will be limited by this amount. A higher number requires more VRAM.
</member>
- <member name="rendering/quality/shadow_atlas/quadrant_1_subdiv" type="int" setter="" getter="" default="2">
- Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
+ <member name="rendering/reflections/reflection_atlas/reflection_size" type="int" setter="" getter="" default="256">
+ Size of cubemap faces for [ReflectionProbe]s. A higher number requires more VRAM and may make reflection probe updating slower.
</member>
- <member name="rendering/quality/shadow_atlas/quadrant_2_subdiv" type="int" setter="" getter="" default="3">
- Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
+ <member name="rendering/reflections/reflection_atlas/reflection_size.mobile" type="int" setter="" getter="" default="128">
+ Lower-end override for [member rendering/reflections/reflection_atlas/reflection_size] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/quality/shadow_atlas/quadrant_3_subdiv" type="int" setter="" getter="" default="4">
- Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
+ <member name="rendering/reflections/sky_reflections/fast_filter_high_quality" type="bool" setter="" getter="" default="false">
+ Use a higher quality variant of the fast filtering algorithm. Significantly slower than using default quality, but results in smoother reflections. Should only be used when the scene is especially detailed.
</member>
- <member name="rendering/quality/shadow_atlas/size" type="int" setter="" getter="" default="4096">
- Size for shadow atlas (used for OmniLights and SpotLights). See documentation.
+ <member name="rendering/reflections/sky_reflections/ggx_samples" type="int" setter="" getter="" default="1024">
+ Sets the number of samples to take when using importance sampling for [Sky]s and [ReflectionProbe]s. A higher value will result in smoother, higher quality reflections, but increases time to calculate radiance maps. In general, fewer samples are needed for simpler, low dynamic range environments while more samples are needed for HDR environments and environments with a high level of detail.
</member>
- <member name="rendering/quality/shadow_atlas/size.mobile" type="int" setter="" getter="" default="2048">
- Lower-end override for [member rendering/quality/shadow_atlas/size] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/reflections/sky_reflections/ggx_samples.mobile" type="int" setter="" getter="" default="128">
+ Lower-end override for [member rendering/reflections/sky_reflections/ggx_samples] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/quality/shadows/soft_shadow_quality" type="int" setter="" getter="" default="2">
- Quality setting for shadows cast by [OmniLight3D]s and [SpotLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
+ <member name="rendering/reflections/sky_reflections/roughness_layers" type="int" setter="" getter="" default="8">
+ Limits the number of layers to use in radiance maps when using importance sampling. A lower number will be slightly faster and take up less VRAM.
</member>
- <member name="rendering/quality/shadows/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0">
- Lower-end override for [member rendering/quality/shadows/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/reflections/sky_reflections/texture_array_reflections" type="bool" setter="" getter="" default="true">
+ If [code]true[/code], uses texture arrays instead of mipmaps for reflection probes and panorama backgrounds (sky). This reduces jitter noise and upscaling artifacts on reflections, but is significantly slower to compute and uses [member rendering/reflections/sky_reflections/roughness_layers] times more memory.
</member>
- <member name="rendering/quality/ssao/adaptive_target" type="float" setter="" getter="" default="0.5">
- Quality target to use when [member rendering/quality/ssao/quality] is set to [code]ULTRA[/code]. A value of [code]0.0[/code] provides a quality and speed similar to [code]MEDIUM[/code] while a value of [code]1.0[/code] provides much higher quality than any of the other settings at the cost of performance.
+ <member name="rendering/reflections/sky_reflections/texture_array_reflections.mobile" type="bool" setter="" getter="" default="false">
+ Lower-end override for [member rendering/reflections/sky_reflections/texture_array_reflections] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/quality/ssao/blur_passes" type="int" setter="" getter="" default="2">
- Number of blur passes to use when computing screen-space ambient occlusion. A higher number will result in a smoother look, but will be slower to compute and will have less high-frequency detail.
+ <member name="rendering/shading/overrides/force_blinn_over_ggx" type="bool" setter="" getter="" default="false">
+ If [code]true[/code], uses faster but lower-quality Blinn model to generate blurred reflections instead of the GGX model.
</member>
- <member name="rendering/quality/ssao/fadeout_from" type="float" setter="" getter="" default="50.0">
- Distance at which the screen-space ambient occlusion effect starts to fade out. Use this hide ambient occlusion at great distances.
+ <member name="rendering/shading/overrides/force_blinn_over_ggx.mobile" type="bool" setter="" getter="" default="true">
+ Lower-end override for [member rendering/shading/overrides/force_blinn_over_ggx] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/quality/ssao/fadeout_to" type="float" setter="" getter="" default="300.0">
- Distance at which the screen-space ambient occlusion is fully faded out. Use this hide ambient occlusion at great distances.
+ <member name="rendering/shading/overrides/force_lambert_over_burley" type="bool" setter="" getter="" default="false">
+ If [code]true[/code], uses faster but lower-quality Lambert material lighting model instead of Burley.
</member>
- <member name="rendering/quality/ssao/half_size" type="bool" setter="" getter="" default="false">
- If [code]true[/code], screen-space ambient occlusion will be rendered at half size and then upscaled before being added to the scene. This is significantly faster but may miss small details.
+ <member name="rendering/shading/overrides/force_lambert_over_burley.mobile" type="bool" setter="" getter="" default="true">
+ Lower-end override for [member rendering/shading/overrides/force_lambert_over_burley] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/quality/ssao/half_size.mobile" type="bool" setter="" getter="" default="true">
- Lower-end override for [member rendering/quality/ssao/half_size] on mobile devices, due to performance concerns.
+ <member name="rendering/shading/overrides/force_vertex_shading" type="bool" setter="" getter="" default="false">
+ If [code]true[/code], forces vertex shading for all rendering. This can increase performance a lot, but also reduces quality immensely. Can be used to optimize performance on low-end mobile devices.
</member>
- <member name="rendering/quality/ssao/quality" type="int" setter="" getter="" default="2">
- Sets the quality of the screen-space ambient occlusion effect. Higher values take more samples and so will result in better quality, at the cost of performance. Setting to [code]ULTRA[/code] will use the [member rendering/quality/ssao/adaptive_target] setting.
+ <member name="rendering/shading/overrides/force_vertex_shading.mobile" type="bool" setter="" getter="" default="true">
+ Lower-end override for [member rendering/shading/overrides/force_vertex_shading] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale" type="float" setter="" getter="" default="0.01">
- Scales the depth over which the subsurface scattering effect is applied. A high value may allow light to scatter into a part of the mesh or another mesh that is close in screen space but far in depth.
+ <member name="rendering/shadows/directional_shadow/16_bits" type="bool" setter="" getter="" default="true">
</member>
- <member name="rendering/quality/subsurface_scattering/subsurface_scattering_quality" type="int" setter="" getter="" default="1">
- Sets the quality of the subsurface scattering effect. Higher values are slower but look nicer.
+ <member name="rendering/shadows/directional_shadow/size" type="int" setter="" getter="" default="4096">
+ The directional shadow's size in pixels. Higher values will result in sharper shadows, at the cost of performance. The value will be rounded up to the nearest power of 2.
</member>
- <member name="rendering/quality/subsurface_scattering/subsurface_scattering_scale" type="float" setter="" getter="" default="0.05">
- Scales the distance over which samples are taken for subsurface scattering effect. Changing this does not impact performance, but higher values will result in significant artifacts as the samples will become obviously spread out. A lower value results in a smaller spread of scattered light.
+ <member name="rendering/shadows/directional_shadow/size.mobile" type="int" setter="" getter="" default="2048">
+ Lower-end override for [member rendering/shadows/directional_shadow/size] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/quality/texture_filters/anisotropic_filtering_level" type="int" setter="" getter="" default="2">
- Sets the maximum number of samples to take when using anisotropic filtering on textures (as a power of two). A higher sample count will result in sharper textures at oblique angles, but is more expensive to compute. A value of [code]0[/code] forcibly disables anisotropic filtering, even on materials where it is enabled.
+ <member name="rendering/shadows/directional_shadow/soft_shadow_quality" type="int" setter="" getter="" default="2">
+ Quality setting for shadows cast by [DirectionalLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
</member>
- <member name="rendering/quality/texture_filters/use_nearest_mipmap_filter" type="bool" setter="" getter="" default="false">
- If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used.
+ <member name="rendering/shadows/directional_shadow/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0">
+ Lower-end override for [member rendering/shadows/directional_shadow/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/sdfgi/frames_to_converge" type="int" setter="" getter="" default="4">
+ <member name="rendering/shadows/shadow_atlas/16_bits" type="bool" setter="" getter="" default="true">
</member>
- <member name="rendering/sdfgi/frames_to_update_lights" type="int" setter="" getter="" default="2">
+ <member name="rendering/shadows/shadow_atlas/quadrant_0_subdiv" type="int" setter="" getter="" default="2">
+ Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
- <member name="rendering/sdfgi/probe_ray_count" type="int" setter="" getter="" default="1">
+ <member name="rendering/shadows/shadow_atlas/quadrant_1_subdiv" type="int" setter="" getter="" default="2">
+ Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
- <member name="rendering/spatial_indexer/threaded_cull_minimum_instances" type="int" setter="" getter="" default="1000">
+ <member name="rendering/shadows/shadow_atlas/quadrant_2_subdiv" type="int" setter="" getter="" default="3">
+ Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
- <member name="rendering/spatial_indexer/update_iterations_per_frame" type="int" setter="" getter="" default="10">
+ <member name="rendering/shadows/shadow_atlas/quadrant_3_subdiv" type="int" setter="" getter="" default="4">
+ Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
- <member name="rendering/threads/thread_model" type="int" setter="" getter="" default="1">
- Thread model for rendering. Rendering on a thread can vastly improve performance, but synchronizing to the main thread can cause a bit more jitter.
+ <member name="rendering/shadows/shadow_atlas/size" type="int" setter="" getter="" default="4096">
+ Size for shadow atlas (used for OmniLights and SpotLights). See documentation.
</member>
- <member name="rendering/volumetric_fog/directional_shadow_shrink" type="int" setter="" getter="" default="512">
+ <member name="rendering/shadows/shadow_atlas/size.mobile" type="int" setter="" getter="" default="2048">
+ Lower-end override for [member rendering/shadows/shadow_atlas/size] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/volumetric_fog/positional_shadow_shrink" type="int" setter="" getter="" default="512">
+ <member name="rendering/shadows/shadows/soft_shadow_quality" type="int" setter="" getter="" default="2">
+ Quality setting for shadows cast by [OmniLight3D]s and [SpotLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
</member>
- <member name="rendering/volumetric_fog/use_filter" type="int" setter="" getter="" default="0">
+ <member name="rendering/shadows/shadows/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0">
+ Lower-end override for [member rendering/shadows/shadows/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/volumetric_fog/volume_depth" type="int" setter="" getter="" default="128">
+ <member name="rendering/textures/default_filters/anisotropic_filtering_level" type="int" setter="" getter="" default="2">
+ Sets the maximum number of samples to take when using anisotropic filtering on textures (as a power of two). A higher sample count will result in sharper textures at oblique angles, but is more expensive to compute. A value of [code]0[/code] forcibly disables anisotropic filtering, even on materials where it is enabled.
</member>
- <member name="rendering/volumetric_fog/volume_size" type="int" setter="" getter="" default="64">
+ <member name="rendering/textures/default_filters/use_nearest_mipmap_filter" type="bool" setter="" getter="" default="false">
+ If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used.
</member>
- <member name="rendering/vram_compression/import_bptc" type="bool" setter="" getter="" default="false">
+ <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.
</member>
- <member name="rendering/vram_compression/import_etc" type="bool" setter="" getter="" default="false">
+ <member name="rendering/textures/vram_compression/import_etc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression algorithm. This algorithm doesn't support alpha channels in textures.
</member>
- <member name="rendering/vram_compression/import_etc2" type="bool" setter="" getter="" default="true">
+ <member name="rendering/textures/vram_compression/import_etc2" type="bool" setter="" getter="" default="true">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression 2 algorithm. This texture compression algorithm is only supported when using the Vulkan renderer.
</member>
- <member name="rendering/vram_compression/import_pvrtc" type="bool" setter="" getter="" default="false">
+ <member name="rendering/textures/vram_compression/import_pvrtc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the PowerVR Texture Compression algorithm. This texture compression algorithm is only supported on iOS.
</member>
- <member name="rendering/vram_compression/import_s3tc" type="bool" setter="" getter="" default="true">
+ <member name="rendering/textures/vram_compression/import_s3tc" type="bool" setter="" getter="" default="true">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles.
</member>
<member name="rendering/vulkan/descriptor_pools/max_descriptors_per_pool" type="int" setter="" getter="" default="64">
diff --git a/doc/classes/Quat.xml b/doc/classes/Quat.xml
index ef83ae7fb9..1c0a3e37c0 100644
--- a/doc/classes/Quat.xml
+++ b/doc/classes/Quat.xml
@@ -83,7 +83,7 @@
Constructs a quaternion defined by the given values.
</description>
</method>
- <method name="cubic_slerp">
+ <method name="cubic_slerp" qualifiers="const">
<return type="Quat">
</return>
<argument index="0" name="b" type="Quat">
@@ -98,7 +98,7 @@
Performs a cubic spherical interpolation between quaternions [code]pre_a[/code], this vector, [code]b[/code], and [code]post_b[/code], by the given amount [code]weight[/code].
</description>
</method>
- <method name="dot">
+ <method name="dot" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="with" type="Quat">
@@ -107,51 +107,51 @@
Returns the dot product of two quaternions.
</description>
</method>
- <method name="get_euler">
+ <method name="get_euler" qualifiers="const">
<return type="Vector3">
</return>
<description>
Returns Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last) corresponding to the rotation represented by the unit quaternion. Returned vector contains the rotation angles in the format (X angle, Y angle, Z angle).
</description>
</method>
- <method name="inverse">
+ <method name="inverse" qualifiers="const">
<return type="Quat">
</return>
<description>
Returns the inverse of the quaternion.
</description>
</method>
- <method name="is_equal_approx">
+ <method name="is_equal_approx" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="to" type="Quat">
</argument>
<description>
- Returns [code]true[/code] if this quaterion and [code]quat[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component.
+ Returns [code]true[/code] if this quaternion and [code]quat[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component.
</description>
</method>
- <method name="is_normalized">
+ <method name="is_normalized" qualifiers="const">
<return type="bool">
</return>
<description>
Returns whether the quaternion is normalized or not.
</description>
</method>
- <method name="length">
+ <method name="length" qualifiers="const">
<return type="float">
</return>
<description>
Returns the length of the quaternion.
</description>
</method>
- <method name="length_squared">
+ <method name="length_squared" qualifiers="const">
<return type="float">
</return>
<description>
Returns the length of the quaternion, squared.
</description>
</method>
- <method name="normalized">
+ <method name="normalized" qualifiers="const">
<return type="Quat">
</return>
<description>
@@ -258,7 +258,7 @@
<description>
</description>
</method>
- <method name="slerp">
+ <method name="slerp" qualifiers="const">
<return type="Quat">
</return>
<argument index="0" name="to" type="Quat">
@@ -270,7 +270,7 @@
[b]Note:[/b] Both quaternions must be normalized.
</description>
</method>
- <method name="slerpni">
+ <method name="slerpni" qualifiers="const">
<return type="Quat">
</return>
<argument index="0" name="to" type="Quat">
diff --git a/doc/classes/RID.xml b/doc/classes/RID.xml
index 0ee34d4194..e686a4b8fd 100644
--- a/doc/classes/RID.xml
+++ b/doc/classes/RID.xml
@@ -25,7 +25,7 @@
Constructs a [RID] as a copy of the given [RID].
</description>
</method>
- <method name="get_id">
+ <method name="get_id" qualifiers="const">
<return type="int">
</return>
<description>
diff --git a/doc/classes/RayCast3D.xml b/doc/classes/RayCast3D.xml
index d24e86a08b..443890438f 100644
--- a/doc/classes/RayCast3D.xml
+++ b/doc/classes/RayCast3D.xml
@@ -136,6 +136,13 @@
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1">
The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information.
</member>
+ <member name="debug_shape_custom_color" type="Color" setter="set_debug_shape_custom_color" getter="get_debug_shape_custom_color" default="Color( 0, 0, 0, 1 )">
+ The custom color to use to draw the shape in the editor and at run-time if [b]Visible Collision Shapes[/b] is enabled in the [b]Debug[/b] menu. This color will be highlighted at run-time if the [RayCast3D] is colliding with something.
+ If set to [code]Color(0.0, 0.0, 0.0)[/code] (by default), the color set in [member ProjectSettings.debug/shapes/collision/shape_color] is used.
+ </member>
+ <member name="debug_shape_thickness" type="float" setter="set_debug_shape_thickness" getter="get_debug_shape_thickness" default="2.0">
+ If set to [code]1[/code], a line is used as the debug shape. Otherwise, a truncated pyramid is drawn to represent the [RayCast3D]. Requires [b]Visible Collision Shapes[/b] to be enabled in the [b]Debug[/b] menu for the debug shape to be visible at run-time.
+ </member>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true">
If [code]true[/code], collisions will be reported.
</member>
diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml
index 5d7ff39587..352a18e326 100644
--- a/doc/classes/Rect2.xml
+++ b/doc/classes/Rect2.xml
@@ -65,14 +65,14 @@
Constructs a [Rect2] by x, y, width, and height.
</description>
</method>
- <method name="abs">
+ <method name="abs" qualifiers="const">
<return type="Rect2">
</return>
<description>
Returns a [Rect2] with equivalent position and area, modified so that the top-left corner is the origin and [code]width[/code] and [code]height[/code] are positive.
</description>
</method>
- <method name="encloses">
+ <method name="encloses" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="b" type="Rect2">
@@ -81,7 +81,7 @@
Returns [code]true[/code] if this [Rect2] completely encloses another one.
</description>
</method>
- <method name="expand">
+ <method name="expand" qualifiers="const">
<return type="Rect2">
</return>
<argument index="0" name="to" type="Vector2">
@@ -90,14 +90,14 @@
Returns this [Rect2] expanded to include a given point.
</description>
</method>
- <method name="get_area">
+ <method name="get_area" qualifiers="const">
<return type="float">
</return>
<description>
Returns the area of the [Rect2].
</description>
</method>
- <method name="grow">
+ <method name="grow" qualifiers="const">
<return type="Rect2">
</return>
<argument index="0" name="amount" type="float">
@@ -106,7 +106,7 @@
Returns a copy of the [Rect2] grown by the specified [code]amount[/code] on all sides.
</description>
</method>
- <method name="grow_individual">
+ <method name="grow_individual" qualifiers="const">
<return type="Rect2">
</return>
<argument index="0" name="left" type="float">
@@ -121,7 +121,7 @@
Returns a copy of the [Rect2] grown by the specified amount on each side individually.
</description>
</method>
- <method name="grow_side">
+ <method name="grow_side" qualifiers="const">
<return type="Rect2">
</return>
<argument index="0" name="side" type="int">
@@ -132,14 +132,14 @@
Returns a copy of the [Rect2] grown by the specified [code]amount[/code] on the specified [enum Side].
</description>
</method>
- <method name="has_no_area">
+ <method name="has_no_area" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the [Rect2] is flat or empty.
</description>
</method>
- <method name="has_point">
+ <method name="has_point" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="point" type="Vector2">
@@ -148,7 +148,7 @@
Returns [code]true[/code] if the [Rect2] contains a point.
</description>
</method>
- <method name="intersection">
+ <method name="intersection" qualifiers="const">
<return type="Rect2">
</return>
<argument index="0" name="b" type="Rect2">
@@ -158,7 +158,7 @@
If the rectangles do not intersect, an empty [Rect2] is returned.
</description>
</method>
- <method name="intersects">
+ <method name="intersects" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="b" type="Rect2">
@@ -170,7 +170,7 @@
If [code]include_borders[/code] is [code]true[/code], they will also be considered overlapping if their borders touch, even without intersection.
</description>
</method>
- <method name="is_equal_approx">
+ <method name="is_equal_approx" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="rect" type="Rect2">
@@ -179,7 +179,7 @@
Returns [code]true[/code] if this [Rect2] and [code]rect[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
</description>
</method>
- <method name="merge">
+ <method name="merge" qualifiers="const">
<return type="Rect2">
</return>
<argument index="0" name="b" type="Rect2">
@@ -221,7 +221,7 @@
Beginning corner. Typically has values lower than [member end].
</member>
<member name="size" type="Vector2" setter="" getter="" default="Vector2( 0, 0 )">
- Size from [member position] to [member end]. Typically all components are positive.
+ Size from [member position] to [member end]. Typically, all components are positive.
If the size is negative, you can use [method abs] to fix it.
</member>
</members>
diff --git a/doc/classes/Rect2i.xml b/doc/classes/Rect2i.xml
index e581ccdb11..84bef9b406 100644
--- a/doc/classes/Rect2i.xml
+++ b/doc/classes/Rect2i.xml
@@ -63,14 +63,14 @@
Constructs a [Rect2i] by x, y, width, and height.
</description>
</method>
- <method name="abs">
+ <method name="abs" qualifiers="const">
<return type="Rect2i">
</return>
<description>
Returns a [Rect2i] with equivalent position and area, modified so that the top-left corner is the origin and [code]width[/code] and [code]height[/code] are positive.
</description>
</method>
- <method name="encloses">
+ <method name="encloses" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="b" type="Rect2i">
@@ -79,7 +79,7 @@
Returns [code]true[/code] if this [Rect2i] completely encloses another one.
</description>
</method>
- <method name="expand">
+ <method name="expand" qualifiers="const">
<return type="Rect2i">
</return>
<argument index="0" name="to" type="Vector2i">
@@ -88,14 +88,14 @@
Returns this [Rect2i] expanded to include a given point.
</description>
</method>
- <method name="get_area">
+ <method name="get_area" qualifiers="const">
<return type="int">
</return>
<description>
Returns the area of the [Rect2i].
</description>
</method>
- <method name="grow">
+ <method name="grow" qualifiers="const">
<return type="Rect2i">
</return>
<argument index="0" name="amount" type="int">
@@ -104,7 +104,7 @@
Returns a copy of the [Rect2i] grown by the specified [code]amount[/code] on all sides.
</description>
</method>
- <method name="grow_individual">
+ <method name="grow_individual" qualifiers="const">
<return type="Rect2i">
</return>
<argument index="0" name="left" type="int">
@@ -119,7 +119,7 @@
Returns a copy of the [Rect2i] grown by the specified amount on each side individually.
</description>
</method>
- <method name="grow_side">
+ <method name="grow_side" qualifiers="const">
<return type="Rect2i">
</return>
<argument index="0" name="side" type="int">
@@ -130,14 +130,14 @@
Returns a copy of the [Rect2i] grown by the specified [code]amount[/code] on the specified [enum Side].
</description>
</method>
- <method name="has_no_area">
+ <method name="has_no_area" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the [Rect2i] is flat or empty.
</description>
</method>
- <method name="has_point">
+ <method name="has_point" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="point" type="Vector2i">
@@ -146,7 +146,7 @@
Returns [code]true[/code] if the [Rect2i] contains a point.
</description>
</method>
- <method name="intersection">
+ <method name="intersection" qualifiers="const">
<return type="Rect2i">
</return>
<argument index="0" name="b" type="Rect2i">
@@ -156,7 +156,7 @@
If the rectangles do not intersect, an empty [Rect2i] is returned.
</description>
</method>
- <method name="intersects">
+ <method name="intersects" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="b" type="Rect2i">
@@ -166,7 +166,7 @@
If [code]include_borders[/code] is [code]true[/code], they will also be considered overlapping if their borders touch, even without intersection.
</description>
</method>
- <method name="merge">
+ <method name="merge" qualifiers="const">
<return type="Rect2i">
</return>
<argument index="0" name="b" type="Rect2i">
@@ -200,7 +200,7 @@
Beginning corner. Typically has values lower than [member end].
</member>
<member name="size" type="Vector2i" setter="" getter="" default="Vector2i( 0, 0 )">
- Size from [member position] to [member end]. Typically all components are positive.
+ Size from [member position] to [member end]. Typically, all components are positive.
If the size is negative, you can use [method abs] to fix it.
</member>
</members>
diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml
index d0fb2b9d47..841d2bde72 100644
--- a/doc/classes/RenderingDevice.xml
+++ b/doc/classes/RenderingDevice.xml
@@ -74,6 +74,8 @@
<method name="compute_list_begin">
<return type="int">
</return>
+ <argument index="0" name="allow_draw_overlap" type="bool" default="false">
+ </argument>
<description>
</description>
</method>
@@ -443,6 +445,24 @@
<description>
</description>
</method>
+ <method name="get_device_name" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_device_pipeline_cache_uuid" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_device_vendor_name" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_frame_delay" qualifiers="const">
<return type="int">
</return>
@@ -470,7 +490,7 @@
</argument>
<argument index="2" name="data" type="PackedByteArray" default="PackedByteArray( )">
</argument>
- <argument index="3" name="arg3" type="bool" default="false">
+ <argument index="3" name="use_restart_indices" type="bool" default="false">
</argument>
<description>
</description>
@@ -823,6 +843,8 @@
</constant>
<constant name="BARRIER_MASK_ALL" value="7">
</constant>
+ <constant name="BARRIER_MASK_NO_BARRIER" value="8">
+ </constant>
<constant name="DATA_FORMAT_R4G4_UNORM_PACK8" value="0" enum="DataFormat">
</constant>
<constant name="DATA_FORMAT_R4G4B4A4_UNORM_PACK16" value="1" enum="DataFormat">
@@ -1587,13 +1609,15 @@
</constant>
<constant name="INITIAL_ACTION_CLEAR_REGION" value="1" enum="InitialAction">
</constant>
- <constant name="INITIAL_ACTION_KEEP" value="2" enum="InitialAction">
+ <constant name="INITIAL_ACTION_CLEAR_REGION_CONTINUE" value="2" enum="InitialAction">
+ </constant>
+ <constant name="INITIAL_ACTION_KEEP" value="3" enum="InitialAction">
</constant>
- <constant name="INITIAL_ACTION_DROP" value="3" enum="InitialAction">
+ <constant name="INITIAL_ACTION_DROP" value="4" enum="InitialAction">
</constant>
- <constant name="INITIAL_ACTION_CONTINUE" value="4" enum="InitialAction">
+ <constant name="INITIAL_ACTION_CONTINUE" value="5" enum="InitialAction">
</constant>
- <constant name="INITIAL_ACTION_MAX" value="5" enum="InitialAction">
+ <constant name="INITIAL_ACTION_MAX" value="6" enum="InitialAction">
</constant>
<constant name="FINAL_ACTION_READ" value="0" enum="FinalAction">
</constant>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index efc751bb94..f82301bcf4 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -10,7 +10,7 @@
Resources are created using the [code]*_create[/code] functions.
All objects are drawn to a viewport. You can use the [Viewport] attached to the [SceneTree] or you can create one yourself with [method viewport_create]. When using a custom scenario or canvas, the scenario or canvas needs to be attached to the viewport using [method viewport_set_scenario] or [method viewport_attach_canvas].
In 3D, all visual objects must be associated with a scenario. The scenario is a visual representation of the world. If accessing the rendering server from a running game, the scenario can be accessed from the scene tree from any [Node3D] node with [method Node3D.get_world_3d]. Otherwise, a scenario can be created with [method scenario_create].
- Similarly in 2D, a canvas is needed to draw all canvas items.
+ Similarly, in 2D, a canvas is needed to draw all canvas items.
In 3D, all visible objects are comprised of a resource and an instance. A resource can be a mesh, a particle system, a light, or any other 3D object. In order to be visible resources must be attached to an instance using [method instance_set_base]. The instance must also be attached to the scenario using [method instance_set_scenario] in order to be visible.
In 2D, all visible objects are some form of canvas item. In order to be visible, a canvas item needs to be the child of a canvas attached to a viewport, or it needs to be the child of another canvas item that is eventually attached to the canvas.
</description>
@@ -1292,7 +1292,7 @@
<argument index="1" name="margin" type="float">
</argument>
<description>
- Sets a margin to increase the size of the AABB when culling objects from the view frustum. This allows you avoid culling objects that fall outside the view frustum. Equivalent to [member GeometryInstance3D.extra_cull_margin].
+ Sets a margin to increase the size of the AABB when culling objects from the view frustum. This allows you to avoid culling objects that fall outside the view frustum. Equivalent to [member GeometryInstance3D.extra_cull_margin].
</description>
</method>
<method name="instance_set_layer_mask">
@@ -1520,7 +1520,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
- If [code]true[/code], reverses the backface culling of the mesh. This can be useful when you have a flat mesh that has a light behind it. If you need to cast a shadow on both sides of the mesh, set the mesh to use double sided shadows with [method instance_geometry_set_cast_shadows_setting]. Equivalent to [member Light3D.shadow_reverse_cull_face].
+ If [code]true[/code], reverses the backface culling of the mesh. This can be useful when you have a flat mesh that has a light behind it. If you need to cast a shadow on both sides of the mesh, set the mesh to use double-sided shadows with [method instance_geometry_set_cast_shadows_setting]. Equivalent to [member Light3D.shadow_reverse_cull_face].
</description>
</method>
<method name="light_set_shadow">
@@ -1802,7 +1802,7 @@
Updates a specific region of a vertex buffer for the specified surface. Warning: this function alters the vertex buffer directly with no safety mechanisms, you can easily corrupt your mesh.
</description>
</method>
- <method name="multimesh_allocate">
+ <method name="multimesh_allocate_data">
<return type="void">
</return>
<argument index="0" name="multimesh" type="RID">
@@ -2204,7 +2204,7 @@
<argument index="1" name="time" type="float">
</argument>
<description>
- Sets the preprocess time for the particles animation. This lets you delay starting an animation until after the particles have begun emitting. Equivalent to [member GPUParticles3D.preprocess].
+ Sets the preprocess time for the particles' animation. This lets you delay starting an animation until after the particles have begun emitting. Equivalent to [member GPUParticles3D.preprocess].
</description>
</method>
<method name="particles_set_process_material">
@@ -2549,7 +2549,7 @@
Sets a shader's default texture. Overwrites the texture given by name.
</description>
</method>
- <method name="skeleton_allocate">
+ <method name="skeleton_allocate_data">
<return type="void">
</return>
<argument index="0" name="skeleton" type="RID">
@@ -2559,7 +2559,6 @@
<argument index="2" name="is_2d_skeleton" type="bool" default="false">
</argument>
<description>
- Allocates the GPU buffers for this skeleton.
</description>
</method>
<method name="skeleton_bone_get_transform" qualifiers="const">
@@ -2705,11 +2704,14 @@
<description>
Copies the viewport to a region of the screen specified by [code]rect[/code]. If [method viewport_set_render_direct_to_screen] is [code]true[/code], then the viewport does not use a framebuffer and the contents of the viewport are rendered directly to screen. However, note that the root viewport is drawn last, therefore it will draw over the screen. Accordingly, you must set the root viewport to an area that does not cover the area that you have attached this viewport to.
For example, you can set the root viewport to not render at all with the following code:
- [codeblock]
+ FIXME: The method seems to be non-existent.
+ [codeblocks]
+ [gdscript]
func _ready():
get_viewport().set_attach_to_screen_rect(Rect2())
$Viewport.set_attach_to_screen_rect(Rect2(0, 0, 600, 600))
- [/codeblock]
+ [/gdscript]
+ [/codeblocks]
Using this can result in significant optimization, especially on lower-end devices. However, it comes at the cost of having to manage your viewports manually. For a further optimization see, [method viewport_set_render_direct_to_screen].
</description>
</method>
@@ -3453,7 +3455,7 @@
<constant name="VIEWPORT_DEBUG_DRAW_GI_BUFFER" value="17" enum="ViewportDebugDraw">
</constant>
<constant name="SKY_MODE_QUALITY" value="1" enum="SkyMode">
- Uses high quality importance sampling to process the radiance map. In general, this results in much higher quality than [constant Sky.PROCESS_MODE_REALTIME] but takes much longer to generate. This should not be used if you plan on changing the sky at runtime. If you are finding that the reflection is not blurry enough and is showing sparkles or fireflies, try increasing [member ProjectSettings.rendering/quality/reflections/ggx_samples].
+ Uses high quality importance sampling to process the radiance map. In general, this results in much higher quality than [constant Sky.PROCESS_MODE_REALTIME] but takes much longer to generate. This should not be used if you plan on changing the sky at runtime. If you are finding that the reflection is not blurry enough and is showing sparkles or fireflies, try increasing [member ProjectSettings.rendering/reflections/sky_reflections/ggx_samples].
</constant>
<constant name="SKY_MODE_REALTIME" value="3" enum="SkyMode">
Uses the fast filtering algorithm to process the radiance map. In general this results in lower quality, but substantially faster run times.
diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml
index ad0c438f98..9943f644cf 100644
--- a/doc/classes/ResourceFormatLoader.xml
+++ b/doc/classes/ResourceFormatLoader.xml
@@ -6,7 +6,7 @@
<description>
Godot loads resources in the editor or in exported games using ResourceFormatLoaders. They are queried automatically via the [ResourceLoader] singleton, or when a resource with internal dependencies is loaded. Each file type may load as a different resource type, so multiple ResourceFormatLoaders are registered in the engine.
Extending this class allows you to define your own loader. Be sure to respect the documented return types and values. You should give it a global class name with [code]class_name[/code] for it to be registered. Like built-in ResourceFormatLoaders, it will be called automatically when loading resources of its handled type(s). You may also implement a [ResourceFormatSaver].
- [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].stex[/code] ([StreamTexture2D]) first, so they can be loaded with better efficiency on the graphics card.
+ [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends on if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].stex[/code] ([StreamTexture2D]) first, so they can be loaded with better efficiency on the graphics card.
</description>
<tutorials>
</tutorials>
@@ -57,8 +57,13 @@
</argument>
<argument index="1" name="original_path" type="String">
</argument>
+ <argument index="2" name="use_sub_threads" type="bool">
+ </argument>
+ <argument index="3" name="cache_mode" type="int">
+ </argument>
<description>
Loads a resource when the engine finds this loader to be compatible. If the loaded resource is the result of an import, [code]original_path[/code] will target the source file. Returns a [Resource] object on success, or an [enum Error] constant in case of failure.
+ The [code]cache_mode[/code] property defines whether and how the cache should be used or updated when loading the resource. See [enum CacheMode] for details.
</description>
</method>
<method name="rename_dependencies" qualifiers="virtual">
@@ -75,5 +80,11 @@
</method>
</methods>
<constants>
+ <constant name="CACHE_MODE_IGNORE" value="0" enum="CacheMode">
+ </constant>
+ <constant name="CACHE_MODE_REUSE" value="1" enum="CacheMode">
+ </constant>
+ <constant name="CACHE_MODE_REPLACE" value="2" enum="CacheMode">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/ResourceLoader.xml b/doc/classes/ResourceLoader.xml
index c55a51c7ae..c81b21333f 100644
--- a/doc/classes/ResourceLoader.xml
+++ b/doc/classes/ResourceLoader.xml
@@ -58,13 +58,13 @@
</argument>
<argument index="1" name="type_hint" type="String" default="&quot;&quot;">
</argument>
- <argument index="2" name="no_cache" type="bool" default="false">
+ <argument index="2" name="cache_mode" type="int" enum="ResourceLoader.CacheMode" default="1">
</argument>
<description>
Loads a resource at the given [code]path[/code], caching the result for further access.
The registered [ResourceFormatLoader]s are queried sequentially to find the first one which can handle the file's extension, and then attempt loading. If loading fails, the remaining ResourceFormatLoaders are also attempted.
An optional [code]type_hint[/code] can be used to further specify the [Resource] type that should be handled by the [ResourceFormatLoader]. Anything that inherits from [Resource] can be used as a type hint, for example [Image].
- If [code]no_cache[/code] is [code]true[/code], the resource cache will be bypassed and the resource will be loaded anew. Otherwise, the cached resource will be returned if it exists.
+ The [code]cache_mode[/code] property defines whether and how the cache should be used or updated when loading the resource. See [enum CacheMode] for details.
Returns an empty resource if no [ResourceFormatLoader] could handle the file.
GDScript has a simplified [method @GDScript.load] built-in method which can be used in most situations, leaving the use of [ResourceLoader] for more advanced scenarios.
</description>
@@ -127,5 +127,11 @@
<constant name="THREAD_LOAD_LOADED" value="3" enum="ThreadLoadStatus">
The resource was loaded successfully and can be accessed via [method load_threaded_get].
</constant>
+ <constant name="CACHE_MODE_IGNORE" value="0" enum="CacheMode">
+ </constant>
+ <constant name="CACHE_MODE_REUSE" value="1" enum="CacheMode">
+ </constant>
+ <constant name="CACHE_MODE_REPLACE" value="2" enum="CacheMode">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/RichTextEffect.xml b/doc/classes/RichTextEffect.xml
index 726b26fbc7..edab35f162 100644
--- a/doc/classes/RichTextEffect.xml
+++ b/doc/classes/RichTextEffect.xml
@@ -6,10 +6,16 @@
<description>
A custom effect for use with [RichTextLabel].
[b]Note:[/b] For a [RichTextEffect] to be usable, a BBCode tag must be defined as a member variable called [code]bbcode[/code] in the script.
- [codeblock]
+ [codeblocks]
+ [gdscript]
# The RichTextEffect will be usable like this: `[example]Some text[/example]`
var bbcode = "example"
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ // The RichTextEffect will be usable like this: `[example]Some text[/example]`
+ public string bbcode = "example";
+ [/csharp]
+ [/codeblocks]
[b]Note:[/b] As soon as a [RichTextLabel] contains at least one [RichTextEffect], it will continuously process the effect unless the project is paused. This may impact battery life negatively.
</description>
<tutorials>
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 35eae32c7b..7ca70f5a7a 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -80,6 +80,27 @@
Returns the total number of paragraphs (newlines or [code]p[/code] tags in the tag stack's text tags). Considers wrapped text as one paragraph.
</description>
</method>
+ <method name="get_selected_text" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ Returns the current selection text. Does not include BBCodes.
+ </description>
+ </method>
+ <method name="get_selection_from" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the current selection first character index if a selection is active, [code]-1[/code] otherwise. Does not include BBCodes.
+ </description>
+ </method>
+ <method name="get_selection_to" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the current selection last character index if a selection is active, [code]-1[/code] otherwise. Does not include BBCodes.
+ </description>
+ </method>
<method name="get_total_character_count" qualifiers="const">
<return type="int">
</return>
@@ -597,6 +618,9 @@
<theme_item name="focus" type="StyleBox">
The background The background used when the [RichTextLabel] is focused.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The default tint of text outline.
+ </theme_item>
<theme_item name="font_selected_color" type="Color" default="Color( 0, 0, 0, 1 )">
The color of selected text, used when [member selection_enabled] is [code]true[/code].
</theme_item>
@@ -627,6 +651,9 @@
<theme_item name="normal_font_size" type="int">
The default text font size.
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
<theme_item name="selection_color" type="Color" default="Color( 0.1, 0.1, 1, 0.8 )">
The color of the selection box.
</theme_item>
diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml
index 6b27c77f26..ed375a8b1e 100644
--- a/doc/classes/RigidBody2D.xml
+++ b/doc/classes/RigidBody2D.xml
@@ -4,7 +4,7 @@
A body that is controlled by the 2D physics engine.
</brief_description>
<description>
- This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties.
+ This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead, you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties.
A RigidBody2D has 4 behavior [member mode]s: Rigid, Static, Character, and Kinematic.
[b]Note:[/b] You should not change a RigidBody2D's [code]position[/code] or [code]linear_velocity[/code] every frame or even very often. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state.
Please also keep in mind that physics bodies manage their own transform which overwrites the ones you set. So any direct or indirect transformation (including scaling of the node or its parent) will be visible in the editor only, and immediately reset at runtime.
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index cfe6e4f738..9366d7dd44 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
As one of the most important classes, the [SceneTree] manages the hierarchy of nodes in a scene as well as scenes themselves. Nodes can be added, retrieved and removed. The whole scene tree (and thus the current scene) can be paused. Scenes can be loaded, switched and reloaded.
- You can also use the [SceneTree] to organize your nodes into groups: every node can be assigned as many groups as you want to create, e.g. a "enemy" group. You can then iterate these groups or even call methods and set properties on all the group's members at once.
+ You can also use the [SceneTree] to organize your nodes into groups: every node can be assigned as many groups as you want to create, e.g. an "enemy" group. You can then iterate these groups or even call methods and set properties on all the group's members at once.
[SceneTree] is the default [MainLoop] implementation used by scenes, and is thus in charge of the game loop.
</description>
<tutorials>
@@ -64,20 +64,38 @@
</return>
<argument index="0" name="time_sec" type="float">
</argument>
- <argument index="1" name="pause_mode_process" type="bool" default="true">
+ <argument index="1" name="process_always" type="bool" default="true">
</argument>
<description>
- Returns a [SceneTreeTimer] which will [signal SceneTreeTimer.timeout] after the given time in seconds elapsed in this [SceneTree]. If [code]pause_mode_process[/code] is set to [code]false[/code], pausing the [SceneTree] will also pause the timer.
+ Returns a [SceneTreeTimer] which will [signal SceneTreeTimer.timeout] after the given time in seconds elapsed in this [SceneTree]. If [code]process_always[/code] is set to [code]false[/code], pausing the [SceneTree] will also pause the timer.
Commonly used to create a one-shot delay timer as in the following example:
- [codeblock]
+ [codeblocks]
+ [gdscript]
func some_function():
print("start")
yield(get_tree().create_timer(1.0), "timeout")
print("end")
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ public async void SomeFunction()
+ {
+ GD.Print("start");
+ await ToSignal(GetTree().CreateTimer(1.0f), "timeout");
+ GD.Print("end");
+ }
+ [/csharp]
+ [/codeblocks]
The timer will be automatically freed after its time elapses.
</description>
</method>
+ <method name="get_first_node_in_group">
+ <return type="Node">
+ </return>
+ <argument index="0" name="group" type="StringName">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="get_frame" qualifiers="const">
<return type="int">
</return>
@@ -181,10 +199,12 @@
<method name="quit">
<return type="void">
</return>
- <argument index="0" name="exit_code" type="int" default="-1">
+ <argument index="0" name="exit_code" type="int" default="0">
</argument>
<description>
- Quits the application at the end of the current iteration. A process [code]exit_code[/code] can optionally be passed as an argument. If this argument is [code]0[/code] or greater, it will override the [member OS.exit_code] defined before quitting the application.
+ Quits the application at the end of the current iteration. Argument [code]exit_code[/code] can optionally be given (defaulting to 0) to customize the exit status code.
+ By convention, an exit code of [code]0[/code] indicates success whereas a non-zero exit code indicates an error.
+ For portability reasons, the exit code should be set between 0 and 125 (inclusive).
</description>
</method>
<method name="reload_current_scene">
@@ -361,6 +381,11 @@
Emitted whenever the [SceneTree] hierarchy changed (children being moved or renamed, etc.).
</description>
</signal>
+ <signal name="tree_process_mode_changed">
+ <description>
+ This signal is only emitted in the editor, it allows the editor to update the visibility of disabled nodes. Emitted whenever any node's [member Node.process_mode] is changed.
+ </description>
+ </signal>
</signals>
<constants>
<constant name="GROUP_CALL_DEFAULT" value="0" enum="GroupCallFlags">
diff --git a/doc/classes/SceneTreeTimer.xml b/doc/classes/SceneTreeTimer.xml
index a4a83fa65b..b223bf6821 100644
--- a/doc/classes/SceneTreeTimer.xml
+++ b/doc/classes/SceneTreeTimer.xml
@@ -6,12 +6,22 @@
<description>
A one-shot timer managed by the scene tree, which emits [signal timeout] on completion. See also [method SceneTree.create_timer].
As opposed to [Timer], it does not require the instantiation of a node. Commonly used to create a one-shot delay timer as in the following example:
- [codeblock]
+ [codeblocks]
+ [gdscript]
func some_function():
print("Timer started.")
yield(get_tree().create_timer(1.0), "timeout")
print("Timer ended.")
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ public async void SomeFunction()
+ {
+ GD.Print("Timer started.");
+ await ToSignal(GetTree().CreateTimer(1.0f), "timeout");
+ GD.Print("Timer ended.");
+ }
+ [/csharp]
+ [/codeblocks]
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/ScriptCreateDialog.xml b/doc/classes/ScriptCreateDialog.xml
index aa60ecb12b..7185213c44 100644
--- a/doc/classes/ScriptCreateDialog.xml
+++ b/doc/classes/ScriptCreateDialog.xml
@@ -5,12 +5,24 @@
</brief_description>
<description>
The [ScriptCreateDialog] creates script files according to a given template for a given scripting language. The standard use is to configure its fields prior to calling one of the [method Window.popup] methods.
- [codeblock]
+ [codeblocks]
+ [gdscript]
func _ready():
- dialog.config("Node", "res://new_node.gd") # For in-engine types
- dialog.config("\"res://base_node.gd\"", "res://derived_node.gd") # For script types
+ var dialog = ScriptCreateDialog.new();
+ dialog.config("Node", "res://new_node.gd") # For in-engine types.
+ dialog.config("\"res://base_node.gd\"", "res://derived_node.gd") # For script types.
dialog.popup_centered()
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ public override void _Ready()
+ {
+ var dialog = new ScriptCreateDialog();
+ dialog.Config("Node", "res://NewNode.cs"); // For in-engine types.
+ dialog.Config("\"res://BaseNode.cs\"", "res://DerivedNode.cs"); // For script types.
+ dialog.PopupCentered();
+ }
+ [/csharp]
+ [/codeblocks]
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/ScriptEditor.xml b/doc/classes/ScriptEditor.xml
index d5a32dd20c..28620bd29b 100644
--- a/doc/classes/ScriptEditor.xml
+++ b/doc/classes/ScriptEditor.xml
@@ -37,6 +37,7 @@
<return type="ScriptEditorBase">
</return>
<description>
+ Returns the [ScriptEditorBase] object that the user is currently editing.
</description>
</method>
<method name="get_current_script">
@@ -60,6 +61,7 @@
<return type="Array">
</return>
<description>
+ Returns an array with all [ScriptEditorBase] objects which are currently open in editor.
</description>
</method>
<method name="get_open_scripts" qualifiers="const">
@@ -95,6 +97,8 @@
<argument index="0" name="syntax_highlighter" type="EditorSyntaxHighlighter">
</argument>
<description>
+ Registers the [EditorSyntaxHighlighter] to the editor, the [EditorSyntaxHighlighter] will be available on all open scripts.
+ [b]Note:[/b] Does not apply to scripts that are already opened.
</description>
</method>
<method name="unregister_syntax_highlighter">
@@ -103,6 +107,8 @@
<argument index="0" name="syntax_highlighter" type="EditorSyntaxHighlighter">
</argument>
<description>
+ Unregisters the [EditorSyntaxHighlighter] from the editor.
+ [b]Note:[/b] The [EditorSyntaxHighlighter] will still be applied to scripts that are already opened.
</description>
</method>
</methods>
diff --git a/doc/classes/ScriptEditorBase.xml b/doc/classes/ScriptEditorBase.xml
index 9968ae06c3..ee498de302 100644
--- a/doc/classes/ScriptEditorBase.xml
+++ b/doc/classes/ScriptEditorBase.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ScriptEditorBase" inherits="VBoxContainer" version="4.0">
<brief_description>
+ Base editor for editing scripts in the [ScriptEditor].
</brief_description>
<description>
+ Base editor for editing scripts in the [ScriptEditor], this does not include documentation items.
</description>
<tutorials>
</tutorials>
@@ -13,34 +15,40 @@
<argument index="0" name="highlighter" type="Object">
</argument>
<description>
+ Adds a [EditorSyntaxHighlighter] to the open script.
</description>
</method>
</methods>
<signals>
<signal name="edited_script_changed">
<description>
+ Emitted after script validation. For visual scripts on modification.
</description>
</signal>
<signal name="go_to_help">
<argument index="0" name="what" type="String">
</argument>
<description>
+ Emitted when the user requests a specific documentation page.
</description>
</signal>
<signal name="name_changed">
<description>
+ Emitted after script validation or when the edited resource has changed. Not used by visual scripts.
</description>
</signal>
<signal name="replace_in_files_requested">
<argument index="0" name="text" type="String">
</argument>
<description>
+ Emitted when the user request to find and replace text in the file system. Not used by visual scripts.
</description>
</signal>
<signal name="request_help">
<argument index="0" name="topic" type="String">
</argument>
<description>
+ Emitted when the user requests contextual help.
</description>
</signal>
<signal name="request_open_script_at_line">
@@ -49,16 +57,19 @@
<argument index="1" name="line" type="int">
</argument>
<description>
+ Emitted when the user requests a script.
</description>
</signal>
<signal name="request_save_history">
<description>
+ Emitted when the user contextual goto and the item is in the same script.
</description>
</signal>
<signal name="search_in_files_requested">
<argument index="0" name="text" type="String">
</argument>
<description>
+ Emitted when the user request to search text in the file system. Not used by visual scripts.
</description>
</signal>
</signals>
diff --git a/doc/classes/Shape3D.xml b/doc/classes/Shape3D.xml
index 2d8bb5d051..f8b749aebf 100644
--- a/doc/classes/Shape3D.xml
+++ b/doc/classes/Shape3D.xml
@@ -13,7 +13,8 @@
</methods>
<members>
<member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.04">
- The collision margin for the shape.
+ The collision margin for the shape. Used in Bullet Physics only.
+ Collision margins allow collision detection to be more efficient by adding an extra shell around shapes. Collision algorithms are more expensive when objects overlap by more than their margin, so a higher value for margins is better for performance, at the cost of accuracy around edges as it makes them less sharp.
</member>
</members>
<constants>
diff --git a/doc/classes/Signal.xml b/doc/classes/Signal.xml
index b7a2258fc1..84efc974c0 100644
--- a/doc/classes/Signal.xml
+++ b/doc/classes/Signal.xml
@@ -57,42 +57,42 @@
Disconnects this signal from the specified [Callable].
</description>
</method>
- <method name="emit" qualifiers="vararg">
+ <method name="emit" qualifiers="vararg const">
<return type="void">
</return>
<description>
Emits this signal to all connected objects.
</description>
</method>
- <method name="get_connections">
+ <method name="get_connections" qualifiers="const">
<return type="Array">
</return>
<description>
Returns the list of [Callable]s connected to this signal.
</description>
</method>
- <method name="get_name">
+ <method name="get_name" qualifiers="const">
<return type="StringName">
</return>
<description>
Returns the name of this signal.
</description>
</method>
- <method name="get_object">
+ <method name="get_object" qualifiers="const">
<return type="Object">
</return>
<description>
Returns the object emitting this signal.
</description>
</method>
- <method name="get_object_id">
+ <method name="get_object_id" qualifiers="const">
<return type="int">
</return>
<description>
Returns the ID of the object emitting this signal (see [method Object.get_instance_id]).
</description>
</method>
- <method name="is_connected">
+ <method name="is_connected" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="callable" type="Callable">
@@ -101,7 +101,7 @@
Returns [code]true[/code] if the specified [Callable] is connected to this signal.
</description>
</method>
- <method name="is_null">
+ <method name="is_null" qualifiers="const">
<return type="bool">
</return>
<description>
diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml
index fe2cc1f5ad..cb72ae7e4c 100644
--- a/doc/classes/Skeleton3D.xml
+++ b/doc/classes/Skeleton3D.xml
@@ -297,7 +297,7 @@
<argument index="0" name="bone_idx" type="int">
</argument>
<description>
- Unparents the bone at [code]bone_idx[/code] and sets its rest position to that of it's parent prior to being reset.
+ Unparents the bone at [code]bone_idx[/code] and sets its rest position to that of its parent prior to being reset.
</description>
</method>
<method name="world_transform_to_bone_transform">
diff --git a/doc/classes/Sky.xml b/doc/classes/Sky.xml
index a77515b3e6..d9553a3be3 100644
--- a/doc/classes/Sky.xml
+++ b/doc/classes/Sky.xml
@@ -52,13 +52,13 @@
Automatically selects the appropriate process mode based on your sky shader. If your shader uses [code]TIME[/code] or [code]POSITION[/code], this will use [constant PROCESS_MODE_REALTIME]. If your shader uses any of the [code]LIGHT_*[/code] variables or any custom uniforms, this uses [constant PROCESS_MODE_INCREMENTAL]. Otherwise, this defaults to [constant PROCESS_MODE_QUALITY].
</constant>
<constant name="PROCESS_MODE_QUALITY" value="1" enum="ProcessMode">
- Uses high quality importance sampling to process the radiance map. In general, this results in much higher quality than [constant PROCESS_MODE_REALTIME] but takes much longer to generate. This should not be used if you plan on changing the sky at runtime. If you are finding that the reflection is not blurry enough and is showing sparkles or fireflies, try increasing [member ProjectSettings.rendering/quality/reflections/ggx_samples].
+ Uses high quality importance sampling to process the radiance map. In general, this results in much higher quality than [constant PROCESS_MODE_REALTIME] but takes much longer to generate. This should not be used if you plan on changing the sky at runtime. If you are finding that the reflection is not blurry enough and is showing sparkles or fireflies, try increasing [member ProjectSettings.rendering/reflections/sky_reflections/ggx_samples].
</constant>
<constant name="PROCESS_MODE_INCREMENTAL" value="2" enum="ProcessMode">
- Uses the same high quality importance sampling to process the radiance map as [constant PROCESS_MODE_QUALITY], but updates over several frames. The number of frames is determined by [member ProjectSettings.rendering/quality/reflections/roughness_layers]. Use this when you need highest quality radiance maps, but have a sky that updates slowly.
+ Uses the same high quality importance sampling to process the radiance map as [constant PROCESS_MODE_QUALITY], but updates over several frames. The number of frames is determined by [member ProjectSettings.rendering/reflections/sky_reflections/roughness_layers]. Use this when you need highest quality radiance maps, but have a sky that updates slowly.
</constant>
<constant name="PROCESS_MODE_REALTIME" value="3" enum="ProcessMode">
- Uses the fast filtering algorithm to process the radiance map. In general this results in lower quality, but substantially faster run times. If you need better quality, but still need to update the sky every frame, consider turning on [member ProjectSettings.rendering/quality/reflections/fast_filter_high_quality].
+ Uses the fast filtering algorithm to process the radiance map. In general this results in lower quality, but substantially faster run times. If you need better quality, but still need to update the sky every frame, consider turning on [member ProjectSettings.rendering/reflections/sky_reflections/fast_filter_high_quality].
[b]Note:[/b] The fast filtering algorithm is limited to 256x256 cubemaps, so [member radiance_size] must be set to [constant RADIANCE_SIZE_256].
</constant>
</constants>
diff --git a/doc/classes/SoftBody3D.xml b/doc/classes/SoftBody3D.xml
index d3ab955570..29f8ecd432 100644
--- a/doc/classes/SoftBody3D.xml
+++ b/doc/classes/SoftBody3D.xml
@@ -77,8 +77,6 @@
</method>
</methods>
<members>
- <member name="areaAngular_stiffness" type="float" setter="set_areaAngular_stiffness" getter="get_areaAngular_stiffness" default="0.5">
- </member>
<member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1">
The physics layers this SoftBody3D is in.
Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the collision_mask property.
@@ -87,30 +85,26 @@
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1">
The physics layers this SoftBody3D scans for collisions. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information.
</member>
- <member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.01">
+ <member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.0">
</member>
<member name="drag_coefficient" type="float" setter="set_drag_coefficient" getter="get_drag_coefficient" default="0.0">
</member>
- <member name="linear_stiffness" type="float" setter="set_linear_stiffness" getter="get_linear_stiffness" default="0.5">
+ <member name="linear_stiffness" type="float" setter="set_linear_stiffness" getter="get_linear_stiffness" default="0.0">
</member>
<member name="parent_collision_ignore" type="NodePath" setter="set_parent_collision_ignore" getter="get_parent_collision_ignore" default="NodePath(&quot;&quot;)">
[NodePath] to a [CollisionObject3D] this SoftBody3D should avoid clipping.
</member>
- <member name="pose_matching_coefficient" type="float" setter="set_pose_matching_coefficient" getter="get_pose_matching_coefficient" default="0.0">
- </member>
<member name="pressure_coefficient" type="float" setter="set_pressure_coefficient" getter="get_pressure_coefficient" default="0.0">
</member>
<member name="ray_pickable" type="bool" setter="set_ray_pickable" getter="is_ray_pickable" default="true">
If [code]true[/code], the [SoftBody3D] will respond to [RayCast3D]s.
</member>
- <member name="simulation_precision" type="int" setter="set_simulation_precision" getter="get_simulation_precision" default="5">
+ <member name="simulation_precision" type="int" setter="set_simulation_precision" getter="get_simulation_precision" default="0">
Increasing this value will improve the resulting simulation, but can affect performance. Use with care.
</member>
- <member name="total_mass" type="float" setter="set_total_mass" getter="get_total_mass" default="1.0">
+ <member name="total_mass" type="float" setter="set_total_mass" getter="get_total_mass" default="0.0">
The SoftBody3D's mass.
</member>
- <member name="volume_stiffness" type="float" setter="set_volume_stiffness" getter="get_volume_stiffness" default="0.5">
- </member>
</members>
<constants>
</constants>
diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml
index e674ceb57e..7e2481f458 100644
--- a/doc/classes/SpinBox.xml
+++ b/doc/classes/SpinBox.xml
@@ -6,15 +6,25 @@
<description>
SpinBox is a numerical input text field. It allows entering integers and floats.
[b]Example:[/b]
- [codeblock]
+ [codeblocks]
+ [gdscript]
var spin_box = SpinBox.new()
add_child(spin_box)
var line_edit = spin_box.get_line_edit()
line_edit.context_menu_enabled = false
spin_box.align = LineEdit.ALIGN_RIGHT
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ var spinBox = new SpinBox();
+ AddChild(spinBox);
+ var lineEdit = spinBox.GetLineEdit();
+ lineEdit.ContextMenuEnabled = false;
+ spinBox.Align = LineEdit.AlignEnum.Right;
+ [/csharp]
+ [/codeblocks]
The above code will create a [SpinBox], disable context menu on it and set the text alignment to right.
See [Range] class for more options over the [SpinBox].
+ [b]Note:[/b] [SpinBox] relies on an underlying [LineEdit] node. To theme a [SpinBox]'s background, add theme items for [LineEdit] and customize them.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Sprite2D.xml b/doc/classes/Sprite2D.xml
index c56596423d..617ad3a371 100644
--- a/doc/classes/Sprite2D.xml
+++ b/doc/classes/Sprite2D.xml
@@ -15,12 +15,29 @@
</return>
<description>
Returns a [Rect2] representing the Sprite2D's boundary in local coordinates. Can be used to detect if the Sprite2D was clicked. Example:
- [codeblock]
+ [codeblocks]
+ [gdscript]
func _input(event):
- if event is InputEventMouseButton and event.pressed and event.button_index == BUTTON_LEFT:
+ if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
if get_rect().has_point(to_local(event.position)):
print("A click!")
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ public override void _Input(InputEvent inputEvent)
+ {
+ if (inputEvent is InputEventMouseButton inputEventMouse)
+ {
+ if (inputEventMouse.Pressed &amp;&amp; inputEventMouse.ButtonIndex == (int)ButtonList.Left)
+ {
+ if (GetRect().HasPoint(ToLocal(inputEventMouse.Position)))
+ {
+ GD.Print("A click!");
+ }
+ }
+ }
+ }
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="is_pixel_opaque" qualifiers="const">
@@ -56,11 +73,11 @@
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2( 0, 0 )">
The texture's drawing offset.
</member>
- <member name="region_enabled" type="bool" setter="set_region" getter="is_region" default="false">
+ <member name="region_enabled" type="bool" setter="set_region_enabled" getter="is_region_enabled" default="false">
If [code]true[/code], texture is cut from a larger atlas texture. See [member region_rect].
</member>
- <member name="region_filter_clip" type="bool" setter="set_region_filter_clip" getter="is_region_filter_clip_enabled" default="false">
- If [code]true[/code], the outermost pixels get blurred out.
+ <member name="region_filter_clip_enabled" type="bool" setter="set_region_filter_clip_enabled" getter="is_region_filter_clip_enabled" default="false">
+ If [code]true[/code], the outermost pixels get blurred out. [member region_enabled] must be [code]true[/code].
</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/Sprite3D.xml b/doc/classes/Sprite3D.xml
index f9b947fa3d..658fd1a4f2 100644
--- a/doc/classes/Sprite3D.xml
+++ b/doc/classes/Sprite3D.xml
@@ -20,7 +20,7 @@
<member name="hframes" type="int" setter="set_hframes" getter="get_hframes" default="1">
The number of columns in the sprite sheet.
</member>
- <member name="region_enabled" type="bool" setter="set_region" getter="is_region" default="false">
+ <member name="region_enabled" type="bool" setter="set_region_enabled" getter="is_region_enabled" default="false">
If [code]true[/code], texture will be cut from a larger atlas texture. See [member region_rect].
</member>
<member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect" default="Rect2( 0, 0, 0, 0 )">
diff --git a/doc/classes/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml
index 44b08408c1..06b9c2b042 100644
--- a/doc/classes/SpriteBase3D.xml
+++ b/doc/classes/SpriteBase3D.xml
@@ -73,7 +73,7 @@
The texture's drawing offset.
</member>
<member name="opacity" type="float" setter="set_opacity" getter="get_opacity" default="1.0">
- The objects visibility on a scale from [code]0[/code] fully invisible to [code]1[/code] fully visible.
+ The objects' visibility on a scale from [code]0[/code] fully invisible to [code]1[/code] fully visible.
</member>
<member name="pixel_size" type="float" setter="set_pixel_size" getter="get_pixel_size" default="0.01">
The size of one pixel's width on the sprite to scale it in 3D.
@@ -102,7 +102,7 @@
This mode performs standard alpha blending. It can display translucent areas, but transparency sorting issues may be visible when multiple transparent materials are overlapping.
</constant>
<constant name="ALPHA_CUT_DISCARD" value="1" enum="AlphaCutMode">
- This mode only allows fully transparent or fully opaque pixels. Harsh edges will be visible unless some form of screen-space antialiasing is enabled (see [member ProjectSettings.rendering/quality/screen_filters/screen_space_aa]). On the bright side, this mode doesn't suffer from transparency sorting issues when multiple transparent materials are overlapping. This mode is also known as [i]alpha testing[/i] or [i]1-bit transparency[/i].
+ This mode only allows fully transparent or fully opaque pixels. Harsh edges will be visible unless some form of screen-space antialiasing is enabled (see [member ProjectSettings.rendering/anti_aliasing/quality/screen_space_aa]). On the bright side, this mode doesn't suffer from transparency sorting issues when multiple transparent materials are overlapping. This mode is also known as [i]alpha testing[/i] or [i]1-bit transparency[/i].
</constant>
<constant name="ALPHA_CUT_OPAQUE_PREPASS" value="2" enum="AlphaCutMode">
This mode draws fully opaque pixels in the depth prepass. This is slower than [constant ALPHA_CUT_DISABLED] or [constant ALPHA_CUT_DISCARD], but it allows displaying translucent areas and smooth edges while using proper sorting.
diff --git a/doc/classes/StreamPeer.xml b/doc/classes/StreamPeer.xml
index a73d3c8212..a1b858acf6 100644
--- a/doc/classes/StreamPeer.xml
+++ b/doc/classes/StreamPeer.xml
@@ -212,9 +212,14 @@
<description>
Puts a zero-terminated ASCII string into the stream prepended by a 32-bit unsigned integer representing its size.
Note: To put an ASCII string without prepending its size, you can use [method put_data]:
- [codeblock]
+ [codeblocks]
+ [gdscript]
put_data("Hello world".to_ascii())
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ PutData("Hello World".ToAscii());
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="put_u16">
@@ -261,9 +266,14 @@
<description>
Puts a zero-terminated UTF-8 string into the stream prepended by a 32 bits unsigned integer representing its size.
Note: To put an UTF-8 string without prepending its size, you can use [method put_data]:
- [codeblock]
+ [codeblocks]
+ [gdscript]
put_data("Hello world".to_utf8())
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ PutData("Hello World".ToUTF8());
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="put_var">
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index c03f6357ab..416438e648 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -44,7 +44,7 @@
Constructs a new String from the given [StringName].
</description>
</method>
- <method name="begins_with">
+ <method name="begins_with" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="text" type="String">
@@ -53,14 +53,14 @@
Returns [code]true[/code] if the string begins with the given string.
</description>
</method>
- <method name="bigrams">
+ <method name="bigrams" qualifiers="const">
<return type="PackedStringArray">
</return>
<description>
Returns the bigrams (pairs of consecutive letters) of this string.
</description>
</method>
- <method name="bin_to_int">
+ <method name="bin_to_int" qualifiers="const">
<return type="int">
</return>
<description>
@@ -77,14 +77,14 @@
[/codeblocks]
</description>
</method>
- <method name="c_escape">
+ <method name="c_escape" qualifiers="const">
<return type="String">
</return>
<description>
Returns a copy of the string with special characters escaped using the C language standard.
</description>
</method>
- <method name="c_unescape">
+ <method name="c_unescape" qualifiers="const">
<return type="String">
</return>
<description>
@@ -92,14 +92,14 @@
[b]Note:[/b] Unlike the GDScript parser, this method doesn't support the [code]\uXXXX[/code] escape sequence.
</description>
</method>
- <method name="capitalize">
+ <method name="capitalize" qualifiers="const">
<return type="String">
</return>
<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].
</description>
</method>
- <method name="casecmp_to">
+ <method name="casecmp_to" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="to" type="String">
@@ -111,7 +111,15 @@
To get a boolean result from a string comparison, use the [code]==[/code] operator instead. See also [method nocasecmp_to] and [method naturalnocasecmp_to].
</description>
</method>
- <method name="count">
+ <method name="chr" qualifiers="static">
+ <return type="String">
+ </return>
+ <argument index="0" name="char" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="count" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="what" type="String">
@@ -124,7 +132,7 @@
Returns the number of occurrences of substring [code]what[/code] between [code]from[/code] and [code]to[/code] positions. If [code]from[/code] and [code]to[/code] equals 0 the whole string will be used. If only [code]to[/code] equals 0 the remained substring will be used.
</description>
</method>
- <method name="countn">
+ <method name="countn" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="what" type="String">
@@ -137,14 +145,14 @@
Returns the number of occurrences of substring [code]what[/code] (ignoring case) between [code]from[/code] and [code]to[/code] positions. If [code]from[/code] and [code]to[/code] equals 0 the whole string will be used. If only [code]to[/code] equals 0 the remained substring will be used.
</description>
</method>
- <method name="dedent">
+ <method name="dedent" qualifiers="const">
<return type="String">
</return>
<description>
Returns a copy of the string with indentation (leading tabs and spaces) removed.
</description>
</method>
- <method name="ends_with">
+ <method name="ends_with" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="text" type="String">
@@ -153,7 +161,7 @@
Returns [code]true[/code] if the string ends with the given string.
</description>
</method>
- <method name="find">
+ <method name="find" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="what" type="String">
@@ -163,14 +171,18 @@
<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:
- [codeblock]
- # Will evaluate to `false`.
- if "i" in "team":
- pass
- [/codeblock]
+ [codeblocks]
+ [gdscript]
+ print("i" in "team") # Will print `false`.
+ [/gdscript]
+ [csharp]
+ // C# has no in operator, but we can use `Contains()`.
+ GD.Print("team".Contains("i")); // Will print `false`.
+ [/csharp]
+ [/codeblocks]
</description>
</method>
- <method name="findn">
+ <method name="findn" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="what" type="String">
@@ -181,7 +193,7 @@
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.
</description>
</method>
- <method name="format">
+ <method name="format" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="values" type="Variant">
@@ -192,42 +204,42 @@
Formats the string by replacing all occurrences of [code]placeholder[/code] with [code]values[/code].
</description>
</method>
- <method name="get_base_dir">
+ <method name="get_base_dir" qualifiers="const">
<return type="String">
</return>
<description>
If the string is a valid file path, returns the base directory name.
</description>
</method>
- <method name="get_basename">
+ <method name="get_basename" qualifiers="const">
<return type="String">
</return>
<description>
If the string is a valid file path, returns the full file path without the extension.
</description>
</method>
- <method name="get_extension">
+ <method name="get_extension" qualifiers="const">
<return type="String">
</return>
<description>
If the string is a valid file path, returns the extension.
</description>
</method>
- <method name="get_file">
+ <method name="get_file" qualifiers="const">
<return type="String">
</return>
<description>
If the string is a valid file path, returns the filename.
</description>
</method>
- <method name="hash">
+ <method name="hash" qualifiers="const">
<return type="int">
</return>
<description>
Hashes the string and returns a 32-bit integer.
</description>
</method>
- <method name="hex_to_int">
+ <method name="hex_to_int" qualifiers="const">
<return type="int">
</return>
<description>
@@ -244,7 +256,15 @@
[/codeblocks]
</description>
</method>
- <method name="insert">
+ <method name="humanize_size" qualifiers="static">
+ <return type="String">
+ </return>
+ <argument index="0" name="size" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="insert" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="position" type="int">
@@ -255,28 +275,28 @@
Returns a copy of the string with the substring [code]what[/code] inserted at the given position.
</description>
</method>
- <method name="is_abs_path">
+ <method name="is_abs_path" qualifiers="const">
<return type="bool">
</return>
<description>
If the string is a path to a file or directory, returns [code]true[/code] if the path is absolute.
</description>
</method>
- <method name="is_empty">
+ <method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the length of the string equals [code]0[/code].
</description>
</method>
- <method name="is_rel_path">
+ <method name="is_rel_path" qualifiers="const">
<return type="bool">
</return>
<description>
If the string is a path to a file or directory, returns [code]true[/code] if the path is relative.
</description>
</method>
- <method name="is_subsequence_of">
+ <method name="is_subsequence_of" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="text" type="String">
@@ -285,7 +305,7 @@
Returns [code]true[/code] if this string is a subsequence of the given string.
</description>
</method>
- <method name="is_subsequence_ofi">
+ <method name="is_subsequence_ofi" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="text" type="String">
@@ -294,7 +314,7 @@
Returns [code]true[/code] if this string is a subsequence of the given string, without considering case.
</description>
</method>
- <method name="is_valid_filename">
+ <method name="is_valid_filename" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -302,14 +322,14 @@
[code]: / \ ? * " | % &lt; &gt;[/code]
</description>
</method>
- <method name="is_valid_float">
+ <method name="is_valid_float" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if this string contains a valid float.
</description>
</method>
- <method name="is_valid_hex_number">
+ <method name="is_valid_hex_number" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="with_prefix" type="bool" default="false">
@@ -318,35 +338,35 @@
Returns [code]true[/code] if this string contains a valid hexadecimal number. If [code]with_prefix[/code] is [code]true[/code], then a validity of the hexadecimal number is determined by [code]0x[/code] prefix, for instance: [code]0xDEADC0DE[/code].
</description>
</method>
- <method name="is_valid_html_color">
+ <method name="is_valid_html_color" qualifiers="const">
<return type="bool">
</return>
<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].
</description>
</method>
- <method name="is_valid_identifier">
+ <method name="is_valid_identifier" qualifiers="const">
<return type="bool">
</return>
<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.
</description>
</method>
- <method name="is_valid_integer">
+ <method name="is_valid_integer" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if this string contains a valid integer.
</description>
</method>
- <method name="is_valid_ip_address">
+ <method name="is_valid_ip_address" qualifiers="const">
<return type="bool">
</return>
<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.
</description>
</method>
- <method name="join">
+ <method name="join" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="parts" type="PackedStringArray">
@@ -354,19 +374,24 @@
<description>
Return a [String] which is the concatenation of the [code]parts[/code]. The separator between elements is the string providing this method.
Example:
- [codeblock]
+ [codeblocks]
+ [gdscript]
print(", ".join(["One", "Two", "Three", "Four"]))
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ GD.Print(String.Join(",", new string[] {"One", "Two", "Three", "Four"}));
+ [/csharp]
+ [/codeblocks]
</description>
</method>
- <method name="json_escape">
+ <method name="json_escape" qualifiers="const">
<return type="String">
</return>
<description>
Returns a copy of the string with special characters escaped using the JSON standard.
</description>
</method>
- <method name="left">
+ <method name="left" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="position" type="int">
@@ -375,14 +400,14 @@
Returns a number of characters from the left of the string.
</description>
</method>
- <method name="length">
+ <method name="length" qualifiers="const">
<return type="int">
</return>
<description>
Returns the string's amount of characters.
</description>
</method>
- <method name="lpad">
+ <method name="lpad" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="min_length" type="int">
@@ -393,7 +418,7 @@
Formats a string to be at least [code]min_length[/code] long by adding [code]character[/code]s to the left of the string.
</description>
</method>
- <method name="lstrip">
+ <method name="lstrip" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="chars" type="String">
@@ -403,7 +428,7 @@
[b]Note:[/b] The [code]chars[/code] is not a prefix. See [method trim_prefix] method that will remove a single prefix string rather than a set of characters.
</description>
</method>
- <method name="match">
+ <method name="match" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="expr" type="String">
@@ -412,7 +437,7 @@
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]).
</description>
</method>
- <method name="matchn">
+ <method name="matchn" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="expr" type="String">
@@ -421,21 +446,21 @@
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]).
</description>
</method>
- <method name="md5_buffer">
+ <method name="md5_buffer" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
Returns the MD5 hash of the string as an array of bytes.
</description>
</method>
- <method name="md5_text">
+ <method name="md5_text" qualifiers="const">
<return type="String">
</return>
<description>
Returns the MD5 hash of the string as a string.
</description>
</method>
- <method name="naturalnocasecmp_to">
+ <method name="naturalnocasecmp_to" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="to" type="String">
@@ -448,7 +473,7 @@
To get a boolean 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">
+ <method name="nocasecmp_to" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="to" type="String">
@@ -460,6 +485,24 @@
To get a boolean 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">
+ <return type="String">
+ </return>
+ <argument index="0" name="number" type="float">
+ </argument>
+ <argument index="1" name="decimals" type="int" default="-1">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="num_scientific" qualifiers="static">
+ <return type="String">
+ </return>
+ <argument index="0" name="number" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="operator !=" qualifiers="operator">
<return type="bool">
</return>
@@ -540,7 +583,7 @@
<description>
</description>
</method>
- <method name="pad_decimals">
+ <method name="pad_decimals" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="digits" type="int">
@@ -549,7 +592,7 @@
Formats a number to have an exact number of [code]digits[/code] after the decimal point.
</description>
</method>
- <method name="pad_zeros">
+ <method name="pad_zeros" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="digits" type="int">
@@ -558,7 +601,7 @@
Formats a number to have an exact number of [code]digits[/code] before the decimal point.
</description>
</method>
- <method name="plus_file">
+ <method name="plus_file" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="file" type="String">
@@ -567,7 +610,7 @@
If the string is a path, this concatenates [code]file[/code] at the end of the string as a subpath. E.g. [code]"this/is".plus_file("path") == "this/is/path"[/code].
</description>
</method>
- <method name="repeat">
+ <method name="repeat" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="count" type="int">
@@ -576,7 +619,7 @@
Returns original string repeated a number of times. The number of repetitions is given by the argument.
</description>
</method>
- <method name="replace">
+ <method name="replace" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="what" type="String">
@@ -587,7 +630,7 @@
Replaces occurrences of a case-sensitive substring with the given one inside the string.
</description>
</method>
- <method name="replacen">
+ <method name="replacen" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="what" type="String">
@@ -598,7 +641,7 @@
Replaces occurrences of a case-insensitive substring with the given one inside the string.
</description>
</method>
- <method name="rfind">
+ <method name="rfind" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="what" type="String">
@@ -609,7 +652,7 @@
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.
</description>
</method>
- <method name="rfindn">
+ <method name="rfindn" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="what" type="String">
@@ -620,7 +663,7 @@
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.
</description>
</method>
- <method name="right">
+ <method name="right" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="position" type="int">
@@ -629,7 +672,7 @@
Returns the right side of the string from a given position.
</description>
</method>
- <method name="rpad">
+ <method name="rpad" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="min_length" type="int">
@@ -640,7 +683,7 @@
Formats a string to be at least [code]min_length[/code] long by adding [code]character[/code]s to the right of the string.
</description>
</method>
- <method name="rsplit">
+ <method name="rsplit" qualifiers="const">
<return type="PackedStringArray">
</return>
<argument index="0" name="delimiter" type="String">
@@ -654,16 +697,21 @@
The splits in the returned array are sorted in the same order as the original string, from left to right.
If [code]maxsplit[/code] is specified, it defines the number of splits to do from the right up to [code]maxsplit[/code]. The default value of 0 means that all items are split, thus giving the same result as [method split].
Example:
- [codeblock]
+ [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 "Four"
print(some_array[1]) # Prints "Three,Two,One"
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ // There is no Rsplit.
+ [/csharp]
+ [/codeblocks]
</description>
</method>
- <method name="rstrip">
+ <method name="rstrip" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="chars" type="String">
@@ -673,35 +721,35 @@
[b]Note:[/b] The [code]chars[/code] is not a suffix. See [method trim_suffix] method that will remove a single suffix string rather than a set of characters.
</description>
</method>
- <method name="sha1_buffer">
+ <method name="sha1_buffer" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
Returns the SHA-1 hash of the string as an array of bytes.
</description>
</method>
- <method name="sha1_text">
+ <method name="sha1_text" qualifiers="const">
<return type="String">
</return>
<description>
Returns the SHA-1 hash of the string as a string.
</description>
</method>
- <method name="sha256_buffer">
+ <method name="sha256_buffer" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
Returns the SHA-256 hash of the string as an array of bytes.
</description>
</method>
- <method name="sha256_text">
+ <method name="sha256_text" qualifiers="const">
<return type="String">
</return>
<description>
Returns the SHA-256 hash of the string as a string.
</description>
</method>
- <method name="similarity">
+ <method name="similarity" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="text" type="String">
@@ -710,7 +758,7 @@
Returns the similarity index of the text compared to this string. 1 means totally similar and 0 means totally dissimilar.
</description>
</method>
- <method name="split">
+ <method name="split" qualifiers="const">
<return type="PackedStringArray">
</return>
<argument index="0" name="delimiter" type="String">
@@ -723,17 +771,25 @@
Splits the string by a [code]delimiter[/code] string and returns an array of the substrings. The [code]delimiter[/code] can be of any length.
If [code]maxsplit[/code] is specified, it defines the number of splits to do from the left up to [code]maxsplit[/code]. The default value of [code]0[/code] means that all items are split.
Example:
- [codeblock]
+ [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 "One"
- print(some_array[1]) # Prints "Two,Three,Four"
- [/codeblock]
+ print(some_array[0]) # Prints "Four"
+ print(some_array[1]) # Prints "Three,Two,One"
+ [/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"
+ [/csharp]
+ [/codeblocks]
If you need to split strings with more complex rules, use the [RegEx] class instead.
</description>
</method>
- <method name="split_floats">
+ <method name="split_floats" qualifiers="const">
<return type="PackedFloat32Array">
</return>
<argument index="0" name="delimiter" type="String">
@@ -745,7 +801,7 @@
For example, [code]"1,2.5,3"[/code] will return [code][1,2.5,3][/code] if split by [code]","[/code].
</description>
</method>
- <method name="strip_edges">
+ <method name="strip_edges" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="left" type="bool" default="true">
@@ -756,14 +812,14 @@
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.
</description>
</method>
- <method name="strip_escapes">
+ <method name="strip_escapes" qualifiers="const">
<return type="String">
</return>
<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.
</description>
</method>
- <method name="substr">
+ <method name="substr" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="from" type="int">
@@ -774,63 +830,63 @@
Returns part of the string from the position [code]from[/code] with length [code]len[/code]. Argument [code]len[/code] is optional and using [code]-1[/code] will return remaining characters from given position.
</description>
</method>
- <method name="to_ascii_buffer">
+ <method name="to_ascii_buffer" qualifiers="const">
<return type="PackedByteArray">
</return>
<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.
</description>
</method>
- <method name="to_float">
+ <method name="to_float" qualifiers="const">
<return type="float">
</return>
<description>
Converts a string containing a decimal number into a [code]float[/code].
</description>
</method>
- <method name="to_int">
+ <method name="to_int" qualifiers="const">
<return type="int">
</return>
<description>
Converts a string containing an integer number into an [code]int[/code].
</description>
</method>
- <method name="to_lower">
+ <method name="to_lower" qualifiers="const">
<return type="String">
</return>
<description>
Returns the string converted to lowercase.
</description>
</method>
- <method name="to_upper">
+ <method name="to_upper" qualifiers="const">
<return type="String">
</return>
<description>
Returns the string converted to uppercase.
</description>
</method>
- <method name="to_utf16_buffer">
+ <method name="to_utf16_buffer" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
Converts the String (which is an array of characters) to UTF-16 encoded [PackedByteArray] (which is an array of bytes).
</description>
</method>
- <method name="to_utf32_buffer">
+ <method name="to_utf32_buffer" qualifiers="const">
<return type="PackedByteArray">
</return>
<description>
Converts the String (which is an array of characters) to UTF-32 encoded [PackedByteArray] (which is an array of bytes).
</description>
</method>
- <method name="to_utf8_buffer">
+ <method name="to_utf8_buffer" qualifiers="const">
<return type="PackedByteArray">
</return>
<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].
</description>
</method>
- <method name="trim_prefix">
+ <method name="trim_prefix" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="prefix" type="String">
@@ -839,7 +895,7 @@
Removes a given string from the start if it starts with it or leaves the string unchanged.
</description>
</method>
- <method name="trim_suffix">
+ <method name="trim_suffix" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="suffix" type="String">
@@ -848,7 +904,7 @@
Removes a given string from the end if it ends with it or leaves the string unchanged.
</description>
</method>
- <method name="unicode_at">
+ <method name="unicode_at" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="at" type="int">
@@ -857,7 +913,7 @@
Returns the character code at position [code]at[/code].
</description>
</method>
- <method name="uri_decode">
+ <method name="uri_decode" qualifiers="const">
<return type="String">
</return>
<description>
@@ -872,7 +928,7 @@
[/codeblocks]
</description>
</method>
- <method name="uri_encode">
+ <method name="uri_encode" qualifiers="const">
<return type="String">
</return>
<description>
@@ -887,7 +943,14 @@
[/codeblocks]
</description>
</method>
- <method name="xml_escape">
+ <method name="validate_node_name" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ Removes any characters from the string that are prohibited in [Node] names ([code].[/code] [code]:[/code] [code]@[/code] [code]/[/code] [code]"[/code]).
+ </description>
+ </method>
+ <method name="xml_escape" qualifiers="const">
<return type="String">
</return>
<argument index="0" name="escape_quotes" type="bool" default="false">
@@ -896,7 +959,7 @@
Returns a copy of the string with special characters escaped using the XML standard. If [code]escape_quotes[/code] is [code]true[/code], the single quote ([code]'[/code]) and double quote ([code]"[/code]) characters are also escaped.
</description>
</method>
- <method name="xml_unescape">
+ <method name="xml_unescape" qualifiers="const">
<return type="String">
</return>
<description>
diff --git a/doc/classes/StringName.xml b/doc/classes/StringName.xml
index af0074f080..be32f6a234 100644
--- a/doc/classes/StringName.xml
+++ b/doc/classes/StringName.xml
@@ -4,7 +4,7 @@
An optimized string type for unique names.
</brief_description>
<description>
- [StringName]s are immutable strings designed for general-purpose represention of unique names. [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.
+ [StringName]s are immutable strings designed for general-purpose representation of unique names. [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.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/StyleBoxFlat.xml b/doc/classes/StyleBoxFlat.xml
index 13ea7df294..d66ae210ec 100644
--- a/doc/classes/StyleBoxFlat.xml
+++ b/doc/classes/StyleBoxFlat.xml
@@ -4,12 +4,12 @@
Customizable [StyleBox] with a given set of parameters (no texture required).
</brief_description>
<description>
- This [StyleBox] can be used to achieve all kinds of looks without the need of a texture. Those properties are customizable:
+ This [StyleBox] can be used to achieve all kinds of looks without the need of a texture. The following properties are customizable:
- Color
- Border width (individual width for each border)
- Rounded corners (individual radius for each corner)
- Shadow (with blur and offset)
- Setting corner radius to high values is allowed. As soon as corners would overlap, the stylebox will switch to a relative system. Example:
+ Setting corner radius to high values is allowed. As soon as corners overlap, the stylebox will switch to a relative system. Example:
[codeblock]
height = 30
corner_radius_top_left = 50
@@ -178,8 +178,8 @@
Border width for the top border.
</member>
<member name="corner_detail" type="int" setter="set_corner_detail" getter="get_corner_detail" default="8">
- This sets the amount of vertices used for each corner. Higher values result in rounder corners but take more processing power to compute. When choosing a value, you should take the corner radius ([method set_corner_radius_all]) into account.
- For corner radii smaller than 10, [code]4[/code] or [code]5[/code] should be enough. For corner radii smaller than 30, values between [code]8[/code] and [code]12[/code] should be enough.
+ This sets the number of vertices used for each corner. Higher values result in rounder corners but take more processing power to compute. When choosing a value, you should take the corner radius ([method set_corner_radius_all]) into account.
+ For corner radii less than 10, [code]4[/code] or [code]5[/code] should be enough. For corner radii less than 30, values between [code]8[/code] and [code]12[/code] should be enough.
A corner detail of [code]1[/code] will result in chamfered corners instead of rounded corners, which is useful for some artistic effects.
</member>
<member name="corner_radius_bottom_left" type="int" setter="set_corner_radius" getter="get_corner_radius" default="0">
diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml
index e10b65e309..f5d83c0c46 100644
--- a/doc/classes/SurfaceTool.xml
+++ b/doc/classes/SurfaceTool.xml
@@ -5,13 +5,22 @@
</brief_description>
<description>
The [SurfaceTool] is used to construct a [Mesh] by specifying vertex attributes individually. It can be used to construct a [Mesh] from a script. All properties except indices need to be added before calling [method add_vertex]. For example, to add vertex colors and UVs:
- [codeblock]
+ [codeblocks]
+ [gdscript]
var st = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES)
st.set_color(Color(1, 0, 0))
st.set_uv(Vector2(0, 0))
st.set_vertex(Vector3(0, 0, 0))
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ var st = new SurfaceTool();
+ st.Begin(Mesh.PrimitiveType.Triangles);
+ st.SetColor(new Color(1, 0, 0));
+ st.SetUv(new Vector2(0, 0));
+ st.SetVertex(new Vector3(0, 0, 0));
+ [/csharp]
+ [/codeblocks]
The above [SurfaceTool] now contains one vertex of a triangle which has a UV coordinate and a specified [Color]. If another vertex were added without calling [method set_uv] or [method set_color], then the last values would be used.
Vertex attributes must be passed [b]before[/b] calling [method add_vertex]. Failure to do so will result in an error when committing the vertex information to a mesh.
Additionally, the attributes used before the first vertex is added determine the format of the mesh. For example, if you only add UVs to the first vertex, you cannot add color to any of the subsequent vertices.
@@ -155,8 +164,8 @@
<argument index="0" name="flip" type="bool" default="false">
</argument>
<description>
- Generates normals from vertices so you do not have to do it manually. If [code]flip[/code] is [code]true[/code], the resulting normals will be inverted.
- Requires the primitive type to be set to [constant Mesh.PRIMITIVE_TRIANGLES].
+ Generates normals from vertices so you do not have to do it manually. If [code]flip[/code] is [code]true[/code], the resulting normals will be inverted. [method generate_normals] should be called [i]after[/i] generating geometry and [i]before[/i] committing the mesh using [method commit] or [method commit_to_arrays].
+ [b]Note:[/b] [method generate_normals] only works if the primitive type to be set to [constant Mesh.PRIMITIVE_TRIANGLES].
</description>
</method>
<method name="generate_tangents">
@@ -190,7 +199,7 @@
<return type="void">
</return>
<description>
- Shrinks the vertex array by creating an index array (avoids reusing vertices).
+ Shrinks the vertex array by creating an index array. This can improve performance by avoiding vertex reuse.
</description>
</method>
<method name="optimize_indices_for_cache">
@@ -205,7 +214,7 @@
<argument index="0" name="bones" type="PackedInt32Array">
</argument>
<description>
- Specifies an array of bones for the next vertex to use. [code]bones[/code] must contain 4 integers.
+ Specifies an array of bones to use for the [i]next[/i] vertex. [code]bones[/code] must contain 4 integers.
</description>
</method>
<method name="set_color">
@@ -214,7 +223,7 @@
<argument index="0" name="color" type="Color">
</argument>
<description>
- Specifies a [Color] for the next vertex to use.
+ Specifies a [Color] to use for the [i]next[/i] vertex. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all.
[b]Note:[/b] The material must have [member BaseMaterial3D.vertex_color_use_as_albedo] enabled for the vertex color to be visible.
</description>
</method>
@@ -253,7 +262,7 @@
<argument index="0" name="normal" type="Vector3">
</argument>
<description>
- Specifies a normal for the next vertex to use.
+ Specifies a normal to use for the [i]next[/i] vertex. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all.
</description>
</method>
<method name="set_skin_weight_count">
@@ -279,7 +288,7 @@
<argument index="0" name="tangent" type="Plane">
</argument>
<description>
- Specifies a tangent for the next vertex to use.
+ Specifies a tangent to use for the [i]next[/i] vertex. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all.
</description>
</method>
<method name="set_uv">
@@ -288,7 +297,7 @@
<argument index="0" name="uv" type="Vector2">
</argument>
<description>
- Specifies a set of UV coordinates to use for the next vertex.
+ Specifies a set of UV coordinates to use for the [i]next[/i] vertex. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all.
</description>
</method>
<method name="set_uv2">
@@ -297,7 +306,7 @@
<argument index="0" name="uv2" type="Vector2">
</argument>
<description>
- Specifies an optional second set of UV coordinates to use for the next vertex.
+ Specifies an optional second set of UV coordinates to use for the [i]next[/i] vertex. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all.
</description>
</method>
<method name="set_weights">
@@ -306,7 +315,7 @@
<argument index="0" name="weights" type="PackedFloat32Array">
</argument>
<description>
- Specifies weight values for next vertex to use. [code]weights[/code] must contain 4 values.
+ Specifies weight values to use for the [i]next[/i] vertex. [code]weights[/code] must contain 4 values. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all.
</description>
</method>
</methods>
diff --git a/doc/classes/SyntaxHighlighter.xml b/doc/classes/SyntaxHighlighter.xml
index 2d6e3de02a..642d75fa9b 100644
--- a/doc/classes/SyntaxHighlighter.xml
+++ b/doc/classes/SyntaxHighlighter.xml
@@ -1,50 +1,83 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="SyntaxHighlighter" inherits="Resource" version="4.0">
<brief_description>
+ Base Syntax highlighter resource for [TextEdit].
</brief_description>
<description>
+ Base syntax highlighter resource all syntax highlighters extend from, provides syntax highlighting data to [TextEdit].
+ The associated [TextEdit] node will call into the [SyntaxHighlighter] on a as needed basis.
+ [b]Note:[/b] Each Syntax highlighter instance should not be shared across multiple [TextEdit] nodes.
</description>
<tutorials>
</tutorials>
<methods>
+ <method name="_clear_highlighting_cache" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <description>
+ Virtual method which can be overridden to clear any local caches.
+ </description>
+ </method>
<method name="_get_line_syntax_highlighting" qualifiers="virtual">
<return type="Dictionary">
</return>
- <argument index="0" name="p_line" type="int">
+ <argument index="0" name="line" type="int">
</argument>
<description>
+ Virtual method which can be overridden to return syntax highlighting data.
+ See [method get_line_syntax_highlighting] for more details.
</description>
</method>
<method name="_update_cache" qualifiers="virtual">
<return type="void">
</return>
<description>
+ Virtual method which can be overridden to update any local caches.
</description>
</method>
<method name="clear_highlighting_cache">
<return type="void">
</return>
<description>
+ Clears all cached syntax highlighting data.
+ Then calls overridable method [method _clear_highlighting_cache].
</description>
</method>
<method name="get_line_syntax_highlighting">
<return type="Dictionary">
</return>
- <argument index="0" name="p_line" type="int">
+ <argument index="0" name="line" type="int">
</argument>
<description>
+ Returns syntax highlighting data for a single line. If the line is not cached, calls [method _get_line_syntax_highlighting] to calculate the data.
+ The return [Dictionary] is column number to [Dictionary]. The column number notes the start of a region, the region will end if another region is found, or at the end of the line. The nested [Dictionary] contains the data for that region, currently only the key "color" is supported.
+ [b]Example return:[/b]
+ [codeblock]
+ var color_map = {
+ 0: {
+ "color": Color(1, 0, 0)
+ },
+ 5: {
+ "color": Color(0, 1, 0)
+ }
+ }
+ [/codeblock]
+ This will color columns 0-4 red, and columns 5-eol in green.
</description>
</method>
<method name="get_text_edit">
<return type="TextEdit">
</return>
<description>
+ Returns the associated [TextEdit] node.
</description>
</method>
<method name="update_cache">
<return type="void">
</return>
<description>
+ Clears then updates the [SyntaxHighlighter] caches. Override [method _update_cache] for a callback.
+ [b]Note:[/b] This is called automatically when the associated [TextEdit] node, updates its own cache.
</description>
</method>
</methods>
diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml
index 52577e6102..ddf6b465a4 100644
--- a/doc/classes/TabContainer.xml
+++ b/doc/classes/TabContainer.xml
@@ -201,6 +201,9 @@
<theme_item name="font_disabled_color" type="Color" default="Color( 0.9, 0.9, 0.9, 0.2 )">
Font color of disabled tabs.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the tab name.
+ </theme_item>
<theme_item name="font_selected_color" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
Font color of the currently selected tab.
</theme_item>
@@ -225,6 +228,9 @@
<theme_item name="menu_highlight" type="Texture2D">
The icon for the menu button (see [method set_popup]) when it's being hovered with the cursor.
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the tab text outline.
+ </theme_item>
<theme_item name="panel" type="StyleBox">
The style for the background fill.
</theme_item>
diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml
index 0c7b992cbf..24c114c18b 100644
--- a/doc/classes/Tabs.xml
+++ b/doc/classes/Tabs.xml
@@ -261,7 +261,7 @@
If [code]true[/code], tabs can be rearranged with mouse drag.
</member>
<member name="scrolling_enabled" type="bool" setter="set_scrolling_enabled" getter="get_scrolling_enabled" default="true">
- if [code]true[/code], the mouse's scroll wheel cab be used to navigate the scroll view.
+ if [code]true[/code], the mouse's scroll wheel can be used to navigate the scroll view.
</member>
<member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="Tabs.TabAlign" default="1">
The alignment of all tabs. See [enum TabAlign] for details.
@@ -362,6 +362,9 @@
<theme_item name="font_disabled_color" type="Color" default="Color( 0.9, 0.9, 0.9, 0.2 )">
Font color of disabled tabs.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the tab name.
+ </theme_item>
<theme_item name="font_selected_color" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
Font color of the currently selected tab.
</theme_item>
@@ -380,6 +383,9 @@
<theme_item name="increment_highlight" type="Texture2D">
Icon for the right arrow button that appears when there are too many tabs to fit in the container width. Used when the button is being hovered with the cursor.
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the tab text outline.
+ </theme_item>
<theme_item name="panel" type="StyleBox">
</theme_item>
<theme_item name="tab_disabled" type="StyleBox">
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index af4543374a..088bcd1c3c 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -402,13 +402,24 @@
<description>
Perform a search inside the text. Search flags can be specified in the [enum SearchFlags] enum.
Returns an empty [code]Dictionary[/code] if no result was found. Otherwise, returns a [code]Dictionary[/code] containing [code]line[/code] and [code]column[/code] entries, e.g:
- [codeblock]
- var result = search(key, flags, line, column)
- if !result.is_empty():
+ [codeblocks]
+ [gdscript]
+ var result = search("print", SEARCH_WHOLE_WORDS, 0, 0)
+ if !result.empty():
# Result found.
var line_number = result.line
var column_number = result.column
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ int[] result = Search("print", (uint)TextEdit.SearchFlags.WholeWords, 0, 0);
+ if (result.Length &gt; 0)
+ {
+ // Result found.
+ int lineNumber = result[(int)TextEdit.SearchResult.Line];
+ int columnNumber = result[(int)TextEdit.SearchResult.Column];
+ }
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="select">
@@ -725,6 +736,7 @@
Set additional options for BiDi override.
</member>
<member name="syntax_highlighter" type="SyntaxHighlighter" setter="set_syntax_highlighter" getter="get_syntax_highlighter">
+ Sets the [SyntaxHighlighter] to use.
</member>
<member name="text" type="String" setter="set_text" getter="get_text" default="&quot;&quot;">
String value of the [TextEdit].
@@ -914,7 +926,7 @@
</constants>
<theme_items>
<theme_item name="background_color" type="Color" default="Color( 0, 0, 0, 0 )">
- Sets the background [Color] of this [TextEdit]. [member syntax_highlighting] has to be enabled.
+ Sets the background [Color] of this [TextEdit].
</theme_item>
<theme_item name="brace_mismatch_color" type="Color" default="Color( 1, 0.2, 0.2, 1 )">
</theme_item>
@@ -953,6 +965,9 @@
<theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
Sets the font [Color].
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the [TextEdit].
+ </theme_item>
<theme_item name="font_readonly_color" type="Color" default="Color( 0.88, 0.88, 0.88, 0.5 )">
</theme_item>
<theme_item name="font_selected_color" type="Color" default="Color( 0, 0, 0, 1 )">
@@ -970,6 +985,9 @@
<theme_item name="normal" type="StyleBox">
Sets the [StyleBox] of this [TextEdit].
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
<theme_item name="read_only" type="StyleBox">
Sets the [StyleBox] of this [TextEdit] when [member readonly] is enabled.
</theme_item>
diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml
index 99eb8b81d4..69bf823ccd 100644
--- a/doc/classes/TextParagraph.xml
+++ b/doc/classes/TextParagraph.xml
@@ -145,7 +145,7 @@
<argument index="4" name="dc_color" type="Color" default="Color( 1, 1, 1, 1 )">
</argument>
<description>
- Draw outilines of all lines of the text and drop cap into a canvas item at a given position, with [code]color[/code]. [code]pos[/code] specifies the top left corner of the bounding box.
+ Draw outlines of all lines of the text and drop cap into a canvas item at a given position, with [code]color[/code]. [code]pos[/code] specifies the top left corner of the bounding box.
</description>
</method>
<method name="get_dropcap_lines" qualifiers="const">
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index 791646000b..4a41b68fee 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -9,6 +9,19 @@
<tutorials>
</tutorials>
<methods>
+ <method name="create_font_bitmap">
+ <return type="RID">
+ </return>
+ <argument index="0" name="height" type="float">
+ </argument>
+ <argument index="1" name="ascent" type="float">
+ </argument>
+ <argument index="2" name="base_size" type="int">
+ </argument>
+ <description>
+ Creates new, empty bitmap font. To free the resulting font, use [method free_rid] method.
+ </description>
+ </method>
<method name="create_font_memory">
<return type="RID">
</return>
@@ -78,6 +91,51 @@
Draws box displaying character hexadecimal code. Used for replacing missing characters.
</description>
</method>
+ <method name="font_bitmap_add_char">
+ <return type="void">
+ </return>
+ <argument index="0" name="font" type="RID">
+ </argument>
+ <argument index="1" name="char" type="int">
+ </argument>
+ <argument index="2" name="texture_idx" type="int">
+ </argument>
+ <argument index="3" name="rect" type="Rect2">
+ </argument>
+ <argument index="4" name="align" type="Vector2">
+ </argument>
+ <argument index="5" name="advance" type="float">
+ </argument>
+ <description>
+ Adds a character to the font, where [code]character[/code] is the Unicode value, [code]texture[/code] is the texture index, [code]rect[/code] is the region in the texture (in pixels!), [code]align[/code] is the (optional) alignment for the character and [code]advance[/code] is the (optional) advance.
+ </description>
+ </method>
+ <method name="font_bitmap_add_kerning_pair">
+ <return type="void">
+ </return>
+ <argument index="0" name="font" type="RID">
+ </argument>
+ <argument index="1" name="A" type="int">
+ </argument>
+ <argument index="2" name="B" type="int">
+ </argument>
+ <argument index="3" name="kerning" type="int">
+ </argument>
+ <description>
+ Adds a kerning pair to the bitmap font as a difference. Kerning pairs are special cases where a typeface advance is determined by the next character.
+ </description>
+ </method>
+ <method name="font_bitmap_add_texture">
+ <return type="void">
+ </return>
+ <argument index="0" name="font" type="RID">
+ </argument>
+ <argument index="1" name="texture" type="Texture">
+ </argument>
+ <description>
+ Adds a texture to the bitmap font.
+ </description>
+ </method>
<method name="font_draw_glyph" qualifiers="const">
<return type="Vector2">
</return>
@@ -295,6 +353,24 @@
Returns list of script support overrides.
</description>
</method>
+ <method name="font_get_spacing_glyph" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="font" type="RID">
+ </argument>
+ <description>
+ Returns extra spacing for each glyph in pixels.
+ </description>
+ </method>
+ <method name="font_get_spacing_space" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="font" type="RID">
+ </argument>
+ <description>
+ Sets extra spacing for each glyph in pixels.
+ </description>
+ </method>
<method name="font_get_supported_chars" qualifiers="const">
<return type="String">
</return>
@@ -490,6 +566,28 @@
Adds override for [method font_is_script_supported].
</description>
</method>
+ <method name="font_set_spacing_glyph">
+ <return type="void">
+ </return>
+ <argument index="0" name="font" type="RID">
+ </argument>
+ <argument index="1" name="value" type="int">
+ </argument>
+ <description>
+ Returns extra spacing for the space character in pixels.
+ </description>
+ </method>
+ <method name="font_set_spacing_space">
+ <return type="void">
+ </return>
+ <argument index="0" name="font" type="RID">
+ </argument>
+ <argument index="1" name="value" type="int">
+ </argument>
+ <description>
+ Sets extra spacing for the space character in pixels.
+ </description>
+ </method>
<method name="font_set_variation">
<return type="void">
</return>
@@ -655,7 +753,7 @@
<method name="shaped_text_clear">
<return type="void">
</return>
- <argument index="0" name="arg0" type="RID">
+ <argument index="0" name="rid" type="RID">
</argument>
<description>
Clears text buffer (removes text and inline objects).
diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml
index 3f7f22ebcd..9f976838e9 100644
--- a/doc/classes/Theme.xml
+++ b/doc/classes/Theme.xml
@@ -236,7 +236,8 @@
<argument index="1" name="node_type" type="StringName">
</argument>
<description>
- Returns the icon [StyleBox] at [code]name[/code] if the theme has [code]node_type[/code].
+ Returns the [StyleBox] at [code]name[/code] if the theme has [code]node_type[/code].
+ Valid [code]name[/code]s may be found using [method get_stylebox_list]. Valid [code]node_type[/code]s may be found using [method get_stylebox_type_list].
</description>
</method>
<method name="get_stylebox_list" qualifiers="const">
@@ -246,6 +247,7 @@
</argument>
<description>
Returns all the [StyleBox]s as a [PackedStringArray] filled with each [StyleBox]'s name, for use in [method get_stylebox], if the theme has [code]node_type[/code].
+ Valid [code]node_type[/code]s may be found using [method get_stylebox_type_list].
</description>
</method>
<method name="get_stylebox_type_list" qualifiers="const">
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index a12ef614e3..7ed8ad6d4a 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -172,12 +172,22 @@
[b]Note:[/b] Data such as navigation polygons and collision shapes are not immediately updated for performance reasons.
If you need these to be immediately updated, you can call [method update_dirty_quadrants].
Overriding this method also overrides it internally, allowing custom logic to be implemented when tiles are placed/removed:
- [codeblock]
+ [codeblocks]
+ [gdscript]
func set_cell(x, y, tile, flip_x=false, flip_y=false, transpose=false, autotile_coord=Vector2())
# Write your custom logic here.
# To call the default method:
.set_cell(x, y, tile, flip_x, flip_y, transpose, autotile_coord)
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ public void SetCell(int x, int y, int tile, bool flipX = false, bool flipY = false, bool transpose = false, Vector2 autotileCoord = new Vector2())
+ {
+ // Write your custom logic here.
+ // To call the default method:
+ base.SetCell(x, y, tile, flipX, flipY, transpose, autotileCoord);
+ }
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="set_cellv">
@@ -262,6 +272,9 @@
</method>
</methods>
<members>
+ <member name="bake_navigation" type="bool" setter="set_bake_navigation" getter="is_baking_navigation" default="false">
+ If [code]true[/code], this TileMap bakes a navigation region.
+ </member>
<member name="cell_clip_uv" type="bool" setter="set_clip_uv" getter="get_clip_uv" default="false">
If [code]true[/code], the cell's UVs will be clipped.
</member>
diff --git a/doc/classes/Timer.xml b/doc/classes/Timer.xml
index ab75e21ce8..807d8033c1 100644
--- a/doc/classes/Timer.xml
+++ b/doc/classes/Timer.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
Counts down a specified interval and emits a signal on reaching 0. Can be set to repeat or "one-shot" mode.
- [b]Note:[/b] To create an one-shot timer without instantiating a node, use [method SceneTree.create_timer].
+ [b]Note:[/b] To create a one-shot timer without instantiating a node, use [method SceneTree.create_timer].
</description>
<tutorials>
<link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link>
@@ -47,8 +47,8 @@
<member name="paused" type="bool" setter="set_paused" getter="is_paused">
If [code]true[/code], the timer is paused and will not process until it is unpaused again, even if [method start] is called.
</member>
- <member name="process_mode" type="int" setter="set_timer_process_mode" getter="get_timer_process_mode" enum="Timer.TimerProcessMode" default="1">
- Processing mode. See [enum TimerProcessMode].
+ <member name="process_callback" type="int" setter="set_timer_process_callback" getter="get_timer_process_callback" enum="Timer.TimerProcessCallback" default="1">
+ Processing callback. See [enum TimerProcessCallback].
</member>
<member name="time_left" type="float" setter="" getter="get_time_left">
The timer's remaining time in seconds. Returns 0 if the timer is inactive.
@@ -66,10 +66,10 @@
</signal>
</signals>
<constants>
- <constant name="TIMER_PROCESS_PHYSICS" value="0" enum="TimerProcessMode">
+ <constant name="TIMER_PROCESS_PHYSICS" value="0" enum="TimerProcessCallback">
Update the timer during the physics step at each frame (fixed framerate processing).
</constant>
- <constant name="TIMER_PROCESS_IDLE" value="1" enum="TimerProcessMode">
+ <constant name="TIMER_PROCESS_IDLE" value="1" enum="TimerProcessCallback">
Update the timer during the idle time at each frame.
</constant>
</constants>
diff --git a/doc/classes/TouchScreenButton.xml b/doc/classes/TouchScreenButton.xml
index 355804f2a3..bb4c17c531 100644
--- a/doc/classes/TouchScreenButton.xml
+++ b/doc/classes/TouchScreenButton.xml
@@ -4,7 +4,7 @@
Button for touch screen devices for gameplay use.
</brief_description>
<description>
- TouchScreenButton allows you to create on-screen buttons for touch devices. It's intended for gameplay use, such as a unit you have to touch to move.
+ TouchScreenButton allows you to create on-screen buttons for touch devices. It's intended for gameplay use, such as a unit you have to touch to move. Unlike [Button], TouchScreenButton supports multitouch out of the box. Several TouchScreenButtons can be pressed at the same time with touch input.
This node inherits from [Node2D]. Unlike with [Control] nodes, you cannot set anchors on it. If you want to create menus or user interfaces, you may want to use [Button] nodes instead. To make button nodes react to touch events, you can enable the Emulate Mouse option in the Project Settings.
You can configure TouchScreenButton to be visible only on touch devices, helping you develop your game both for desktop and mobile devices.
</description>
@@ -30,7 +30,8 @@
The button's texture for the normal state.
</member>
<member name="passby_press" type="bool" setter="set_passby_press" getter="is_passby_press_enabled" default="false">
- If [code]true[/code], pass-by presses are enabled.
+ If [code]true[/code], the [signal pressed] and [signal released] signals are emitted whenever a pressed finger goes in and out of the button, even if the pressure started outside the active area of the button.
+ [b]Note:[/b] this is a "pass-by" (not "bypass") press mode.
</member>
<member name="pressed" type="Texture2D" setter="set_texture_pressed" getter="get_texture_pressed">
The button's texture for the pressed state.
@@ -42,7 +43,7 @@
If [code]true[/code], the button's shape is centered in the provided texture. If no texture is used, this property has no effect.
</member>
<member name="shape_visible" type="bool" setter="set_shape_visible" getter="is_shape_visible" default="true">
- If [code]true[/code], the button's shape is visible.
+ If [code]true[/code], the button's shape is visible in the editor.
</member>
<member name="visibility_mode" type="int" setter="set_visibility_mode" getter="get_visibility_mode" enum="TouchScreenButton.VisibilityMode" default="0">
The button's visibility mode. See [enum VisibilityMode] for possible values.
diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml
index cda69f6a64..9d8721e2de 100644
--- a/doc/classes/Transform.xml
+++ b/doc/classes/Transform.xml
@@ -58,14 +58,14 @@
Constructs a Transform from four [Vector3] values (matrix columns). Each axis corresponds to local basis vectors (some of which may be scaled).
</description>
</method>
- <method name="affine_inverse">
+ <method name="affine_inverse" qualifiers="const">
<return type="Transform">
</return>
<description>
Returns the inverse of the transform, under the assumption that the transformation is composed of rotation, scaling and translation.
</description>
</method>
- <method name="interpolate_with">
+ <method name="interpolate_with" qualifiers="const">
<return type="Transform">
</return>
<argument index="0" name="xform" type="Transform">
@@ -76,14 +76,14 @@
Interpolates the transform to other Transform by weight amount (on the range of 0.0 to 1.0).
</description>
</method>
- <method name="inverse">
+ <method name="inverse" qualifiers="const">
<return type="Transform">
</return>
<description>
Returns the inverse of the transform, under the assumption that the transformation is composed of rotation and translation (no scaling, use affine_inverse for transforms with scaling).
</description>
</method>
- <method name="is_equal_approx">
+ <method name="is_equal_approx" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="xform" type="Transform">
@@ -92,12 +92,12 @@
Returns [code]true[/code] if this transform and [code]transform[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
</description>
</method>
- <method name="looking_at">
+ <method name="looking_at" qualifiers="const">
<return type="Transform">
</return>
<argument index="0" name="target" type="Vector3">
</argument>
- <argument index="1" name="up" type="Vector3">
+ <argument index="1" name="up" type="Vector3" default="Vector3( 0, 1, 0 )">
</argument>
<description>
Returns a copy of the transform rotated such that its -Z axis points towards the [code]target[/code] position.
@@ -153,14 +153,14 @@
<description>
</description>
</method>
- <method name="orthonormalized">
+ <method name="orthonormalized" qualifiers="const">
<return type="Transform">
</return>
<description>
Returns the transform with the basis orthogonal (90 degrees), and normalized axis vectors.
</description>
</method>
- <method name="rotated">
+ <method name="rotated" qualifiers="const">
<return type="Transform">
</return>
<argument index="0" name="axis" type="Vector3">
@@ -171,7 +171,7 @@
Rotates the transform around the given axis by the given angle (in radians), using matrix multiplication. The axis must be a normalized vector.
</description>
</method>
- <method name="scaled">
+ <method name="scaled" qualifiers="const">
<return type="Transform">
</return>
<argument index="0" name="scale" type="Vector3">
@@ -180,7 +180,7 @@
Scales basis and origin of the transform by the given scale factor, using matrix multiplication.
</description>
</method>
- <method name="translated">
+ <method name="translated" qualifiers="const">
<return type="Transform">
</return>
<argument index="0" name="offset" type="Vector3">
diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml
index 406774cbfe..6ae7fbcf79 100644
--- a/doc/classes/Transform2D.xml
+++ b/doc/classes/Transform2D.xml
@@ -54,14 +54,14 @@
Constructs the transform from 3 [Vector2] values representing [member x], [member y], and the [member origin] (the three column vectors).
</description>
</method>
- <method name="affine_inverse">
+ <method name="affine_inverse" qualifiers="const">
<return type="Transform2D">
</return>
<description>
Returns the inverse of the transform, under the assumption that the transformation is composed of rotation, scaling and translation.
</description>
</method>
- <method name="basis_xform">
+ <method name="basis_xform" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="v" type="Vector2">
@@ -71,7 +71,7 @@
This method does not account for translation (the origin vector).
</description>
</method>
- <method name="basis_xform_inv">
+ <method name="basis_xform_inv" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="v" type="Vector2">
@@ -81,28 +81,28 @@
This method does not account for translation (the origin vector).
</description>
</method>
- <method name="get_origin">
+ <method name="get_origin" qualifiers="const">
<return type="Vector2">
</return>
<description>
Returns the transform's origin (translation).
</description>
</method>
- <method name="get_rotation">
+ <method name="get_rotation" qualifiers="const">
<return type="float">
</return>
<description>
Returns the transform's rotation (in radians).
</description>
</method>
- <method name="get_scale">
+ <method name="get_scale" qualifiers="const">
<return type="Vector2">
</return>
<description>
Returns the scale.
</description>
</method>
- <method name="interpolate_with">
+ <method name="interpolate_with" qualifiers="const">
<return type="Transform2D">
</return>
<argument index="0" name="xform" type="Transform2D">
@@ -113,14 +113,14 @@
Returns a transform interpolated between this transform and another by a given [code]weight[/code] (on the range of 0.0 to 1.0).
</description>
</method>
- <method name="inverse">
+ <method name="inverse" qualifiers="const">
<return type="Transform2D">
</return>
<description>
Returns the inverse of the transform, under the assumption that the transformation is composed of rotation and translation (no scaling, use [method affine_inverse] for transforms with scaling).
</description>
</method>
- <method name="is_equal_approx">
+ <method name="is_equal_approx" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="xform" type="Transform2D">
@@ -185,14 +185,14 @@
<description>
</description>
</method>
- <method name="orthonormalized">
+ <method name="orthonormalized" qualifiers="const">
<return type="Transform2D">
</return>
<description>
Returns the transform with the basis orthogonal (90 degrees), and normalized axis vectors (scale of 1 or -1).
</description>
</method>
- <method name="rotated">
+ <method name="rotated" qualifiers="const">
<return type="Transform2D">
</return>
<argument index="0" name="phi" type="float">
@@ -201,7 +201,7 @@
Rotates the transform by the given angle (in radians), using matrix multiplication.
</description>
</method>
- <method name="scaled">
+ <method name="scaled" qualifiers="const">
<return type="Transform2D">
</return>
<argument index="0" name="scale" type="Vector2">
@@ -210,7 +210,7 @@
Scales the transform by the given scale factor, using matrix multiplication.
</description>
</method>
- <method name="translated">
+ <method name="translated" qualifiers="const">
<return type="Transform2D">
</return>
<argument index="0" name="offset" type="Vector2">
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 406bda412a..a09f1bf470 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -6,16 +6,30 @@
<description>
This shows a tree of items that can be selected, expanded and collapsed. The tree can have multiple columns with custom controls like text editing, buttons and popups. It can be useful for structured displays and interactions.
Trees are built via code, using [TreeItem] objects to create the structure. They have a single root but multiple roots can be simulated if a dummy hidden root is added.
- [codeblock]
+ [codeblocks]
+ [gdscript]
func _ready():
var tree = Tree.new()
var root = tree.create_item()
- tree.set_hide_root(true)
+ tree.hide_root = true
var child1 = tree.create_item(root)
var child2 = tree.create_item(root)
var subchild1 = tree.create_item(child1)
subchild1.set_text(0, "Subchild1")
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ public override void _Ready()
+ {
+ var tree = new Tree();
+ TreeItem root = tree.CreateItem();
+ tree.HideRoot = true;
+ TreeItem child1 = tree.CreateItem(root);
+ TreeItem child2 = tree.CreateItem(root);
+ TreeItem subchild1 = tree.CreateItem(child1);
+ subchild1.SetText(0, "Subchild1");
+ }
+ [/csharp]
+ [/codeblocks]
To iterate over all the [TreeItem] objects in a [Tree] object, use [method TreeItem.get_next] and [method TreeItem.get_children] after getting the root through [method get_root]. You can use [method Object.free] on a [TreeItem] to remove it from the [Tree].
</description>
<tutorials>
@@ -57,6 +71,13 @@
The new item will be the [code]idx[/code]th child of parent, or it will be the last child if there are not enough siblings.
</description>
</method>
+ <method name="edit_selected">
+ <return type="bool">
+ </return>
+ <description>
+ Edits the selected tree item as if it was clicked. The item must be set editable with [method TreeItem.set_editable]. Returns [code]true[/code] if the item could be edited. Fails if no item is selected.
+ </description>
+ </method>
<method name="ensure_cursor_is_visible">
<return type="void">
</return>
@@ -145,13 +166,26 @@
</return>
<description>
Returns the currently edited item. Can be used with [signal item_edited] to get the item that was modified.
- [codeblock]
+ [codeblocks]
+ [gdscript]
func _ready():
$Tree.item_edited.connect(on_Tree_item_edited)
func on_Tree_item_edited():
print($Tree.get_edited()) # This item just got edited (e.g. checked).
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ public override void _Ready()
+ {
+ GetNode&lt;Tree&gt;("Tree").ItemEdited += OnTreeItemEdited;
+ }
+
+ public void OnTreeItemEdited()
+ {
+ GD.Print(GetNode&lt;Tree&gt;("Tree").GetEdited()); // This item just got edited (e.g. checked).
+ }
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="get_edited_column" qualifiers="const">
@@ -230,6 +264,14 @@
To tell whether a column of an item is selected, use [method TreeItem.is_selected].
</description>
</method>
+ <method name="scroll_to_item">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="Object">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_column_expand">
<return type="void">
</return>
@@ -524,6 +566,9 @@
<theme_item name="font_color" type="Color" default="Color( 0.69, 0.69, 0.69, 1 )">
Default text [Color] of the item.
</theme_item>
+ <theme_item name="font_outline_color" type="Color" default="Color( 1, 1, 1, 1 )">
+ The tint of text outline of the item.
+ </theme_item>
<theme_item name="font_selected_color" type="Color" default="Color( 1, 1, 1, 1 )">
Text [Color] used when the item is selected.
</theme_item>
@@ -539,6 +584,9 @@
<theme_item name="item_margin" type="int" default="12">
The horizontal margin at the start of an item. This is used when folding is enabled for the item.
</theme_item>
+ <theme_item name="outline_size" type="int" default="0">
+ The size of the text outline.
+ </theme_item>
<theme_item name="relationship_line_color" type="Color" default="Color( 0.27, 0.27, 0.27, 1 )">
[Color] of the relationship lines.
</theme_item>
diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml
index 56ccaaf383..00cca40093 100644
--- a/doc/classes/Tween.xml
+++ b/doc/classes/Tween.xml
@@ -7,14 +7,23 @@
Tweens are useful for animations requiring a numerical property to be interpolated over a range of values. The name [i]tween[/i] comes from [i]in-betweening[/i], an animation technique where you specify [i]keyframes[/i] and the computer interpolates the frames that appear between them.
[Tween] is more suited than [AnimationPlayer] for animations where you don't know the final values in advance. For example, interpolating a dynamically-chosen camera zoom value is best done with a [Tween] node; it would be difficult to do the same thing with an [AnimationPlayer] node.
Here is a brief usage example that makes a 2D node move smoothly between two positions:
- [codeblock]
+ [codeblocks]
+ [gdscript]
var tween = get_node("Tween")
tween.interpolate_property($Node2D, "position",
Vector2(0, 0), Vector2(100, 100), 1,
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
tween.start()
- [/codeblock]
- Many methods require a property name, such as [code]"position"[/code] above. You can find the correct property name by hovering over the property in the Inspector. You can also provide the components of a property directly by using [code]"property:component"[/code] (eg. [code]position:x[/code]), where it would only apply to that particular component.
+ [/gdscript]
+ [csharp]
+ var tween = GetNode&lt;Tween&gt;("Tween");
+ tween.InterpolateProperty(GetNode&lt;Node2D&gt;("Node2D"), "position",
+ new Vector2(0, 0), new Vector2(100, 100), 1,
+ Tween.TransitionType.Linear, Tween.EaseType.InOut);
+ tween.Start();
+ [/csharp]
+ [/codeblocks]
+ Many methods require a property name, such as [code]"position"[/code] above. You can find the correct property name by hovering over the property in the Inspector. You can also provide the components of a property directly by using [code]"property:component"[/code] (e.g. [code]position:x[/code]), where it would only apply to that particular component.
Many of the methods accept [code]trans_type[/code] and [code]ease_type[/code]. The first accepts an [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [url=https://easings.net/]easings.net[/url] for some examples). The second accepts an [enum EaseType] constant, and controls where the [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [constant EASE_IN_OUT], and use the one that looks best.
[url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/tween_cheatsheet.png]Tween easing and transition types cheatsheet[/url]
</description>
diff --git a/doc/classes/UDPServer.xml b/doc/classes/UDPServer.xml
index aabfed85f0..0fc00f67f8 100644
--- a/doc/classes/UDPServer.xml
+++ b/doc/classes/UDPServer.xml
@@ -7,8 +7,9 @@
A simple server that opens a UDP socket and returns connected [PacketPeerUDP] upon receiving new packets. See also [method PacketPeerUDP.connect_to_host].
After starting the server ([method listen]), you will need to [method poll] it at regular intervals (e.g. inside [method Node._process]) for it to process new packets, delivering them to the appropriate [PacketPeerUDP], and taking new connections.
Below a small example of how it can be used:
- [codeblock]
- # server.gd
+ [codeblocks]
+ [gdscript]
+ class_name Server
extends Node
var server := UDPServer.new()
@@ -21,20 +22,57 @@
server.poll() # Important!
if server.is_connection_available():
var peer : PacketPeerUDP = server.take_connection()
- var pkt = peer.get_packet()
+ var packet = peer.get_packet()
print("Accepted peer: %s:%s" % [peer.get_packet_ip(), peer.get_packet_port()])
- print("Received data: %s" % [pkt.get_string_from_utf8()])
+ print("Received data: %s" % [packet.get_string_from_utf8()])
# Reply so it knows we received the message.
- peer.put_packet(pkt)
+ peer.put_packet(packet)
# Keep a reference so we can keep contacting the remote peer.
peers.append(peer)
for i in range(0, peers.size()):
pass # Do something with the connected peers.
+ [/gdscript]
+ [csharp]
+ using Godot;
+ using System;
+ using System.Collections.Generic;
- [/codeblock]
- [codeblock]
- # client.gd
+ public class Server : Node
+ {
+ public UDPServer Server = new UDPServer();
+ public List&lt;PacketPeerUDP&gt; Peers = new List&lt;PacketPeerUDP&gt;();
+
+ public override void _Ready()
+ {
+ Server.Listen(4242);
+ }
+
+ public override void _Process(float delta)
+ {
+ Server.Poll(); // Important!
+ if (Server.IsConnectionAvailable())
+ {
+ PacketPeerUDP peer = Server.TakeConnection();
+ byte[] packet = peer.GetPacket();
+ GD.Print($"Accepted Peer: {peer.GetPacketIp()}:{peer.GetPacketPort()}");
+ GD.Print($"Received Data: {packet.GetStringFromUTF8()}");
+ // Reply so it knows we received the message.
+ peer.PutPacket(packet);
+ // Keep a reference so we can keep contacting the remote peer.
+ Peers.Add(peer);
+ }
+ foreach (var peer in Peers)
+ {
+ // Do something with the peers.
+ }
+ }
+ }
+ [/csharp]
+ [/codeblocks]
+ [codeblocks]
+ [gdscript]
+ class_name Client
extends Node
var udp := PacketPeerUDP.new()
@@ -50,7 +88,37 @@
if udp.get_available_packet_count() &gt; 0:
print("Connected: %s" % udp.get_packet().get_string_from_utf8())
connected = true
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ using Godot;
+ using System;
+
+ public class Client : Node
+ {
+ public PacketPeerUDP Udp = new PacketPeerUDP();
+ public bool Connected = false;
+
+ public override void _Ready()
+ {
+ Udp.ConnectToHost("127.0.0.1", 4242);
+ }
+
+ public override void _Process(float delta)
+ {
+ if (!Connected)
+ {
+ // Try to contact server
+ Udp.PutPacket("The Answer Is..42!".ToUTF8());
+ }
+ if (Udp.GetAvailablePacketCount() &gt; 0)
+ {
+ GD.Print($"Connected: {Udp.GetPacket().GetStringFromUTF8()}");
+ Connected = true;
+ }
+ }
+ }
+ [/csharp]
+ [/codeblocks]
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml
index 0e4a76a1a9..aba6183124 100644
--- a/doc/classes/UndoRedo.xml
+++ b/doc/classes/UndoRedo.xml
@@ -7,7 +7,8 @@
Helper to manage undo/redo operations in the editor or custom tools. It works by registering methods and property changes inside "actions".
Common behavior is to create an action, then add do/undo calls to functions or property changes, then committing the action.
Here's an example on how to add an action to the Godot editor's own [UndoRedo], from a plugin:
- [codeblock]
+ [codeblocks]
+ [gdscript]
var undo_redo = get_undo_redo() # Method of EditorPlugin.
func do_something():
@@ -24,7 +25,37 @@
undo_redo.add_do_property(node, "position", Vector2(100,100))
undo_redo.add_undo_property(node, "position", node.position)
undo_redo.commit_action()
- [/codeblock]
+ [/gdscript]
+ [csharp]
+ public UndoRedo UndoRedo;
+
+ public override void _Ready()
+ {
+ UndoRedo = GetUndoRedo(); // Method of EditorPlugin.
+ }
+
+ public void DoSomething()
+ {
+ // Put your code here.
+ }
+
+ public void UndoSomething()
+ {
+ // Put here the code that reverts what's done by "DoSomething()".
+ }
+
+ private void OnMyButtonPressed()
+ {
+ var node = GetNode&lt;Node2D&gt;("MyNode2D");
+ UndoRedo.CreateAction("Move the node");
+ UndoRedo.AddDoMethod(this, nameof(DoSomething));
+ UndoRedo.AddUndoMethod(this, nameof(UndoSomething));
+ UndoRedo.AddDoProperty(node, "position", new Vector2(100, 100));
+ UndoRedo.AddUndoProperty(node, "position", node.Position);
+ UndoRedo.CommitAction();
+ }
+ [/csharp]
+ [/codeblocks]
[method create_action], [method add_do_method], [method add_undo_method], [method add_do_property], [method add_undo_property], and [method commit_action] should be called one after the other, like in the example. Not doing so could lead to crashes.
If you don't need to register a method, you can leave [method add_do_method] and [method add_undo_method] out; the same goes for properties. You can also register more than one method/property.
</description>
@@ -131,7 +162,7 @@
<method name="get_action_name">
<return type="String">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="id" type="int">
</argument>
<description>
Gets the action name from its index.
@@ -155,7 +186,7 @@
<return type="int">
</return>
<description>
- Return how many element are in the history.
+ Return how many elements are in the history.
</description>
</method>
<method name="get_version" qualifiers="const">
diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml
index 4159a38d96..b979425b85 100644
--- a/doc/classes/Vector2.xml
+++ b/doc/classes/Vector2.xml
@@ -53,14 +53,14 @@
Constructs a new [Vector2] from the given [code]x[/code] and [code]y[/code].
</description>
</method>
- <method name="abs">
+ <method name="abs" qualifiers="const">
<return type="Vector2">
</return>
<description>
Returns a new vector with all components in absolute values (i.e. positive).
</description>
</method>
- <method name="angle">
+ <method name="angle" qualifiers="const">
<return type="float">
</return>
<description>
@@ -69,7 +69,7 @@
Equivalent to the result of [method @GlobalScope.atan2] when called with the vector's [member y] and [member x] as parameters: [code]atan2(y, x)[/code].
</description>
</method>
- <method name="angle_to">
+ <method name="angle_to" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="to" type="Vector2">
@@ -78,7 +78,7 @@
Returns the angle to the given vector, in radians.
</description>
</method>
- <method name="angle_to_point">
+ <method name="angle_to_point" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="to" type="Vector2">
@@ -87,14 +87,14 @@
Returns the angle between the line connecting the two points and the X axis, in radians.
</description>
</method>
- <method name="aspect">
+ <method name="aspect" qualifiers="const">
<return type="float">
</return>
<description>
Returns the aspect ratio of this vector, the ratio of [member x] to [member y].
</description>
</method>
- <method name="bounce">
+ <method name="bounce" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="n" type="Vector2">
@@ -103,14 +103,14 @@
Returns the vector "bounced off" from a plane defined by the given normal.
</description>
</method>
- <method name="ceil">
+ <method name="ceil" qualifiers="const">
<return type="Vector2">
</return>
<description>
Returns the vector with all components rounded up (towards positive infinity).
</description>
</method>
- <method name="clamped">
+ <method name="clamped" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="length" type="float">
@@ -119,7 +119,7 @@
Returns the vector with a maximum length by limiting its length to [code]length[/code].
</description>
</method>
- <method name="cross">
+ <method name="cross" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="with" type="Vector2">
@@ -128,7 +128,7 @@
Returns the cross product of this vector and [code]with[/code].
</description>
</method>
- <method name="cubic_interpolate">
+ <method name="cubic_interpolate" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="b" type="Vector2">
@@ -143,7 +143,7 @@
Cubically interpolates between this vector and [code]b[/code] using [code]pre_a[/code] and [code]post_b[/code] as handles, and returns the result at position [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation.
</description>
</method>
- <method name="direction_to">
+ <method name="direction_to" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="b" type="Vector2">
@@ -152,7 +152,7 @@
Returns the normalized vector pointing from this vector to [code]b[/code]. This is equivalent to using [code](b - a).normalized()[/code].
</description>
</method>
- <method name="distance_squared_to">
+ <method name="distance_squared_to" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="to" type="Vector2">
@@ -162,7 +162,7 @@
This method runs faster than [method distance_to], so prefer it if you need to compare vectors or need the squared distance for some formula.
</description>
</method>
- <method name="distance_to">
+ <method name="distance_to" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="to" type="Vector2">
@@ -171,7 +171,7 @@
Returns the distance between this vector and [code]to[/code].
</description>
</method>
- <method name="dot">
+ <method name="dot" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="with" type="Vector2">
@@ -183,14 +183,14 @@
[b]Note:[/b] [code]a.dot(b)[/code] is equivalent to [code]b.dot(a)[/code].
</description>
</method>
- <method name="floor">
+ <method name="floor" qualifiers="const">
<return type="Vector2">
</return>
<description>
Returns the vector with all components rounded down (towards negative infinity).
</description>
</method>
- <method name="is_equal_approx">
+ <method name="is_equal_approx" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="to" type="Vector2">
@@ -199,21 +199,21 @@
Returns [code]true[/code] if this vector and [code]v[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component.
</description>
</method>
- <method name="is_normalized">
+ <method name="is_normalized" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the vector is normalized, [code]false[/code] otherwise.
</description>
</method>
- <method name="length">
+ <method name="length" qualifiers="const">
<return type="float">
</return>
<description>
Returns the length (magnitude) of this vector.
</description>
</method>
- <method name="length_squared">
+ <method name="length_squared" qualifiers="const">
<return type="float">
</return>
<description>
@@ -221,7 +221,7 @@
This method runs faster than [method length], so prefer it if you need to compare vectors or need the squared distance for some formula.
</description>
</method>
- <method name="lerp">
+ <method name="lerp" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="to" type="Vector2">
@@ -232,7 +232,7 @@
Returns the result of the linear interpolation between this vector and [code]b[/code] by amount [code]t[/code]. [code]t[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation.
</description>
</method>
- <method name="move_toward">
+ <method name="move_toward" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="to" type="Vector2">
@@ -243,7 +243,7 @@
Moves the vector toward [code]to[/code] by the fixed [code]delta[/code] amount.
</description>
</method>
- <method name="normalized">
+ <method name="normalized" qualifiers="const">
<return type="Vector2">
</return>
<description>
@@ -390,14 +390,14 @@
<description>
</description>
</method>
- <method name="orthogonal">
+ <method name="orthogonal" qualifiers="const">
<return type="Vector2">
</return>
<description>
Returns a perpendicular vector rotated 90 degrees counter-clockwise compared to the original, with the same length.
</description>
</method>
- <method name="posmod">
+ <method name="posmod" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="mod" type="float">
@@ -406,7 +406,7 @@
Returns a vector composed of the [method @GlobalScope.fposmod] of this vector's components and [code]mod[/code].
</description>
</method>
- <method name="posmodv">
+ <method name="posmodv" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="modv" type="Vector2">
@@ -415,7 +415,7 @@
Returns a vector composed of the [method @GlobalScope.fposmod] of this vector's components and [code]modv[/code]'s components.
</description>
</method>
- <method name="project">
+ <method name="project" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="b" type="Vector2">
@@ -424,7 +424,7 @@
Returns the vector projected onto the vector [code]b[/code].
</description>
</method>
- <method name="reflect">
+ <method name="reflect" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="n" type="Vector2">
@@ -433,7 +433,7 @@
Returns the vector reflected from a plane defined by the given normal.
</description>
</method>
- <method name="rotated">
+ <method name="rotated" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="phi" type="float">
@@ -442,21 +442,21 @@
Returns the vector rotated by [code]phi[/code] radians. See also [method @GlobalScope.deg2rad].
</description>
</method>
- <method name="round">
+ <method name="round" qualifiers="const">
<return type="Vector2">
</return>
<description>
Returns the vector with all components rounded to the nearest integer, with halfway cases rounded away from zero.
</description>
</method>
- <method name="sign">
+ <method name="sign" qualifiers="const">
<return type="Vector2">
</return>
<description>
Returns the vector with each component set to one or negative one, depending on the signs of the components, or zero if the component is zero, by calling [method @GlobalScope.sign] on each component.
</description>
</method>
- <method name="slerp">
+ <method name="slerp" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="to" type="Vector2">
@@ -468,7 +468,7 @@
[b]Note:[/b] Both vectors must be normalized.
</description>
</method>
- <method name="slide">
+ <method name="slide" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="n" type="Vector2">
@@ -477,7 +477,7 @@
Returns this vector slid along a plane defined by the given normal.
</description>
</method>
- <method name="snapped">
+ <method name="snapped" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="step" type="Vector2">
diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml
index a4ea5c2742..b38b968ba3 100644
--- a/doc/classes/Vector2i.xml
+++ b/doc/classes/Vector2i.xml
@@ -50,14 +50,14 @@
Constructs a new [Vector2i] from the given [code]x[/code] and [code]y[/code].
</description>
</method>
- <method name="abs">
+ <method name="abs" qualifiers="const">
<return type="Vector2i">
</return>
<description>
Returns a new vector with all components in absolute values (i.e. positive).
</description>
</method>
- <method name="aspect">
+ <method name="aspect" qualifiers="const">
<return type="float">
</return>
<description>
@@ -212,7 +212,7 @@
<description>
</description>
</method>
- <method name="sign">
+ <method name="sign" qualifiers="const">
<return type="Vector2i">
</return>
<description>
diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml
index 2d129a2c86..bd568e01ec 100644
--- a/doc/classes/Vector3.xml
+++ b/doc/classes/Vector3.xml
@@ -55,23 +55,23 @@
Returns a [Vector3] with the given components.
</description>
</method>
- <method name="abs">
+ <method name="abs" qualifiers="const">
<return type="Vector3">
</return>
<description>
Returns a new vector with all components in absolute values (i.e. positive).
</description>
</method>
- <method name="angle_to">
+ <method name="angle_to" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="to" type="Vector3">
</argument>
<description>
- Returns the minimum angle to the given vector, in radians.
+ Returns the unsigned minimum angle to the given vector, in radians.
</description>
</method>
- <method name="bounce">
+ <method name="bounce" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="n" type="Vector3">
@@ -80,14 +80,14 @@
Returns the vector "bounced off" from a plane defined by the given normal.
</description>
</method>
- <method name="ceil">
+ <method name="ceil" qualifiers="const">
<return type="Vector3">
</return>
<description>
Returns a new vector with all components rounded up (towards positive infinity).
</description>
</method>
- <method name="cross">
+ <method name="cross" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="with" type="Vector3">
@@ -96,7 +96,7 @@
Returns the cross product of this vector and [code]b[/code].
</description>
</method>
- <method name="cubic_interpolate">
+ <method name="cubic_interpolate" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="b" type="Vector3">
@@ -111,7 +111,7 @@
Performs a cubic interpolation between vectors [code]pre_a[/code], [code]a[/code], [code]b[/code], [code]post_b[/code] ([code]a[/code] is current), by the given amount [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation.
</description>
</method>
- <method name="direction_to">
+ <method name="direction_to" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="b" type="Vector3">
@@ -120,7 +120,7 @@
Returns the normalized vector pointing from this vector to [code]b[/code]. This is equivalent to using [code](b - a).normalized()[/code].
</description>
</method>
- <method name="distance_squared_to">
+ <method name="distance_squared_to" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="b" type="Vector3">
@@ -130,7 +130,7 @@
This method runs faster than [method distance_to], so prefer it if you need to compare vectors or need the squared distance for some formula.
</description>
</method>
- <method name="distance_to">
+ <method name="distance_to" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="b" type="Vector3">
@@ -139,7 +139,7 @@
Returns the distance between this vector and [code]b[/code].
</description>
</method>
- <method name="dot">
+ <method name="dot" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="with" type="Vector3">
@@ -151,21 +151,21 @@
[b]Note:[/b] [code]a.dot(b)[/code] is equivalent to [code]b.dot(a)[/code].
</description>
</method>
- <method name="floor">
+ <method name="floor" qualifiers="const">
<return type="Vector3">
</return>
<description>
Returns a new vector with all components rounded down (towards negative infinity).
</description>
</method>
- <method name="inverse">
+ <method name="inverse" qualifiers="const">
<return type="Vector3">
</return>
<description>
Returns the inverse of the vector. This is the same as [code]Vector3( 1.0 / v.x, 1.0 / v.y, 1.0 / v.z )[/code].
</description>
</method>
- <method name="is_equal_approx">
+ <method name="is_equal_approx" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="to" type="Vector3">
@@ -174,21 +174,21 @@
Returns [code]true[/code] if this vector and [code]v[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component.
</description>
</method>
- <method name="is_normalized">
+ <method name="is_normalized" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the vector is normalized, [code]false[/code] otherwise.
</description>
</method>
- <method name="length">
+ <method name="length" qualifiers="const">
<return type="float">
</return>
<description>
Returns the length (magnitude) of this vector.
</description>
</method>
- <method name="length_squared">
+ <method name="length_squared" qualifiers="const">
<return type="float">
</return>
<description>
@@ -196,7 +196,7 @@
This method runs faster than [method length], so prefer it if you need to compare vectors or need the squared distance for some formula.
</description>
</method>
- <method name="lerp">
+ <method name="lerp" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="to" type="Vector3">
@@ -207,21 +207,21 @@
Returns the result of the linear interpolation between this vector and [code]b[/code] by amount [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation.
</description>
</method>
- <method name="max_axis">
+ <method name="max_axis" qualifiers="const">
<return type="int">
</return>
<description>
Returns the axis of the vector's largest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_X].
</description>
</method>
- <method name="min_axis">
+ <method name="min_axis" qualifiers="const">
<return type="int">
</return>
<description>
Returns the axis of the vector's smallest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_Z].
</description>
</method>
- <method name="move_toward">
+ <method name="move_toward" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="to" type="Vector3">
@@ -232,7 +232,7 @@
Moves this vector toward [code]to[/code] by the fixed [code]delta[/code] amount.
</description>
</method>
- <method name="normalized">
+ <method name="normalized" qualifiers="const">
<return type="Vector3">
</return>
<description>
@@ -395,7 +395,7 @@
<description>
</description>
</method>
- <method name="outer">
+ <method name="outer" qualifiers="const">
<return type="Basis">
</return>
<argument index="0" name="with" type="Vector3">
@@ -404,7 +404,7 @@
Returns the outer product with [code]b[/code].
</description>
</method>
- <method name="posmod">
+ <method name="posmod" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="mod" type="float">
@@ -413,7 +413,7 @@
Returns a vector composed of the [method @GlobalScope.fposmod] of this vector's components and [code]mod[/code].
</description>
</method>
- <method name="posmodv">
+ <method name="posmodv" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="modv" type="Vector3">
@@ -422,7 +422,7 @@
Returns a vector composed of the [method @GlobalScope.fposmod] of this vector's components and [code]modv[/code]'s components.
</description>
</method>
- <method name="project">
+ <method name="project" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="b" type="Vector3">
@@ -431,7 +431,7 @@
Returns this vector projected onto another vector [code]b[/code].
</description>
</method>
- <method name="reflect">
+ <method name="reflect" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="n" type="Vector3">
@@ -440,7 +440,7 @@
Returns this vector reflected from a plane defined by the given normal.
</description>
</method>
- <method name="rotated">
+ <method name="rotated" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="by_axis" type="Vector3">
@@ -451,21 +451,32 @@
Rotates this vector around a given axis by [code]phi[/code] radians. The axis must be a normalized vector.
</description>
</method>
- <method name="round">
+ <method name="round" qualifiers="const">
<return type="Vector3">
</return>
<description>
Returns this vector with all components rounded to the nearest integer, with halfway cases rounded away from zero.
</description>
</method>
- <method name="sign">
+ <method name="sign" qualifiers="const">
<return type="Vector3">
</return>
<description>
Returns a vector with each component set to one or negative one, depending on the signs of this vector's components, or zero if the component is zero, by calling [method @GlobalScope.sign] on each component.
</description>
</method>
- <method name="slerp">
+ <method name="signed_angle_to" qualifiers="const">
+ <return type="float">
+ </return>
+ <argument index="0" name="to" type="Vector3">
+ </argument>
+ <argument index="1" name="axis" type="Vector3">
+ </argument>
+ <description>
+ Returns the signed angle to the given vector, in radians. The sign of the angle is positive in a counter-clockwise direction and negative in a clockwise direction when viewed from the side specified by the [code]axis[/code].
+ </description>
+ </method>
+ <method name="slerp" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="to" type="Vector3">
@@ -477,7 +488,7 @@
[b]Note:[/b] Both vectors must be normalized.
</description>
</method>
- <method name="slide">
+ <method name="slide" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="n" type="Vector3">
@@ -486,7 +497,7 @@
Returns this vector slid along a plane defined by the given normal.
</description>
</method>
- <method name="snapped">
+ <method name="snapped" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="step" type="Vector3">
@@ -495,7 +506,7 @@
Returns this vector with each component snapped to the nearest multiple of [code]step[/code]. This can also be used to round to an arbitrary number of decimals.
</description>
</method>
- <method name="to_diagonal_matrix">
+ <method name="to_diagonal_matrix" qualifiers="const">
<return type="Basis">
</return>
<description>
diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml
index a1ae2aceab..ea5945f5b7 100644
--- a/doc/classes/Vector3i.xml
+++ b/doc/classes/Vector3i.xml
@@ -52,20 +52,20 @@
Returns a [Vector3i] with the given components.
</description>
</method>
- <method name="abs">
+ <method name="abs" qualifiers="const">
<return type="Vector3i">
</return>
<description>
</description>
</method>
- <method name="max_axis">
+ <method name="max_axis" qualifiers="const">
<return type="int">
</return>
<description>
Returns the axis of the vector's largest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_X].
</description>
</method>
- <method name="min_axis">
+ <method name="min_axis" qualifiers="const">
<return type="int">
</return>
<description>
@@ -220,7 +220,7 @@
<description>
</description>
</method>
- <method name="sign">
+ <method name="sign" qualifiers="const">
<return type="Vector3i">
</return>
<description>
diff --git a/doc/classes/VisualShaderNodeCustom.xml b/doc/classes/VisualShaderNodeCustom.xml
index 59b501660a..17fc2f8c4d 100644
--- a/doc/classes/VisualShaderNodeCustom.xml
+++ b/doc/classes/VisualShaderNodeCustom.xml
@@ -20,7 +20,7 @@
<return type="String">
</return>
<description>
- Override this method to define the path to the associated custom node in the Visual Shader Editor's members dialog. The path may looks like [code]"MyGame/MyFunctions/Noise"[/code].
+ Override this method to define the path to the associated custom node in the Visual Shader Editor's members dialog. The path may look like [code]"MyGame/MyFunctions/Noise"[/code].
Defining this method is [b]optional[/b]. If not overridden, the node will be filed under the "Addons" category.
</description>
</method>
diff --git a/doc/classes/VisualShaderNodeDeterminant.xml b/doc/classes/VisualShaderNodeDeterminant.xml
index 72be31872d..6b042f6172 100644
--- a/doc/classes/VisualShaderNodeDeterminant.xml
+++ b/doc/classes/VisualShaderNodeDeterminant.xml
@@ -4,7 +4,7 @@
Calculates the determinant of a [Transform] within the visual shader graph.
</brief_description>
<description>
- Translates to [code]deteminant(x)[/code] in the shader language.
+ Translates to [code]determinant(x)[/code] in the shader language.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/VisualShaderNodeExpression.xml b/doc/classes/VisualShaderNodeExpression.xml
index f571edaab3..c2cbf41f45 100644
--- a/doc/classes/VisualShaderNodeExpression.xml
+++ b/doc/classes/VisualShaderNodeExpression.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
Custom Godot Shading Language expression, with a custom amount of input and output ports.
- The provided code is directly injected into the graph's matching shader function ([code]vertex[/code], [code]fragment[/code], or [code]light[/code]), so it cannot be used to to declare functions, varyings, uniforms, or global constants. See [VisualShaderNodeGlobalExpression] for such global definitions.
+ The provided code is directly injected into the graph's matching shader function ([code]vertex[/code], [code]fragment[/code], or [code]light[/code]), so it cannot be used to declare functions, varyings, uniforms, or global constants. See [VisualShaderNodeGlobalExpression] for such global definitions.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/VisualShaderNodeFaceForward.xml b/doc/classes/VisualShaderNodeFaceForward.xml
index 5ef08ea8c2..48f84e5495 100644
--- a/doc/classes/VisualShaderNodeFaceForward.xml
+++ b/doc/classes/VisualShaderNodeFaceForward.xml
@@ -4,7 +4,7 @@
Returns the vector that points in the same direction as a reference vector within the visual shader graph.
</brief_description>
<description>
- Translates to [code]faceforward(N, I, Nref)[/code] in the shader language. The function has three vector parameters: [code]N[/code], the vector to orient, [code]I[/code], the incident vector, and [code]Nref[/code], the reference vector. If the dot product of [code]I[/code] and [code]Nref[/code] is smaller than zero the return value is [code]N[/code]. Otherwise [code]-N[/code] is returned.
+ Translates to [code]faceforward(N, I, Nref)[/code] in the shader language. The function has three vector parameters: [code]N[/code], the vector to orient, [code]I[/code], the incident vector, and [code]Nref[/code], the reference vector. If the dot product of [code]I[/code] and [code]Nref[/code] is smaller than zero the return value is [code]N[/code]. Otherwise, [code]-N[/code] is returned.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/VisualShaderNodeGroupBase.xml b/doc/classes/VisualShaderNodeGroupBase.xml
index afa14c776e..be3f7f173d 100644
--- a/doc/classes/VisualShaderNodeGroupBase.xml
+++ b/doc/classes/VisualShaderNodeGroupBase.xml
@@ -74,7 +74,7 @@
<return type="String">
</return>
<description>
- Returns a [String] description of the input ports as as colon-separated list using the format [code]id,type,name;[/code] (see [method add_input_port]).
+ Returns a [String] description of the input ports as a colon-separated list using the format [code]id,type,name;[/code] (see [method add_input_port]).
</description>
</method>
<method name="get_output_port_count" qualifiers="const">
@@ -88,7 +88,7 @@
<return type="String">
</return>
<description>
- Returns a [String] description of the output ports as as colon-separated list using the format [code]id,type,name;[/code] (see [method add_output_port]).
+ Returns a [String] description of the output ports as a colon-separated list using the format [code]id,type,name;[/code] (see [method add_output_port]).
</description>
</method>
<method name="has_input_port" qualifiers="const">
diff --git a/doc/classes/VisualShaderNodeIf.xml b/doc/classes/VisualShaderNodeIf.xml
index ad0b21a370..418999863b 100644
--- a/doc/classes/VisualShaderNodeIf.xml
+++ b/doc/classes/VisualShaderNodeIf.xml
@@ -4,7 +4,7 @@
Compares two floating-point numbers in order to return a required vector within the visual shader graph.
</brief_description>
<description>
- First two ports are scalar floatin-point numbers to compare, third is tolerance comparison amount and last three ports represents a vectors returned if [code]a == b[/code], [code]a &gt; b[/code] and [code]a &lt; b[/code] respectively.
+ First two ports are scalar floating-point numbers to compare, third is tolerance comparison amount and last three ports represents a vectors returned if [code]a == b[/code], [code]a &gt; b[/code] and [code]a &lt; b[/code] respectively.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/VisualShaderNodeInput.xml b/doc/classes/VisualShaderNodeInput.xml
index 8e819b011c..067f78dffe 100644
--- a/doc/classes/VisualShaderNodeInput.xml
+++ b/doc/classes/VisualShaderNodeInput.xml
@@ -14,7 +14,7 @@
<return type="String">
</return>
<description>
- Returns a translated name of the current constant in the Godot Shader Language. eg. [code]"ALBEDO"[/code] if the [member input_name] equal to [code]"albedo"[/code].
+ Returns a translated name of the current constant in the Godot Shader Language. E.g. [code]"ALBEDO"[/code] if the [member input_name] equal to [code]"albedo"[/code].
</description>
</method>
</methods>
diff --git a/doc/classes/VisualShaderNodeSDFToScreenUV.xml b/doc/classes/VisualShaderNodeSDFToScreenUV.xml
index ea04180095..40fb66e364 100644
--- a/doc/classes/VisualShaderNodeSDFToScreenUV.xml
+++ b/doc/classes/VisualShaderNodeSDFToScreenUV.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeSDFToScreenUV" inherits="VisualShaderNode" version="4.0">
<brief_description>
- A function to convert a SDF (signed-distance field) to screen UV, to be used within the visual shader graph.
+ A function to convert an SDF (signed-distance field) to screen UV, to be used within the visual shader graph.
</brief_description>
<description>
Translates to [code]sdf_to_screen_uv(sdf_pos)[/code] in the shader language.
diff --git a/doc/classes/VisualShaderNodeScreenUVToSDF.xml b/doc/classes/VisualShaderNodeScreenUVToSDF.xml
index 438c8dc67b..2e121ffc54 100644
--- a/doc/classes/VisualShaderNodeScreenUVToSDF.xml
+++ b/doc/classes/VisualShaderNodeScreenUVToSDF.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeScreenUVToSDF" inherits="VisualShaderNode" version="4.0">
<brief_description>
- A function to convert screen UV to a SDF (signed-distance field), to be used within the visual shader graph.
+ A function to convert screen UV to an SDF (signed-distance field), to be used within the visual shader graph.
</brief_description>
<description>
Translates to [code]screen_uv_to_sdf(uv)[/code] in the shader language. If the UV port isn't connected, [code]SCREEN_UV[/code] is used instead.
diff --git a/doc/classes/VisualShaderNodeSmoothStep.xml b/doc/classes/VisualShaderNodeSmoothStep.xml
index fa22d16da8..0ed53a8c26 100644
--- a/doc/classes/VisualShaderNodeSmoothStep.xml
+++ b/doc/classes/VisualShaderNodeSmoothStep.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
Translates to [code]smoothstep(edge0, edge1, x)[/code] in the shader language.
- Returns [code]0.0[/code] if [code]x[/code] is smaller than [code]edge0[/code] and [code]1.0[/code] if [code]x[/code] is larger than [code]edge1[/code]. Otherwise the return value is interpolated between [code]0.0[/code] and [code]1.0[/code] using Hermite polynomials.
+ Returns [code]0.0[/code] if [code]x[/code] is smaller than [code]edge0[/code] and [code]1.0[/code] if [code]x[/code] is larger than [code]edge1[/code]. Otherwise, the return value is interpolated between [code]0.0[/code] and [code]1.0[/code] using Hermite polynomials.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/VisualShaderNodeTextureSDF.xml b/doc/classes/VisualShaderNodeTextureSDF.xml
index 7d3d654bd0..b5c89c2c31 100644
--- a/doc/classes/VisualShaderNodeTextureSDF.xml
+++ b/doc/classes/VisualShaderNodeTextureSDF.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeTextureSDF" inherits="VisualShaderNode" version="4.0">
<brief_description>
- Performs a SDF (signed-distance field) texture lookup within the visual shader graph.
+ Performs an SDF (signed-distance field) texture lookup within the visual shader graph.
</brief_description>
<description>
Translates to [code]texture_sdf(sdf_pos)[/code] in the shader language.
diff --git a/doc/classes/VisualShaderNodeTextureSDFNormal.xml b/doc/classes/VisualShaderNodeTextureSDFNormal.xml
index 5dbf3e545a..25fe1c4b28 100644
--- a/doc/classes/VisualShaderNodeTextureSDFNormal.xml
+++ b/doc/classes/VisualShaderNodeTextureSDFNormal.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeTextureSDFNormal" inherits="VisualShaderNode" version="4.0">
<brief_description>
- Performs a SDF (signed-distance field) normal texture lookup within the visual shader graph.
+ Performs an SDF (signed-distance field) normal texture lookup within the visual shader graph.
</brief_description>
<description>
Translates to [code]texture_sdf_normal(sdf_pos)[/code] in the shader language.
diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml
index 0f887c7705..b99a251a11 100644
--- a/doc/classes/Window.xml
+++ b/doc/classes/Window.xml
@@ -276,7 +276,7 @@
<method name="set_ime_active">
<return type="void">
</return>
- <argument index="0" name="arg0" type="bool">
+ <argument index="0" name="active" type="bool">
</argument>
<description>
</description>
@@ -284,7 +284,7 @@
<method name="set_ime_position">
<return type="void">
</return>
- <argument index="0" name="arg0" type="Vector2i">
+ <argument index="0" name="position" type="Vector2i">
</argument>
<description>
</description>
@@ -474,8 +474,17 @@
</theme_item>
<theme_item name="title_font" type="Font">
</theme_item>
+ <theme_item name="title_font_size" type="int">
+ The size of the title font.
+ </theme_item>
<theme_item name="title_height" type="int" default="20">
</theme_item>
+ <theme_item name="title_outline_modulate" type="Color" default="Color( 1, 1, 1, 1 )">
+ The color of the title outline.
+ </theme_item>
+ <theme_item name="title_outline_size" type="int" default="0">
+ The size of the title outline.
+ </theme_item>
<theme_item name="window_panel" type="StyleBox">
</theme_item>
</theme_items>
diff --git a/doc/classes/World2D.xml b/doc/classes/World2D.xml
index 25033cdb09..20b3afbd0b 100644
--- a/doc/classes/World2D.xml
+++ b/doc/classes/World2D.xml
@@ -18,6 +18,9 @@
<member name="direct_space_state" type="PhysicsDirectSpaceState2D" setter="" getter="get_direct_space_state">
Direct access to the world's physics 2D space state. Used for querying current and potential collisions. When using multi-threaded physics, access is limited to [code]_physics_process(delta)[/code] in the main thread.
</member>
+ <member name="navigation_map" type="RID" setter="" getter="get_navigation_map">
+ The [RID] of this world's navigation map. Used by the [NavigationServer2D].
+ </member>
<member name="space" type="RID" setter="" getter="get_space">
The [RID] of this world's physics space resource. Used by the [PhysicsServer2D] for 2D physics, treating it as both a space and an area.
</member>
diff --git a/doc/classes/World3D.xml b/doc/classes/World3D.xml
index fe92077432..610ecacff4 100644
--- a/doc/classes/World3D.xml
+++ b/doc/classes/World3D.xml
@@ -23,6 +23,9 @@
<member name="fallback_environment" type="Environment" setter="set_fallback_environment" getter="get_fallback_environment">
The World3D's fallback_environment will be used if the World3D's [Environment] fails or is missing.
</member>
+ <member name="navigation_map" type="RID" setter="" getter="get_navigation_map">
+ The [RID] of this world's navigation map. Used by the [NavigationServer3D].
+ </member>
<member name="scenario" type="RID" setter="" getter="get_scenario">
The World3D's visual scenario.
</member>
diff --git a/doc/classes/XRController3D.xml b/doc/classes/XRController3D.xml
index a4a86cc22a..5d8c23bd6f 100644
--- a/doc/classes/XRController3D.xml
+++ b/doc/classes/XRController3D.xml
@@ -62,7 +62,7 @@
<argument index="0" name="button" type="int">
</argument>
<description>
- Returns [code]true[/code] if the button at index [code]button[/code] is pressed. See [enum JoyButtonList].
+ Returns [code]true[/code] if the button at index [code]button[/code] is pressed. See [enum JoyButton].
</description>
</method>
</methods>
diff --git a/doc/classes/bool.xml b/doc/classes/bool.xml
index 03e8bee7d5..8da1eb3c88 100644
--- a/doc/classes/bool.xml
+++ b/doc/classes/bool.xml
@@ -4,7 +4,7 @@
Boolean built-in type.
</brief_description>
<description>
- Boolean is a built-in type. There are two boolean values: [code]true[/code] and [code]false[/code]. You can think of it as an switch with on or off (1 or 0) setting. Booleans are used in programming for logic in condition statements, like [code]if[/code] statements.
+ Boolean is a built-in type. There are two boolean values: [code]true[/code] and [code]false[/code]. You can think of it as a switch with on or off (1 or 0) setting. Booleans are used in programming for logic in condition statements, like [code]if[/code] statements.
Booleans can be directly used in [code]if[/code] statements. The code below demonstrates this on the [code]if can_shoot:[/code] line. You don't need to use [code]== true[/code], you only need [code]if can_shoot:[/code]. Similarly, use [code]if not can_shoot:[/code] rather than [code]== false[/code].
[codeblocks]
[gdscript]
@@ -49,6 +49,7 @@
[/csharp]
[/codeblocks]
The following code will set [code]can_shoot[/code] to [code]false[/code] and start a timer. This will prevent player from shooting until the timer runs out. Next [code]can_shoot[/code] will be set to [code]true[/code] again allowing player to shoot once again.
+ [codeblocks]
[gdscript]
var _can_shoot = true
onready var _cool_down = $CoolDownTimer
diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py
index 5335116c8a..ae3cc73098 100755
--- a/doc/tools/makerst.py
+++ b/doc/tools/makerst.py
@@ -110,6 +110,9 @@ class ClassDef:
self.theme_items = None # type: Optional[OrderedDict[str, List[ThemeItemDef]]]
self.tutorials = [] # type: List[str]
+ # Used to match the class with XML source for output filtering purposes.
+ self.filepath = "" # type: str
+
class State:
def __init__(self): # type: () -> None
@@ -118,11 +121,12 @@ class State:
self.classes = OrderedDict() # type: OrderedDict[str, ClassDef]
self.current_class = "" # type: str
- def parse_class(self, class_root): # type: (ET.Element) -> None
+ def parse_class(self, class_root, filepath): # type: (ET.Element, str) -> None
class_name = class_root.attrib["name"]
class_def = ClassDef(class_name)
self.classes[class_name] = class_def
+ class_def.filepath = filepath
inherits = class_root.get("inherits")
if inherits is not None:
@@ -278,6 +282,7 @@ def parse_arguments(root): # type: (ET.Element) -> List[ParameterDef]
def main(): # type: () -> None
parser = argparse.ArgumentParser()
parser.add_argument("path", nargs="+", help="A path to an XML file or a directory containing XML files to parse.")
+ parser.add_argument("--filter", default="", help="The filepath pattern for XML files to filter.")
group = parser.add_mutually_exclusive_group()
group.add_argument("--output", "-o", default=".", help="The directory to save output .rst files in.")
group.add_argument(
@@ -333,17 +338,21 @@ def main(): # type: () -> None
print_error("Duplicate class '{}'".format(name), state)
continue
- classes[name] = doc
+ classes[name] = (doc, cur_file)
for name, data in classes.items():
try:
- state.parse_class(data)
+ state.parse_class(data[0], data[1])
except Exception as e:
print_error("Exception while parsing class '{}': {}".format(name, e), state)
state.sort_classes()
+ pattern = re.compile(args.filter)
+
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)
diff --git a/doc/translations/README.md b/doc/translations/README.md
new file mode 100644
index 0000000000..a941eeaf49
--- /dev/null
+++ b/doc/translations/README.md
@@ -0,0 +1 @@
+These `.po` and `.pot` files come from Weblate. Do not modify them manually.
diff --git a/doc/translations/classes.pot b/doc/translations/classes.pot
index 4cd89924ee..d14b0d9b1f 100644
--- a/doc/translations/classes.pot
+++ b/doc/translations/classes.pot
@@ -25583,7 +25583,7 @@ msgstr ""
#: doc/classes/Input.xml:99
msgid ""
"Returns the current value of the joypad axis at given index (see [enum "
-"JoyAxisList])."
+"JoyAxis])."
msgstr ""
#: doc/classes/Input.xml:108
@@ -25592,7 +25592,7 @@ msgstr ""
#: doc/classes/Input.xml:117
msgid ""
-"Receives a [enum JoyAxisList] axis and returns its equivalent name as a "
+"Receives a [enum JoyAxis] axis and returns its equivalent name as a "
"string."
msgstr ""
@@ -25602,7 +25602,7 @@ msgstr ""
#: doc/classes/Input.xml:135
msgid ""
-"Receives a gamepad button from [enum JoyButtonList] and returns its "
+"Receives a gamepad button from [enum JoyButton] and returns its "
"equivalent name as a string."
msgstr ""
@@ -25677,7 +25677,7 @@ msgstr ""
#: doc/classes/Input.xml:238
msgid ""
"Returns [code]true[/code] if you are pressing the joypad button (see [enum "
-"JoyButtonList])."
+"JoyButton])."
msgstr ""
#: doc/classes/Input.xml:247
@@ -26077,7 +26077,7 @@ msgid ""
msgstr ""
#: doc/classes/InputEventJoypadButton.xml:16
-msgid "Button identifier. One of the [enum JoyButtonList] button constants."
+msgid "Button identifier. One of the [enum JoyButton] button constants."
msgstr ""
#: doc/classes/InputEventJoypadButton.xml:19
@@ -26105,7 +26105,7 @@ msgid ""
msgstr ""
#: doc/classes/InputEventJoypadMotion.xml:16
-msgid "Axis identifier. Use one of the [enum JoyAxisList] axis constants."
+msgid "Axis identifier. Use one of the [enum JoyAxis] axis constants."
msgstr ""
#: doc/classes/InputEventJoypadMotion.xml:19
@@ -60259,7 +60259,7 @@ msgstr ""
#: doc/classes/XRController3D.xml:65
msgid ""
"Returns [code]true[/code] if the button at index [code]button[/code] is "
-"pressed. See [enum JoyButtonList]."
+"pressed. See [enum JoyButton]."
msgstr ""
#: doc/classes/XRController3D.xml:71
diff --git a/doc/translations/fr.po b/doc/translations/fr.po
index c4fe08e67b..f3e26ebc61 100644
--- a/doc/translations/fr.po
+++ b/doc/translations/fr.po
@@ -25946,7 +25946,7 @@ msgstr ""
#: doc/classes/Input.xml:99
msgid ""
"Returns the current value of the joypad axis at given index (see [enum "
-"JoyAxisList])."
+"JoyAxis])."
msgstr ""
#: doc/classes/Input.xml:108
@@ -25955,7 +25955,7 @@ msgstr ""
#: doc/classes/Input.xml:117
msgid ""
-"Receives a [enum JoyAxisList] axis and returns its equivalent name as a "
+"Receives a [enum JoyAxis] axis and returns its equivalent name as a "
"string."
msgstr ""
@@ -25965,7 +25965,7 @@ msgstr ""
#: doc/classes/Input.xml:135
msgid ""
-"Receives a gamepad button from [enum JoyButtonList] and returns its "
+"Receives a gamepad button from [enum JoyButton] and returns its "
"equivalent name as a string."
msgstr ""
@@ -26041,7 +26041,7 @@ msgstr ""
#, fuzzy
msgid ""
"Returns [code]true[/code] if you are pressing the joypad button (see [enum "
-"JoyButtonList])."
+"JoyButton])."
msgstr ""
"Retourne [code]true[/code] (vrai) si la chaîne de caractères finit par la "
"chaîne de caractères donnée."
@@ -26443,7 +26443,7 @@ msgid ""
msgstr ""
#: doc/classes/InputEventJoypadButton.xml:16
-msgid "Button identifier. One of the [enum JoyButtonList] button constants."
+msgid "Button identifier. One of the [enum JoyButton] button constants."
msgstr ""
#: doc/classes/InputEventJoypadButton.xml:19
@@ -26471,7 +26471,7 @@ msgid ""
msgstr ""
#: doc/classes/InputEventJoypadMotion.xml:16
-msgid "Axis identifier. Use one of the [enum JoyAxisList] axis constants."
+msgid "Axis identifier. Use one of the [enum JoyAxis] axis constants."
msgstr ""
#: doc/classes/InputEventJoypadMotion.xml:19
@@ -60738,7 +60738,7 @@ msgstr ""
#, fuzzy
msgid ""
"Returns [code]true[/code] if the button at index [code]button[/code] is "
-"pressed. See [enum JoyButtonList]."
+"pressed. See [enum JoyButton]."
msgstr ""
"Renvoie [code]true[/code] (vrai) si [code]s[/code] vaut zéro ou quasiment "
"zéro."
diff --git a/drivers/alsa/SCsub b/drivers/alsa/SCsub
index 91e1140b75..1d76bb18c4 100644
--- a/drivers/alsa/SCsub
+++ b/drivers/alsa/SCsub
@@ -2,4 +2,7 @@
Import("env")
+if "alsa" in env and env["alsa"]:
+ env.add_source_files(env.drivers_sources, "asound-so_wrap.c")
+
env.add_source_files(env.drivers_sources, "*.cpp")
diff --git a/drivers/alsa/asound-so_wrap.c b/drivers/alsa/asound-so_wrap.c
new file mode 100644
index 0000000000..65624bcb70
--- /dev/null
+++ b/drivers/alsa/asound-so_wrap.c
@@ -0,0 +1,14092 @@
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-22 19:22:12
+// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/alsa/asoundlib.h --sys-include <alsa/asoundlib.h> --soname libasound.so.2 --init-name asound --omit-prefix snd_pcm_sw_params_set_tstamp_type --omit-prefix snd_pcm_status_get_audio_htstamp_report --omit-prefix snd_pcm_sw_params_get_tstamp_type --omit-prefix snd_pcm_status_set_audio_htstamp_config --output-header asound-so_wrap.h --output-implementation asound-so_wrap.c
+//
+#include <stdint.h>
+
+#define snd_asoundlib_version snd_asoundlib_version_dylibloader_orig_asound
+#define snd_dlpath snd_dlpath_dylibloader_orig_asound
+#define snd_dlopen snd_dlopen_dylibloader_orig_asound
+#define snd_dlsym snd_dlsym_dylibloader_orig_asound
+#define snd_dlclose snd_dlclose_dylibloader_orig_asound
+#define snd_async_add_handler snd_async_add_handler_dylibloader_orig_asound
+#define snd_async_del_handler snd_async_del_handler_dylibloader_orig_asound
+#define snd_async_handler_get_fd snd_async_handler_get_fd_dylibloader_orig_asound
+#define snd_async_handler_get_signo snd_async_handler_get_signo_dylibloader_orig_asound
+#define snd_async_handler_get_callback_private snd_async_handler_get_callback_private_dylibloader_orig_asound
+#define snd_shm_area_create snd_shm_area_create_dylibloader_orig_asound
+#define snd_shm_area_share snd_shm_area_share_dylibloader_orig_asound
+#define snd_shm_area_destroy snd_shm_area_destroy_dylibloader_orig_asound
+#define snd_user_file snd_user_file_dylibloader_orig_asound
+#define snd_input_stdio_open snd_input_stdio_open_dylibloader_orig_asound
+#define snd_input_stdio_attach snd_input_stdio_attach_dylibloader_orig_asound
+#define snd_input_buffer_open snd_input_buffer_open_dylibloader_orig_asound
+#define snd_input_close snd_input_close_dylibloader_orig_asound
+#define snd_input_scanf snd_input_scanf_dylibloader_orig_asound
+#define snd_input_gets snd_input_gets_dylibloader_orig_asound
+#define snd_input_getc snd_input_getc_dylibloader_orig_asound
+#define snd_input_ungetc snd_input_ungetc_dylibloader_orig_asound
+#define snd_output_stdio_open snd_output_stdio_open_dylibloader_orig_asound
+#define snd_output_stdio_attach snd_output_stdio_attach_dylibloader_orig_asound
+#define snd_output_buffer_open snd_output_buffer_open_dylibloader_orig_asound
+#define snd_output_buffer_string snd_output_buffer_string_dylibloader_orig_asound
+#define snd_output_close snd_output_close_dylibloader_orig_asound
+#define snd_output_printf snd_output_printf_dylibloader_orig_asound
+#define snd_output_vprintf snd_output_vprintf_dylibloader_orig_asound
+#define snd_output_puts snd_output_puts_dylibloader_orig_asound
+#define snd_output_putc snd_output_putc_dylibloader_orig_asound
+#define snd_output_flush snd_output_flush_dylibloader_orig_asound
+#define snd_strerror snd_strerror_dylibloader_orig_asound
+#define snd_lib_error_set_handler snd_lib_error_set_handler_dylibloader_orig_asound
+#define snd_lib_error_set_local snd_lib_error_set_local_dylibloader_orig_asound
+#define snd_config_topdir snd_config_topdir_dylibloader_orig_asound
+#define snd_config_top snd_config_top_dylibloader_orig_asound
+#define snd_config_load snd_config_load_dylibloader_orig_asound
+#define snd_config_load_override snd_config_load_override_dylibloader_orig_asound
+#define snd_config_save snd_config_save_dylibloader_orig_asound
+#define snd_config_update snd_config_update_dylibloader_orig_asound
+#define snd_config_update_r snd_config_update_r_dylibloader_orig_asound
+#define snd_config_update_free snd_config_update_free_dylibloader_orig_asound
+#define snd_config_update_free_global snd_config_update_free_global_dylibloader_orig_asound
+#define snd_config_update_ref snd_config_update_ref_dylibloader_orig_asound
+#define snd_config_ref snd_config_ref_dylibloader_orig_asound
+#define snd_config_unref snd_config_unref_dylibloader_orig_asound
+#define snd_config_search snd_config_search_dylibloader_orig_asound
+#define snd_config_searchv snd_config_searchv_dylibloader_orig_asound
+#define snd_config_search_definition snd_config_search_definition_dylibloader_orig_asound
+#define snd_config_expand snd_config_expand_dylibloader_orig_asound
+#define snd_config_evaluate snd_config_evaluate_dylibloader_orig_asound
+#define snd_config_add snd_config_add_dylibloader_orig_asound
+#define snd_config_add_before snd_config_add_before_dylibloader_orig_asound
+#define snd_config_add_after snd_config_add_after_dylibloader_orig_asound
+#define snd_config_remove snd_config_remove_dylibloader_orig_asound
+#define snd_config_delete snd_config_delete_dylibloader_orig_asound
+#define snd_config_delete_compound_members snd_config_delete_compound_members_dylibloader_orig_asound
+#define snd_config_copy snd_config_copy_dylibloader_orig_asound
+#define snd_config_make snd_config_make_dylibloader_orig_asound
+#define snd_config_make_integer snd_config_make_integer_dylibloader_orig_asound
+#define snd_config_make_integer64 snd_config_make_integer64_dylibloader_orig_asound
+#define snd_config_make_real snd_config_make_real_dylibloader_orig_asound
+#define snd_config_make_string snd_config_make_string_dylibloader_orig_asound
+#define snd_config_make_pointer snd_config_make_pointer_dylibloader_orig_asound
+#define snd_config_make_compound snd_config_make_compound_dylibloader_orig_asound
+#define snd_config_imake_integer snd_config_imake_integer_dylibloader_orig_asound
+#define snd_config_imake_integer64 snd_config_imake_integer64_dylibloader_orig_asound
+#define snd_config_imake_real snd_config_imake_real_dylibloader_orig_asound
+#define snd_config_imake_string snd_config_imake_string_dylibloader_orig_asound
+#define snd_config_imake_safe_string snd_config_imake_safe_string_dylibloader_orig_asound
+#define snd_config_imake_pointer snd_config_imake_pointer_dylibloader_orig_asound
+#define snd_config_get_type snd_config_get_type_dylibloader_orig_asound
+#define snd_config_is_array snd_config_is_array_dylibloader_orig_asound
+#define snd_config_set_id snd_config_set_id_dylibloader_orig_asound
+#define snd_config_set_integer snd_config_set_integer_dylibloader_orig_asound
+#define snd_config_set_integer64 snd_config_set_integer64_dylibloader_orig_asound
+#define snd_config_set_real snd_config_set_real_dylibloader_orig_asound
+#define snd_config_set_string snd_config_set_string_dylibloader_orig_asound
+#define snd_config_set_ascii snd_config_set_ascii_dylibloader_orig_asound
+#define snd_config_set_pointer snd_config_set_pointer_dylibloader_orig_asound
+#define snd_config_get_id snd_config_get_id_dylibloader_orig_asound
+#define snd_config_get_integer snd_config_get_integer_dylibloader_orig_asound
+#define snd_config_get_integer64 snd_config_get_integer64_dylibloader_orig_asound
+#define snd_config_get_real snd_config_get_real_dylibloader_orig_asound
+#define snd_config_get_ireal snd_config_get_ireal_dylibloader_orig_asound
+#define snd_config_get_string snd_config_get_string_dylibloader_orig_asound
+#define snd_config_get_ascii snd_config_get_ascii_dylibloader_orig_asound
+#define snd_config_get_pointer snd_config_get_pointer_dylibloader_orig_asound
+#define snd_config_test_id snd_config_test_id_dylibloader_orig_asound
+#define snd_config_iterator_first snd_config_iterator_first_dylibloader_orig_asound
+#define snd_config_iterator_next snd_config_iterator_next_dylibloader_orig_asound
+#define snd_config_iterator_end snd_config_iterator_end_dylibloader_orig_asound
+#define snd_config_iterator_entry snd_config_iterator_entry_dylibloader_orig_asound
+#define snd_config_get_bool_ascii snd_config_get_bool_ascii_dylibloader_orig_asound
+#define snd_config_get_bool snd_config_get_bool_dylibloader_orig_asound
+#define snd_config_get_ctl_iface_ascii snd_config_get_ctl_iface_ascii_dylibloader_orig_asound
+#define snd_config_get_ctl_iface snd_config_get_ctl_iface_dylibloader_orig_asound
+#define snd_names_list snd_names_list_dylibloader_orig_asound
+#define snd_names_list_free snd_names_list_free_dylibloader_orig_asound
+#define snd_pcm_open snd_pcm_open_dylibloader_orig_asound
+#define snd_pcm_open_lconf snd_pcm_open_lconf_dylibloader_orig_asound
+#define snd_pcm_open_fallback snd_pcm_open_fallback_dylibloader_orig_asound
+#define snd_pcm_close snd_pcm_close_dylibloader_orig_asound
+#define snd_pcm_name snd_pcm_name_dylibloader_orig_asound
+#define snd_pcm_type snd_pcm_type_dylibloader_orig_asound
+#define snd_pcm_stream snd_pcm_stream_dylibloader_orig_asound
+#define snd_pcm_poll_descriptors_count snd_pcm_poll_descriptors_count_dylibloader_orig_asound
+#define snd_pcm_poll_descriptors snd_pcm_poll_descriptors_dylibloader_orig_asound
+#define snd_pcm_poll_descriptors_revents snd_pcm_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_pcm_nonblock snd_pcm_nonblock_dylibloader_orig_asound
+#define snd_async_add_pcm_handler snd_async_add_pcm_handler_dylibloader_orig_asound
+#define snd_async_handler_get_pcm snd_async_handler_get_pcm_dylibloader_orig_asound
+#define snd_pcm_info snd_pcm_info_dylibloader_orig_asound
+#define snd_pcm_hw_params_current snd_pcm_hw_params_current_dylibloader_orig_asound
+#define snd_pcm_hw_params snd_pcm_hw_params_dylibloader_orig_asound
+#define snd_pcm_hw_free snd_pcm_hw_free_dylibloader_orig_asound
+#define snd_pcm_sw_params_current snd_pcm_sw_params_current_dylibloader_orig_asound
+#define snd_pcm_sw_params snd_pcm_sw_params_dylibloader_orig_asound
+#define snd_pcm_prepare snd_pcm_prepare_dylibloader_orig_asound
+#define snd_pcm_reset snd_pcm_reset_dylibloader_orig_asound
+#define snd_pcm_status snd_pcm_status_dylibloader_orig_asound
+#define snd_pcm_start snd_pcm_start_dylibloader_orig_asound
+#define snd_pcm_drop snd_pcm_drop_dylibloader_orig_asound
+#define snd_pcm_drain snd_pcm_drain_dylibloader_orig_asound
+#define snd_pcm_pause snd_pcm_pause_dylibloader_orig_asound
+#define snd_pcm_state snd_pcm_state_dylibloader_orig_asound
+#define snd_pcm_hwsync snd_pcm_hwsync_dylibloader_orig_asound
+#define snd_pcm_delay snd_pcm_delay_dylibloader_orig_asound
+#define snd_pcm_resume snd_pcm_resume_dylibloader_orig_asound
+#define snd_pcm_htimestamp snd_pcm_htimestamp_dylibloader_orig_asound
+#define snd_pcm_avail snd_pcm_avail_dylibloader_orig_asound
+#define snd_pcm_avail_update snd_pcm_avail_update_dylibloader_orig_asound
+#define snd_pcm_avail_delay snd_pcm_avail_delay_dylibloader_orig_asound
+#define snd_pcm_rewindable snd_pcm_rewindable_dylibloader_orig_asound
+#define snd_pcm_rewind snd_pcm_rewind_dylibloader_orig_asound
+#define snd_pcm_forwardable snd_pcm_forwardable_dylibloader_orig_asound
+#define snd_pcm_forward snd_pcm_forward_dylibloader_orig_asound
+#define snd_pcm_writei snd_pcm_writei_dylibloader_orig_asound
+#define snd_pcm_readi snd_pcm_readi_dylibloader_orig_asound
+#define snd_pcm_writen snd_pcm_writen_dylibloader_orig_asound
+#define snd_pcm_readn snd_pcm_readn_dylibloader_orig_asound
+#define snd_pcm_wait snd_pcm_wait_dylibloader_orig_asound
+#define snd_pcm_link snd_pcm_link_dylibloader_orig_asound
+#define snd_pcm_unlink snd_pcm_unlink_dylibloader_orig_asound
+#define snd_pcm_query_chmaps snd_pcm_query_chmaps_dylibloader_orig_asound
+#define snd_pcm_query_chmaps_from_hw snd_pcm_query_chmaps_from_hw_dylibloader_orig_asound
+#define snd_pcm_free_chmaps snd_pcm_free_chmaps_dylibloader_orig_asound
+#define snd_pcm_get_chmap snd_pcm_get_chmap_dylibloader_orig_asound
+#define snd_pcm_set_chmap snd_pcm_set_chmap_dylibloader_orig_asound
+#define snd_pcm_chmap_type_name snd_pcm_chmap_type_name_dylibloader_orig_asound
+#define snd_pcm_chmap_name snd_pcm_chmap_name_dylibloader_orig_asound
+#define snd_pcm_chmap_long_name snd_pcm_chmap_long_name_dylibloader_orig_asound
+#define snd_pcm_chmap_print snd_pcm_chmap_print_dylibloader_orig_asound
+#define snd_pcm_chmap_from_string snd_pcm_chmap_from_string_dylibloader_orig_asound
+#define snd_pcm_chmap_parse_string snd_pcm_chmap_parse_string_dylibloader_orig_asound
+#define snd_pcm_recover snd_pcm_recover_dylibloader_orig_asound
+#define snd_pcm_set_params snd_pcm_set_params_dylibloader_orig_asound
+#define snd_pcm_get_params snd_pcm_get_params_dylibloader_orig_asound
+#define snd_pcm_info_sizeof snd_pcm_info_sizeof_dylibloader_orig_asound
+#define snd_pcm_info_malloc snd_pcm_info_malloc_dylibloader_orig_asound
+#define snd_pcm_info_free snd_pcm_info_free_dylibloader_orig_asound
+#define snd_pcm_info_copy snd_pcm_info_copy_dylibloader_orig_asound
+#define snd_pcm_info_get_device snd_pcm_info_get_device_dylibloader_orig_asound
+#define snd_pcm_info_get_subdevice snd_pcm_info_get_subdevice_dylibloader_orig_asound
+#define snd_pcm_info_get_stream snd_pcm_info_get_stream_dylibloader_orig_asound
+#define snd_pcm_info_get_card snd_pcm_info_get_card_dylibloader_orig_asound
+#define snd_pcm_info_get_id snd_pcm_info_get_id_dylibloader_orig_asound
+#define snd_pcm_info_get_name snd_pcm_info_get_name_dylibloader_orig_asound
+#define snd_pcm_info_get_subdevice_name snd_pcm_info_get_subdevice_name_dylibloader_orig_asound
+#define snd_pcm_info_get_class snd_pcm_info_get_class_dylibloader_orig_asound
+#define snd_pcm_info_get_subclass snd_pcm_info_get_subclass_dylibloader_orig_asound
+#define snd_pcm_info_get_subdevices_count snd_pcm_info_get_subdevices_count_dylibloader_orig_asound
+#define snd_pcm_info_get_subdevices_avail snd_pcm_info_get_subdevices_avail_dylibloader_orig_asound
+#define snd_pcm_info_get_sync snd_pcm_info_get_sync_dylibloader_orig_asound
+#define snd_pcm_info_set_device snd_pcm_info_set_device_dylibloader_orig_asound
+#define snd_pcm_info_set_subdevice snd_pcm_info_set_subdevice_dylibloader_orig_asound
+#define snd_pcm_info_set_stream snd_pcm_info_set_stream_dylibloader_orig_asound
+#define snd_pcm_hw_params_any snd_pcm_hw_params_any_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_mmap_sample_resolution snd_pcm_hw_params_can_mmap_sample_resolution_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_double snd_pcm_hw_params_is_double_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_batch snd_pcm_hw_params_is_batch_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_block_transfer snd_pcm_hw_params_is_block_transfer_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_monotonic snd_pcm_hw_params_is_monotonic_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_overrange snd_pcm_hw_params_can_overrange_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_pause snd_pcm_hw_params_can_pause_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_resume snd_pcm_hw_params_can_resume_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_half_duplex snd_pcm_hw_params_is_half_duplex_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_joint_duplex snd_pcm_hw_params_is_joint_duplex_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_sync_start snd_pcm_hw_params_can_sync_start_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_disable_period_wakeup snd_pcm_hw_params_can_disable_period_wakeup_dylibloader_orig_asound
+#define snd_pcm_hw_params_supports_audio_wallclock_ts snd_pcm_hw_params_supports_audio_wallclock_ts_dylibloader_orig_asound
+#define snd_pcm_hw_params_supports_audio_ts_type snd_pcm_hw_params_supports_audio_ts_type_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_rate_numden snd_pcm_hw_params_get_rate_numden_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_sbits snd_pcm_hw_params_get_sbits_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_fifo_size snd_pcm_hw_params_get_fifo_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_sizeof snd_pcm_hw_params_sizeof_dylibloader_orig_asound
+#define snd_pcm_hw_params_malloc snd_pcm_hw_params_malloc_dylibloader_orig_asound
+#define snd_pcm_hw_params_free snd_pcm_hw_params_free_dylibloader_orig_asound
+#define snd_pcm_hw_params_copy snd_pcm_hw_params_copy_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_access snd_pcm_hw_params_get_access_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_access snd_pcm_hw_params_test_access_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_access snd_pcm_hw_params_set_access_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_access_first snd_pcm_hw_params_set_access_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_access_last snd_pcm_hw_params_set_access_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_access_mask snd_pcm_hw_params_set_access_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_access_mask snd_pcm_hw_params_get_access_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_format snd_pcm_hw_params_get_format_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_format snd_pcm_hw_params_test_format_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_format snd_pcm_hw_params_set_format_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_format_first snd_pcm_hw_params_set_format_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_format_last snd_pcm_hw_params_set_format_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_format_mask snd_pcm_hw_params_set_format_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_format_mask snd_pcm_hw_params_get_format_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_subformat snd_pcm_hw_params_get_subformat_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_subformat snd_pcm_hw_params_test_subformat_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_subformat snd_pcm_hw_params_set_subformat_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_subformat_first snd_pcm_hw_params_set_subformat_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_subformat_last snd_pcm_hw_params_set_subformat_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_subformat_mask snd_pcm_hw_params_set_subformat_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_subformat_mask snd_pcm_hw_params_get_subformat_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_channels snd_pcm_hw_params_get_channels_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_channels_min snd_pcm_hw_params_get_channels_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_channels_max snd_pcm_hw_params_get_channels_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_channels snd_pcm_hw_params_test_channels_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels snd_pcm_hw_params_set_channels_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_min snd_pcm_hw_params_set_channels_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_max snd_pcm_hw_params_set_channels_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_minmax snd_pcm_hw_params_set_channels_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_near snd_pcm_hw_params_set_channels_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_first snd_pcm_hw_params_set_channels_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_last snd_pcm_hw_params_set_channels_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_rate snd_pcm_hw_params_get_rate_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_rate_min snd_pcm_hw_params_get_rate_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_rate_max snd_pcm_hw_params_get_rate_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_rate snd_pcm_hw_params_test_rate_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate snd_pcm_hw_params_set_rate_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_min snd_pcm_hw_params_set_rate_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_max snd_pcm_hw_params_set_rate_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_minmax snd_pcm_hw_params_set_rate_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_near snd_pcm_hw_params_set_rate_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_first snd_pcm_hw_params_set_rate_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_last snd_pcm_hw_params_set_rate_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_resample snd_pcm_hw_params_set_rate_resample_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_rate_resample snd_pcm_hw_params_get_rate_resample_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_export_buffer snd_pcm_hw_params_set_export_buffer_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_export_buffer snd_pcm_hw_params_get_export_buffer_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_wakeup snd_pcm_hw_params_set_period_wakeup_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_wakeup snd_pcm_hw_params_get_period_wakeup_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_time snd_pcm_hw_params_get_period_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_time_min snd_pcm_hw_params_get_period_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_time_max snd_pcm_hw_params_get_period_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_period_time snd_pcm_hw_params_test_period_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time snd_pcm_hw_params_set_period_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_min snd_pcm_hw_params_set_period_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_max snd_pcm_hw_params_set_period_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_minmax snd_pcm_hw_params_set_period_time_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_near snd_pcm_hw_params_set_period_time_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_first snd_pcm_hw_params_set_period_time_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_last snd_pcm_hw_params_set_period_time_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_size snd_pcm_hw_params_get_period_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_size_min snd_pcm_hw_params_get_period_size_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_size_max snd_pcm_hw_params_get_period_size_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_period_size snd_pcm_hw_params_test_period_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size snd_pcm_hw_params_set_period_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_min snd_pcm_hw_params_set_period_size_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_max snd_pcm_hw_params_set_period_size_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_minmax snd_pcm_hw_params_set_period_size_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_near snd_pcm_hw_params_set_period_size_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_first snd_pcm_hw_params_set_period_size_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_last snd_pcm_hw_params_set_period_size_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_integer snd_pcm_hw_params_set_period_size_integer_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_periods snd_pcm_hw_params_get_periods_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_periods_min snd_pcm_hw_params_get_periods_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_periods_max snd_pcm_hw_params_get_periods_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_periods snd_pcm_hw_params_test_periods_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods snd_pcm_hw_params_set_periods_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_min snd_pcm_hw_params_set_periods_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_max snd_pcm_hw_params_set_periods_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_minmax snd_pcm_hw_params_set_periods_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_near snd_pcm_hw_params_set_periods_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_first snd_pcm_hw_params_set_periods_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_last snd_pcm_hw_params_set_periods_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_integer snd_pcm_hw_params_set_periods_integer_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_time snd_pcm_hw_params_get_buffer_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_time_min snd_pcm_hw_params_get_buffer_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_time_max snd_pcm_hw_params_get_buffer_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_buffer_time snd_pcm_hw_params_test_buffer_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time snd_pcm_hw_params_set_buffer_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_min snd_pcm_hw_params_set_buffer_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_max snd_pcm_hw_params_set_buffer_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_minmax snd_pcm_hw_params_set_buffer_time_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_near snd_pcm_hw_params_set_buffer_time_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_first snd_pcm_hw_params_set_buffer_time_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_last snd_pcm_hw_params_set_buffer_time_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_size snd_pcm_hw_params_get_buffer_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_size_min snd_pcm_hw_params_get_buffer_size_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_size_max snd_pcm_hw_params_get_buffer_size_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_buffer_size snd_pcm_hw_params_test_buffer_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size snd_pcm_hw_params_set_buffer_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_min snd_pcm_hw_params_set_buffer_size_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_max snd_pcm_hw_params_set_buffer_size_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_minmax snd_pcm_hw_params_set_buffer_size_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_near snd_pcm_hw_params_set_buffer_size_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_first snd_pcm_hw_params_set_buffer_size_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_last snd_pcm_hw_params_set_buffer_size_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_min_align snd_pcm_hw_params_get_min_align_dylibloader_orig_asound
+#define snd_pcm_sw_params_sizeof snd_pcm_sw_params_sizeof_dylibloader_orig_asound
+#define snd_pcm_sw_params_malloc snd_pcm_sw_params_malloc_dylibloader_orig_asound
+#define snd_pcm_sw_params_free snd_pcm_sw_params_free_dylibloader_orig_asound
+#define snd_pcm_sw_params_copy snd_pcm_sw_params_copy_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_boundary snd_pcm_sw_params_get_boundary_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_tstamp_mode snd_pcm_sw_params_set_tstamp_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_tstamp_mode snd_pcm_sw_params_get_tstamp_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_avail_min snd_pcm_sw_params_set_avail_min_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_avail_min snd_pcm_sw_params_get_avail_min_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_period_event snd_pcm_sw_params_set_period_event_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_period_event snd_pcm_sw_params_get_period_event_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_start_threshold snd_pcm_sw_params_set_start_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_start_threshold snd_pcm_sw_params_get_start_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_stop_threshold snd_pcm_sw_params_set_stop_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_stop_threshold snd_pcm_sw_params_get_stop_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_silence_threshold snd_pcm_sw_params_set_silence_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_silence_threshold snd_pcm_sw_params_get_silence_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_silence_size snd_pcm_sw_params_set_silence_size_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_silence_size snd_pcm_sw_params_get_silence_size_dylibloader_orig_asound
+#define snd_pcm_access_mask_sizeof snd_pcm_access_mask_sizeof_dylibloader_orig_asound
+#define snd_pcm_access_mask_malloc snd_pcm_access_mask_malloc_dylibloader_orig_asound
+#define snd_pcm_access_mask_free snd_pcm_access_mask_free_dylibloader_orig_asound
+#define snd_pcm_access_mask_copy snd_pcm_access_mask_copy_dylibloader_orig_asound
+#define snd_pcm_access_mask_none snd_pcm_access_mask_none_dylibloader_orig_asound
+#define snd_pcm_access_mask_any snd_pcm_access_mask_any_dylibloader_orig_asound
+#define snd_pcm_access_mask_test snd_pcm_access_mask_test_dylibloader_orig_asound
+#define snd_pcm_access_mask_empty snd_pcm_access_mask_empty_dylibloader_orig_asound
+#define snd_pcm_access_mask_set snd_pcm_access_mask_set_dylibloader_orig_asound
+#define snd_pcm_access_mask_reset snd_pcm_access_mask_reset_dylibloader_orig_asound
+#define snd_pcm_format_mask_sizeof snd_pcm_format_mask_sizeof_dylibloader_orig_asound
+#define snd_pcm_format_mask_malloc snd_pcm_format_mask_malloc_dylibloader_orig_asound
+#define snd_pcm_format_mask_free snd_pcm_format_mask_free_dylibloader_orig_asound
+#define snd_pcm_format_mask_copy snd_pcm_format_mask_copy_dylibloader_orig_asound
+#define snd_pcm_format_mask_none snd_pcm_format_mask_none_dylibloader_orig_asound
+#define snd_pcm_format_mask_any snd_pcm_format_mask_any_dylibloader_orig_asound
+#define snd_pcm_format_mask_test snd_pcm_format_mask_test_dylibloader_orig_asound
+#define snd_pcm_format_mask_empty snd_pcm_format_mask_empty_dylibloader_orig_asound
+#define snd_pcm_format_mask_set snd_pcm_format_mask_set_dylibloader_orig_asound
+#define snd_pcm_format_mask_reset snd_pcm_format_mask_reset_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_sizeof snd_pcm_subformat_mask_sizeof_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_malloc snd_pcm_subformat_mask_malloc_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_free snd_pcm_subformat_mask_free_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_copy snd_pcm_subformat_mask_copy_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_none snd_pcm_subformat_mask_none_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_any snd_pcm_subformat_mask_any_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_test snd_pcm_subformat_mask_test_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_empty snd_pcm_subformat_mask_empty_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_set snd_pcm_subformat_mask_set_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_reset snd_pcm_subformat_mask_reset_dylibloader_orig_asound
+#define snd_pcm_status_sizeof snd_pcm_status_sizeof_dylibloader_orig_asound
+#define snd_pcm_status_malloc snd_pcm_status_malloc_dylibloader_orig_asound
+#define snd_pcm_status_free snd_pcm_status_free_dylibloader_orig_asound
+#define snd_pcm_status_copy snd_pcm_status_copy_dylibloader_orig_asound
+#define snd_pcm_status_get_state snd_pcm_status_get_state_dylibloader_orig_asound
+#define snd_pcm_status_get_trigger_tstamp snd_pcm_status_get_trigger_tstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_trigger_htstamp snd_pcm_status_get_trigger_htstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_tstamp snd_pcm_status_get_tstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_htstamp snd_pcm_status_get_htstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_audio_htstamp snd_pcm_status_get_audio_htstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_driver_htstamp snd_pcm_status_get_driver_htstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_delay snd_pcm_status_get_delay_dylibloader_orig_asound
+#define snd_pcm_status_get_avail snd_pcm_status_get_avail_dylibloader_orig_asound
+#define snd_pcm_status_get_avail_max snd_pcm_status_get_avail_max_dylibloader_orig_asound
+#define snd_pcm_status_get_overrange snd_pcm_status_get_overrange_dylibloader_orig_asound
+#define snd_pcm_type_name snd_pcm_type_name_dylibloader_orig_asound
+#define snd_pcm_stream_name snd_pcm_stream_name_dylibloader_orig_asound
+#define snd_pcm_access_name snd_pcm_access_name_dylibloader_orig_asound
+#define snd_pcm_format_name snd_pcm_format_name_dylibloader_orig_asound
+#define snd_pcm_format_description snd_pcm_format_description_dylibloader_orig_asound
+#define snd_pcm_subformat_name snd_pcm_subformat_name_dylibloader_orig_asound
+#define snd_pcm_subformat_description snd_pcm_subformat_description_dylibloader_orig_asound
+#define snd_pcm_format_value snd_pcm_format_value_dylibloader_orig_asound
+#define snd_pcm_tstamp_mode_name snd_pcm_tstamp_mode_name_dylibloader_orig_asound
+#define snd_pcm_state_name snd_pcm_state_name_dylibloader_orig_asound
+#define snd_pcm_dump snd_pcm_dump_dylibloader_orig_asound
+#define snd_pcm_dump_hw_setup snd_pcm_dump_hw_setup_dylibloader_orig_asound
+#define snd_pcm_dump_sw_setup snd_pcm_dump_sw_setup_dylibloader_orig_asound
+#define snd_pcm_dump_setup snd_pcm_dump_setup_dylibloader_orig_asound
+#define snd_pcm_hw_params_dump snd_pcm_hw_params_dump_dylibloader_orig_asound
+#define snd_pcm_sw_params_dump snd_pcm_sw_params_dump_dylibloader_orig_asound
+#define snd_pcm_status_dump snd_pcm_status_dump_dylibloader_orig_asound
+#define snd_pcm_mmap_begin snd_pcm_mmap_begin_dylibloader_orig_asound
+#define snd_pcm_mmap_commit snd_pcm_mmap_commit_dylibloader_orig_asound
+#define snd_pcm_mmap_writei snd_pcm_mmap_writei_dylibloader_orig_asound
+#define snd_pcm_mmap_readi snd_pcm_mmap_readi_dylibloader_orig_asound
+#define snd_pcm_mmap_writen snd_pcm_mmap_writen_dylibloader_orig_asound
+#define snd_pcm_mmap_readn snd_pcm_mmap_readn_dylibloader_orig_asound
+#define snd_pcm_format_signed snd_pcm_format_signed_dylibloader_orig_asound
+#define snd_pcm_format_unsigned snd_pcm_format_unsigned_dylibloader_orig_asound
+#define snd_pcm_format_linear snd_pcm_format_linear_dylibloader_orig_asound
+#define snd_pcm_format_float snd_pcm_format_float_dylibloader_orig_asound
+#define snd_pcm_format_little_endian snd_pcm_format_little_endian_dylibloader_orig_asound
+#define snd_pcm_format_big_endian snd_pcm_format_big_endian_dylibloader_orig_asound
+#define snd_pcm_format_cpu_endian snd_pcm_format_cpu_endian_dylibloader_orig_asound
+#define snd_pcm_format_width snd_pcm_format_width_dylibloader_orig_asound
+#define snd_pcm_format_physical_width snd_pcm_format_physical_width_dylibloader_orig_asound
+#define snd_pcm_build_linear_format snd_pcm_build_linear_format_dylibloader_orig_asound
+#define snd_pcm_format_size snd_pcm_format_size_dylibloader_orig_asound
+#define snd_pcm_format_silence snd_pcm_format_silence_dylibloader_orig_asound
+#define snd_pcm_format_silence_16 snd_pcm_format_silence_16_dylibloader_orig_asound
+#define snd_pcm_format_silence_32 snd_pcm_format_silence_32_dylibloader_orig_asound
+#define snd_pcm_format_silence_64 snd_pcm_format_silence_64_dylibloader_orig_asound
+#define snd_pcm_format_set_silence snd_pcm_format_set_silence_dylibloader_orig_asound
+#define snd_pcm_bytes_to_frames snd_pcm_bytes_to_frames_dylibloader_orig_asound
+#define snd_pcm_frames_to_bytes snd_pcm_frames_to_bytes_dylibloader_orig_asound
+#define snd_pcm_bytes_to_samples snd_pcm_bytes_to_samples_dylibloader_orig_asound
+#define snd_pcm_samples_to_bytes snd_pcm_samples_to_bytes_dylibloader_orig_asound
+#define snd_pcm_area_silence snd_pcm_area_silence_dylibloader_orig_asound
+#define snd_pcm_areas_silence snd_pcm_areas_silence_dylibloader_orig_asound
+#define snd_pcm_area_copy snd_pcm_area_copy_dylibloader_orig_asound
+#define snd_pcm_areas_copy snd_pcm_areas_copy_dylibloader_orig_asound
+#define snd_pcm_areas_copy_wrap snd_pcm_areas_copy_wrap_dylibloader_orig_asound
+#define snd_pcm_hook_get_pcm snd_pcm_hook_get_pcm_dylibloader_orig_asound
+#define snd_pcm_hook_get_private snd_pcm_hook_get_private_dylibloader_orig_asound
+#define snd_pcm_hook_set_private snd_pcm_hook_set_private_dylibloader_orig_asound
+#define snd_pcm_hook_add snd_pcm_hook_add_dylibloader_orig_asound
+#define snd_pcm_hook_remove snd_pcm_hook_remove_dylibloader_orig_asound
+#define snd_pcm_meter_get_bufsize snd_pcm_meter_get_bufsize_dylibloader_orig_asound
+#define snd_pcm_meter_get_channels snd_pcm_meter_get_channels_dylibloader_orig_asound
+#define snd_pcm_meter_get_rate snd_pcm_meter_get_rate_dylibloader_orig_asound
+#define snd_pcm_meter_get_now snd_pcm_meter_get_now_dylibloader_orig_asound
+#define snd_pcm_meter_get_boundary snd_pcm_meter_get_boundary_dylibloader_orig_asound
+#define snd_pcm_meter_add_scope snd_pcm_meter_add_scope_dylibloader_orig_asound
+#define snd_pcm_meter_search_scope snd_pcm_meter_search_scope_dylibloader_orig_asound
+#define snd_pcm_scope_malloc snd_pcm_scope_malloc_dylibloader_orig_asound
+#define snd_pcm_scope_set_ops snd_pcm_scope_set_ops_dylibloader_orig_asound
+#define snd_pcm_scope_set_name snd_pcm_scope_set_name_dylibloader_orig_asound
+#define snd_pcm_scope_get_name snd_pcm_scope_get_name_dylibloader_orig_asound
+#define snd_pcm_scope_get_callback_private snd_pcm_scope_get_callback_private_dylibloader_orig_asound
+#define snd_pcm_scope_set_callback_private snd_pcm_scope_set_callback_private_dylibloader_orig_asound
+#define snd_pcm_scope_s16_open snd_pcm_scope_s16_open_dylibloader_orig_asound
+#define snd_pcm_scope_s16_get_channel_buffer snd_pcm_scope_s16_get_channel_buffer_dylibloader_orig_asound
+#define snd_spcm_init snd_spcm_init_dylibloader_orig_asound
+#define snd_spcm_init_duplex snd_spcm_init_duplex_dylibloader_orig_asound
+#define snd_spcm_init_get_params snd_spcm_init_get_params_dylibloader_orig_asound
+#define snd_pcm_start_mode_name snd_pcm_start_mode_name_dylibloader_orig_asound
+#define snd_pcm_xrun_mode_name snd_pcm_xrun_mode_name_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_start_mode snd_pcm_sw_params_set_start_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_start_mode snd_pcm_sw_params_get_start_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_xrun_mode snd_pcm_sw_params_set_xrun_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_xrun_mode snd_pcm_sw_params_get_xrun_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_xfer_align snd_pcm_sw_params_set_xfer_align_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_xfer_align snd_pcm_sw_params_get_xfer_align_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_sleep_min snd_pcm_sw_params_set_sleep_min_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_sleep_min snd_pcm_sw_params_get_sleep_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_tick_time snd_pcm_hw_params_get_tick_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_tick_time_min snd_pcm_hw_params_get_tick_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_tick_time_max snd_pcm_hw_params_get_tick_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_tick_time snd_pcm_hw_params_test_tick_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time snd_pcm_hw_params_set_tick_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_min snd_pcm_hw_params_set_tick_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_max snd_pcm_hw_params_set_tick_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_minmax snd_pcm_hw_params_set_tick_time_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_near snd_pcm_hw_params_set_tick_time_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_first snd_pcm_hw_params_set_tick_time_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_last snd_pcm_hw_params_set_tick_time_last_dylibloader_orig_asound
+#define snd_rawmidi_open snd_rawmidi_open_dylibloader_orig_asound
+#define snd_rawmidi_open_lconf snd_rawmidi_open_lconf_dylibloader_orig_asound
+#define snd_rawmidi_close snd_rawmidi_close_dylibloader_orig_asound
+#define snd_rawmidi_poll_descriptors_count snd_rawmidi_poll_descriptors_count_dylibloader_orig_asound
+#define snd_rawmidi_poll_descriptors snd_rawmidi_poll_descriptors_dylibloader_orig_asound
+#define snd_rawmidi_poll_descriptors_revents snd_rawmidi_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_rawmidi_nonblock snd_rawmidi_nonblock_dylibloader_orig_asound
+#define snd_rawmidi_info_sizeof snd_rawmidi_info_sizeof_dylibloader_orig_asound
+#define snd_rawmidi_info_malloc snd_rawmidi_info_malloc_dylibloader_orig_asound
+#define snd_rawmidi_info_free snd_rawmidi_info_free_dylibloader_orig_asound
+#define snd_rawmidi_info_copy snd_rawmidi_info_copy_dylibloader_orig_asound
+#define snd_rawmidi_info_get_device snd_rawmidi_info_get_device_dylibloader_orig_asound
+#define snd_rawmidi_info_get_subdevice snd_rawmidi_info_get_subdevice_dylibloader_orig_asound
+#define snd_rawmidi_info_get_stream snd_rawmidi_info_get_stream_dylibloader_orig_asound
+#define snd_rawmidi_info_get_card snd_rawmidi_info_get_card_dylibloader_orig_asound
+#define snd_rawmidi_info_get_flags snd_rawmidi_info_get_flags_dylibloader_orig_asound
+#define snd_rawmidi_info_get_id snd_rawmidi_info_get_id_dylibloader_orig_asound
+#define snd_rawmidi_info_get_name snd_rawmidi_info_get_name_dylibloader_orig_asound
+#define snd_rawmidi_info_get_subdevice_name snd_rawmidi_info_get_subdevice_name_dylibloader_orig_asound
+#define snd_rawmidi_info_get_subdevices_count snd_rawmidi_info_get_subdevices_count_dylibloader_orig_asound
+#define snd_rawmidi_info_get_subdevices_avail snd_rawmidi_info_get_subdevices_avail_dylibloader_orig_asound
+#define snd_rawmidi_info_set_device snd_rawmidi_info_set_device_dylibloader_orig_asound
+#define snd_rawmidi_info_set_subdevice snd_rawmidi_info_set_subdevice_dylibloader_orig_asound
+#define snd_rawmidi_info_set_stream snd_rawmidi_info_set_stream_dylibloader_orig_asound
+#define snd_rawmidi_info snd_rawmidi_info_dylibloader_orig_asound
+#define snd_rawmidi_params_sizeof snd_rawmidi_params_sizeof_dylibloader_orig_asound
+#define snd_rawmidi_params_malloc snd_rawmidi_params_malloc_dylibloader_orig_asound
+#define snd_rawmidi_params_free snd_rawmidi_params_free_dylibloader_orig_asound
+#define snd_rawmidi_params_copy snd_rawmidi_params_copy_dylibloader_orig_asound
+#define snd_rawmidi_params_set_buffer_size snd_rawmidi_params_set_buffer_size_dylibloader_orig_asound
+#define snd_rawmidi_params_get_buffer_size snd_rawmidi_params_get_buffer_size_dylibloader_orig_asound
+#define snd_rawmidi_params_set_avail_min snd_rawmidi_params_set_avail_min_dylibloader_orig_asound
+#define snd_rawmidi_params_get_avail_min snd_rawmidi_params_get_avail_min_dylibloader_orig_asound
+#define snd_rawmidi_params_set_no_active_sensing snd_rawmidi_params_set_no_active_sensing_dylibloader_orig_asound
+#define snd_rawmidi_params_get_no_active_sensing snd_rawmidi_params_get_no_active_sensing_dylibloader_orig_asound
+#define snd_rawmidi_params snd_rawmidi_params_dylibloader_orig_asound
+#define snd_rawmidi_params_current snd_rawmidi_params_current_dylibloader_orig_asound
+#define snd_rawmidi_status_sizeof snd_rawmidi_status_sizeof_dylibloader_orig_asound
+#define snd_rawmidi_status_malloc snd_rawmidi_status_malloc_dylibloader_orig_asound
+#define snd_rawmidi_status_free snd_rawmidi_status_free_dylibloader_orig_asound
+#define snd_rawmidi_status_copy snd_rawmidi_status_copy_dylibloader_orig_asound
+#define snd_rawmidi_status_get_tstamp snd_rawmidi_status_get_tstamp_dylibloader_orig_asound
+#define snd_rawmidi_status_get_avail snd_rawmidi_status_get_avail_dylibloader_orig_asound
+#define snd_rawmidi_status_get_xruns snd_rawmidi_status_get_xruns_dylibloader_orig_asound
+#define snd_rawmidi_status snd_rawmidi_status_dylibloader_orig_asound
+#define snd_rawmidi_drain snd_rawmidi_drain_dylibloader_orig_asound
+#define snd_rawmidi_drop snd_rawmidi_drop_dylibloader_orig_asound
+#define snd_rawmidi_write snd_rawmidi_write_dylibloader_orig_asound
+#define snd_rawmidi_read snd_rawmidi_read_dylibloader_orig_asound
+#define snd_rawmidi_name snd_rawmidi_name_dylibloader_orig_asound
+#define snd_rawmidi_type snd_rawmidi_type_dylibloader_orig_asound
+#define snd_rawmidi_stream snd_rawmidi_stream_dylibloader_orig_asound
+#define snd_timer_query_open snd_timer_query_open_dylibloader_orig_asound
+#define snd_timer_query_open_lconf snd_timer_query_open_lconf_dylibloader_orig_asound
+#define snd_timer_query_close snd_timer_query_close_dylibloader_orig_asound
+#define snd_timer_query_next_device snd_timer_query_next_device_dylibloader_orig_asound
+#define snd_timer_query_info snd_timer_query_info_dylibloader_orig_asound
+#define snd_timer_query_params snd_timer_query_params_dylibloader_orig_asound
+#define snd_timer_query_status snd_timer_query_status_dylibloader_orig_asound
+#define snd_timer_open snd_timer_open_dylibloader_orig_asound
+#define snd_timer_open_lconf snd_timer_open_lconf_dylibloader_orig_asound
+#define snd_timer_close snd_timer_close_dylibloader_orig_asound
+#define snd_async_add_timer_handler snd_async_add_timer_handler_dylibloader_orig_asound
+#define snd_async_handler_get_timer snd_async_handler_get_timer_dylibloader_orig_asound
+#define snd_timer_poll_descriptors_count snd_timer_poll_descriptors_count_dylibloader_orig_asound
+#define snd_timer_poll_descriptors snd_timer_poll_descriptors_dylibloader_orig_asound
+#define snd_timer_poll_descriptors_revents snd_timer_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_timer_info snd_timer_info_dylibloader_orig_asound
+#define snd_timer_params snd_timer_params_dylibloader_orig_asound
+#define snd_timer_status snd_timer_status_dylibloader_orig_asound
+#define snd_timer_start snd_timer_start_dylibloader_orig_asound
+#define snd_timer_stop snd_timer_stop_dylibloader_orig_asound
+#define snd_timer_continue snd_timer_continue_dylibloader_orig_asound
+#define snd_timer_read snd_timer_read_dylibloader_orig_asound
+#define snd_timer_id_sizeof snd_timer_id_sizeof_dylibloader_orig_asound
+#define snd_timer_id_malloc snd_timer_id_malloc_dylibloader_orig_asound
+#define snd_timer_id_free snd_timer_id_free_dylibloader_orig_asound
+#define snd_timer_id_copy snd_timer_id_copy_dylibloader_orig_asound
+#define snd_timer_id_set_class snd_timer_id_set_class_dylibloader_orig_asound
+#define snd_timer_id_get_class snd_timer_id_get_class_dylibloader_orig_asound
+#define snd_timer_id_set_sclass snd_timer_id_set_sclass_dylibloader_orig_asound
+#define snd_timer_id_get_sclass snd_timer_id_get_sclass_dylibloader_orig_asound
+#define snd_timer_id_set_card snd_timer_id_set_card_dylibloader_orig_asound
+#define snd_timer_id_get_card snd_timer_id_get_card_dylibloader_orig_asound
+#define snd_timer_id_set_device snd_timer_id_set_device_dylibloader_orig_asound
+#define snd_timer_id_get_device snd_timer_id_get_device_dylibloader_orig_asound
+#define snd_timer_id_set_subdevice snd_timer_id_set_subdevice_dylibloader_orig_asound
+#define snd_timer_id_get_subdevice snd_timer_id_get_subdevice_dylibloader_orig_asound
+#define snd_timer_ginfo_sizeof snd_timer_ginfo_sizeof_dylibloader_orig_asound
+#define snd_timer_ginfo_malloc snd_timer_ginfo_malloc_dylibloader_orig_asound
+#define snd_timer_ginfo_free snd_timer_ginfo_free_dylibloader_orig_asound
+#define snd_timer_ginfo_copy snd_timer_ginfo_copy_dylibloader_orig_asound
+#define snd_timer_ginfo_set_tid snd_timer_ginfo_set_tid_dylibloader_orig_asound
+#define snd_timer_ginfo_get_tid snd_timer_ginfo_get_tid_dylibloader_orig_asound
+#define snd_timer_ginfo_get_flags snd_timer_ginfo_get_flags_dylibloader_orig_asound
+#define snd_timer_ginfo_get_card snd_timer_ginfo_get_card_dylibloader_orig_asound
+#define snd_timer_ginfo_get_id snd_timer_ginfo_get_id_dylibloader_orig_asound
+#define snd_timer_ginfo_get_name snd_timer_ginfo_get_name_dylibloader_orig_asound
+#define snd_timer_ginfo_get_resolution snd_timer_ginfo_get_resolution_dylibloader_orig_asound
+#define snd_timer_ginfo_get_resolution_min snd_timer_ginfo_get_resolution_min_dylibloader_orig_asound
+#define snd_timer_ginfo_get_resolution_max snd_timer_ginfo_get_resolution_max_dylibloader_orig_asound
+#define snd_timer_ginfo_get_clients snd_timer_ginfo_get_clients_dylibloader_orig_asound
+#define snd_timer_info_sizeof snd_timer_info_sizeof_dylibloader_orig_asound
+#define snd_timer_info_malloc snd_timer_info_malloc_dylibloader_orig_asound
+#define snd_timer_info_free snd_timer_info_free_dylibloader_orig_asound
+#define snd_timer_info_copy snd_timer_info_copy_dylibloader_orig_asound
+#define snd_timer_info_is_slave snd_timer_info_is_slave_dylibloader_orig_asound
+#define snd_timer_info_get_card snd_timer_info_get_card_dylibloader_orig_asound
+#define snd_timer_info_get_id snd_timer_info_get_id_dylibloader_orig_asound
+#define snd_timer_info_get_name snd_timer_info_get_name_dylibloader_orig_asound
+#define snd_timer_info_get_resolution snd_timer_info_get_resolution_dylibloader_orig_asound
+#define snd_timer_params_sizeof snd_timer_params_sizeof_dylibloader_orig_asound
+#define snd_timer_params_malloc snd_timer_params_malloc_dylibloader_orig_asound
+#define snd_timer_params_free snd_timer_params_free_dylibloader_orig_asound
+#define snd_timer_params_copy snd_timer_params_copy_dylibloader_orig_asound
+#define snd_timer_params_set_auto_start snd_timer_params_set_auto_start_dylibloader_orig_asound
+#define snd_timer_params_get_auto_start snd_timer_params_get_auto_start_dylibloader_orig_asound
+#define snd_timer_params_set_exclusive snd_timer_params_set_exclusive_dylibloader_orig_asound
+#define snd_timer_params_get_exclusive snd_timer_params_get_exclusive_dylibloader_orig_asound
+#define snd_timer_params_set_early_event snd_timer_params_set_early_event_dylibloader_orig_asound
+#define snd_timer_params_get_early_event snd_timer_params_get_early_event_dylibloader_orig_asound
+#define snd_timer_params_set_ticks snd_timer_params_set_ticks_dylibloader_orig_asound
+#define snd_timer_params_get_ticks snd_timer_params_get_ticks_dylibloader_orig_asound
+#define snd_timer_params_set_queue_size snd_timer_params_set_queue_size_dylibloader_orig_asound
+#define snd_timer_params_get_queue_size snd_timer_params_get_queue_size_dylibloader_orig_asound
+#define snd_timer_params_set_filter snd_timer_params_set_filter_dylibloader_orig_asound
+#define snd_timer_params_get_filter snd_timer_params_get_filter_dylibloader_orig_asound
+#define snd_timer_status_sizeof snd_timer_status_sizeof_dylibloader_orig_asound
+#define snd_timer_status_malloc snd_timer_status_malloc_dylibloader_orig_asound
+#define snd_timer_status_free snd_timer_status_free_dylibloader_orig_asound
+#define snd_timer_status_copy snd_timer_status_copy_dylibloader_orig_asound
+#define snd_timer_status_get_timestamp snd_timer_status_get_timestamp_dylibloader_orig_asound
+#define snd_timer_status_get_resolution snd_timer_status_get_resolution_dylibloader_orig_asound
+#define snd_timer_status_get_lost snd_timer_status_get_lost_dylibloader_orig_asound
+#define snd_timer_status_get_overrun snd_timer_status_get_overrun_dylibloader_orig_asound
+#define snd_timer_status_get_queue snd_timer_status_get_queue_dylibloader_orig_asound
+#define snd_timer_info_get_ticks snd_timer_info_get_ticks_dylibloader_orig_asound
+#define snd_hwdep_open snd_hwdep_open_dylibloader_orig_asound
+#define snd_hwdep_close snd_hwdep_close_dylibloader_orig_asound
+#define snd_hwdep_poll_descriptors snd_hwdep_poll_descriptors_dylibloader_orig_asound
+#define snd_hwdep_poll_descriptors_count snd_hwdep_poll_descriptors_count_dylibloader_orig_asound
+#define snd_hwdep_poll_descriptors_revents snd_hwdep_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_hwdep_nonblock snd_hwdep_nonblock_dylibloader_orig_asound
+#define snd_hwdep_info snd_hwdep_info_dylibloader_orig_asound
+#define snd_hwdep_dsp_status snd_hwdep_dsp_status_dylibloader_orig_asound
+#define snd_hwdep_dsp_load snd_hwdep_dsp_load_dylibloader_orig_asound
+#define snd_hwdep_ioctl snd_hwdep_ioctl_dylibloader_orig_asound
+#define snd_hwdep_write snd_hwdep_write_dylibloader_orig_asound
+#define snd_hwdep_read snd_hwdep_read_dylibloader_orig_asound
+#define snd_hwdep_info_sizeof snd_hwdep_info_sizeof_dylibloader_orig_asound
+#define snd_hwdep_info_malloc snd_hwdep_info_malloc_dylibloader_orig_asound
+#define snd_hwdep_info_free snd_hwdep_info_free_dylibloader_orig_asound
+#define snd_hwdep_info_copy snd_hwdep_info_copy_dylibloader_orig_asound
+#define snd_hwdep_info_get_device snd_hwdep_info_get_device_dylibloader_orig_asound
+#define snd_hwdep_info_get_card snd_hwdep_info_get_card_dylibloader_orig_asound
+#define snd_hwdep_info_get_id snd_hwdep_info_get_id_dylibloader_orig_asound
+#define snd_hwdep_info_get_name snd_hwdep_info_get_name_dylibloader_orig_asound
+#define snd_hwdep_info_get_iface snd_hwdep_info_get_iface_dylibloader_orig_asound
+#define snd_hwdep_info_set_device snd_hwdep_info_set_device_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_sizeof snd_hwdep_dsp_status_sizeof_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_malloc snd_hwdep_dsp_status_malloc_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_free snd_hwdep_dsp_status_free_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_copy snd_hwdep_dsp_status_copy_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_get_version snd_hwdep_dsp_status_get_version_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_get_id snd_hwdep_dsp_status_get_id_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_get_num_dsps snd_hwdep_dsp_status_get_num_dsps_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_get_dsp_loaded snd_hwdep_dsp_status_get_dsp_loaded_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_get_chip_ready snd_hwdep_dsp_status_get_chip_ready_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_sizeof snd_hwdep_dsp_image_sizeof_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_malloc snd_hwdep_dsp_image_malloc_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_free snd_hwdep_dsp_image_free_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_copy snd_hwdep_dsp_image_copy_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_get_index snd_hwdep_dsp_image_get_index_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_get_name snd_hwdep_dsp_image_get_name_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_get_image snd_hwdep_dsp_image_get_image_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_get_length snd_hwdep_dsp_image_get_length_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_set_index snd_hwdep_dsp_image_set_index_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_set_name snd_hwdep_dsp_image_set_name_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_set_image snd_hwdep_dsp_image_set_image_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_set_length snd_hwdep_dsp_image_set_length_dylibloader_orig_asound
+#define snd_card_load snd_card_load_dylibloader_orig_asound
+#define snd_card_next snd_card_next_dylibloader_orig_asound
+#define snd_card_get_index snd_card_get_index_dylibloader_orig_asound
+#define snd_card_get_name snd_card_get_name_dylibloader_orig_asound
+#define snd_card_get_longname snd_card_get_longname_dylibloader_orig_asound
+#define snd_device_name_hint snd_device_name_hint_dylibloader_orig_asound
+#define snd_device_name_free_hint snd_device_name_free_hint_dylibloader_orig_asound
+#define snd_device_name_get_hint snd_device_name_get_hint_dylibloader_orig_asound
+#define snd_ctl_open snd_ctl_open_dylibloader_orig_asound
+#define snd_ctl_open_lconf snd_ctl_open_lconf_dylibloader_orig_asound
+#define snd_ctl_open_fallback snd_ctl_open_fallback_dylibloader_orig_asound
+#define snd_ctl_close snd_ctl_close_dylibloader_orig_asound
+#define snd_ctl_nonblock snd_ctl_nonblock_dylibloader_orig_asound
+#define snd_async_add_ctl_handler snd_async_add_ctl_handler_dylibloader_orig_asound
+#define snd_async_handler_get_ctl snd_async_handler_get_ctl_dylibloader_orig_asound
+#define snd_ctl_poll_descriptors_count snd_ctl_poll_descriptors_count_dylibloader_orig_asound
+#define snd_ctl_poll_descriptors snd_ctl_poll_descriptors_dylibloader_orig_asound
+#define snd_ctl_poll_descriptors_revents snd_ctl_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_ctl_subscribe_events snd_ctl_subscribe_events_dylibloader_orig_asound
+#define snd_ctl_card_info snd_ctl_card_info_dylibloader_orig_asound
+#define snd_ctl_elem_list snd_ctl_elem_list_dylibloader_orig_asound
+#define snd_ctl_elem_info snd_ctl_elem_info_dylibloader_orig_asound
+#define snd_ctl_elem_read snd_ctl_elem_read_dylibloader_orig_asound
+#define snd_ctl_elem_write snd_ctl_elem_write_dylibloader_orig_asound
+#define snd_ctl_elem_lock snd_ctl_elem_lock_dylibloader_orig_asound
+#define snd_ctl_elem_unlock snd_ctl_elem_unlock_dylibloader_orig_asound
+#define snd_ctl_elem_tlv_read snd_ctl_elem_tlv_read_dylibloader_orig_asound
+#define snd_ctl_elem_tlv_write snd_ctl_elem_tlv_write_dylibloader_orig_asound
+#define snd_ctl_elem_tlv_command snd_ctl_elem_tlv_command_dylibloader_orig_asound
+#define snd_ctl_hwdep_next_device snd_ctl_hwdep_next_device_dylibloader_orig_asound
+#define snd_ctl_hwdep_info snd_ctl_hwdep_info_dylibloader_orig_asound
+#define snd_ctl_pcm_next_device snd_ctl_pcm_next_device_dylibloader_orig_asound
+#define snd_ctl_pcm_info snd_ctl_pcm_info_dylibloader_orig_asound
+#define snd_ctl_pcm_prefer_subdevice snd_ctl_pcm_prefer_subdevice_dylibloader_orig_asound
+#define snd_ctl_rawmidi_next_device snd_ctl_rawmidi_next_device_dylibloader_orig_asound
+#define snd_ctl_rawmidi_info snd_ctl_rawmidi_info_dylibloader_orig_asound
+#define snd_ctl_rawmidi_prefer_subdevice snd_ctl_rawmidi_prefer_subdevice_dylibloader_orig_asound
+#define snd_ctl_set_power_state snd_ctl_set_power_state_dylibloader_orig_asound
+#define snd_ctl_get_power_state snd_ctl_get_power_state_dylibloader_orig_asound
+#define snd_ctl_read snd_ctl_read_dylibloader_orig_asound
+#define snd_ctl_wait snd_ctl_wait_dylibloader_orig_asound
+#define snd_ctl_name snd_ctl_name_dylibloader_orig_asound
+#define snd_ctl_type snd_ctl_type_dylibloader_orig_asound
+#define snd_ctl_elem_type_name snd_ctl_elem_type_name_dylibloader_orig_asound
+#define snd_ctl_elem_iface_name snd_ctl_elem_iface_name_dylibloader_orig_asound
+#define snd_ctl_event_type_name snd_ctl_event_type_name_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_mask snd_ctl_event_elem_get_mask_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_numid snd_ctl_event_elem_get_numid_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_id snd_ctl_event_elem_get_id_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_interface snd_ctl_event_elem_get_interface_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_device snd_ctl_event_elem_get_device_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_subdevice snd_ctl_event_elem_get_subdevice_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_name snd_ctl_event_elem_get_name_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_index snd_ctl_event_elem_get_index_dylibloader_orig_asound
+#define snd_ctl_elem_list_alloc_space snd_ctl_elem_list_alloc_space_dylibloader_orig_asound
+#define snd_ctl_elem_list_free_space snd_ctl_elem_list_free_space_dylibloader_orig_asound
+#define snd_ctl_ascii_elem_id_get snd_ctl_ascii_elem_id_get_dylibloader_orig_asound
+#define snd_ctl_ascii_elem_id_parse snd_ctl_ascii_elem_id_parse_dylibloader_orig_asound
+#define snd_ctl_ascii_value_parse snd_ctl_ascii_value_parse_dylibloader_orig_asound
+#define snd_ctl_elem_id_sizeof snd_ctl_elem_id_sizeof_dylibloader_orig_asound
+#define snd_ctl_elem_id_malloc snd_ctl_elem_id_malloc_dylibloader_orig_asound
+#define snd_ctl_elem_id_free snd_ctl_elem_id_free_dylibloader_orig_asound
+#define snd_ctl_elem_id_clear snd_ctl_elem_id_clear_dylibloader_orig_asound
+#define snd_ctl_elem_id_copy snd_ctl_elem_id_copy_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_numid snd_ctl_elem_id_get_numid_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_interface snd_ctl_elem_id_get_interface_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_device snd_ctl_elem_id_get_device_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_subdevice snd_ctl_elem_id_get_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_name snd_ctl_elem_id_get_name_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_index snd_ctl_elem_id_get_index_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_numid snd_ctl_elem_id_set_numid_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_interface snd_ctl_elem_id_set_interface_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_device snd_ctl_elem_id_set_device_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_subdevice snd_ctl_elem_id_set_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_name snd_ctl_elem_id_set_name_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_index snd_ctl_elem_id_set_index_dylibloader_orig_asound
+#define snd_ctl_card_info_sizeof snd_ctl_card_info_sizeof_dylibloader_orig_asound
+#define snd_ctl_card_info_malloc snd_ctl_card_info_malloc_dylibloader_orig_asound
+#define snd_ctl_card_info_free snd_ctl_card_info_free_dylibloader_orig_asound
+#define snd_ctl_card_info_clear snd_ctl_card_info_clear_dylibloader_orig_asound
+#define snd_ctl_card_info_copy snd_ctl_card_info_copy_dylibloader_orig_asound
+#define snd_ctl_card_info_get_card snd_ctl_card_info_get_card_dylibloader_orig_asound
+#define snd_ctl_card_info_get_id snd_ctl_card_info_get_id_dylibloader_orig_asound
+#define snd_ctl_card_info_get_driver snd_ctl_card_info_get_driver_dylibloader_orig_asound
+#define snd_ctl_card_info_get_name snd_ctl_card_info_get_name_dylibloader_orig_asound
+#define snd_ctl_card_info_get_longname snd_ctl_card_info_get_longname_dylibloader_orig_asound
+#define snd_ctl_card_info_get_mixername snd_ctl_card_info_get_mixername_dylibloader_orig_asound
+#define snd_ctl_card_info_get_components snd_ctl_card_info_get_components_dylibloader_orig_asound
+#define snd_ctl_event_sizeof snd_ctl_event_sizeof_dylibloader_orig_asound
+#define snd_ctl_event_malloc snd_ctl_event_malloc_dylibloader_orig_asound
+#define snd_ctl_event_free snd_ctl_event_free_dylibloader_orig_asound
+#define snd_ctl_event_clear snd_ctl_event_clear_dylibloader_orig_asound
+#define snd_ctl_event_copy snd_ctl_event_copy_dylibloader_orig_asound
+#define snd_ctl_event_get_type snd_ctl_event_get_type_dylibloader_orig_asound
+#define snd_ctl_elem_list_sizeof snd_ctl_elem_list_sizeof_dylibloader_orig_asound
+#define snd_ctl_elem_list_malloc snd_ctl_elem_list_malloc_dylibloader_orig_asound
+#define snd_ctl_elem_list_free snd_ctl_elem_list_free_dylibloader_orig_asound
+#define snd_ctl_elem_list_clear snd_ctl_elem_list_clear_dylibloader_orig_asound
+#define snd_ctl_elem_list_copy snd_ctl_elem_list_copy_dylibloader_orig_asound
+#define snd_ctl_elem_list_set_offset snd_ctl_elem_list_set_offset_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_used snd_ctl_elem_list_get_used_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_count snd_ctl_elem_list_get_count_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_id snd_ctl_elem_list_get_id_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_numid snd_ctl_elem_list_get_numid_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_interface snd_ctl_elem_list_get_interface_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_device snd_ctl_elem_list_get_device_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_subdevice snd_ctl_elem_list_get_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_name snd_ctl_elem_list_get_name_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_index snd_ctl_elem_list_get_index_dylibloader_orig_asound
+#define snd_ctl_elem_info_sizeof snd_ctl_elem_info_sizeof_dylibloader_orig_asound
+#define snd_ctl_elem_info_malloc snd_ctl_elem_info_malloc_dylibloader_orig_asound
+#define snd_ctl_elem_info_free snd_ctl_elem_info_free_dylibloader_orig_asound
+#define snd_ctl_elem_info_clear snd_ctl_elem_info_clear_dylibloader_orig_asound
+#define snd_ctl_elem_info_copy snd_ctl_elem_info_copy_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_type snd_ctl_elem_info_get_type_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_readable snd_ctl_elem_info_is_readable_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_writable snd_ctl_elem_info_is_writable_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_volatile snd_ctl_elem_info_is_volatile_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_inactive snd_ctl_elem_info_is_inactive_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_locked snd_ctl_elem_info_is_locked_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_tlv_readable snd_ctl_elem_info_is_tlv_readable_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_tlv_writable snd_ctl_elem_info_is_tlv_writable_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_tlv_commandable snd_ctl_elem_info_is_tlv_commandable_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_owner snd_ctl_elem_info_is_owner_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_user snd_ctl_elem_info_is_user_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_owner snd_ctl_elem_info_get_owner_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_count snd_ctl_elem_info_get_count_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_min snd_ctl_elem_info_get_min_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_max snd_ctl_elem_info_get_max_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_step snd_ctl_elem_info_get_step_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_min64 snd_ctl_elem_info_get_min64_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_max64 snd_ctl_elem_info_get_max64_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_step64 snd_ctl_elem_info_get_step64_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_items snd_ctl_elem_info_get_items_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_item snd_ctl_elem_info_set_item_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_item_name snd_ctl_elem_info_get_item_name_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_dimensions snd_ctl_elem_info_get_dimensions_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_dimension snd_ctl_elem_info_get_dimension_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_dimension snd_ctl_elem_info_set_dimension_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_id snd_ctl_elem_info_get_id_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_numid snd_ctl_elem_info_get_numid_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_interface snd_ctl_elem_info_get_interface_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_device snd_ctl_elem_info_get_device_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_subdevice snd_ctl_elem_info_get_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_name snd_ctl_elem_info_get_name_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_index snd_ctl_elem_info_get_index_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_id snd_ctl_elem_info_set_id_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_numid snd_ctl_elem_info_set_numid_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_interface snd_ctl_elem_info_set_interface_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_device snd_ctl_elem_info_set_device_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_subdevice snd_ctl_elem_info_set_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_name snd_ctl_elem_info_set_name_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_index snd_ctl_elem_info_set_index_dylibloader_orig_asound
+#define snd_ctl_add_integer_elem_set snd_ctl_add_integer_elem_set_dylibloader_orig_asound
+#define snd_ctl_add_integer64_elem_set snd_ctl_add_integer64_elem_set_dylibloader_orig_asound
+#define snd_ctl_add_boolean_elem_set snd_ctl_add_boolean_elem_set_dylibloader_orig_asound
+#define snd_ctl_add_enumerated_elem_set snd_ctl_add_enumerated_elem_set_dylibloader_orig_asound
+#define snd_ctl_add_bytes_elem_set snd_ctl_add_bytes_elem_set_dylibloader_orig_asound
+#define snd_ctl_elem_add_integer snd_ctl_elem_add_integer_dylibloader_orig_asound
+#define snd_ctl_elem_add_integer64 snd_ctl_elem_add_integer64_dylibloader_orig_asound
+#define snd_ctl_elem_add_boolean snd_ctl_elem_add_boolean_dylibloader_orig_asound
+#define snd_ctl_elem_add_enumerated snd_ctl_elem_add_enumerated_dylibloader_orig_asound
+#define snd_ctl_elem_add_iec958 snd_ctl_elem_add_iec958_dylibloader_orig_asound
+#define snd_ctl_elem_remove snd_ctl_elem_remove_dylibloader_orig_asound
+#define snd_ctl_elem_value_sizeof snd_ctl_elem_value_sizeof_dylibloader_orig_asound
+#define snd_ctl_elem_value_malloc snd_ctl_elem_value_malloc_dylibloader_orig_asound
+#define snd_ctl_elem_value_free snd_ctl_elem_value_free_dylibloader_orig_asound
+#define snd_ctl_elem_value_clear snd_ctl_elem_value_clear_dylibloader_orig_asound
+#define snd_ctl_elem_value_copy snd_ctl_elem_value_copy_dylibloader_orig_asound
+#define snd_ctl_elem_value_compare snd_ctl_elem_value_compare_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_id snd_ctl_elem_value_get_id_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_numid snd_ctl_elem_value_get_numid_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_interface snd_ctl_elem_value_get_interface_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_device snd_ctl_elem_value_get_device_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_subdevice snd_ctl_elem_value_get_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_name snd_ctl_elem_value_get_name_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_index snd_ctl_elem_value_get_index_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_id snd_ctl_elem_value_set_id_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_numid snd_ctl_elem_value_set_numid_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_interface snd_ctl_elem_value_set_interface_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_device snd_ctl_elem_value_set_device_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_subdevice snd_ctl_elem_value_set_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_name snd_ctl_elem_value_set_name_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_index snd_ctl_elem_value_set_index_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_boolean snd_ctl_elem_value_get_boolean_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_integer snd_ctl_elem_value_get_integer_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_integer64 snd_ctl_elem_value_get_integer64_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_enumerated snd_ctl_elem_value_get_enumerated_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_byte snd_ctl_elem_value_get_byte_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_boolean snd_ctl_elem_value_set_boolean_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_integer snd_ctl_elem_value_set_integer_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_integer64 snd_ctl_elem_value_set_integer64_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_enumerated snd_ctl_elem_value_set_enumerated_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_byte snd_ctl_elem_value_set_byte_dylibloader_orig_asound
+#define snd_ctl_elem_set_bytes snd_ctl_elem_set_bytes_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_bytes snd_ctl_elem_value_get_bytes_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_iec958 snd_ctl_elem_value_get_iec958_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_iec958 snd_ctl_elem_value_set_iec958_dylibloader_orig_asound
+#define snd_tlv_parse_dB_info snd_tlv_parse_dB_info_dylibloader_orig_asound
+#define snd_tlv_get_dB_range snd_tlv_get_dB_range_dylibloader_orig_asound
+#define snd_tlv_convert_to_dB snd_tlv_convert_to_dB_dylibloader_orig_asound
+#define snd_tlv_convert_from_dB snd_tlv_convert_from_dB_dylibloader_orig_asound
+#define snd_ctl_get_dB_range snd_ctl_get_dB_range_dylibloader_orig_asound
+#define snd_ctl_convert_to_dB snd_ctl_convert_to_dB_dylibloader_orig_asound
+#define snd_ctl_convert_from_dB snd_ctl_convert_from_dB_dylibloader_orig_asound
+#define snd_hctl_compare_fast snd_hctl_compare_fast_dylibloader_orig_asound
+#define snd_hctl_open snd_hctl_open_dylibloader_orig_asound
+#define snd_hctl_open_ctl snd_hctl_open_ctl_dylibloader_orig_asound
+#define snd_hctl_close snd_hctl_close_dylibloader_orig_asound
+#define snd_hctl_nonblock snd_hctl_nonblock_dylibloader_orig_asound
+#define snd_hctl_poll_descriptors_count snd_hctl_poll_descriptors_count_dylibloader_orig_asound
+#define snd_hctl_poll_descriptors snd_hctl_poll_descriptors_dylibloader_orig_asound
+#define snd_hctl_poll_descriptors_revents snd_hctl_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_hctl_get_count snd_hctl_get_count_dylibloader_orig_asound
+#define snd_hctl_set_compare snd_hctl_set_compare_dylibloader_orig_asound
+#define snd_hctl_first_elem snd_hctl_first_elem_dylibloader_orig_asound
+#define snd_hctl_last_elem snd_hctl_last_elem_dylibloader_orig_asound
+#define snd_hctl_find_elem snd_hctl_find_elem_dylibloader_orig_asound
+#define snd_hctl_set_callback snd_hctl_set_callback_dylibloader_orig_asound
+#define snd_hctl_set_callback_private snd_hctl_set_callback_private_dylibloader_orig_asound
+#define snd_hctl_get_callback_private snd_hctl_get_callback_private_dylibloader_orig_asound
+#define snd_hctl_load snd_hctl_load_dylibloader_orig_asound
+#define snd_hctl_free snd_hctl_free_dylibloader_orig_asound
+#define snd_hctl_handle_events snd_hctl_handle_events_dylibloader_orig_asound
+#define snd_hctl_name snd_hctl_name_dylibloader_orig_asound
+#define snd_hctl_wait snd_hctl_wait_dylibloader_orig_asound
+#define snd_hctl_ctl snd_hctl_ctl_dylibloader_orig_asound
+#define snd_hctl_elem_next snd_hctl_elem_next_dylibloader_orig_asound
+#define snd_hctl_elem_prev snd_hctl_elem_prev_dylibloader_orig_asound
+#define snd_hctl_elem_info snd_hctl_elem_info_dylibloader_orig_asound
+#define snd_hctl_elem_read snd_hctl_elem_read_dylibloader_orig_asound
+#define snd_hctl_elem_write snd_hctl_elem_write_dylibloader_orig_asound
+#define snd_hctl_elem_tlv_read snd_hctl_elem_tlv_read_dylibloader_orig_asound
+#define snd_hctl_elem_tlv_write snd_hctl_elem_tlv_write_dylibloader_orig_asound
+#define snd_hctl_elem_tlv_command snd_hctl_elem_tlv_command_dylibloader_orig_asound
+#define snd_hctl_elem_get_hctl snd_hctl_elem_get_hctl_dylibloader_orig_asound
+#define snd_hctl_elem_get_id snd_hctl_elem_get_id_dylibloader_orig_asound
+#define snd_hctl_elem_get_numid snd_hctl_elem_get_numid_dylibloader_orig_asound
+#define snd_hctl_elem_get_interface snd_hctl_elem_get_interface_dylibloader_orig_asound
+#define snd_hctl_elem_get_device snd_hctl_elem_get_device_dylibloader_orig_asound
+#define snd_hctl_elem_get_subdevice snd_hctl_elem_get_subdevice_dylibloader_orig_asound
+#define snd_hctl_elem_get_name snd_hctl_elem_get_name_dylibloader_orig_asound
+#define snd_hctl_elem_get_index snd_hctl_elem_get_index_dylibloader_orig_asound
+#define snd_hctl_elem_set_callback snd_hctl_elem_set_callback_dylibloader_orig_asound
+#define snd_hctl_elem_get_callback_private snd_hctl_elem_get_callback_private_dylibloader_orig_asound
+#define snd_hctl_elem_set_callback_private snd_hctl_elem_set_callback_private_dylibloader_orig_asound
+#define snd_sctl_build snd_sctl_build_dylibloader_orig_asound
+#define snd_sctl_free snd_sctl_free_dylibloader_orig_asound
+#define snd_sctl_install snd_sctl_install_dylibloader_orig_asound
+#define snd_sctl_remove snd_sctl_remove_dylibloader_orig_asound
+#define snd_mixer_open snd_mixer_open_dylibloader_orig_asound
+#define snd_mixer_close snd_mixer_close_dylibloader_orig_asound
+#define snd_mixer_first_elem snd_mixer_first_elem_dylibloader_orig_asound
+#define snd_mixer_last_elem snd_mixer_last_elem_dylibloader_orig_asound
+#define snd_mixer_handle_events snd_mixer_handle_events_dylibloader_orig_asound
+#define snd_mixer_attach snd_mixer_attach_dylibloader_orig_asound
+#define snd_mixer_attach_hctl snd_mixer_attach_hctl_dylibloader_orig_asound
+#define snd_mixer_detach snd_mixer_detach_dylibloader_orig_asound
+#define snd_mixer_detach_hctl snd_mixer_detach_hctl_dylibloader_orig_asound
+#define snd_mixer_get_hctl snd_mixer_get_hctl_dylibloader_orig_asound
+#define snd_mixer_poll_descriptors_count snd_mixer_poll_descriptors_count_dylibloader_orig_asound
+#define snd_mixer_poll_descriptors snd_mixer_poll_descriptors_dylibloader_orig_asound
+#define snd_mixer_poll_descriptors_revents snd_mixer_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_mixer_load snd_mixer_load_dylibloader_orig_asound
+#define snd_mixer_free snd_mixer_free_dylibloader_orig_asound
+#define snd_mixer_wait snd_mixer_wait_dylibloader_orig_asound
+#define snd_mixer_set_compare snd_mixer_set_compare_dylibloader_orig_asound
+#define snd_mixer_set_callback snd_mixer_set_callback_dylibloader_orig_asound
+#define snd_mixer_get_callback_private snd_mixer_get_callback_private_dylibloader_orig_asound
+#define snd_mixer_set_callback_private snd_mixer_set_callback_private_dylibloader_orig_asound
+#define snd_mixer_get_count snd_mixer_get_count_dylibloader_orig_asound
+#define snd_mixer_class_unregister snd_mixer_class_unregister_dylibloader_orig_asound
+#define snd_mixer_elem_next snd_mixer_elem_next_dylibloader_orig_asound
+#define snd_mixer_elem_prev snd_mixer_elem_prev_dylibloader_orig_asound
+#define snd_mixer_elem_set_callback snd_mixer_elem_set_callback_dylibloader_orig_asound
+#define snd_mixer_elem_get_callback_private snd_mixer_elem_get_callback_private_dylibloader_orig_asound
+#define snd_mixer_elem_set_callback_private snd_mixer_elem_set_callback_private_dylibloader_orig_asound
+#define snd_mixer_elem_get_type snd_mixer_elem_get_type_dylibloader_orig_asound
+#define snd_mixer_class_register snd_mixer_class_register_dylibloader_orig_asound
+#define snd_mixer_elem_new snd_mixer_elem_new_dylibloader_orig_asound
+#define snd_mixer_elem_add snd_mixer_elem_add_dylibloader_orig_asound
+#define snd_mixer_elem_remove snd_mixer_elem_remove_dylibloader_orig_asound
+#define snd_mixer_elem_free snd_mixer_elem_free_dylibloader_orig_asound
+#define snd_mixer_elem_info snd_mixer_elem_info_dylibloader_orig_asound
+#define snd_mixer_elem_value snd_mixer_elem_value_dylibloader_orig_asound
+#define snd_mixer_elem_attach snd_mixer_elem_attach_dylibloader_orig_asound
+#define snd_mixer_elem_detach snd_mixer_elem_detach_dylibloader_orig_asound
+#define snd_mixer_elem_empty snd_mixer_elem_empty_dylibloader_orig_asound
+#define snd_mixer_elem_get_private snd_mixer_elem_get_private_dylibloader_orig_asound
+#define snd_mixer_class_sizeof snd_mixer_class_sizeof_dylibloader_orig_asound
+#define snd_mixer_class_malloc snd_mixer_class_malloc_dylibloader_orig_asound
+#define snd_mixer_class_free snd_mixer_class_free_dylibloader_orig_asound
+#define snd_mixer_class_copy snd_mixer_class_copy_dylibloader_orig_asound
+#define snd_mixer_class_get_mixer snd_mixer_class_get_mixer_dylibloader_orig_asound
+#define snd_mixer_class_get_event snd_mixer_class_get_event_dylibloader_orig_asound
+#define snd_mixer_class_get_private snd_mixer_class_get_private_dylibloader_orig_asound
+#define snd_mixer_class_get_compare snd_mixer_class_get_compare_dylibloader_orig_asound
+#define snd_mixer_class_set_event snd_mixer_class_set_event_dylibloader_orig_asound
+#define snd_mixer_class_set_private snd_mixer_class_set_private_dylibloader_orig_asound
+#define snd_mixer_class_set_private_free snd_mixer_class_set_private_free_dylibloader_orig_asound
+#define snd_mixer_class_set_compare snd_mixer_class_set_compare_dylibloader_orig_asound
+#define snd_mixer_selem_channel_name snd_mixer_selem_channel_name_dylibloader_orig_asound
+#define snd_mixer_selem_register snd_mixer_selem_register_dylibloader_orig_asound
+#define snd_mixer_selem_get_id snd_mixer_selem_get_id_dylibloader_orig_asound
+#define snd_mixer_selem_get_name snd_mixer_selem_get_name_dylibloader_orig_asound
+#define snd_mixer_selem_get_index snd_mixer_selem_get_index_dylibloader_orig_asound
+#define snd_mixer_find_selem snd_mixer_find_selem_dylibloader_orig_asound
+#define snd_mixer_selem_is_active snd_mixer_selem_is_active_dylibloader_orig_asound
+#define snd_mixer_selem_is_playback_mono snd_mixer_selem_is_playback_mono_dylibloader_orig_asound
+#define snd_mixer_selem_has_playback_channel snd_mixer_selem_has_playback_channel_dylibloader_orig_asound
+#define snd_mixer_selem_is_capture_mono snd_mixer_selem_is_capture_mono_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_channel snd_mixer_selem_has_capture_channel_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_group snd_mixer_selem_get_capture_group_dylibloader_orig_asound
+#define snd_mixer_selem_has_common_volume snd_mixer_selem_has_common_volume_dylibloader_orig_asound
+#define snd_mixer_selem_has_playback_volume snd_mixer_selem_has_playback_volume_dylibloader_orig_asound
+#define snd_mixer_selem_has_playback_volume_joined snd_mixer_selem_has_playback_volume_joined_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_volume snd_mixer_selem_has_capture_volume_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_volume_joined snd_mixer_selem_has_capture_volume_joined_dylibloader_orig_asound
+#define snd_mixer_selem_has_common_switch snd_mixer_selem_has_common_switch_dylibloader_orig_asound
+#define snd_mixer_selem_has_playback_switch snd_mixer_selem_has_playback_switch_dylibloader_orig_asound
+#define snd_mixer_selem_has_playback_switch_joined snd_mixer_selem_has_playback_switch_joined_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_switch snd_mixer_selem_has_capture_switch_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_switch_joined snd_mixer_selem_has_capture_switch_joined_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_switch_exclusive snd_mixer_selem_has_capture_switch_exclusive_dylibloader_orig_asound
+#define snd_mixer_selem_ask_playback_vol_dB snd_mixer_selem_ask_playback_vol_dB_dylibloader_orig_asound
+#define snd_mixer_selem_ask_capture_vol_dB snd_mixer_selem_ask_capture_vol_dB_dylibloader_orig_asound
+#define snd_mixer_selem_ask_playback_dB_vol snd_mixer_selem_ask_playback_dB_vol_dylibloader_orig_asound
+#define snd_mixer_selem_ask_capture_dB_vol snd_mixer_selem_ask_capture_dB_vol_dylibloader_orig_asound
+#define snd_mixer_selem_get_playback_volume snd_mixer_selem_get_playback_volume_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_volume snd_mixer_selem_get_capture_volume_dylibloader_orig_asound
+#define snd_mixer_selem_get_playback_dB snd_mixer_selem_get_playback_dB_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_dB snd_mixer_selem_get_capture_dB_dylibloader_orig_asound
+#define snd_mixer_selem_get_playback_switch snd_mixer_selem_get_playback_switch_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_switch snd_mixer_selem_get_capture_switch_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_volume snd_mixer_selem_set_playback_volume_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_volume snd_mixer_selem_set_capture_volume_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_dB snd_mixer_selem_set_playback_dB_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_dB snd_mixer_selem_set_capture_dB_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_volume_all snd_mixer_selem_set_playback_volume_all_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_volume_all snd_mixer_selem_set_capture_volume_all_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_dB_all snd_mixer_selem_set_playback_dB_all_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_dB_all snd_mixer_selem_set_capture_dB_all_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_switch snd_mixer_selem_set_playback_switch_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_switch snd_mixer_selem_set_capture_switch_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_switch_all snd_mixer_selem_set_playback_switch_all_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_switch_all snd_mixer_selem_set_capture_switch_all_dylibloader_orig_asound
+#define snd_mixer_selem_get_playback_volume_range snd_mixer_selem_get_playback_volume_range_dylibloader_orig_asound
+#define snd_mixer_selem_get_playback_dB_range snd_mixer_selem_get_playback_dB_range_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_volume_range snd_mixer_selem_set_playback_volume_range_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_volume_range snd_mixer_selem_get_capture_volume_range_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_dB_range snd_mixer_selem_get_capture_dB_range_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_volume_range snd_mixer_selem_set_capture_volume_range_dylibloader_orig_asound
+#define snd_mixer_selem_is_enumerated snd_mixer_selem_is_enumerated_dylibloader_orig_asound
+#define snd_mixer_selem_is_enum_playback snd_mixer_selem_is_enum_playback_dylibloader_orig_asound
+#define snd_mixer_selem_is_enum_capture snd_mixer_selem_is_enum_capture_dylibloader_orig_asound
+#define snd_mixer_selem_get_enum_items snd_mixer_selem_get_enum_items_dylibloader_orig_asound
+#define snd_mixer_selem_get_enum_item_name snd_mixer_selem_get_enum_item_name_dylibloader_orig_asound
+#define snd_mixer_selem_get_enum_item snd_mixer_selem_get_enum_item_dylibloader_orig_asound
+#define snd_mixer_selem_set_enum_item snd_mixer_selem_set_enum_item_dylibloader_orig_asound
+#define snd_mixer_selem_id_sizeof snd_mixer_selem_id_sizeof_dylibloader_orig_asound
+#define snd_mixer_selem_id_malloc snd_mixer_selem_id_malloc_dylibloader_orig_asound
+#define snd_mixer_selem_id_free snd_mixer_selem_id_free_dylibloader_orig_asound
+#define snd_mixer_selem_id_copy snd_mixer_selem_id_copy_dylibloader_orig_asound
+#define snd_mixer_selem_id_get_name snd_mixer_selem_id_get_name_dylibloader_orig_asound
+#define snd_mixer_selem_id_get_index snd_mixer_selem_id_get_index_dylibloader_orig_asound
+#define snd_mixer_selem_id_set_name snd_mixer_selem_id_set_name_dylibloader_orig_asound
+#define snd_mixer_selem_id_set_index snd_mixer_selem_id_set_index_dylibloader_orig_asound
+#define snd_mixer_selem_id_parse snd_mixer_selem_id_parse_dylibloader_orig_asound
+#define snd_seq_open snd_seq_open_dylibloader_orig_asound
+#define snd_seq_open_lconf snd_seq_open_lconf_dylibloader_orig_asound
+#define snd_seq_name snd_seq_name_dylibloader_orig_asound
+#define snd_seq_type snd_seq_type_dylibloader_orig_asound
+#define snd_seq_close snd_seq_close_dylibloader_orig_asound
+#define snd_seq_poll_descriptors_count snd_seq_poll_descriptors_count_dylibloader_orig_asound
+#define snd_seq_poll_descriptors snd_seq_poll_descriptors_dylibloader_orig_asound
+#define snd_seq_poll_descriptors_revents snd_seq_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_seq_nonblock snd_seq_nonblock_dylibloader_orig_asound
+#define snd_seq_client_id snd_seq_client_id_dylibloader_orig_asound
+#define snd_seq_get_output_buffer_size snd_seq_get_output_buffer_size_dylibloader_orig_asound
+#define snd_seq_get_input_buffer_size snd_seq_get_input_buffer_size_dylibloader_orig_asound
+#define snd_seq_set_output_buffer_size snd_seq_set_output_buffer_size_dylibloader_orig_asound
+#define snd_seq_set_input_buffer_size snd_seq_set_input_buffer_size_dylibloader_orig_asound
+#define snd_seq_system_info_sizeof snd_seq_system_info_sizeof_dylibloader_orig_asound
+#define snd_seq_system_info_malloc snd_seq_system_info_malloc_dylibloader_orig_asound
+#define snd_seq_system_info_free snd_seq_system_info_free_dylibloader_orig_asound
+#define snd_seq_system_info_copy snd_seq_system_info_copy_dylibloader_orig_asound
+#define snd_seq_system_info_get_queues snd_seq_system_info_get_queues_dylibloader_orig_asound
+#define snd_seq_system_info_get_clients snd_seq_system_info_get_clients_dylibloader_orig_asound
+#define snd_seq_system_info_get_ports snd_seq_system_info_get_ports_dylibloader_orig_asound
+#define snd_seq_system_info_get_channels snd_seq_system_info_get_channels_dylibloader_orig_asound
+#define snd_seq_system_info_get_cur_clients snd_seq_system_info_get_cur_clients_dylibloader_orig_asound
+#define snd_seq_system_info_get_cur_queues snd_seq_system_info_get_cur_queues_dylibloader_orig_asound
+#define snd_seq_system_info snd_seq_system_info_dylibloader_orig_asound
+#define snd_seq_client_info_sizeof snd_seq_client_info_sizeof_dylibloader_orig_asound
+#define snd_seq_client_info_malloc snd_seq_client_info_malloc_dylibloader_orig_asound
+#define snd_seq_client_info_free snd_seq_client_info_free_dylibloader_orig_asound
+#define snd_seq_client_info_copy snd_seq_client_info_copy_dylibloader_orig_asound
+#define snd_seq_client_info_get_client snd_seq_client_info_get_client_dylibloader_orig_asound
+#define snd_seq_client_info_get_type snd_seq_client_info_get_type_dylibloader_orig_asound
+#define snd_seq_client_info_get_name snd_seq_client_info_get_name_dylibloader_orig_asound
+#define snd_seq_client_info_get_broadcast_filter snd_seq_client_info_get_broadcast_filter_dylibloader_orig_asound
+#define snd_seq_client_info_get_error_bounce snd_seq_client_info_get_error_bounce_dylibloader_orig_asound
+#define snd_seq_client_info_get_card snd_seq_client_info_get_card_dylibloader_orig_asound
+#define snd_seq_client_info_get_pid snd_seq_client_info_get_pid_dylibloader_orig_asound
+#define snd_seq_client_info_get_event_filter snd_seq_client_info_get_event_filter_dylibloader_orig_asound
+#define snd_seq_client_info_get_num_ports snd_seq_client_info_get_num_ports_dylibloader_orig_asound
+#define snd_seq_client_info_get_event_lost snd_seq_client_info_get_event_lost_dylibloader_orig_asound
+#define snd_seq_client_info_set_client snd_seq_client_info_set_client_dylibloader_orig_asound
+#define snd_seq_client_info_set_name snd_seq_client_info_set_name_dylibloader_orig_asound
+#define snd_seq_client_info_set_broadcast_filter snd_seq_client_info_set_broadcast_filter_dylibloader_orig_asound
+#define snd_seq_client_info_set_error_bounce snd_seq_client_info_set_error_bounce_dylibloader_orig_asound
+#define snd_seq_client_info_set_event_filter snd_seq_client_info_set_event_filter_dylibloader_orig_asound
+#define snd_seq_client_info_event_filter_clear snd_seq_client_info_event_filter_clear_dylibloader_orig_asound
+#define snd_seq_client_info_event_filter_add snd_seq_client_info_event_filter_add_dylibloader_orig_asound
+#define snd_seq_client_info_event_filter_del snd_seq_client_info_event_filter_del_dylibloader_orig_asound
+#define snd_seq_client_info_event_filter_check snd_seq_client_info_event_filter_check_dylibloader_orig_asound
+#define snd_seq_get_client_info snd_seq_get_client_info_dylibloader_orig_asound
+#define snd_seq_get_any_client_info snd_seq_get_any_client_info_dylibloader_orig_asound
+#define snd_seq_set_client_info snd_seq_set_client_info_dylibloader_orig_asound
+#define snd_seq_query_next_client snd_seq_query_next_client_dylibloader_orig_asound
+#define snd_seq_client_pool_sizeof snd_seq_client_pool_sizeof_dylibloader_orig_asound
+#define snd_seq_client_pool_malloc snd_seq_client_pool_malloc_dylibloader_orig_asound
+#define snd_seq_client_pool_free snd_seq_client_pool_free_dylibloader_orig_asound
+#define snd_seq_client_pool_copy snd_seq_client_pool_copy_dylibloader_orig_asound
+#define snd_seq_client_pool_get_client snd_seq_client_pool_get_client_dylibloader_orig_asound
+#define snd_seq_client_pool_get_output_pool snd_seq_client_pool_get_output_pool_dylibloader_orig_asound
+#define snd_seq_client_pool_get_input_pool snd_seq_client_pool_get_input_pool_dylibloader_orig_asound
+#define snd_seq_client_pool_get_output_room snd_seq_client_pool_get_output_room_dylibloader_orig_asound
+#define snd_seq_client_pool_get_output_free snd_seq_client_pool_get_output_free_dylibloader_orig_asound
+#define snd_seq_client_pool_get_input_free snd_seq_client_pool_get_input_free_dylibloader_orig_asound
+#define snd_seq_client_pool_set_output_pool snd_seq_client_pool_set_output_pool_dylibloader_orig_asound
+#define snd_seq_client_pool_set_input_pool snd_seq_client_pool_set_input_pool_dylibloader_orig_asound
+#define snd_seq_client_pool_set_output_room snd_seq_client_pool_set_output_room_dylibloader_orig_asound
+#define snd_seq_get_client_pool snd_seq_get_client_pool_dylibloader_orig_asound
+#define snd_seq_set_client_pool snd_seq_set_client_pool_dylibloader_orig_asound
+#define snd_seq_port_info_sizeof snd_seq_port_info_sizeof_dylibloader_orig_asound
+#define snd_seq_port_info_malloc snd_seq_port_info_malloc_dylibloader_orig_asound
+#define snd_seq_port_info_free snd_seq_port_info_free_dylibloader_orig_asound
+#define snd_seq_port_info_copy snd_seq_port_info_copy_dylibloader_orig_asound
+#define snd_seq_port_info_get_client snd_seq_port_info_get_client_dylibloader_orig_asound
+#define snd_seq_port_info_get_port snd_seq_port_info_get_port_dylibloader_orig_asound
+#define snd_seq_port_info_get_addr snd_seq_port_info_get_addr_dylibloader_orig_asound
+#define snd_seq_port_info_get_name snd_seq_port_info_get_name_dylibloader_orig_asound
+#define snd_seq_port_info_get_capability snd_seq_port_info_get_capability_dylibloader_orig_asound
+#define snd_seq_port_info_get_type snd_seq_port_info_get_type_dylibloader_orig_asound
+#define snd_seq_port_info_get_midi_channels snd_seq_port_info_get_midi_channels_dylibloader_orig_asound
+#define snd_seq_port_info_get_midi_voices snd_seq_port_info_get_midi_voices_dylibloader_orig_asound
+#define snd_seq_port_info_get_synth_voices snd_seq_port_info_get_synth_voices_dylibloader_orig_asound
+#define snd_seq_port_info_get_read_use snd_seq_port_info_get_read_use_dylibloader_orig_asound
+#define snd_seq_port_info_get_write_use snd_seq_port_info_get_write_use_dylibloader_orig_asound
+#define snd_seq_port_info_get_port_specified snd_seq_port_info_get_port_specified_dylibloader_orig_asound
+#define snd_seq_port_info_get_timestamping snd_seq_port_info_get_timestamping_dylibloader_orig_asound
+#define snd_seq_port_info_get_timestamp_real snd_seq_port_info_get_timestamp_real_dylibloader_orig_asound
+#define snd_seq_port_info_get_timestamp_queue snd_seq_port_info_get_timestamp_queue_dylibloader_orig_asound
+#define snd_seq_port_info_set_client snd_seq_port_info_set_client_dylibloader_orig_asound
+#define snd_seq_port_info_set_port snd_seq_port_info_set_port_dylibloader_orig_asound
+#define snd_seq_port_info_set_addr snd_seq_port_info_set_addr_dylibloader_orig_asound
+#define snd_seq_port_info_set_name snd_seq_port_info_set_name_dylibloader_orig_asound
+#define snd_seq_port_info_set_capability snd_seq_port_info_set_capability_dylibloader_orig_asound
+#define snd_seq_port_info_set_type snd_seq_port_info_set_type_dylibloader_orig_asound
+#define snd_seq_port_info_set_midi_channels snd_seq_port_info_set_midi_channels_dylibloader_orig_asound
+#define snd_seq_port_info_set_midi_voices snd_seq_port_info_set_midi_voices_dylibloader_orig_asound
+#define snd_seq_port_info_set_synth_voices snd_seq_port_info_set_synth_voices_dylibloader_orig_asound
+#define snd_seq_port_info_set_port_specified snd_seq_port_info_set_port_specified_dylibloader_orig_asound
+#define snd_seq_port_info_set_timestamping snd_seq_port_info_set_timestamping_dylibloader_orig_asound
+#define snd_seq_port_info_set_timestamp_real snd_seq_port_info_set_timestamp_real_dylibloader_orig_asound
+#define snd_seq_port_info_set_timestamp_queue snd_seq_port_info_set_timestamp_queue_dylibloader_orig_asound
+#define snd_seq_create_port snd_seq_create_port_dylibloader_orig_asound
+#define snd_seq_delete_port snd_seq_delete_port_dylibloader_orig_asound
+#define snd_seq_get_port_info snd_seq_get_port_info_dylibloader_orig_asound
+#define snd_seq_get_any_port_info snd_seq_get_any_port_info_dylibloader_orig_asound
+#define snd_seq_set_port_info snd_seq_set_port_info_dylibloader_orig_asound
+#define snd_seq_query_next_port snd_seq_query_next_port_dylibloader_orig_asound
+#define snd_seq_port_subscribe_sizeof snd_seq_port_subscribe_sizeof_dylibloader_orig_asound
+#define snd_seq_port_subscribe_malloc snd_seq_port_subscribe_malloc_dylibloader_orig_asound
+#define snd_seq_port_subscribe_free snd_seq_port_subscribe_free_dylibloader_orig_asound
+#define snd_seq_port_subscribe_copy snd_seq_port_subscribe_copy_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_sender snd_seq_port_subscribe_get_sender_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_dest snd_seq_port_subscribe_get_dest_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_queue snd_seq_port_subscribe_get_queue_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_exclusive snd_seq_port_subscribe_get_exclusive_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_time_update snd_seq_port_subscribe_get_time_update_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_time_real snd_seq_port_subscribe_get_time_real_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_sender snd_seq_port_subscribe_set_sender_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_dest snd_seq_port_subscribe_set_dest_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_queue snd_seq_port_subscribe_set_queue_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_exclusive snd_seq_port_subscribe_set_exclusive_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_time_update snd_seq_port_subscribe_set_time_update_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_time_real snd_seq_port_subscribe_set_time_real_dylibloader_orig_asound
+#define snd_seq_get_port_subscription snd_seq_get_port_subscription_dylibloader_orig_asound
+#define snd_seq_subscribe_port snd_seq_subscribe_port_dylibloader_orig_asound
+#define snd_seq_unsubscribe_port snd_seq_unsubscribe_port_dylibloader_orig_asound
+#define snd_seq_query_subscribe_sizeof snd_seq_query_subscribe_sizeof_dylibloader_orig_asound
+#define snd_seq_query_subscribe_malloc snd_seq_query_subscribe_malloc_dylibloader_orig_asound
+#define snd_seq_query_subscribe_free snd_seq_query_subscribe_free_dylibloader_orig_asound
+#define snd_seq_query_subscribe_copy snd_seq_query_subscribe_copy_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_client snd_seq_query_subscribe_get_client_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_port snd_seq_query_subscribe_get_port_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_root snd_seq_query_subscribe_get_root_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_type snd_seq_query_subscribe_get_type_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_index snd_seq_query_subscribe_get_index_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_num_subs snd_seq_query_subscribe_get_num_subs_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_addr snd_seq_query_subscribe_get_addr_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_queue snd_seq_query_subscribe_get_queue_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_exclusive snd_seq_query_subscribe_get_exclusive_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_time_update snd_seq_query_subscribe_get_time_update_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_time_real snd_seq_query_subscribe_get_time_real_dylibloader_orig_asound
+#define snd_seq_query_subscribe_set_client snd_seq_query_subscribe_set_client_dylibloader_orig_asound
+#define snd_seq_query_subscribe_set_port snd_seq_query_subscribe_set_port_dylibloader_orig_asound
+#define snd_seq_query_subscribe_set_root snd_seq_query_subscribe_set_root_dylibloader_orig_asound
+#define snd_seq_query_subscribe_set_type snd_seq_query_subscribe_set_type_dylibloader_orig_asound
+#define snd_seq_query_subscribe_set_index snd_seq_query_subscribe_set_index_dylibloader_orig_asound
+#define snd_seq_query_port_subscribers snd_seq_query_port_subscribers_dylibloader_orig_asound
+#define snd_seq_queue_info_sizeof snd_seq_queue_info_sizeof_dylibloader_orig_asound
+#define snd_seq_queue_info_malloc snd_seq_queue_info_malloc_dylibloader_orig_asound
+#define snd_seq_queue_info_free snd_seq_queue_info_free_dylibloader_orig_asound
+#define snd_seq_queue_info_copy snd_seq_queue_info_copy_dylibloader_orig_asound
+#define snd_seq_queue_info_get_queue snd_seq_queue_info_get_queue_dylibloader_orig_asound
+#define snd_seq_queue_info_get_name snd_seq_queue_info_get_name_dylibloader_orig_asound
+#define snd_seq_queue_info_get_owner snd_seq_queue_info_get_owner_dylibloader_orig_asound
+#define snd_seq_queue_info_get_locked snd_seq_queue_info_get_locked_dylibloader_orig_asound
+#define snd_seq_queue_info_get_flags snd_seq_queue_info_get_flags_dylibloader_orig_asound
+#define snd_seq_queue_info_set_name snd_seq_queue_info_set_name_dylibloader_orig_asound
+#define snd_seq_queue_info_set_owner snd_seq_queue_info_set_owner_dylibloader_orig_asound
+#define snd_seq_queue_info_set_locked snd_seq_queue_info_set_locked_dylibloader_orig_asound
+#define snd_seq_queue_info_set_flags snd_seq_queue_info_set_flags_dylibloader_orig_asound
+#define snd_seq_create_queue snd_seq_create_queue_dylibloader_orig_asound
+#define snd_seq_alloc_named_queue snd_seq_alloc_named_queue_dylibloader_orig_asound
+#define snd_seq_alloc_queue snd_seq_alloc_queue_dylibloader_orig_asound
+#define snd_seq_free_queue snd_seq_free_queue_dylibloader_orig_asound
+#define snd_seq_get_queue_info snd_seq_get_queue_info_dylibloader_orig_asound
+#define snd_seq_set_queue_info snd_seq_set_queue_info_dylibloader_orig_asound
+#define snd_seq_query_named_queue snd_seq_query_named_queue_dylibloader_orig_asound
+#define snd_seq_get_queue_usage snd_seq_get_queue_usage_dylibloader_orig_asound
+#define snd_seq_set_queue_usage snd_seq_set_queue_usage_dylibloader_orig_asound
+#define snd_seq_queue_status_sizeof snd_seq_queue_status_sizeof_dylibloader_orig_asound
+#define snd_seq_queue_status_malloc snd_seq_queue_status_malloc_dylibloader_orig_asound
+#define snd_seq_queue_status_free snd_seq_queue_status_free_dylibloader_orig_asound
+#define snd_seq_queue_status_copy snd_seq_queue_status_copy_dylibloader_orig_asound
+#define snd_seq_queue_status_get_queue snd_seq_queue_status_get_queue_dylibloader_orig_asound
+#define snd_seq_queue_status_get_events snd_seq_queue_status_get_events_dylibloader_orig_asound
+#define snd_seq_queue_status_get_tick_time snd_seq_queue_status_get_tick_time_dylibloader_orig_asound
+#define snd_seq_queue_status_get_real_time snd_seq_queue_status_get_real_time_dylibloader_orig_asound
+#define snd_seq_queue_status_get_status snd_seq_queue_status_get_status_dylibloader_orig_asound
+#define snd_seq_get_queue_status snd_seq_get_queue_status_dylibloader_orig_asound
+#define snd_seq_queue_tempo_sizeof snd_seq_queue_tempo_sizeof_dylibloader_orig_asound
+#define snd_seq_queue_tempo_malloc snd_seq_queue_tempo_malloc_dylibloader_orig_asound
+#define snd_seq_queue_tempo_free snd_seq_queue_tempo_free_dylibloader_orig_asound
+#define snd_seq_queue_tempo_copy snd_seq_queue_tempo_copy_dylibloader_orig_asound
+#define snd_seq_queue_tempo_get_queue snd_seq_queue_tempo_get_queue_dylibloader_orig_asound
+#define snd_seq_queue_tempo_get_tempo snd_seq_queue_tempo_get_tempo_dylibloader_orig_asound
+#define snd_seq_queue_tempo_get_ppq snd_seq_queue_tempo_get_ppq_dylibloader_orig_asound
+#define snd_seq_queue_tempo_get_skew snd_seq_queue_tempo_get_skew_dylibloader_orig_asound
+#define snd_seq_queue_tempo_get_skew_base snd_seq_queue_tempo_get_skew_base_dylibloader_orig_asound
+#define snd_seq_queue_tempo_set_tempo snd_seq_queue_tempo_set_tempo_dylibloader_orig_asound
+#define snd_seq_queue_tempo_set_ppq snd_seq_queue_tempo_set_ppq_dylibloader_orig_asound
+#define snd_seq_queue_tempo_set_skew snd_seq_queue_tempo_set_skew_dylibloader_orig_asound
+#define snd_seq_queue_tempo_set_skew_base snd_seq_queue_tempo_set_skew_base_dylibloader_orig_asound
+#define snd_seq_get_queue_tempo snd_seq_get_queue_tempo_dylibloader_orig_asound
+#define snd_seq_set_queue_tempo snd_seq_set_queue_tempo_dylibloader_orig_asound
+#define snd_seq_queue_timer_sizeof snd_seq_queue_timer_sizeof_dylibloader_orig_asound
+#define snd_seq_queue_timer_malloc snd_seq_queue_timer_malloc_dylibloader_orig_asound
+#define snd_seq_queue_timer_free snd_seq_queue_timer_free_dylibloader_orig_asound
+#define snd_seq_queue_timer_copy snd_seq_queue_timer_copy_dylibloader_orig_asound
+#define snd_seq_queue_timer_get_queue snd_seq_queue_timer_get_queue_dylibloader_orig_asound
+#define snd_seq_queue_timer_get_type snd_seq_queue_timer_get_type_dylibloader_orig_asound
+#define snd_seq_queue_timer_get_id snd_seq_queue_timer_get_id_dylibloader_orig_asound
+#define snd_seq_queue_timer_get_resolution snd_seq_queue_timer_get_resolution_dylibloader_orig_asound
+#define snd_seq_queue_timer_set_type snd_seq_queue_timer_set_type_dylibloader_orig_asound
+#define snd_seq_queue_timer_set_id snd_seq_queue_timer_set_id_dylibloader_orig_asound
+#define snd_seq_queue_timer_set_resolution snd_seq_queue_timer_set_resolution_dylibloader_orig_asound
+#define snd_seq_get_queue_timer snd_seq_get_queue_timer_dylibloader_orig_asound
+#define snd_seq_set_queue_timer snd_seq_set_queue_timer_dylibloader_orig_asound
+#define snd_seq_free_event snd_seq_free_event_dylibloader_orig_asound
+#define snd_seq_event_length snd_seq_event_length_dylibloader_orig_asound
+#define snd_seq_event_output snd_seq_event_output_dylibloader_orig_asound
+#define snd_seq_event_output_buffer snd_seq_event_output_buffer_dylibloader_orig_asound
+#define snd_seq_event_output_direct snd_seq_event_output_direct_dylibloader_orig_asound
+#define snd_seq_event_input snd_seq_event_input_dylibloader_orig_asound
+#define snd_seq_event_input_pending snd_seq_event_input_pending_dylibloader_orig_asound
+#define snd_seq_drain_output snd_seq_drain_output_dylibloader_orig_asound
+#define snd_seq_event_output_pending snd_seq_event_output_pending_dylibloader_orig_asound
+#define snd_seq_extract_output snd_seq_extract_output_dylibloader_orig_asound
+#define snd_seq_drop_output snd_seq_drop_output_dylibloader_orig_asound
+#define snd_seq_drop_output_buffer snd_seq_drop_output_buffer_dylibloader_orig_asound
+#define snd_seq_drop_input snd_seq_drop_input_dylibloader_orig_asound
+#define snd_seq_drop_input_buffer snd_seq_drop_input_buffer_dylibloader_orig_asound
+#define snd_seq_remove_events_sizeof snd_seq_remove_events_sizeof_dylibloader_orig_asound
+#define snd_seq_remove_events_malloc snd_seq_remove_events_malloc_dylibloader_orig_asound
+#define snd_seq_remove_events_free snd_seq_remove_events_free_dylibloader_orig_asound
+#define snd_seq_remove_events_copy snd_seq_remove_events_copy_dylibloader_orig_asound
+#define snd_seq_remove_events_get_condition snd_seq_remove_events_get_condition_dylibloader_orig_asound
+#define snd_seq_remove_events_get_queue snd_seq_remove_events_get_queue_dylibloader_orig_asound
+#define snd_seq_remove_events_get_time snd_seq_remove_events_get_time_dylibloader_orig_asound
+#define snd_seq_remove_events_get_dest snd_seq_remove_events_get_dest_dylibloader_orig_asound
+#define snd_seq_remove_events_get_channel snd_seq_remove_events_get_channel_dylibloader_orig_asound
+#define snd_seq_remove_events_get_event_type snd_seq_remove_events_get_event_type_dylibloader_orig_asound
+#define snd_seq_remove_events_get_tag snd_seq_remove_events_get_tag_dylibloader_orig_asound
+#define snd_seq_remove_events_set_condition snd_seq_remove_events_set_condition_dylibloader_orig_asound
+#define snd_seq_remove_events_set_queue snd_seq_remove_events_set_queue_dylibloader_orig_asound
+#define snd_seq_remove_events_set_time snd_seq_remove_events_set_time_dylibloader_orig_asound
+#define snd_seq_remove_events_set_dest snd_seq_remove_events_set_dest_dylibloader_orig_asound
+#define snd_seq_remove_events_set_channel snd_seq_remove_events_set_channel_dylibloader_orig_asound
+#define snd_seq_remove_events_set_event_type snd_seq_remove_events_set_event_type_dylibloader_orig_asound
+#define snd_seq_remove_events_set_tag snd_seq_remove_events_set_tag_dylibloader_orig_asound
+#define snd_seq_remove_events snd_seq_remove_events_dylibloader_orig_asound
+#define snd_seq_set_bit snd_seq_set_bit_dylibloader_orig_asound
+#define snd_seq_unset_bit snd_seq_unset_bit_dylibloader_orig_asound
+#define snd_seq_change_bit snd_seq_change_bit_dylibloader_orig_asound
+#define snd_seq_get_bit snd_seq_get_bit_dylibloader_orig_asound
+#define snd_seq_control_queue snd_seq_control_queue_dylibloader_orig_asound
+#define snd_seq_create_simple_port snd_seq_create_simple_port_dylibloader_orig_asound
+#define snd_seq_delete_simple_port snd_seq_delete_simple_port_dylibloader_orig_asound
+#define snd_seq_connect_from snd_seq_connect_from_dylibloader_orig_asound
+#define snd_seq_connect_to snd_seq_connect_to_dylibloader_orig_asound
+#define snd_seq_disconnect_from snd_seq_disconnect_from_dylibloader_orig_asound
+#define snd_seq_disconnect_to snd_seq_disconnect_to_dylibloader_orig_asound
+#define snd_seq_set_client_name snd_seq_set_client_name_dylibloader_orig_asound
+#define snd_seq_set_client_event_filter snd_seq_set_client_event_filter_dylibloader_orig_asound
+#define snd_seq_set_client_pool_output snd_seq_set_client_pool_output_dylibloader_orig_asound
+#define snd_seq_set_client_pool_output_room snd_seq_set_client_pool_output_room_dylibloader_orig_asound
+#define snd_seq_set_client_pool_input snd_seq_set_client_pool_input_dylibloader_orig_asound
+#define snd_seq_sync_output_queue snd_seq_sync_output_queue_dylibloader_orig_asound
+#define snd_seq_parse_address snd_seq_parse_address_dylibloader_orig_asound
+#define snd_seq_reset_pool_output snd_seq_reset_pool_output_dylibloader_orig_asound
+#define snd_seq_reset_pool_input snd_seq_reset_pool_input_dylibloader_orig_asound
+#define snd_midi_event_new snd_midi_event_new_dylibloader_orig_asound
+#define snd_midi_event_resize_buffer snd_midi_event_resize_buffer_dylibloader_orig_asound
+#define snd_midi_event_free snd_midi_event_free_dylibloader_orig_asound
+#define snd_midi_event_init snd_midi_event_init_dylibloader_orig_asound
+#define snd_midi_event_reset_encode snd_midi_event_reset_encode_dylibloader_orig_asound
+#define snd_midi_event_reset_decode snd_midi_event_reset_decode_dylibloader_orig_asound
+#define snd_midi_event_no_status snd_midi_event_no_status_dylibloader_orig_asound
+#define snd_midi_event_encode snd_midi_event_encode_dylibloader_orig_asound
+#define snd_midi_event_encode_byte snd_midi_event_encode_byte_dylibloader_orig_asound
+#define snd_midi_event_decode snd_midi_event_decode_dylibloader_orig_asound
+#include <alsa/asoundlib.h>
+#undef snd_asoundlib_version
+#undef snd_dlpath
+#undef snd_dlopen
+#undef snd_dlsym
+#undef snd_dlclose
+#undef snd_async_add_handler
+#undef snd_async_del_handler
+#undef snd_async_handler_get_fd
+#undef snd_async_handler_get_signo
+#undef snd_async_handler_get_callback_private
+#undef snd_shm_area_create
+#undef snd_shm_area_share
+#undef snd_shm_area_destroy
+#undef snd_user_file
+#undef snd_input_stdio_open
+#undef snd_input_stdio_attach
+#undef snd_input_buffer_open
+#undef snd_input_close
+#undef snd_input_scanf
+#undef snd_input_gets
+#undef snd_input_getc
+#undef snd_input_ungetc
+#undef snd_output_stdio_open
+#undef snd_output_stdio_attach
+#undef snd_output_buffer_open
+#undef snd_output_buffer_string
+#undef snd_output_close
+#undef snd_output_printf
+#undef snd_output_vprintf
+#undef snd_output_puts
+#undef snd_output_putc
+#undef snd_output_flush
+#undef snd_strerror
+#undef snd_lib_error_set_handler
+#undef snd_lib_error_set_local
+#undef snd_config_topdir
+#undef snd_config_top
+#undef snd_config_load
+#undef snd_config_load_override
+#undef snd_config_save
+#undef snd_config_update
+#undef snd_config_update_r
+#undef snd_config_update_free
+#undef snd_config_update_free_global
+#undef snd_config_update_ref
+#undef snd_config_ref
+#undef snd_config_unref
+#undef snd_config_search
+#undef snd_config_searchv
+#undef snd_config_search_definition
+#undef snd_config_expand
+#undef snd_config_evaluate
+#undef snd_config_add
+#undef snd_config_add_before
+#undef snd_config_add_after
+#undef snd_config_remove
+#undef snd_config_delete
+#undef snd_config_delete_compound_members
+#undef snd_config_copy
+#undef snd_config_make
+#undef snd_config_make_integer
+#undef snd_config_make_integer64
+#undef snd_config_make_real
+#undef snd_config_make_string
+#undef snd_config_make_pointer
+#undef snd_config_make_compound
+#undef snd_config_imake_integer
+#undef snd_config_imake_integer64
+#undef snd_config_imake_real
+#undef snd_config_imake_string
+#undef snd_config_imake_safe_string
+#undef snd_config_imake_pointer
+#undef snd_config_get_type
+#undef snd_config_is_array
+#undef snd_config_set_id
+#undef snd_config_set_integer
+#undef snd_config_set_integer64
+#undef snd_config_set_real
+#undef snd_config_set_string
+#undef snd_config_set_ascii
+#undef snd_config_set_pointer
+#undef snd_config_get_id
+#undef snd_config_get_integer
+#undef snd_config_get_integer64
+#undef snd_config_get_real
+#undef snd_config_get_ireal
+#undef snd_config_get_string
+#undef snd_config_get_ascii
+#undef snd_config_get_pointer
+#undef snd_config_test_id
+#undef snd_config_iterator_first
+#undef snd_config_iterator_next
+#undef snd_config_iterator_end
+#undef snd_config_iterator_entry
+#undef snd_config_get_bool_ascii
+#undef snd_config_get_bool
+#undef snd_config_get_ctl_iface_ascii
+#undef snd_config_get_ctl_iface
+#undef snd_names_list
+#undef snd_names_list_free
+#undef snd_pcm_open
+#undef snd_pcm_open_lconf
+#undef snd_pcm_open_fallback
+#undef snd_pcm_close
+#undef snd_pcm_name
+#undef snd_pcm_type
+#undef snd_pcm_stream
+#undef snd_pcm_poll_descriptors_count
+#undef snd_pcm_poll_descriptors
+#undef snd_pcm_poll_descriptors_revents
+#undef snd_pcm_nonblock
+#undef snd_async_add_pcm_handler
+#undef snd_async_handler_get_pcm
+#undef snd_pcm_info
+#undef snd_pcm_hw_params_current
+#undef snd_pcm_hw_params
+#undef snd_pcm_hw_free
+#undef snd_pcm_sw_params_current
+#undef snd_pcm_sw_params
+#undef snd_pcm_prepare
+#undef snd_pcm_reset
+#undef snd_pcm_status
+#undef snd_pcm_start
+#undef snd_pcm_drop
+#undef snd_pcm_drain
+#undef snd_pcm_pause
+#undef snd_pcm_state
+#undef snd_pcm_hwsync
+#undef snd_pcm_delay
+#undef snd_pcm_resume
+#undef snd_pcm_htimestamp
+#undef snd_pcm_avail
+#undef snd_pcm_avail_update
+#undef snd_pcm_avail_delay
+#undef snd_pcm_rewindable
+#undef snd_pcm_rewind
+#undef snd_pcm_forwardable
+#undef snd_pcm_forward
+#undef snd_pcm_writei
+#undef snd_pcm_readi
+#undef snd_pcm_writen
+#undef snd_pcm_readn
+#undef snd_pcm_wait
+#undef snd_pcm_link
+#undef snd_pcm_unlink
+#undef snd_pcm_query_chmaps
+#undef snd_pcm_query_chmaps_from_hw
+#undef snd_pcm_free_chmaps
+#undef snd_pcm_get_chmap
+#undef snd_pcm_set_chmap
+#undef snd_pcm_chmap_type_name
+#undef snd_pcm_chmap_name
+#undef snd_pcm_chmap_long_name
+#undef snd_pcm_chmap_print
+#undef snd_pcm_chmap_from_string
+#undef snd_pcm_chmap_parse_string
+#undef snd_pcm_recover
+#undef snd_pcm_set_params
+#undef snd_pcm_get_params
+#undef snd_pcm_info_sizeof
+#undef snd_pcm_info_malloc
+#undef snd_pcm_info_free
+#undef snd_pcm_info_copy
+#undef snd_pcm_info_get_device
+#undef snd_pcm_info_get_subdevice
+#undef snd_pcm_info_get_stream
+#undef snd_pcm_info_get_card
+#undef snd_pcm_info_get_id
+#undef snd_pcm_info_get_name
+#undef snd_pcm_info_get_subdevice_name
+#undef snd_pcm_info_get_class
+#undef snd_pcm_info_get_subclass
+#undef snd_pcm_info_get_subdevices_count
+#undef snd_pcm_info_get_subdevices_avail
+#undef snd_pcm_info_get_sync
+#undef snd_pcm_info_set_device
+#undef snd_pcm_info_set_subdevice
+#undef snd_pcm_info_set_stream
+#undef snd_pcm_hw_params_any
+#undef snd_pcm_hw_params_can_mmap_sample_resolution
+#undef snd_pcm_hw_params_is_double
+#undef snd_pcm_hw_params_is_batch
+#undef snd_pcm_hw_params_is_block_transfer
+#undef snd_pcm_hw_params_is_monotonic
+#undef snd_pcm_hw_params_can_overrange
+#undef snd_pcm_hw_params_can_pause
+#undef snd_pcm_hw_params_can_resume
+#undef snd_pcm_hw_params_is_half_duplex
+#undef snd_pcm_hw_params_is_joint_duplex
+#undef snd_pcm_hw_params_can_sync_start
+#undef snd_pcm_hw_params_can_disable_period_wakeup
+#undef snd_pcm_hw_params_supports_audio_wallclock_ts
+#undef snd_pcm_hw_params_supports_audio_ts_type
+#undef snd_pcm_hw_params_get_rate_numden
+#undef snd_pcm_hw_params_get_sbits
+#undef snd_pcm_hw_params_get_fifo_size
+#undef snd_pcm_hw_params_sizeof
+#undef snd_pcm_hw_params_malloc
+#undef snd_pcm_hw_params_free
+#undef snd_pcm_hw_params_copy
+#undef snd_pcm_hw_params_get_access
+#undef snd_pcm_hw_params_test_access
+#undef snd_pcm_hw_params_set_access
+#undef snd_pcm_hw_params_set_access_first
+#undef snd_pcm_hw_params_set_access_last
+#undef snd_pcm_hw_params_set_access_mask
+#undef snd_pcm_hw_params_get_access_mask
+#undef snd_pcm_hw_params_get_format
+#undef snd_pcm_hw_params_test_format
+#undef snd_pcm_hw_params_set_format
+#undef snd_pcm_hw_params_set_format_first
+#undef snd_pcm_hw_params_set_format_last
+#undef snd_pcm_hw_params_set_format_mask
+#undef snd_pcm_hw_params_get_format_mask
+#undef snd_pcm_hw_params_get_subformat
+#undef snd_pcm_hw_params_test_subformat
+#undef snd_pcm_hw_params_set_subformat
+#undef snd_pcm_hw_params_set_subformat_first
+#undef snd_pcm_hw_params_set_subformat_last
+#undef snd_pcm_hw_params_set_subformat_mask
+#undef snd_pcm_hw_params_get_subformat_mask
+#undef snd_pcm_hw_params_get_channels
+#undef snd_pcm_hw_params_get_channels_min
+#undef snd_pcm_hw_params_get_channels_max
+#undef snd_pcm_hw_params_test_channels
+#undef snd_pcm_hw_params_set_channels
+#undef snd_pcm_hw_params_set_channels_min
+#undef snd_pcm_hw_params_set_channels_max
+#undef snd_pcm_hw_params_set_channels_minmax
+#undef snd_pcm_hw_params_set_channels_near
+#undef snd_pcm_hw_params_set_channels_first
+#undef snd_pcm_hw_params_set_channels_last
+#undef snd_pcm_hw_params_get_rate
+#undef snd_pcm_hw_params_get_rate_min
+#undef snd_pcm_hw_params_get_rate_max
+#undef snd_pcm_hw_params_test_rate
+#undef snd_pcm_hw_params_set_rate
+#undef snd_pcm_hw_params_set_rate_min
+#undef snd_pcm_hw_params_set_rate_max
+#undef snd_pcm_hw_params_set_rate_minmax
+#undef snd_pcm_hw_params_set_rate_near
+#undef snd_pcm_hw_params_set_rate_first
+#undef snd_pcm_hw_params_set_rate_last
+#undef snd_pcm_hw_params_set_rate_resample
+#undef snd_pcm_hw_params_get_rate_resample
+#undef snd_pcm_hw_params_set_export_buffer
+#undef snd_pcm_hw_params_get_export_buffer
+#undef snd_pcm_hw_params_set_period_wakeup
+#undef snd_pcm_hw_params_get_period_wakeup
+#undef snd_pcm_hw_params_get_period_time
+#undef snd_pcm_hw_params_get_period_time_min
+#undef snd_pcm_hw_params_get_period_time_max
+#undef snd_pcm_hw_params_test_period_time
+#undef snd_pcm_hw_params_set_period_time
+#undef snd_pcm_hw_params_set_period_time_min
+#undef snd_pcm_hw_params_set_period_time_max
+#undef snd_pcm_hw_params_set_period_time_minmax
+#undef snd_pcm_hw_params_set_period_time_near
+#undef snd_pcm_hw_params_set_period_time_first
+#undef snd_pcm_hw_params_set_period_time_last
+#undef snd_pcm_hw_params_get_period_size
+#undef snd_pcm_hw_params_get_period_size_min
+#undef snd_pcm_hw_params_get_period_size_max
+#undef snd_pcm_hw_params_test_period_size
+#undef snd_pcm_hw_params_set_period_size
+#undef snd_pcm_hw_params_set_period_size_min
+#undef snd_pcm_hw_params_set_period_size_max
+#undef snd_pcm_hw_params_set_period_size_minmax
+#undef snd_pcm_hw_params_set_period_size_near
+#undef snd_pcm_hw_params_set_period_size_first
+#undef snd_pcm_hw_params_set_period_size_last
+#undef snd_pcm_hw_params_set_period_size_integer
+#undef snd_pcm_hw_params_get_periods
+#undef snd_pcm_hw_params_get_periods_min
+#undef snd_pcm_hw_params_get_periods_max
+#undef snd_pcm_hw_params_test_periods
+#undef snd_pcm_hw_params_set_periods
+#undef snd_pcm_hw_params_set_periods_min
+#undef snd_pcm_hw_params_set_periods_max
+#undef snd_pcm_hw_params_set_periods_minmax
+#undef snd_pcm_hw_params_set_periods_near
+#undef snd_pcm_hw_params_set_periods_first
+#undef snd_pcm_hw_params_set_periods_last
+#undef snd_pcm_hw_params_set_periods_integer
+#undef snd_pcm_hw_params_get_buffer_time
+#undef snd_pcm_hw_params_get_buffer_time_min
+#undef snd_pcm_hw_params_get_buffer_time_max
+#undef snd_pcm_hw_params_test_buffer_time
+#undef snd_pcm_hw_params_set_buffer_time
+#undef snd_pcm_hw_params_set_buffer_time_min
+#undef snd_pcm_hw_params_set_buffer_time_max
+#undef snd_pcm_hw_params_set_buffer_time_minmax
+#undef snd_pcm_hw_params_set_buffer_time_near
+#undef snd_pcm_hw_params_set_buffer_time_first
+#undef snd_pcm_hw_params_set_buffer_time_last
+#undef snd_pcm_hw_params_get_buffer_size
+#undef snd_pcm_hw_params_get_buffer_size_min
+#undef snd_pcm_hw_params_get_buffer_size_max
+#undef snd_pcm_hw_params_test_buffer_size
+#undef snd_pcm_hw_params_set_buffer_size
+#undef snd_pcm_hw_params_set_buffer_size_min
+#undef snd_pcm_hw_params_set_buffer_size_max
+#undef snd_pcm_hw_params_set_buffer_size_minmax
+#undef snd_pcm_hw_params_set_buffer_size_near
+#undef snd_pcm_hw_params_set_buffer_size_first
+#undef snd_pcm_hw_params_set_buffer_size_last
+#undef snd_pcm_hw_params_get_min_align
+#undef snd_pcm_sw_params_sizeof
+#undef snd_pcm_sw_params_malloc
+#undef snd_pcm_sw_params_free
+#undef snd_pcm_sw_params_copy
+#undef snd_pcm_sw_params_get_boundary
+#undef snd_pcm_sw_params_set_tstamp_mode
+#undef snd_pcm_sw_params_get_tstamp_mode
+#undef snd_pcm_sw_params_set_avail_min
+#undef snd_pcm_sw_params_get_avail_min
+#undef snd_pcm_sw_params_set_period_event
+#undef snd_pcm_sw_params_get_period_event
+#undef snd_pcm_sw_params_set_start_threshold
+#undef snd_pcm_sw_params_get_start_threshold
+#undef snd_pcm_sw_params_set_stop_threshold
+#undef snd_pcm_sw_params_get_stop_threshold
+#undef snd_pcm_sw_params_set_silence_threshold
+#undef snd_pcm_sw_params_get_silence_threshold
+#undef snd_pcm_sw_params_set_silence_size
+#undef snd_pcm_sw_params_get_silence_size
+#undef snd_pcm_access_mask_sizeof
+#undef snd_pcm_access_mask_malloc
+#undef snd_pcm_access_mask_free
+#undef snd_pcm_access_mask_copy
+#undef snd_pcm_access_mask_none
+#undef snd_pcm_access_mask_any
+#undef snd_pcm_access_mask_test
+#undef snd_pcm_access_mask_empty
+#undef snd_pcm_access_mask_set
+#undef snd_pcm_access_mask_reset
+#undef snd_pcm_format_mask_sizeof
+#undef snd_pcm_format_mask_malloc
+#undef snd_pcm_format_mask_free
+#undef snd_pcm_format_mask_copy
+#undef snd_pcm_format_mask_none
+#undef snd_pcm_format_mask_any
+#undef snd_pcm_format_mask_test
+#undef snd_pcm_format_mask_empty
+#undef snd_pcm_format_mask_set
+#undef snd_pcm_format_mask_reset
+#undef snd_pcm_subformat_mask_sizeof
+#undef snd_pcm_subformat_mask_malloc
+#undef snd_pcm_subformat_mask_free
+#undef snd_pcm_subformat_mask_copy
+#undef snd_pcm_subformat_mask_none
+#undef snd_pcm_subformat_mask_any
+#undef snd_pcm_subformat_mask_test
+#undef snd_pcm_subformat_mask_empty
+#undef snd_pcm_subformat_mask_set
+#undef snd_pcm_subformat_mask_reset
+#undef snd_pcm_status_sizeof
+#undef snd_pcm_status_malloc
+#undef snd_pcm_status_free
+#undef snd_pcm_status_copy
+#undef snd_pcm_status_get_state
+#undef snd_pcm_status_get_trigger_tstamp
+#undef snd_pcm_status_get_trigger_htstamp
+#undef snd_pcm_status_get_tstamp
+#undef snd_pcm_status_get_htstamp
+#undef snd_pcm_status_get_audio_htstamp
+#undef snd_pcm_status_get_driver_htstamp
+#undef snd_pcm_status_get_delay
+#undef snd_pcm_status_get_avail
+#undef snd_pcm_status_get_avail_max
+#undef snd_pcm_status_get_overrange
+#undef snd_pcm_type_name
+#undef snd_pcm_stream_name
+#undef snd_pcm_access_name
+#undef snd_pcm_format_name
+#undef snd_pcm_format_description
+#undef snd_pcm_subformat_name
+#undef snd_pcm_subformat_description
+#undef snd_pcm_format_value
+#undef snd_pcm_tstamp_mode_name
+#undef snd_pcm_state_name
+#undef snd_pcm_dump
+#undef snd_pcm_dump_hw_setup
+#undef snd_pcm_dump_sw_setup
+#undef snd_pcm_dump_setup
+#undef snd_pcm_hw_params_dump
+#undef snd_pcm_sw_params_dump
+#undef snd_pcm_status_dump
+#undef snd_pcm_mmap_begin
+#undef snd_pcm_mmap_commit
+#undef snd_pcm_mmap_writei
+#undef snd_pcm_mmap_readi
+#undef snd_pcm_mmap_writen
+#undef snd_pcm_mmap_readn
+#undef snd_pcm_format_signed
+#undef snd_pcm_format_unsigned
+#undef snd_pcm_format_linear
+#undef snd_pcm_format_float
+#undef snd_pcm_format_little_endian
+#undef snd_pcm_format_big_endian
+#undef snd_pcm_format_cpu_endian
+#undef snd_pcm_format_width
+#undef snd_pcm_format_physical_width
+#undef snd_pcm_build_linear_format
+#undef snd_pcm_format_size
+#undef snd_pcm_format_silence
+#undef snd_pcm_format_silence_16
+#undef snd_pcm_format_silence_32
+#undef snd_pcm_format_silence_64
+#undef snd_pcm_format_set_silence
+#undef snd_pcm_bytes_to_frames
+#undef snd_pcm_frames_to_bytes
+#undef snd_pcm_bytes_to_samples
+#undef snd_pcm_samples_to_bytes
+#undef snd_pcm_area_silence
+#undef snd_pcm_areas_silence
+#undef snd_pcm_area_copy
+#undef snd_pcm_areas_copy
+#undef snd_pcm_areas_copy_wrap
+#undef snd_pcm_hook_get_pcm
+#undef snd_pcm_hook_get_private
+#undef snd_pcm_hook_set_private
+#undef snd_pcm_hook_add
+#undef snd_pcm_hook_remove
+#undef snd_pcm_meter_get_bufsize
+#undef snd_pcm_meter_get_channels
+#undef snd_pcm_meter_get_rate
+#undef snd_pcm_meter_get_now
+#undef snd_pcm_meter_get_boundary
+#undef snd_pcm_meter_add_scope
+#undef snd_pcm_meter_search_scope
+#undef snd_pcm_scope_malloc
+#undef snd_pcm_scope_set_ops
+#undef snd_pcm_scope_set_name
+#undef snd_pcm_scope_get_name
+#undef snd_pcm_scope_get_callback_private
+#undef snd_pcm_scope_set_callback_private
+#undef snd_pcm_scope_s16_open
+#undef snd_pcm_scope_s16_get_channel_buffer
+#undef snd_spcm_init
+#undef snd_spcm_init_duplex
+#undef snd_spcm_init_get_params
+#undef snd_pcm_start_mode_name
+#undef snd_pcm_xrun_mode_name
+#undef snd_pcm_sw_params_set_start_mode
+#undef snd_pcm_sw_params_get_start_mode
+#undef snd_pcm_sw_params_set_xrun_mode
+#undef snd_pcm_sw_params_get_xrun_mode
+#undef snd_pcm_sw_params_set_xfer_align
+#undef snd_pcm_sw_params_get_xfer_align
+#undef snd_pcm_sw_params_set_sleep_min
+#undef snd_pcm_sw_params_get_sleep_min
+#undef snd_pcm_hw_params_get_tick_time
+#undef snd_pcm_hw_params_get_tick_time_min
+#undef snd_pcm_hw_params_get_tick_time_max
+#undef snd_pcm_hw_params_test_tick_time
+#undef snd_pcm_hw_params_set_tick_time
+#undef snd_pcm_hw_params_set_tick_time_min
+#undef snd_pcm_hw_params_set_tick_time_max
+#undef snd_pcm_hw_params_set_tick_time_minmax
+#undef snd_pcm_hw_params_set_tick_time_near
+#undef snd_pcm_hw_params_set_tick_time_first
+#undef snd_pcm_hw_params_set_tick_time_last
+#undef snd_rawmidi_open
+#undef snd_rawmidi_open_lconf
+#undef snd_rawmidi_close
+#undef snd_rawmidi_poll_descriptors_count
+#undef snd_rawmidi_poll_descriptors
+#undef snd_rawmidi_poll_descriptors_revents
+#undef snd_rawmidi_nonblock
+#undef snd_rawmidi_info_sizeof
+#undef snd_rawmidi_info_malloc
+#undef snd_rawmidi_info_free
+#undef snd_rawmidi_info_copy
+#undef snd_rawmidi_info_get_device
+#undef snd_rawmidi_info_get_subdevice
+#undef snd_rawmidi_info_get_stream
+#undef snd_rawmidi_info_get_card
+#undef snd_rawmidi_info_get_flags
+#undef snd_rawmidi_info_get_id
+#undef snd_rawmidi_info_get_name
+#undef snd_rawmidi_info_get_subdevice_name
+#undef snd_rawmidi_info_get_subdevices_count
+#undef snd_rawmidi_info_get_subdevices_avail
+#undef snd_rawmidi_info_set_device
+#undef snd_rawmidi_info_set_subdevice
+#undef snd_rawmidi_info_set_stream
+#undef snd_rawmidi_info
+#undef snd_rawmidi_params_sizeof
+#undef snd_rawmidi_params_malloc
+#undef snd_rawmidi_params_free
+#undef snd_rawmidi_params_copy
+#undef snd_rawmidi_params_set_buffer_size
+#undef snd_rawmidi_params_get_buffer_size
+#undef snd_rawmidi_params_set_avail_min
+#undef snd_rawmidi_params_get_avail_min
+#undef snd_rawmidi_params_set_no_active_sensing
+#undef snd_rawmidi_params_get_no_active_sensing
+#undef snd_rawmidi_params
+#undef snd_rawmidi_params_current
+#undef snd_rawmidi_status_sizeof
+#undef snd_rawmidi_status_malloc
+#undef snd_rawmidi_status_free
+#undef snd_rawmidi_status_copy
+#undef snd_rawmidi_status_get_tstamp
+#undef snd_rawmidi_status_get_avail
+#undef snd_rawmidi_status_get_xruns
+#undef snd_rawmidi_status
+#undef snd_rawmidi_drain
+#undef snd_rawmidi_drop
+#undef snd_rawmidi_write
+#undef snd_rawmidi_read
+#undef snd_rawmidi_name
+#undef snd_rawmidi_type
+#undef snd_rawmidi_stream
+#undef snd_timer_query_open
+#undef snd_timer_query_open_lconf
+#undef snd_timer_query_close
+#undef snd_timer_query_next_device
+#undef snd_timer_query_info
+#undef snd_timer_query_params
+#undef snd_timer_query_status
+#undef snd_timer_open
+#undef snd_timer_open_lconf
+#undef snd_timer_close
+#undef snd_async_add_timer_handler
+#undef snd_async_handler_get_timer
+#undef snd_timer_poll_descriptors_count
+#undef snd_timer_poll_descriptors
+#undef snd_timer_poll_descriptors_revents
+#undef snd_timer_info
+#undef snd_timer_params
+#undef snd_timer_status
+#undef snd_timer_start
+#undef snd_timer_stop
+#undef snd_timer_continue
+#undef snd_timer_read
+#undef snd_timer_id_sizeof
+#undef snd_timer_id_malloc
+#undef snd_timer_id_free
+#undef snd_timer_id_copy
+#undef snd_timer_id_set_class
+#undef snd_timer_id_get_class
+#undef snd_timer_id_set_sclass
+#undef snd_timer_id_get_sclass
+#undef snd_timer_id_set_card
+#undef snd_timer_id_get_card
+#undef snd_timer_id_set_device
+#undef snd_timer_id_get_device
+#undef snd_timer_id_set_subdevice
+#undef snd_timer_id_get_subdevice
+#undef snd_timer_ginfo_sizeof
+#undef snd_timer_ginfo_malloc
+#undef snd_timer_ginfo_free
+#undef snd_timer_ginfo_copy
+#undef snd_timer_ginfo_set_tid
+#undef snd_timer_ginfo_get_tid
+#undef snd_timer_ginfo_get_flags
+#undef snd_timer_ginfo_get_card
+#undef snd_timer_ginfo_get_id
+#undef snd_timer_ginfo_get_name
+#undef snd_timer_ginfo_get_resolution
+#undef snd_timer_ginfo_get_resolution_min
+#undef snd_timer_ginfo_get_resolution_max
+#undef snd_timer_ginfo_get_clients
+#undef snd_timer_info_sizeof
+#undef snd_timer_info_malloc
+#undef snd_timer_info_free
+#undef snd_timer_info_copy
+#undef snd_timer_info_is_slave
+#undef snd_timer_info_get_card
+#undef snd_timer_info_get_id
+#undef snd_timer_info_get_name
+#undef snd_timer_info_get_resolution
+#undef snd_timer_params_sizeof
+#undef snd_timer_params_malloc
+#undef snd_timer_params_free
+#undef snd_timer_params_copy
+#undef snd_timer_params_set_auto_start
+#undef snd_timer_params_get_auto_start
+#undef snd_timer_params_set_exclusive
+#undef snd_timer_params_get_exclusive
+#undef snd_timer_params_set_early_event
+#undef snd_timer_params_get_early_event
+#undef snd_timer_params_set_ticks
+#undef snd_timer_params_get_ticks
+#undef snd_timer_params_set_queue_size
+#undef snd_timer_params_get_queue_size
+#undef snd_timer_params_set_filter
+#undef snd_timer_params_get_filter
+#undef snd_timer_status_sizeof
+#undef snd_timer_status_malloc
+#undef snd_timer_status_free
+#undef snd_timer_status_copy
+#undef snd_timer_status_get_timestamp
+#undef snd_timer_status_get_resolution
+#undef snd_timer_status_get_lost
+#undef snd_timer_status_get_overrun
+#undef snd_timer_status_get_queue
+#undef snd_timer_info_get_ticks
+#undef snd_hwdep_open
+#undef snd_hwdep_close
+#undef snd_hwdep_poll_descriptors
+#undef snd_hwdep_poll_descriptors_count
+#undef snd_hwdep_poll_descriptors_revents
+#undef snd_hwdep_nonblock
+#undef snd_hwdep_info
+#undef snd_hwdep_dsp_status
+#undef snd_hwdep_dsp_load
+#undef snd_hwdep_ioctl
+#undef snd_hwdep_write
+#undef snd_hwdep_read
+#undef snd_hwdep_info_sizeof
+#undef snd_hwdep_info_malloc
+#undef snd_hwdep_info_free
+#undef snd_hwdep_info_copy
+#undef snd_hwdep_info_get_device
+#undef snd_hwdep_info_get_card
+#undef snd_hwdep_info_get_id
+#undef snd_hwdep_info_get_name
+#undef snd_hwdep_info_get_iface
+#undef snd_hwdep_info_set_device
+#undef snd_hwdep_dsp_status_sizeof
+#undef snd_hwdep_dsp_status_malloc
+#undef snd_hwdep_dsp_status_free
+#undef snd_hwdep_dsp_status_copy
+#undef snd_hwdep_dsp_status_get_version
+#undef snd_hwdep_dsp_status_get_id
+#undef snd_hwdep_dsp_status_get_num_dsps
+#undef snd_hwdep_dsp_status_get_dsp_loaded
+#undef snd_hwdep_dsp_status_get_chip_ready
+#undef snd_hwdep_dsp_image_sizeof
+#undef snd_hwdep_dsp_image_malloc
+#undef snd_hwdep_dsp_image_free
+#undef snd_hwdep_dsp_image_copy
+#undef snd_hwdep_dsp_image_get_index
+#undef snd_hwdep_dsp_image_get_name
+#undef snd_hwdep_dsp_image_get_image
+#undef snd_hwdep_dsp_image_get_length
+#undef snd_hwdep_dsp_image_set_index
+#undef snd_hwdep_dsp_image_set_name
+#undef snd_hwdep_dsp_image_set_image
+#undef snd_hwdep_dsp_image_set_length
+#undef snd_card_load
+#undef snd_card_next
+#undef snd_card_get_index
+#undef snd_card_get_name
+#undef snd_card_get_longname
+#undef snd_device_name_hint
+#undef snd_device_name_free_hint
+#undef snd_device_name_get_hint
+#undef snd_ctl_open
+#undef snd_ctl_open_lconf
+#undef snd_ctl_open_fallback
+#undef snd_ctl_close
+#undef snd_ctl_nonblock
+#undef snd_async_add_ctl_handler
+#undef snd_async_handler_get_ctl
+#undef snd_ctl_poll_descriptors_count
+#undef snd_ctl_poll_descriptors
+#undef snd_ctl_poll_descriptors_revents
+#undef snd_ctl_subscribe_events
+#undef snd_ctl_card_info
+#undef snd_ctl_elem_list
+#undef snd_ctl_elem_info
+#undef snd_ctl_elem_read
+#undef snd_ctl_elem_write
+#undef snd_ctl_elem_lock
+#undef snd_ctl_elem_unlock
+#undef snd_ctl_elem_tlv_read
+#undef snd_ctl_elem_tlv_write
+#undef snd_ctl_elem_tlv_command
+#undef snd_ctl_hwdep_next_device
+#undef snd_ctl_hwdep_info
+#undef snd_ctl_pcm_next_device
+#undef snd_ctl_pcm_info
+#undef snd_ctl_pcm_prefer_subdevice
+#undef snd_ctl_rawmidi_next_device
+#undef snd_ctl_rawmidi_info
+#undef snd_ctl_rawmidi_prefer_subdevice
+#undef snd_ctl_set_power_state
+#undef snd_ctl_get_power_state
+#undef snd_ctl_read
+#undef snd_ctl_wait
+#undef snd_ctl_name
+#undef snd_ctl_type
+#undef snd_ctl_elem_type_name
+#undef snd_ctl_elem_iface_name
+#undef snd_ctl_event_type_name
+#undef snd_ctl_event_elem_get_mask
+#undef snd_ctl_event_elem_get_numid
+#undef snd_ctl_event_elem_get_id
+#undef snd_ctl_event_elem_get_interface
+#undef snd_ctl_event_elem_get_device
+#undef snd_ctl_event_elem_get_subdevice
+#undef snd_ctl_event_elem_get_name
+#undef snd_ctl_event_elem_get_index
+#undef snd_ctl_elem_list_alloc_space
+#undef snd_ctl_elem_list_free_space
+#undef snd_ctl_ascii_elem_id_get
+#undef snd_ctl_ascii_elem_id_parse
+#undef snd_ctl_ascii_value_parse
+#undef snd_ctl_elem_id_sizeof
+#undef snd_ctl_elem_id_malloc
+#undef snd_ctl_elem_id_free
+#undef snd_ctl_elem_id_clear
+#undef snd_ctl_elem_id_copy
+#undef snd_ctl_elem_id_get_numid
+#undef snd_ctl_elem_id_get_interface
+#undef snd_ctl_elem_id_get_device
+#undef snd_ctl_elem_id_get_subdevice
+#undef snd_ctl_elem_id_get_name
+#undef snd_ctl_elem_id_get_index
+#undef snd_ctl_elem_id_set_numid
+#undef snd_ctl_elem_id_set_interface
+#undef snd_ctl_elem_id_set_device
+#undef snd_ctl_elem_id_set_subdevice
+#undef snd_ctl_elem_id_set_name
+#undef snd_ctl_elem_id_set_index
+#undef snd_ctl_card_info_sizeof
+#undef snd_ctl_card_info_malloc
+#undef snd_ctl_card_info_free
+#undef snd_ctl_card_info_clear
+#undef snd_ctl_card_info_copy
+#undef snd_ctl_card_info_get_card
+#undef snd_ctl_card_info_get_id
+#undef snd_ctl_card_info_get_driver
+#undef snd_ctl_card_info_get_name
+#undef snd_ctl_card_info_get_longname
+#undef snd_ctl_card_info_get_mixername
+#undef snd_ctl_card_info_get_components
+#undef snd_ctl_event_sizeof
+#undef snd_ctl_event_malloc
+#undef snd_ctl_event_free
+#undef snd_ctl_event_clear
+#undef snd_ctl_event_copy
+#undef snd_ctl_event_get_type
+#undef snd_ctl_elem_list_sizeof
+#undef snd_ctl_elem_list_malloc
+#undef snd_ctl_elem_list_free
+#undef snd_ctl_elem_list_clear
+#undef snd_ctl_elem_list_copy
+#undef snd_ctl_elem_list_set_offset
+#undef snd_ctl_elem_list_get_used
+#undef snd_ctl_elem_list_get_count
+#undef snd_ctl_elem_list_get_id
+#undef snd_ctl_elem_list_get_numid
+#undef snd_ctl_elem_list_get_interface
+#undef snd_ctl_elem_list_get_device
+#undef snd_ctl_elem_list_get_subdevice
+#undef snd_ctl_elem_list_get_name
+#undef snd_ctl_elem_list_get_index
+#undef snd_ctl_elem_info_sizeof
+#undef snd_ctl_elem_info_malloc
+#undef snd_ctl_elem_info_free
+#undef snd_ctl_elem_info_clear
+#undef snd_ctl_elem_info_copy
+#undef snd_ctl_elem_info_get_type
+#undef snd_ctl_elem_info_is_readable
+#undef snd_ctl_elem_info_is_writable
+#undef snd_ctl_elem_info_is_volatile
+#undef snd_ctl_elem_info_is_inactive
+#undef snd_ctl_elem_info_is_locked
+#undef snd_ctl_elem_info_is_tlv_readable
+#undef snd_ctl_elem_info_is_tlv_writable
+#undef snd_ctl_elem_info_is_tlv_commandable
+#undef snd_ctl_elem_info_is_owner
+#undef snd_ctl_elem_info_is_user
+#undef snd_ctl_elem_info_get_owner
+#undef snd_ctl_elem_info_get_count
+#undef snd_ctl_elem_info_get_min
+#undef snd_ctl_elem_info_get_max
+#undef snd_ctl_elem_info_get_step
+#undef snd_ctl_elem_info_get_min64
+#undef snd_ctl_elem_info_get_max64
+#undef snd_ctl_elem_info_get_step64
+#undef snd_ctl_elem_info_get_items
+#undef snd_ctl_elem_info_set_item
+#undef snd_ctl_elem_info_get_item_name
+#undef snd_ctl_elem_info_get_dimensions
+#undef snd_ctl_elem_info_get_dimension
+#undef snd_ctl_elem_info_set_dimension
+#undef snd_ctl_elem_info_get_id
+#undef snd_ctl_elem_info_get_numid
+#undef snd_ctl_elem_info_get_interface
+#undef snd_ctl_elem_info_get_device
+#undef snd_ctl_elem_info_get_subdevice
+#undef snd_ctl_elem_info_get_name
+#undef snd_ctl_elem_info_get_index
+#undef snd_ctl_elem_info_set_id
+#undef snd_ctl_elem_info_set_numid
+#undef snd_ctl_elem_info_set_interface
+#undef snd_ctl_elem_info_set_device
+#undef snd_ctl_elem_info_set_subdevice
+#undef snd_ctl_elem_info_set_name
+#undef snd_ctl_elem_info_set_index
+#undef snd_ctl_add_integer_elem_set
+#undef snd_ctl_add_integer64_elem_set
+#undef snd_ctl_add_boolean_elem_set
+#undef snd_ctl_add_enumerated_elem_set
+#undef snd_ctl_add_bytes_elem_set
+#undef snd_ctl_elem_add_integer
+#undef snd_ctl_elem_add_integer64
+#undef snd_ctl_elem_add_boolean
+#undef snd_ctl_elem_add_enumerated
+#undef snd_ctl_elem_add_iec958
+#undef snd_ctl_elem_remove
+#undef snd_ctl_elem_value_sizeof
+#undef snd_ctl_elem_value_malloc
+#undef snd_ctl_elem_value_free
+#undef snd_ctl_elem_value_clear
+#undef snd_ctl_elem_value_copy
+#undef snd_ctl_elem_value_compare
+#undef snd_ctl_elem_value_get_id
+#undef snd_ctl_elem_value_get_numid
+#undef snd_ctl_elem_value_get_interface
+#undef snd_ctl_elem_value_get_device
+#undef snd_ctl_elem_value_get_subdevice
+#undef snd_ctl_elem_value_get_name
+#undef snd_ctl_elem_value_get_index
+#undef snd_ctl_elem_value_set_id
+#undef snd_ctl_elem_value_set_numid
+#undef snd_ctl_elem_value_set_interface
+#undef snd_ctl_elem_value_set_device
+#undef snd_ctl_elem_value_set_subdevice
+#undef snd_ctl_elem_value_set_name
+#undef snd_ctl_elem_value_set_index
+#undef snd_ctl_elem_value_get_boolean
+#undef snd_ctl_elem_value_get_integer
+#undef snd_ctl_elem_value_get_integer64
+#undef snd_ctl_elem_value_get_enumerated
+#undef snd_ctl_elem_value_get_byte
+#undef snd_ctl_elem_value_set_boolean
+#undef snd_ctl_elem_value_set_integer
+#undef snd_ctl_elem_value_set_integer64
+#undef snd_ctl_elem_value_set_enumerated
+#undef snd_ctl_elem_value_set_byte
+#undef snd_ctl_elem_set_bytes
+#undef snd_ctl_elem_value_get_bytes
+#undef snd_ctl_elem_value_get_iec958
+#undef snd_ctl_elem_value_set_iec958
+#undef snd_tlv_parse_dB_info
+#undef snd_tlv_get_dB_range
+#undef snd_tlv_convert_to_dB
+#undef snd_tlv_convert_from_dB
+#undef snd_ctl_get_dB_range
+#undef snd_ctl_convert_to_dB
+#undef snd_ctl_convert_from_dB
+#undef snd_hctl_compare_fast
+#undef snd_hctl_open
+#undef snd_hctl_open_ctl
+#undef snd_hctl_close
+#undef snd_hctl_nonblock
+#undef snd_hctl_poll_descriptors_count
+#undef snd_hctl_poll_descriptors
+#undef snd_hctl_poll_descriptors_revents
+#undef snd_hctl_get_count
+#undef snd_hctl_set_compare
+#undef snd_hctl_first_elem
+#undef snd_hctl_last_elem
+#undef snd_hctl_find_elem
+#undef snd_hctl_set_callback
+#undef snd_hctl_set_callback_private
+#undef snd_hctl_get_callback_private
+#undef snd_hctl_load
+#undef snd_hctl_free
+#undef snd_hctl_handle_events
+#undef snd_hctl_name
+#undef snd_hctl_wait
+#undef snd_hctl_ctl
+#undef snd_hctl_elem_next
+#undef snd_hctl_elem_prev
+#undef snd_hctl_elem_info
+#undef snd_hctl_elem_read
+#undef snd_hctl_elem_write
+#undef snd_hctl_elem_tlv_read
+#undef snd_hctl_elem_tlv_write
+#undef snd_hctl_elem_tlv_command
+#undef snd_hctl_elem_get_hctl
+#undef snd_hctl_elem_get_id
+#undef snd_hctl_elem_get_numid
+#undef snd_hctl_elem_get_interface
+#undef snd_hctl_elem_get_device
+#undef snd_hctl_elem_get_subdevice
+#undef snd_hctl_elem_get_name
+#undef snd_hctl_elem_get_index
+#undef snd_hctl_elem_set_callback
+#undef snd_hctl_elem_get_callback_private
+#undef snd_hctl_elem_set_callback_private
+#undef snd_sctl_build
+#undef snd_sctl_free
+#undef snd_sctl_install
+#undef snd_sctl_remove
+#undef snd_mixer_open
+#undef snd_mixer_close
+#undef snd_mixer_first_elem
+#undef snd_mixer_last_elem
+#undef snd_mixer_handle_events
+#undef snd_mixer_attach
+#undef snd_mixer_attach_hctl
+#undef snd_mixer_detach
+#undef snd_mixer_detach_hctl
+#undef snd_mixer_get_hctl
+#undef snd_mixer_poll_descriptors_count
+#undef snd_mixer_poll_descriptors
+#undef snd_mixer_poll_descriptors_revents
+#undef snd_mixer_load
+#undef snd_mixer_free
+#undef snd_mixer_wait
+#undef snd_mixer_set_compare
+#undef snd_mixer_set_callback
+#undef snd_mixer_get_callback_private
+#undef snd_mixer_set_callback_private
+#undef snd_mixer_get_count
+#undef snd_mixer_class_unregister
+#undef snd_mixer_elem_next
+#undef snd_mixer_elem_prev
+#undef snd_mixer_elem_set_callback
+#undef snd_mixer_elem_get_callback_private
+#undef snd_mixer_elem_set_callback_private
+#undef snd_mixer_elem_get_type
+#undef snd_mixer_class_register
+#undef snd_mixer_elem_new
+#undef snd_mixer_elem_add
+#undef snd_mixer_elem_remove
+#undef snd_mixer_elem_free
+#undef snd_mixer_elem_info
+#undef snd_mixer_elem_value
+#undef snd_mixer_elem_attach
+#undef snd_mixer_elem_detach
+#undef snd_mixer_elem_empty
+#undef snd_mixer_elem_get_private
+#undef snd_mixer_class_sizeof
+#undef snd_mixer_class_malloc
+#undef snd_mixer_class_free
+#undef snd_mixer_class_copy
+#undef snd_mixer_class_get_mixer
+#undef snd_mixer_class_get_event
+#undef snd_mixer_class_get_private
+#undef snd_mixer_class_get_compare
+#undef snd_mixer_class_set_event
+#undef snd_mixer_class_set_private
+#undef snd_mixer_class_set_private_free
+#undef snd_mixer_class_set_compare
+#undef snd_mixer_selem_channel_name
+#undef snd_mixer_selem_register
+#undef snd_mixer_selem_get_id
+#undef snd_mixer_selem_get_name
+#undef snd_mixer_selem_get_index
+#undef snd_mixer_find_selem
+#undef snd_mixer_selem_is_active
+#undef snd_mixer_selem_is_playback_mono
+#undef snd_mixer_selem_has_playback_channel
+#undef snd_mixer_selem_is_capture_mono
+#undef snd_mixer_selem_has_capture_channel
+#undef snd_mixer_selem_get_capture_group
+#undef snd_mixer_selem_has_common_volume
+#undef snd_mixer_selem_has_playback_volume
+#undef snd_mixer_selem_has_playback_volume_joined
+#undef snd_mixer_selem_has_capture_volume
+#undef snd_mixer_selem_has_capture_volume_joined
+#undef snd_mixer_selem_has_common_switch
+#undef snd_mixer_selem_has_playback_switch
+#undef snd_mixer_selem_has_playback_switch_joined
+#undef snd_mixer_selem_has_capture_switch
+#undef snd_mixer_selem_has_capture_switch_joined
+#undef snd_mixer_selem_has_capture_switch_exclusive
+#undef snd_mixer_selem_ask_playback_vol_dB
+#undef snd_mixer_selem_ask_capture_vol_dB
+#undef snd_mixer_selem_ask_playback_dB_vol
+#undef snd_mixer_selem_ask_capture_dB_vol
+#undef snd_mixer_selem_get_playback_volume
+#undef snd_mixer_selem_get_capture_volume
+#undef snd_mixer_selem_get_playback_dB
+#undef snd_mixer_selem_get_capture_dB
+#undef snd_mixer_selem_get_playback_switch
+#undef snd_mixer_selem_get_capture_switch
+#undef snd_mixer_selem_set_playback_volume
+#undef snd_mixer_selem_set_capture_volume
+#undef snd_mixer_selem_set_playback_dB
+#undef snd_mixer_selem_set_capture_dB
+#undef snd_mixer_selem_set_playback_volume_all
+#undef snd_mixer_selem_set_capture_volume_all
+#undef snd_mixer_selem_set_playback_dB_all
+#undef snd_mixer_selem_set_capture_dB_all
+#undef snd_mixer_selem_set_playback_switch
+#undef snd_mixer_selem_set_capture_switch
+#undef snd_mixer_selem_set_playback_switch_all
+#undef snd_mixer_selem_set_capture_switch_all
+#undef snd_mixer_selem_get_playback_volume_range
+#undef snd_mixer_selem_get_playback_dB_range
+#undef snd_mixer_selem_set_playback_volume_range
+#undef snd_mixer_selem_get_capture_volume_range
+#undef snd_mixer_selem_get_capture_dB_range
+#undef snd_mixer_selem_set_capture_volume_range
+#undef snd_mixer_selem_is_enumerated
+#undef snd_mixer_selem_is_enum_playback
+#undef snd_mixer_selem_is_enum_capture
+#undef snd_mixer_selem_get_enum_items
+#undef snd_mixer_selem_get_enum_item_name
+#undef snd_mixer_selem_get_enum_item
+#undef snd_mixer_selem_set_enum_item
+#undef snd_mixer_selem_id_sizeof
+#undef snd_mixer_selem_id_malloc
+#undef snd_mixer_selem_id_free
+#undef snd_mixer_selem_id_copy
+#undef snd_mixer_selem_id_get_name
+#undef snd_mixer_selem_id_get_index
+#undef snd_mixer_selem_id_set_name
+#undef snd_mixer_selem_id_set_index
+#undef snd_mixer_selem_id_parse
+#undef snd_seq_open
+#undef snd_seq_open_lconf
+#undef snd_seq_name
+#undef snd_seq_type
+#undef snd_seq_close
+#undef snd_seq_poll_descriptors_count
+#undef snd_seq_poll_descriptors
+#undef snd_seq_poll_descriptors_revents
+#undef snd_seq_nonblock
+#undef snd_seq_client_id
+#undef snd_seq_get_output_buffer_size
+#undef snd_seq_get_input_buffer_size
+#undef snd_seq_set_output_buffer_size
+#undef snd_seq_set_input_buffer_size
+#undef snd_seq_system_info_sizeof
+#undef snd_seq_system_info_malloc
+#undef snd_seq_system_info_free
+#undef snd_seq_system_info_copy
+#undef snd_seq_system_info_get_queues
+#undef snd_seq_system_info_get_clients
+#undef snd_seq_system_info_get_ports
+#undef snd_seq_system_info_get_channels
+#undef snd_seq_system_info_get_cur_clients
+#undef snd_seq_system_info_get_cur_queues
+#undef snd_seq_system_info
+#undef snd_seq_client_info_sizeof
+#undef snd_seq_client_info_malloc
+#undef snd_seq_client_info_free
+#undef snd_seq_client_info_copy
+#undef snd_seq_client_info_get_client
+#undef snd_seq_client_info_get_type
+#undef snd_seq_client_info_get_name
+#undef snd_seq_client_info_get_broadcast_filter
+#undef snd_seq_client_info_get_error_bounce
+#undef snd_seq_client_info_get_card
+#undef snd_seq_client_info_get_pid
+#undef snd_seq_client_info_get_event_filter
+#undef snd_seq_client_info_get_num_ports
+#undef snd_seq_client_info_get_event_lost
+#undef snd_seq_client_info_set_client
+#undef snd_seq_client_info_set_name
+#undef snd_seq_client_info_set_broadcast_filter
+#undef snd_seq_client_info_set_error_bounce
+#undef snd_seq_client_info_set_event_filter
+#undef snd_seq_client_info_event_filter_clear
+#undef snd_seq_client_info_event_filter_add
+#undef snd_seq_client_info_event_filter_del
+#undef snd_seq_client_info_event_filter_check
+#undef snd_seq_get_client_info
+#undef snd_seq_get_any_client_info
+#undef snd_seq_set_client_info
+#undef snd_seq_query_next_client
+#undef snd_seq_client_pool_sizeof
+#undef snd_seq_client_pool_malloc
+#undef snd_seq_client_pool_free
+#undef snd_seq_client_pool_copy
+#undef snd_seq_client_pool_get_client
+#undef snd_seq_client_pool_get_output_pool
+#undef snd_seq_client_pool_get_input_pool
+#undef snd_seq_client_pool_get_output_room
+#undef snd_seq_client_pool_get_output_free
+#undef snd_seq_client_pool_get_input_free
+#undef snd_seq_client_pool_set_output_pool
+#undef snd_seq_client_pool_set_input_pool
+#undef snd_seq_client_pool_set_output_room
+#undef snd_seq_get_client_pool
+#undef snd_seq_set_client_pool
+#undef snd_seq_port_info_sizeof
+#undef snd_seq_port_info_malloc
+#undef snd_seq_port_info_free
+#undef snd_seq_port_info_copy
+#undef snd_seq_port_info_get_client
+#undef snd_seq_port_info_get_port
+#undef snd_seq_port_info_get_addr
+#undef snd_seq_port_info_get_name
+#undef snd_seq_port_info_get_capability
+#undef snd_seq_port_info_get_type
+#undef snd_seq_port_info_get_midi_channels
+#undef snd_seq_port_info_get_midi_voices
+#undef snd_seq_port_info_get_synth_voices
+#undef snd_seq_port_info_get_read_use
+#undef snd_seq_port_info_get_write_use
+#undef snd_seq_port_info_get_port_specified
+#undef snd_seq_port_info_get_timestamping
+#undef snd_seq_port_info_get_timestamp_real
+#undef snd_seq_port_info_get_timestamp_queue
+#undef snd_seq_port_info_set_client
+#undef snd_seq_port_info_set_port
+#undef snd_seq_port_info_set_addr
+#undef snd_seq_port_info_set_name
+#undef snd_seq_port_info_set_capability
+#undef snd_seq_port_info_set_type
+#undef snd_seq_port_info_set_midi_channels
+#undef snd_seq_port_info_set_midi_voices
+#undef snd_seq_port_info_set_synth_voices
+#undef snd_seq_port_info_set_port_specified
+#undef snd_seq_port_info_set_timestamping
+#undef snd_seq_port_info_set_timestamp_real
+#undef snd_seq_port_info_set_timestamp_queue
+#undef snd_seq_create_port
+#undef snd_seq_delete_port
+#undef snd_seq_get_port_info
+#undef snd_seq_get_any_port_info
+#undef snd_seq_set_port_info
+#undef snd_seq_query_next_port
+#undef snd_seq_port_subscribe_sizeof
+#undef snd_seq_port_subscribe_malloc
+#undef snd_seq_port_subscribe_free
+#undef snd_seq_port_subscribe_copy
+#undef snd_seq_port_subscribe_get_sender
+#undef snd_seq_port_subscribe_get_dest
+#undef snd_seq_port_subscribe_get_queue
+#undef snd_seq_port_subscribe_get_exclusive
+#undef snd_seq_port_subscribe_get_time_update
+#undef snd_seq_port_subscribe_get_time_real
+#undef snd_seq_port_subscribe_set_sender
+#undef snd_seq_port_subscribe_set_dest
+#undef snd_seq_port_subscribe_set_queue
+#undef snd_seq_port_subscribe_set_exclusive
+#undef snd_seq_port_subscribe_set_time_update
+#undef snd_seq_port_subscribe_set_time_real
+#undef snd_seq_get_port_subscription
+#undef snd_seq_subscribe_port
+#undef snd_seq_unsubscribe_port
+#undef snd_seq_query_subscribe_sizeof
+#undef snd_seq_query_subscribe_malloc
+#undef snd_seq_query_subscribe_free
+#undef snd_seq_query_subscribe_copy
+#undef snd_seq_query_subscribe_get_client
+#undef snd_seq_query_subscribe_get_port
+#undef snd_seq_query_subscribe_get_root
+#undef snd_seq_query_subscribe_get_type
+#undef snd_seq_query_subscribe_get_index
+#undef snd_seq_query_subscribe_get_num_subs
+#undef snd_seq_query_subscribe_get_addr
+#undef snd_seq_query_subscribe_get_queue
+#undef snd_seq_query_subscribe_get_exclusive
+#undef snd_seq_query_subscribe_get_time_update
+#undef snd_seq_query_subscribe_get_time_real
+#undef snd_seq_query_subscribe_set_client
+#undef snd_seq_query_subscribe_set_port
+#undef snd_seq_query_subscribe_set_root
+#undef snd_seq_query_subscribe_set_type
+#undef snd_seq_query_subscribe_set_index
+#undef snd_seq_query_port_subscribers
+#undef snd_seq_queue_info_sizeof
+#undef snd_seq_queue_info_malloc
+#undef snd_seq_queue_info_free
+#undef snd_seq_queue_info_copy
+#undef snd_seq_queue_info_get_queue
+#undef snd_seq_queue_info_get_name
+#undef snd_seq_queue_info_get_owner
+#undef snd_seq_queue_info_get_locked
+#undef snd_seq_queue_info_get_flags
+#undef snd_seq_queue_info_set_name
+#undef snd_seq_queue_info_set_owner
+#undef snd_seq_queue_info_set_locked
+#undef snd_seq_queue_info_set_flags
+#undef snd_seq_create_queue
+#undef snd_seq_alloc_named_queue
+#undef snd_seq_alloc_queue
+#undef snd_seq_free_queue
+#undef snd_seq_get_queue_info
+#undef snd_seq_set_queue_info
+#undef snd_seq_query_named_queue
+#undef snd_seq_get_queue_usage
+#undef snd_seq_set_queue_usage
+#undef snd_seq_queue_status_sizeof
+#undef snd_seq_queue_status_malloc
+#undef snd_seq_queue_status_free
+#undef snd_seq_queue_status_copy
+#undef snd_seq_queue_status_get_queue
+#undef snd_seq_queue_status_get_events
+#undef snd_seq_queue_status_get_tick_time
+#undef snd_seq_queue_status_get_real_time
+#undef snd_seq_queue_status_get_status
+#undef snd_seq_get_queue_status
+#undef snd_seq_queue_tempo_sizeof
+#undef snd_seq_queue_tempo_malloc
+#undef snd_seq_queue_tempo_free
+#undef snd_seq_queue_tempo_copy
+#undef snd_seq_queue_tempo_get_queue
+#undef snd_seq_queue_tempo_get_tempo
+#undef snd_seq_queue_tempo_get_ppq
+#undef snd_seq_queue_tempo_get_skew
+#undef snd_seq_queue_tempo_get_skew_base
+#undef snd_seq_queue_tempo_set_tempo
+#undef snd_seq_queue_tempo_set_ppq
+#undef snd_seq_queue_tempo_set_skew
+#undef snd_seq_queue_tempo_set_skew_base
+#undef snd_seq_get_queue_tempo
+#undef snd_seq_set_queue_tempo
+#undef snd_seq_queue_timer_sizeof
+#undef snd_seq_queue_timer_malloc
+#undef snd_seq_queue_timer_free
+#undef snd_seq_queue_timer_copy
+#undef snd_seq_queue_timer_get_queue
+#undef snd_seq_queue_timer_get_type
+#undef snd_seq_queue_timer_get_id
+#undef snd_seq_queue_timer_get_resolution
+#undef snd_seq_queue_timer_set_type
+#undef snd_seq_queue_timer_set_id
+#undef snd_seq_queue_timer_set_resolution
+#undef snd_seq_get_queue_timer
+#undef snd_seq_set_queue_timer
+#undef snd_seq_free_event
+#undef snd_seq_event_length
+#undef snd_seq_event_output
+#undef snd_seq_event_output_buffer
+#undef snd_seq_event_output_direct
+#undef snd_seq_event_input
+#undef snd_seq_event_input_pending
+#undef snd_seq_drain_output
+#undef snd_seq_event_output_pending
+#undef snd_seq_extract_output
+#undef snd_seq_drop_output
+#undef snd_seq_drop_output_buffer
+#undef snd_seq_drop_input
+#undef snd_seq_drop_input_buffer
+#undef snd_seq_remove_events_sizeof
+#undef snd_seq_remove_events_malloc
+#undef snd_seq_remove_events_free
+#undef snd_seq_remove_events_copy
+#undef snd_seq_remove_events_get_condition
+#undef snd_seq_remove_events_get_queue
+#undef snd_seq_remove_events_get_time
+#undef snd_seq_remove_events_get_dest
+#undef snd_seq_remove_events_get_channel
+#undef snd_seq_remove_events_get_event_type
+#undef snd_seq_remove_events_get_tag
+#undef snd_seq_remove_events_set_condition
+#undef snd_seq_remove_events_set_queue
+#undef snd_seq_remove_events_set_time
+#undef snd_seq_remove_events_set_dest
+#undef snd_seq_remove_events_set_channel
+#undef snd_seq_remove_events_set_event_type
+#undef snd_seq_remove_events_set_tag
+#undef snd_seq_remove_events
+#undef snd_seq_set_bit
+#undef snd_seq_unset_bit
+#undef snd_seq_change_bit
+#undef snd_seq_get_bit
+#undef snd_seq_control_queue
+#undef snd_seq_create_simple_port
+#undef snd_seq_delete_simple_port
+#undef snd_seq_connect_from
+#undef snd_seq_connect_to
+#undef snd_seq_disconnect_from
+#undef snd_seq_disconnect_to
+#undef snd_seq_set_client_name
+#undef snd_seq_set_client_event_filter
+#undef snd_seq_set_client_pool_output
+#undef snd_seq_set_client_pool_output_room
+#undef snd_seq_set_client_pool_input
+#undef snd_seq_sync_output_queue
+#undef snd_seq_parse_address
+#undef snd_seq_reset_pool_output
+#undef snd_seq_reset_pool_input
+#undef snd_midi_event_new
+#undef snd_midi_event_resize_buffer
+#undef snd_midi_event_free
+#undef snd_midi_event_init
+#undef snd_midi_event_reset_encode
+#undef snd_midi_event_reset_decode
+#undef snd_midi_event_no_status
+#undef snd_midi_event_encode
+#undef snd_midi_event_encode_byte
+#undef snd_midi_event_decode
+#include <dlfcn.h>
+#include <stdio.h>
+const char* (*snd_asoundlib_version_dylibloader_wrapper_asound)( void);
+int (*snd_dlpath_dylibloader_wrapper_asound)( char*, size_t,const char*);
+void* (*snd_dlopen_dylibloader_wrapper_asound)(const char*, int, char*, size_t);
+void* (*snd_dlsym_dylibloader_wrapper_asound)( void*,const char*,const char*);
+int (*snd_dlclose_dylibloader_wrapper_asound)( void*);
+int (*snd_async_add_handler_dylibloader_wrapper_asound)( snd_async_handler_t**, int, snd_async_callback_t, void*);
+int (*snd_async_del_handler_dylibloader_wrapper_asound)( snd_async_handler_t*);
+int (*snd_async_handler_get_fd_dylibloader_wrapper_asound)( snd_async_handler_t*);
+int (*snd_async_handler_get_signo_dylibloader_wrapper_asound)( snd_async_handler_t*);
+void* (*snd_async_handler_get_callback_private_dylibloader_wrapper_asound)( snd_async_handler_t*);
+struct snd_shm_area* (*snd_shm_area_create_dylibloader_wrapper_asound)( int, void*);
+struct snd_shm_area* (*snd_shm_area_share_dylibloader_wrapper_asound)(struct snd_shm_area*);
+int (*snd_shm_area_destroy_dylibloader_wrapper_asound)(struct snd_shm_area*);
+int (*snd_user_file_dylibloader_wrapper_asound)(const char*, char**);
+int (*snd_input_stdio_open_dylibloader_wrapper_asound)( snd_input_t**,const char*,const char*);
+int (*snd_input_stdio_attach_dylibloader_wrapper_asound)( snd_input_t**, FILE*, int);
+int (*snd_input_buffer_open_dylibloader_wrapper_asound)( snd_input_t**,const char*, ssize_t);
+int (*snd_input_close_dylibloader_wrapper_asound)( snd_input_t*);
+int (*snd_input_scanf_dylibloader_wrapper_asound)( snd_input_t*,const char*,...);
+char* (*snd_input_gets_dylibloader_wrapper_asound)( snd_input_t*, char*, size_t);
+int (*snd_input_getc_dylibloader_wrapper_asound)( snd_input_t*);
+int (*snd_input_ungetc_dylibloader_wrapper_asound)( snd_input_t*, int);
+int (*snd_output_stdio_open_dylibloader_wrapper_asound)( snd_output_t**,const char*,const char*);
+int (*snd_output_stdio_attach_dylibloader_wrapper_asound)( snd_output_t**, FILE*, int);
+int (*snd_output_buffer_open_dylibloader_wrapper_asound)( snd_output_t**);
+size_t (*snd_output_buffer_string_dylibloader_wrapper_asound)( snd_output_t*, char**);
+int (*snd_output_close_dylibloader_wrapper_asound)( snd_output_t*);
+int (*snd_output_printf_dylibloader_wrapper_asound)( snd_output_t*,const char*,...);
+int (*snd_output_vprintf_dylibloader_wrapper_asound)( snd_output_t*,const char*, va_list);
+int (*snd_output_puts_dylibloader_wrapper_asound)( snd_output_t*,const char*);
+int (*snd_output_putc_dylibloader_wrapper_asound)( snd_output_t*, int);
+int (*snd_output_flush_dylibloader_wrapper_asound)( snd_output_t*);
+const char* (*snd_strerror_dylibloader_wrapper_asound)( int);
+int (*snd_lib_error_set_handler_dylibloader_wrapper_asound)( snd_lib_error_handler_t);
+snd_local_error_handler_t (*snd_lib_error_set_local_dylibloader_wrapper_asound)( snd_local_error_handler_t);
+const char* (*snd_config_topdir_dylibloader_wrapper_asound)( void);
+int (*snd_config_top_dylibloader_wrapper_asound)( snd_config_t**);
+int (*snd_config_load_dylibloader_wrapper_asound)( snd_config_t*, snd_input_t*);
+int (*snd_config_load_override_dylibloader_wrapper_asound)( snd_config_t*, snd_input_t*);
+int (*snd_config_save_dylibloader_wrapper_asound)( snd_config_t*, snd_output_t*);
+int (*snd_config_update_dylibloader_wrapper_asound)( void);
+int (*snd_config_update_r_dylibloader_wrapper_asound)( snd_config_t**, snd_config_update_t**,const char*);
+int (*snd_config_update_free_dylibloader_wrapper_asound)( snd_config_update_t*);
+int (*snd_config_update_free_global_dylibloader_wrapper_asound)( void);
+int (*snd_config_update_ref_dylibloader_wrapper_asound)( snd_config_t**);
+void (*snd_config_ref_dylibloader_wrapper_asound)( snd_config_t*);
+void (*snd_config_unref_dylibloader_wrapper_asound)( snd_config_t*);
+int (*snd_config_search_dylibloader_wrapper_asound)( snd_config_t*,const char*, snd_config_t**);
+int (*snd_config_searchv_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t**,...);
+int (*snd_config_search_definition_dylibloader_wrapper_asound)( snd_config_t*,const char*,const char*, snd_config_t**);
+int (*snd_config_expand_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t*,const char*, snd_config_t*, snd_config_t**);
+int (*snd_config_evaluate_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t*, snd_config_t*, snd_config_t**);
+int (*snd_config_add_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t*);
+int (*snd_config_add_before_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t*);
+int (*snd_config_add_after_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t*);
+int (*snd_config_remove_dylibloader_wrapper_asound)( snd_config_t*);
+int (*snd_config_delete_dylibloader_wrapper_asound)( snd_config_t*);
+int (*snd_config_delete_compound_members_dylibloader_wrapper_asound)(const snd_config_t*);
+int (*snd_config_copy_dylibloader_wrapper_asound)( snd_config_t**, snd_config_t*);
+int (*snd_config_make_dylibloader_wrapper_asound)( snd_config_t**,const char*, snd_config_type_t);
+int (*snd_config_make_integer_dylibloader_wrapper_asound)( snd_config_t**,const char*);
+int (*snd_config_make_integer64_dylibloader_wrapper_asound)( snd_config_t**,const char*);
+int (*snd_config_make_real_dylibloader_wrapper_asound)( snd_config_t**,const char*);
+int (*snd_config_make_string_dylibloader_wrapper_asound)( snd_config_t**,const char*);
+int (*snd_config_make_pointer_dylibloader_wrapper_asound)( snd_config_t**,const char*);
+int (*snd_config_make_compound_dylibloader_wrapper_asound)( snd_config_t**,const char*, int);
+int (*snd_config_imake_integer_dylibloader_wrapper_asound)( snd_config_t**,const char*,const long);
+int (*snd_config_imake_integer64_dylibloader_wrapper_asound)( snd_config_t**,const char*,const long long);
+int (*snd_config_imake_real_dylibloader_wrapper_asound)( snd_config_t**,const char*,const double);
+int (*snd_config_imake_string_dylibloader_wrapper_asound)( snd_config_t**,const char*,const char*);
+int (*snd_config_imake_safe_string_dylibloader_wrapper_asound)( snd_config_t**,const char*,const char*);
+int (*snd_config_imake_pointer_dylibloader_wrapper_asound)( snd_config_t**,const char*,const void*);
+snd_config_type_t (*snd_config_get_type_dylibloader_wrapper_asound)(const snd_config_t*);
+int (*snd_config_is_array_dylibloader_wrapper_asound)(const snd_config_t*);
+int (*snd_config_set_id_dylibloader_wrapper_asound)( snd_config_t*,const char*);
+int (*snd_config_set_integer_dylibloader_wrapper_asound)( snd_config_t*, long);
+int (*snd_config_set_integer64_dylibloader_wrapper_asound)( snd_config_t*, long long);
+int (*snd_config_set_real_dylibloader_wrapper_asound)( snd_config_t*, double);
+int (*snd_config_set_string_dylibloader_wrapper_asound)( snd_config_t*,const char*);
+int (*snd_config_set_ascii_dylibloader_wrapper_asound)( snd_config_t*,const char*);
+int (*snd_config_set_pointer_dylibloader_wrapper_asound)( snd_config_t*,const void*);
+int (*snd_config_get_id_dylibloader_wrapper_asound)(const snd_config_t*,const char**);
+int (*snd_config_get_integer_dylibloader_wrapper_asound)(const snd_config_t*, long*);
+int (*snd_config_get_integer64_dylibloader_wrapper_asound)(const snd_config_t*, long long*);
+int (*snd_config_get_real_dylibloader_wrapper_asound)(const snd_config_t*, double*);
+int (*snd_config_get_ireal_dylibloader_wrapper_asound)(const snd_config_t*, double*);
+int (*snd_config_get_string_dylibloader_wrapper_asound)(const snd_config_t*,const char**);
+int (*snd_config_get_ascii_dylibloader_wrapper_asound)(const snd_config_t*, char**);
+int (*snd_config_get_pointer_dylibloader_wrapper_asound)(const snd_config_t*,const void**);
+int (*snd_config_test_id_dylibloader_wrapper_asound)(const snd_config_t*,const char*);
+snd_config_iterator_t (*snd_config_iterator_first_dylibloader_wrapper_asound)(const snd_config_t*);
+snd_config_iterator_t (*snd_config_iterator_next_dylibloader_wrapper_asound)(const snd_config_iterator_t);
+snd_config_iterator_t (*snd_config_iterator_end_dylibloader_wrapper_asound)(const snd_config_t*);
+snd_config_t* (*snd_config_iterator_entry_dylibloader_wrapper_asound)(const snd_config_iterator_t);
+int (*snd_config_get_bool_ascii_dylibloader_wrapper_asound)(const char*);
+int (*snd_config_get_bool_dylibloader_wrapper_asound)(const snd_config_t*);
+int (*snd_config_get_ctl_iface_ascii_dylibloader_wrapper_asound)(const char*);
+int (*snd_config_get_ctl_iface_dylibloader_wrapper_asound)(const snd_config_t*);
+int (*snd_names_list_dylibloader_wrapper_asound)(const char*, snd_devname_t**);
+void (*snd_names_list_free_dylibloader_wrapper_asound)( snd_devname_t*);
+int (*snd_pcm_open_dylibloader_wrapper_asound)( snd_pcm_t**,const char*, snd_pcm_stream_t, int);
+int (*snd_pcm_open_lconf_dylibloader_wrapper_asound)( snd_pcm_t**,const char*, snd_pcm_stream_t, int, snd_config_t*);
+int (*snd_pcm_open_fallback_dylibloader_wrapper_asound)( snd_pcm_t**, snd_config_t*,const char*,const char*, snd_pcm_stream_t, int);
+int (*snd_pcm_close_dylibloader_wrapper_asound)( snd_pcm_t*);
+const char* (*snd_pcm_name_dylibloader_wrapper_asound)( snd_pcm_t*);
+snd_pcm_type_t (*snd_pcm_type_dylibloader_wrapper_asound)( snd_pcm_t*);
+snd_pcm_stream_t (*snd_pcm_stream_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_poll_descriptors_count_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_poll_descriptors_dylibloader_wrapper_asound)( snd_pcm_t*,struct pollfd*, unsigned int);
+int (*snd_pcm_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_pcm_t*,struct pollfd*, unsigned int, unsigned short*);
+int (*snd_pcm_nonblock_dylibloader_wrapper_asound)( snd_pcm_t*, int);
+int (*snd_async_add_pcm_handler_dylibloader_wrapper_asound)( snd_async_handler_t**, snd_pcm_t*, snd_async_callback_t, void*);
+snd_pcm_t* (*snd_async_handler_get_pcm_dylibloader_wrapper_asound)( snd_async_handler_t*);
+int (*snd_pcm_info_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_info_t*);
+int (*snd_pcm_hw_params_current_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_free_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_sw_params_current_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*);
+int (*snd_pcm_sw_params_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*);
+int (*snd_pcm_prepare_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_reset_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_status_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_status_t*);
+int (*snd_pcm_start_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_drop_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_drain_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_pause_dylibloader_wrapper_asound)( snd_pcm_t*, int);
+snd_pcm_state_t (*snd_pcm_state_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_hwsync_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_delay_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sframes_t*);
+int (*snd_pcm_resume_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_htimestamp_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_uframes_t*, snd_htimestamp_t*);
+snd_pcm_sframes_t (*snd_pcm_avail_dylibloader_wrapper_asound)( snd_pcm_t*);
+snd_pcm_sframes_t (*snd_pcm_avail_update_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_avail_delay_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sframes_t*, snd_pcm_sframes_t*);
+snd_pcm_sframes_t (*snd_pcm_rewindable_dylibloader_wrapper_asound)( snd_pcm_t*);
+snd_pcm_sframes_t (*snd_pcm_rewind_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_uframes_t);
+snd_pcm_sframes_t (*snd_pcm_forwardable_dylibloader_wrapper_asound)( snd_pcm_t*);
+snd_pcm_sframes_t (*snd_pcm_forward_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_uframes_t);
+snd_pcm_sframes_t (*snd_pcm_writei_dylibloader_wrapper_asound)( snd_pcm_t*,const void*, snd_pcm_uframes_t);
+snd_pcm_sframes_t (*snd_pcm_readi_dylibloader_wrapper_asound)( snd_pcm_t*, void*, snd_pcm_uframes_t);
+snd_pcm_sframes_t (*snd_pcm_writen_dylibloader_wrapper_asound)( snd_pcm_t*, void**, snd_pcm_uframes_t);
+snd_pcm_sframes_t (*snd_pcm_readn_dylibloader_wrapper_asound)( snd_pcm_t*, void**, snd_pcm_uframes_t);
+int (*snd_pcm_wait_dylibloader_wrapper_asound)( snd_pcm_t*, int);
+int (*snd_pcm_link_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_t*);
+int (*snd_pcm_unlink_dylibloader_wrapper_asound)( snd_pcm_t*);
+snd_pcm_chmap_query_t** (*snd_pcm_query_chmaps_dylibloader_wrapper_asound)( snd_pcm_t*);
+snd_pcm_chmap_query_t** (*snd_pcm_query_chmaps_from_hw_dylibloader_wrapper_asound)( int, int, int, snd_pcm_stream_t);
+void (*snd_pcm_free_chmaps_dylibloader_wrapper_asound)( snd_pcm_chmap_query_t**);
+snd_pcm_chmap_t* (*snd_pcm_get_chmap_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_set_chmap_dylibloader_wrapper_asound)( snd_pcm_t*,const snd_pcm_chmap_t*);
+const char* (*snd_pcm_chmap_type_name_dylibloader_wrapper_asound)(enum snd_pcm_chmap_type);
+const char* (*snd_pcm_chmap_name_dylibloader_wrapper_asound)(enum snd_pcm_chmap_position);
+const char* (*snd_pcm_chmap_long_name_dylibloader_wrapper_asound)(enum snd_pcm_chmap_position);
+int (*snd_pcm_chmap_print_dylibloader_wrapper_asound)(const snd_pcm_chmap_t*, size_t, char*);
+unsigned int (*snd_pcm_chmap_from_string_dylibloader_wrapper_asound)(const char*);
+snd_pcm_chmap_t* (*snd_pcm_chmap_parse_string_dylibloader_wrapper_asound)(const char*);
+int (*snd_pcm_recover_dylibloader_wrapper_asound)( snd_pcm_t*, int, int);
+int (*snd_pcm_set_params_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_format_t, snd_pcm_access_t, unsigned int, unsigned int, int, unsigned int);
+int (*snd_pcm_get_params_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_uframes_t*, snd_pcm_uframes_t*);
+size_t (*snd_pcm_info_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_pcm_info_malloc_dylibloader_wrapper_asound)( snd_pcm_info_t**);
+void (*snd_pcm_info_free_dylibloader_wrapper_asound)( snd_pcm_info_t*);
+void (*snd_pcm_info_copy_dylibloader_wrapper_asound)( snd_pcm_info_t*,const snd_pcm_info_t*);
+unsigned int (*snd_pcm_info_get_device_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+unsigned int (*snd_pcm_info_get_subdevice_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+snd_pcm_stream_t (*snd_pcm_info_get_stream_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+int (*snd_pcm_info_get_card_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+const char* (*snd_pcm_info_get_id_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+const char* (*snd_pcm_info_get_name_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+const char* (*snd_pcm_info_get_subdevice_name_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+snd_pcm_class_t (*snd_pcm_info_get_class_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+snd_pcm_subclass_t (*snd_pcm_info_get_subclass_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+unsigned int (*snd_pcm_info_get_subdevices_count_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+unsigned int (*snd_pcm_info_get_subdevices_avail_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+snd_pcm_sync_id_t (*snd_pcm_info_get_sync_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+void (*snd_pcm_info_set_device_dylibloader_wrapper_asound)( snd_pcm_info_t*, unsigned int);
+void (*snd_pcm_info_set_subdevice_dylibloader_wrapper_asound)( snd_pcm_info_t*, unsigned int);
+void (*snd_pcm_info_set_stream_dylibloader_wrapper_asound)( snd_pcm_info_t*, snd_pcm_stream_t);
+int (*snd_pcm_hw_params_any_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_can_mmap_sample_resolution_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_is_double_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_is_batch_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_is_block_transfer_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_is_monotonic_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_can_overrange_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_can_pause_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_can_resume_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_is_half_duplex_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_is_joint_duplex_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_can_sync_start_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_can_disable_period_wakeup_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_supports_audio_wallclock_ts_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_supports_audio_ts_type_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, int);
+int (*snd_pcm_hw_params_get_rate_numden_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, unsigned int*);
+int (*snd_pcm_hw_params_get_sbits_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_get_fifo_size_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+size_t (*snd_pcm_hw_params_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_pcm_hw_params_malloc_dylibloader_wrapper_asound)( snd_pcm_hw_params_t**);
+void (*snd_pcm_hw_params_free_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*);
+void (*snd_pcm_hw_params_copy_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*,const snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_get_access_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_access_t*);
+int (*snd_pcm_hw_params_test_access_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_access_t);
+int (*snd_pcm_hw_params_set_access_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_access_t);
+int (*snd_pcm_hw_params_set_access_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_access_t*);
+int (*snd_pcm_hw_params_set_access_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_access_t*);
+int (*snd_pcm_hw_params_set_access_mask_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_access_mask_t*);
+int (*snd_pcm_hw_params_get_access_mask_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*, snd_pcm_access_mask_t*);
+int (*snd_pcm_hw_params_get_format_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_format_t*);
+int (*snd_pcm_hw_params_test_format_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_format_t);
+int (*snd_pcm_hw_params_set_format_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_format_t);
+int (*snd_pcm_hw_params_set_format_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_format_t*);
+int (*snd_pcm_hw_params_set_format_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_format_t*);
+int (*snd_pcm_hw_params_set_format_mask_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_format_mask_t*);
+void (*snd_pcm_hw_params_get_format_mask_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*, snd_pcm_format_mask_t*);
+int (*snd_pcm_hw_params_get_subformat_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_subformat_t*);
+int (*snd_pcm_hw_params_test_subformat_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_subformat_t);
+int (*snd_pcm_hw_params_set_subformat_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_subformat_t);
+int (*snd_pcm_hw_params_set_subformat_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_subformat_t*);
+int (*snd_pcm_hw_params_set_subformat_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_subformat_t*);
+int (*snd_pcm_hw_params_set_subformat_mask_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_subformat_mask_t*);
+void (*snd_pcm_hw_params_get_subformat_mask_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*, snd_pcm_subformat_mask_t*);
+int (*snd_pcm_hw_params_get_channels_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_get_channels_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_get_channels_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_test_channels_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int);
+int (*snd_pcm_hw_params_set_channels_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int);
+int (*snd_pcm_hw_params_set_channels_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_set_channels_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_set_channels_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, unsigned int*);
+int (*snd_pcm_hw_params_set_channels_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_set_channels_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_set_channels_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_get_rate_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_rate_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_rate_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_test_rate_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+int (*snd_pcm_hw_params_set_rate_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+int (*snd_pcm_hw_params_set_rate_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_rate_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_rate_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_rate_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_rate_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_rate_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_rate_resample_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int);
+int (*snd_pcm_hw_params_get_rate_resample_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_set_export_buffer_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int);
+int (*snd_pcm_hw_params_get_export_buffer_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_set_period_wakeup_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int);
+int (*snd_pcm_hw_params_get_period_wakeup_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_get_period_time_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_period_time_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_period_time_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_test_period_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+int (*snd_pcm_hw_params_set_period_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+int (*snd_pcm_hw_params_set_period_time_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_period_time_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_period_time_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_period_time_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_period_time_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_period_time_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_period_size_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+int (*snd_pcm_hw_params_get_period_size_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+int (*snd_pcm_hw_params_get_period_size_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+int (*snd_pcm_hw_params_test_period_size_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t, int);
+int (*snd_pcm_hw_params_set_period_size_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t, int);
+int (*snd_pcm_hw_params_set_period_size_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+int (*snd_pcm_hw_params_set_period_size_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+int (*snd_pcm_hw_params_set_period_size_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*, snd_pcm_uframes_t*, int*);
+int (*snd_pcm_hw_params_set_period_size_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+int (*snd_pcm_hw_params_set_period_size_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+int (*snd_pcm_hw_params_set_period_size_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+int (*snd_pcm_hw_params_set_period_size_integer_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_get_periods_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_periods_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_periods_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_test_periods_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+int (*snd_pcm_hw_params_set_periods_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+int (*snd_pcm_hw_params_set_periods_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_periods_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_periods_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_periods_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_periods_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_periods_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_periods_integer_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*);
+int (*snd_pcm_hw_params_get_buffer_time_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_buffer_time_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_buffer_time_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_test_buffer_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+int (*snd_pcm_hw_params_set_buffer_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+int (*snd_pcm_hw_params_set_buffer_time_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_buffer_time_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_buffer_time_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_buffer_time_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_buffer_time_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_buffer_time_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_buffer_size_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_hw_params_get_buffer_size_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_hw_params_get_buffer_size_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_hw_params_test_buffer_size_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t);
+int (*snd_pcm_hw_params_set_buffer_size_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t);
+int (*snd_pcm_hw_params_set_buffer_size_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_hw_params_set_buffer_size_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_hw_params_set_buffer_size_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_hw_params_set_buffer_size_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_hw_params_set_buffer_size_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_hw_params_set_buffer_size_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_hw_params_get_min_align_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+size_t (*snd_pcm_sw_params_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_pcm_sw_params_malloc_dylibloader_wrapper_asound)( snd_pcm_sw_params_t**);
+void (*snd_pcm_sw_params_free_dylibloader_wrapper_asound)( snd_pcm_sw_params_t*);
+void (*snd_pcm_sw_params_copy_dylibloader_wrapper_asound)( snd_pcm_sw_params_t*,const snd_pcm_sw_params_t*);
+int (*snd_pcm_sw_params_get_boundary_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_sw_params_set_tstamp_mode_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_tstamp_t);
+int (*snd_pcm_sw_params_get_tstamp_mode_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_tstamp_t*);
+int (*snd_pcm_sw_params_set_avail_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+int (*snd_pcm_sw_params_get_avail_min_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_sw_params_set_period_event_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, int);
+int (*snd_pcm_sw_params_get_period_event_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, int*);
+int (*snd_pcm_sw_params_set_start_threshold_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+int (*snd_pcm_sw_params_get_start_threshold_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_sw_params_set_stop_threshold_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+int (*snd_pcm_sw_params_get_stop_threshold_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_sw_params_set_silence_threshold_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+int (*snd_pcm_sw_params_get_silence_threshold_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_sw_params_set_silence_size_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+int (*snd_pcm_sw_params_get_silence_size_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+size_t (*snd_pcm_access_mask_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_pcm_access_mask_malloc_dylibloader_wrapper_asound)( snd_pcm_access_mask_t**);
+void (*snd_pcm_access_mask_free_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*);
+void (*snd_pcm_access_mask_copy_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*,const snd_pcm_access_mask_t*);
+void (*snd_pcm_access_mask_none_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*);
+void (*snd_pcm_access_mask_any_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*);
+int (*snd_pcm_access_mask_test_dylibloader_wrapper_asound)(const snd_pcm_access_mask_t*, snd_pcm_access_t);
+int (*snd_pcm_access_mask_empty_dylibloader_wrapper_asound)(const snd_pcm_access_mask_t*);
+void (*snd_pcm_access_mask_set_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*, snd_pcm_access_t);
+void (*snd_pcm_access_mask_reset_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*, snd_pcm_access_t);
+size_t (*snd_pcm_format_mask_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_pcm_format_mask_malloc_dylibloader_wrapper_asound)( snd_pcm_format_mask_t**);
+void (*snd_pcm_format_mask_free_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*);
+void (*snd_pcm_format_mask_copy_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*,const snd_pcm_format_mask_t*);
+void (*snd_pcm_format_mask_none_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*);
+void (*snd_pcm_format_mask_any_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*);
+int (*snd_pcm_format_mask_test_dylibloader_wrapper_asound)(const snd_pcm_format_mask_t*, snd_pcm_format_t);
+int (*snd_pcm_format_mask_empty_dylibloader_wrapper_asound)(const snd_pcm_format_mask_t*);
+void (*snd_pcm_format_mask_set_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*, snd_pcm_format_t);
+void (*snd_pcm_format_mask_reset_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*, snd_pcm_format_t);
+size_t (*snd_pcm_subformat_mask_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_pcm_subformat_mask_malloc_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t**);
+void (*snd_pcm_subformat_mask_free_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*);
+void (*snd_pcm_subformat_mask_copy_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*,const snd_pcm_subformat_mask_t*);
+void (*snd_pcm_subformat_mask_none_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*);
+void (*snd_pcm_subformat_mask_any_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*);
+int (*snd_pcm_subformat_mask_test_dylibloader_wrapper_asound)(const snd_pcm_subformat_mask_t*, snd_pcm_subformat_t);
+int (*snd_pcm_subformat_mask_empty_dylibloader_wrapper_asound)(const snd_pcm_subformat_mask_t*);
+void (*snd_pcm_subformat_mask_set_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*, snd_pcm_subformat_t);
+void (*snd_pcm_subformat_mask_reset_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*, snd_pcm_subformat_t);
+size_t (*snd_pcm_status_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_pcm_status_malloc_dylibloader_wrapper_asound)( snd_pcm_status_t**);
+void (*snd_pcm_status_free_dylibloader_wrapper_asound)( snd_pcm_status_t*);
+void (*snd_pcm_status_copy_dylibloader_wrapper_asound)( snd_pcm_status_t*,const snd_pcm_status_t*);
+snd_pcm_state_t (*snd_pcm_status_get_state_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
+void (*snd_pcm_status_get_trigger_tstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_timestamp_t*);
+void (*snd_pcm_status_get_trigger_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
+void (*snd_pcm_status_get_tstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_timestamp_t*);
+void (*snd_pcm_status_get_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
+void (*snd_pcm_status_get_audio_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
+void (*snd_pcm_status_get_driver_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
+snd_pcm_sframes_t (*snd_pcm_status_get_delay_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
+snd_pcm_uframes_t (*snd_pcm_status_get_avail_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
+snd_pcm_uframes_t (*snd_pcm_status_get_avail_max_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
+snd_pcm_uframes_t (*snd_pcm_status_get_overrange_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
+const char* (*snd_pcm_type_name_dylibloader_wrapper_asound)( snd_pcm_type_t);
+const char* (*snd_pcm_stream_name_dylibloader_wrapper_asound)(const snd_pcm_stream_t);
+const char* (*snd_pcm_access_name_dylibloader_wrapper_asound)(const snd_pcm_access_t);
+const char* (*snd_pcm_format_name_dylibloader_wrapper_asound)(const snd_pcm_format_t);
+const char* (*snd_pcm_format_description_dylibloader_wrapper_asound)(const snd_pcm_format_t);
+const char* (*snd_pcm_subformat_name_dylibloader_wrapper_asound)(const snd_pcm_subformat_t);
+const char* (*snd_pcm_subformat_description_dylibloader_wrapper_asound)(const snd_pcm_subformat_t);
+snd_pcm_format_t (*snd_pcm_format_value_dylibloader_wrapper_asound)(const char*);
+const char* (*snd_pcm_tstamp_mode_name_dylibloader_wrapper_asound)(const snd_pcm_tstamp_t);
+const char* (*snd_pcm_state_name_dylibloader_wrapper_asound)(const snd_pcm_state_t);
+int (*snd_pcm_dump_dylibloader_wrapper_asound)( snd_pcm_t*, snd_output_t*);
+int (*snd_pcm_dump_hw_setup_dylibloader_wrapper_asound)( snd_pcm_t*, snd_output_t*);
+int (*snd_pcm_dump_sw_setup_dylibloader_wrapper_asound)( snd_pcm_t*, snd_output_t*);
+int (*snd_pcm_dump_setup_dylibloader_wrapper_asound)( snd_pcm_t*, snd_output_t*);
+int (*snd_pcm_hw_params_dump_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*, snd_output_t*);
+int (*snd_pcm_sw_params_dump_dylibloader_wrapper_asound)( snd_pcm_sw_params_t*, snd_output_t*);
+int (*snd_pcm_status_dump_dylibloader_wrapper_asound)( snd_pcm_status_t*, snd_output_t*);
+int (*snd_pcm_mmap_begin_dylibloader_wrapper_asound)( snd_pcm_t*,const snd_pcm_channel_area_t**, snd_pcm_uframes_t*, snd_pcm_uframes_t*);
+snd_pcm_sframes_t (*snd_pcm_mmap_commit_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_uframes_t, snd_pcm_uframes_t);
+snd_pcm_sframes_t (*snd_pcm_mmap_writei_dylibloader_wrapper_asound)( snd_pcm_t*,const void*, snd_pcm_uframes_t);
+snd_pcm_sframes_t (*snd_pcm_mmap_readi_dylibloader_wrapper_asound)( snd_pcm_t*, void*, snd_pcm_uframes_t);
+snd_pcm_sframes_t (*snd_pcm_mmap_writen_dylibloader_wrapper_asound)( snd_pcm_t*, void**, snd_pcm_uframes_t);
+snd_pcm_sframes_t (*snd_pcm_mmap_readn_dylibloader_wrapper_asound)( snd_pcm_t*, void**, snd_pcm_uframes_t);
+int (*snd_pcm_format_signed_dylibloader_wrapper_asound)( snd_pcm_format_t);
+int (*snd_pcm_format_unsigned_dylibloader_wrapper_asound)( snd_pcm_format_t);
+int (*snd_pcm_format_linear_dylibloader_wrapper_asound)( snd_pcm_format_t);
+int (*snd_pcm_format_float_dylibloader_wrapper_asound)( snd_pcm_format_t);
+int (*snd_pcm_format_little_endian_dylibloader_wrapper_asound)( snd_pcm_format_t);
+int (*snd_pcm_format_big_endian_dylibloader_wrapper_asound)( snd_pcm_format_t);
+int (*snd_pcm_format_cpu_endian_dylibloader_wrapper_asound)( snd_pcm_format_t);
+int (*snd_pcm_format_width_dylibloader_wrapper_asound)( snd_pcm_format_t);
+int (*snd_pcm_format_physical_width_dylibloader_wrapper_asound)( snd_pcm_format_t);
+snd_pcm_format_t (*snd_pcm_build_linear_format_dylibloader_wrapper_asound)( int, int, int, int);
+ssize_t (*snd_pcm_format_size_dylibloader_wrapper_asound)( snd_pcm_format_t, size_t);
+uint8_t (*snd_pcm_format_silence_dylibloader_wrapper_asound)( snd_pcm_format_t);
+uint16_t (*snd_pcm_format_silence_16_dylibloader_wrapper_asound)( snd_pcm_format_t);
+uint32_t (*snd_pcm_format_silence_32_dylibloader_wrapper_asound)( snd_pcm_format_t);
+uint64_t (*snd_pcm_format_silence_64_dylibloader_wrapper_asound)( snd_pcm_format_t);
+int (*snd_pcm_format_set_silence_dylibloader_wrapper_asound)( snd_pcm_format_t, void*, unsigned int);
+snd_pcm_sframes_t (*snd_pcm_bytes_to_frames_dylibloader_wrapper_asound)( snd_pcm_t*, ssize_t);
+ssize_t (*snd_pcm_frames_to_bytes_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sframes_t);
+long (*snd_pcm_bytes_to_samples_dylibloader_wrapper_asound)( snd_pcm_t*, ssize_t);
+ssize_t (*snd_pcm_samples_to_bytes_dylibloader_wrapper_asound)( snd_pcm_t*, long);
+int (*snd_pcm_area_silence_dylibloader_wrapper_asound)(const snd_pcm_channel_area_t*, snd_pcm_uframes_t, unsigned int, snd_pcm_format_t);
+int (*snd_pcm_areas_silence_dylibloader_wrapper_asound)(const snd_pcm_channel_area_t*, snd_pcm_uframes_t, unsigned int, snd_pcm_uframes_t, snd_pcm_format_t);
+int (*snd_pcm_area_copy_dylibloader_wrapper_asound)(const snd_pcm_channel_area_t*, snd_pcm_uframes_t,const snd_pcm_channel_area_t*, snd_pcm_uframes_t, unsigned int, snd_pcm_format_t);
+int (*snd_pcm_areas_copy_dylibloader_wrapper_asound)(const snd_pcm_channel_area_t*, snd_pcm_uframes_t,const snd_pcm_channel_area_t*, snd_pcm_uframes_t, unsigned int, snd_pcm_uframes_t, snd_pcm_format_t);
+int (*snd_pcm_areas_copy_wrap_dylibloader_wrapper_asound)(const snd_pcm_channel_area_t*, snd_pcm_uframes_t,const snd_pcm_uframes_t,const snd_pcm_channel_area_t*, snd_pcm_uframes_t,const snd_pcm_uframes_t,const unsigned int, snd_pcm_uframes_t,const snd_pcm_format_t);
+snd_pcm_t* (*snd_pcm_hook_get_pcm_dylibloader_wrapper_asound)( snd_pcm_hook_t*);
+void* (*snd_pcm_hook_get_private_dylibloader_wrapper_asound)( snd_pcm_hook_t*);
+void (*snd_pcm_hook_set_private_dylibloader_wrapper_asound)( snd_pcm_hook_t*, void*);
+int (*snd_pcm_hook_add_dylibloader_wrapper_asound)( snd_pcm_hook_t**, snd_pcm_t*, snd_pcm_hook_type_t, snd_pcm_hook_func_t, void*);
+int (*snd_pcm_hook_remove_dylibloader_wrapper_asound)( snd_pcm_hook_t*);
+snd_pcm_uframes_t (*snd_pcm_meter_get_bufsize_dylibloader_wrapper_asound)( snd_pcm_t*);
+unsigned int (*snd_pcm_meter_get_channels_dylibloader_wrapper_asound)( snd_pcm_t*);
+unsigned int (*snd_pcm_meter_get_rate_dylibloader_wrapper_asound)( snd_pcm_t*);
+snd_pcm_uframes_t (*snd_pcm_meter_get_now_dylibloader_wrapper_asound)( snd_pcm_t*);
+snd_pcm_uframes_t (*snd_pcm_meter_get_boundary_dylibloader_wrapper_asound)( snd_pcm_t*);
+int (*snd_pcm_meter_add_scope_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_scope_t*);
+snd_pcm_scope_t* (*snd_pcm_meter_search_scope_dylibloader_wrapper_asound)( snd_pcm_t*,const char*);
+int (*snd_pcm_scope_malloc_dylibloader_wrapper_asound)( snd_pcm_scope_t**);
+void (*snd_pcm_scope_set_ops_dylibloader_wrapper_asound)( snd_pcm_scope_t*,const snd_pcm_scope_ops_t*);
+void (*snd_pcm_scope_set_name_dylibloader_wrapper_asound)( snd_pcm_scope_t*,const char*);
+const char* (*snd_pcm_scope_get_name_dylibloader_wrapper_asound)( snd_pcm_scope_t*);
+void* (*snd_pcm_scope_get_callback_private_dylibloader_wrapper_asound)( snd_pcm_scope_t*);
+void (*snd_pcm_scope_set_callback_private_dylibloader_wrapper_asound)( snd_pcm_scope_t*, void*);
+int (*snd_pcm_scope_s16_open_dylibloader_wrapper_asound)( snd_pcm_t*,const char*, snd_pcm_scope_t**);
+int16_t* (*snd_pcm_scope_s16_get_channel_buffer_dylibloader_wrapper_asound)( snd_pcm_scope_t*, unsigned int);
+int (*snd_spcm_init_dylibloader_wrapper_asound)( snd_pcm_t*, unsigned int, unsigned int, snd_pcm_format_t, snd_pcm_subformat_t, snd_spcm_latency_t, snd_pcm_access_t, snd_spcm_xrun_type_t);
+int (*snd_spcm_init_duplex_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_t*, unsigned int, unsigned int, snd_pcm_format_t, snd_pcm_subformat_t, snd_spcm_latency_t, snd_pcm_access_t, snd_spcm_xrun_type_t, snd_spcm_duplex_type_t);
+int (*snd_spcm_init_get_params_dylibloader_wrapper_asound)( snd_pcm_t*, unsigned int*, snd_pcm_uframes_t*, snd_pcm_uframes_t*);
+const char* (*snd_pcm_start_mode_name_dylibloader_wrapper_asound)( snd_pcm_start_t);
+const char* (*snd_pcm_xrun_mode_name_dylibloader_wrapper_asound)( snd_pcm_xrun_t);
+int (*snd_pcm_sw_params_set_start_mode_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_start_t);
+snd_pcm_start_t (*snd_pcm_sw_params_get_start_mode_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*);
+int (*snd_pcm_sw_params_set_xrun_mode_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_xrun_t);
+snd_pcm_xrun_t (*snd_pcm_sw_params_get_xrun_mode_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*);
+int (*snd_pcm_sw_params_set_xfer_align_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+int (*snd_pcm_sw_params_get_xfer_align_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+int (*snd_pcm_sw_params_set_sleep_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, unsigned int);
+int (*snd_pcm_sw_params_get_sleep_min_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, unsigned int*);
+int (*snd_pcm_hw_params_get_tick_time_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_tick_time_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_get_tick_time_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_test_tick_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+int (*snd_pcm_hw_params_set_tick_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+int (*snd_pcm_hw_params_set_tick_time_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_tick_time_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_tick_time_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_tick_time_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_tick_time_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_pcm_hw_params_set_tick_time_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+int (*snd_rawmidi_open_dylibloader_wrapper_asound)( snd_rawmidi_t**, snd_rawmidi_t**,const char*, int);
+int (*snd_rawmidi_open_lconf_dylibloader_wrapper_asound)( snd_rawmidi_t**, snd_rawmidi_t**,const char*, int, snd_config_t*);
+int (*snd_rawmidi_close_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+int (*snd_rawmidi_poll_descriptors_count_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+int (*snd_rawmidi_poll_descriptors_dylibloader_wrapper_asound)( snd_rawmidi_t*,struct pollfd*, unsigned int);
+int (*snd_rawmidi_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_rawmidi_t*,struct pollfd*, unsigned int, unsigned short*);
+int (*snd_rawmidi_nonblock_dylibloader_wrapper_asound)( snd_rawmidi_t*, int);
+size_t (*snd_rawmidi_info_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_rawmidi_info_malloc_dylibloader_wrapper_asound)( snd_rawmidi_info_t**);
+void (*snd_rawmidi_info_free_dylibloader_wrapper_asound)( snd_rawmidi_info_t*);
+void (*snd_rawmidi_info_copy_dylibloader_wrapper_asound)( snd_rawmidi_info_t*,const snd_rawmidi_info_t*);
+unsigned int (*snd_rawmidi_info_get_device_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+unsigned int (*snd_rawmidi_info_get_subdevice_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+snd_rawmidi_stream_t (*snd_rawmidi_info_get_stream_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+int (*snd_rawmidi_info_get_card_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+unsigned int (*snd_rawmidi_info_get_flags_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+const char* (*snd_rawmidi_info_get_id_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+const char* (*snd_rawmidi_info_get_name_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+const char* (*snd_rawmidi_info_get_subdevice_name_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+unsigned int (*snd_rawmidi_info_get_subdevices_count_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+unsigned int (*snd_rawmidi_info_get_subdevices_avail_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+void (*snd_rawmidi_info_set_device_dylibloader_wrapper_asound)( snd_rawmidi_info_t*, unsigned int);
+void (*snd_rawmidi_info_set_subdevice_dylibloader_wrapper_asound)( snd_rawmidi_info_t*, unsigned int);
+void (*snd_rawmidi_info_set_stream_dylibloader_wrapper_asound)( snd_rawmidi_info_t*, snd_rawmidi_stream_t);
+int (*snd_rawmidi_info_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_info_t*);
+size_t (*snd_rawmidi_params_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_rawmidi_params_malloc_dylibloader_wrapper_asound)( snd_rawmidi_params_t**);
+void (*snd_rawmidi_params_free_dylibloader_wrapper_asound)( snd_rawmidi_params_t*);
+void (*snd_rawmidi_params_copy_dylibloader_wrapper_asound)( snd_rawmidi_params_t*,const snd_rawmidi_params_t*);
+int (*snd_rawmidi_params_set_buffer_size_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_params_t*, size_t);
+size_t (*snd_rawmidi_params_get_buffer_size_dylibloader_wrapper_asound)(const snd_rawmidi_params_t*);
+int (*snd_rawmidi_params_set_avail_min_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_params_t*, size_t);
+size_t (*snd_rawmidi_params_get_avail_min_dylibloader_wrapper_asound)(const snd_rawmidi_params_t*);
+int (*snd_rawmidi_params_set_no_active_sensing_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_params_t*, int);
+int (*snd_rawmidi_params_get_no_active_sensing_dylibloader_wrapper_asound)(const snd_rawmidi_params_t*);
+int (*snd_rawmidi_params_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_params_t*);
+int (*snd_rawmidi_params_current_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_params_t*);
+size_t (*snd_rawmidi_status_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_rawmidi_status_malloc_dylibloader_wrapper_asound)( snd_rawmidi_status_t**);
+void (*snd_rawmidi_status_free_dylibloader_wrapper_asound)( snd_rawmidi_status_t*);
+void (*snd_rawmidi_status_copy_dylibloader_wrapper_asound)( snd_rawmidi_status_t*,const snd_rawmidi_status_t*);
+void (*snd_rawmidi_status_get_tstamp_dylibloader_wrapper_asound)(const snd_rawmidi_status_t*, snd_htimestamp_t*);
+size_t (*snd_rawmidi_status_get_avail_dylibloader_wrapper_asound)(const snd_rawmidi_status_t*);
+size_t (*snd_rawmidi_status_get_xruns_dylibloader_wrapper_asound)(const snd_rawmidi_status_t*);
+int (*snd_rawmidi_status_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_status_t*);
+int (*snd_rawmidi_drain_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+int (*snd_rawmidi_drop_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+ssize_t (*snd_rawmidi_write_dylibloader_wrapper_asound)( snd_rawmidi_t*,const void*, size_t);
+ssize_t (*snd_rawmidi_read_dylibloader_wrapper_asound)( snd_rawmidi_t*, void*, size_t);
+const char* (*snd_rawmidi_name_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+snd_rawmidi_type_t (*snd_rawmidi_type_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+snd_rawmidi_stream_t (*snd_rawmidi_stream_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+int (*snd_timer_query_open_dylibloader_wrapper_asound)( snd_timer_query_t**,const char*, int);
+int (*snd_timer_query_open_lconf_dylibloader_wrapper_asound)( snd_timer_query_t**,const char*, int, snd_config_t*);
+int (*snd_timer_query_close_dylibloader_wrapper_asound)( snd_timer_query_t*);
+int (*snd_timer_query_next_device_dylibloader_wrapper_asound)( snd_timer_query_t*, snd_timer_id_t*);
+int (*snd_timer_query_info_dylibloader_wrapper_asound)( snd_timer_query_t*, snd_timer_ginfo_t*);
+int (*snd_timer_query_params_dylibloader_wrapper_asound)( snd_timer_query_t*, snd_timer_gparams_t*);
+int (*snd_timer_query_status_dylibloader_wrapper_asound)( snd_timer_query_t*, snd_timer_gstatus_t*);
+int (*snd_timer_open_dylibloader_wrapper_asound)( snd_timer_t**,const char*, int);
+int (*snd_timer_open_lconf_dylibloader_wrapper_asound)( snd_timer_t**,const char*, int, snd_config_t*);
+int (*snd_timer_close_dylibloader_wrapper_asound)( snd_timer_t*);
+int (*snd_async_add_timer_handler_dylibloader_wrapper_asound)( snd_async_handler_t**, snd_timer_t*, snd_async_callback_t, void*);
+snd_timer_t* (*snd_async_handler_get_timer_dylibloader_wrapper_asound)( snd_async_handler_t*);
+int (*snd_timer_poll_descriptors_count_dylibloader_wrapper_asound)( snd_timer_t*);
+int (*snd_timer_poll_descriptors_dylibloader_wrapper_asound)( snd_timer_t*,struct pollfd*, unsigned int);
+int (*snd_timer_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_timer_t*,struct pollfd*, unsigned int, unsigned short*);
+int (*snd_timer_info_dylibloader_wrapper_asound)( snd_timer_t*, snd_timer_info_t*);
+int (*snd_timer_params_dylibloader_wrapper_asound)( snd_timer_t*, snd_timer_params_t*);
+int (*snd_timer_status_dylibloader_wrapper_asound)( snd_timer_t*, snd_timer_status_t*);
+int (*snd_timer_start_dylibloader_wrapper_asound)( snd_timer_t*);
+int (*snd_timer_stop_dylibloader_wrapper_asound)( snd_timer_t*);
+int (*snd_timer_continue_dylibloader_wrapper_asound)( snd_timer_t*);
+ssize_t (*snd_timer_read_dylibloader_wrapper_asound)( snd_timer_t*, void*, size_t);
+size_t (*snd_timer_id_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_timer_id_malloc_dylibloader_wrapper_asound)( snd_timer_id_t**);
+void (*snd_timer_id_free_dylibloader_wrapper_asound)( snd_timer_id_t*);
+void (*snd_timer_id_copy_dylibloader_wrapper_asound)( snd_timer_id_t*,const snd_timer_id_t*);
+void (*snd_timer_id_set_class_dylibloader_wrapper_asound)( snd_timer_id_t*, int);
+int (*snd_timer_id_get_class_dylibloader_wrapper_asound)( snd_timer_id_t*);
+void (*snd_timer_id_set_sclass_dylibloader_wrapper_asound)( snd_timer_id_t*, int);
+int (*snd_timer_id_get_sclass_dylibloader_wrapper_asound)( snd_timer_id_t*);
+void (*snd_timer_id_set_card_dylibloader_wrapper_asound)( snd_timer_id_t*, int);
+int (*snd_timer_id_get_card_dylibloader_wrapper_asound)( snd_timer_id_t*);
+void (*snd_timer_id_set_device_dylibloader_wrapper_asound)( snd_timer_id_t*, int);
+int (*snd_timer_id_get_device_dylibloader_wrapper_asound)( snd_timer_id_t*);
+void (*snd_timer_id_set_subdevice_dylibloader_wrapper_asound)( snd_timer_id_t*, int);
+int (*snd_timer_id_get_subdevice_dylibloader_wrapper_asound)( snd_timer_id_t*);
+size_t (*snd_timer_ginfo_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_timer_ginfo_malloc_dylibloader_wrapper_asound)( snd_timer_ginfo_t**);
+void (*snd_timer_ginfo_free_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+void (*snd_timer_ginfo_copy_dylibloader_wrapper_asound)( snd_timer_ginfo_t*,const snd_timer_ginfo_t*);
+int (*snd_timer_ginfo_set_tid_dylibloader_wrapper_asound)( snd_timer_ginfo_t*, snd_timer_id_t*);
+snd_timer_id_t* (*snd_timer_ginfo_get_tid_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+unsigned int (*snd_timer_ginfo_get_flags_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+int (*snd_timer_ginfo_get_card_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+char* (*snd_timer_ginfo_get_id_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+char* (*snd_timer_ginfo_get_name_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+unsigned long (*snd_timer_ginfo_get_resolution_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+unsigned long (*snd_timer_ginfo_get_resolution_min_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+unsigned long (*snd_timer_ginfo_get_resolution_max_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+unsigned int (*snd_timer_ginfo_get_clients_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+size_t (*snd_timer_info_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_timer_info_malloc_dylibloader_wrapper_asound)( snd_timer_info_t**);
+void (*snd_timer_info_free_dylibloader_wrapper_asound)( snd_timer_info_t*);
+void (*snd_timer_info_copy_dylibloader_wrapper_asound)( snd_timer_info_t*,const snd_timer_info_t*);
+int (*snd_timer_info_is_slave_dylibloader_wrapper_asound)( snd_timer_info_t*);
+int (*snd_timer_info_get_card_dylibloader_wrapper_asound)( snd_timer_info_t*);
+const char* (*snd_timer_info_get_id_dylibloader_wrapper_asound)( snd_timer_info_t*);
+const char* (*snd_timer_info_get_name_dylibloader_wrapper_asound)( snd_timer_info_t*);
+long (*snd_timer_info_get_resolution_dylibloader_wrapper_asound)( snd_timer_info_t*);
+size_t (*snd_timer_params_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_timer_params_malloc_dylibloader_wrapper_asound)( snd_timer_params_t**);
+void (*snd_timer_params_free_dylibloader_wrapper_asound)( snd_timer_params_t*);
+void (*snd_timer_params_copy_dylibloader_wrapper_asound)( snd_timer_params_t*,const snd_timer_params_t*);
+int (*snd_timer_params_set_auto_start_dylibloader_wrapper_asound)( snd_timer_params_t*, int);
+int (*snd_timer_params_get_auto_start_dylibloader_wrapper_asound)( snd_timer_params_t*);
+int (*snd_timer_params_set_exclusive_dylibloader_wrapper_asound)( snd_timer_params_t*, int);
+int (*snd_timer_params_get_exclusive_dylibloader_wrapper_asound)( snd_timer_params_t*);
+int (*snd_timer_params_set_early_event_dylibloader_wrapper_asound)( snd_timer_params_t*, int);
+int (*snd_timer_params_get_early_event_dylibloader_wrapper_asound)( snd_timer_params_t*);
+void (*snd_timer_params_set_ticks_dylibloader_wrapper_asound)( snd_timer_params_t*, long);
+long (*snd_timer_params_get_ticks_dylibloader_wrapper_asound)( snd_timer_params_t*);
+void (*snd_timer_params_set_queue_size_dylibloader_wrapper_asound)( snd_timer_params_t*, long);
+long (*snd_timer_params_get_queue_size_dylibloader_wrapper_asound)( snd_timer_params_t*);
+void (*snd_timer_params_set_filter_dylibloader_wrapper_asound)( snd_timer_params_t*, unsigned int);
+unsigned int (*snd_timer_params_get_filter_dylibloader_wrapper_asound)( snd_timer_params_t*);
+size_t (*snd_timer_status_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_timer_status_malloc_dylibloader_wrapper_asound)( snd_timer_status_t**);
+void (*snd_timer_status_free_dylibloader_wrapper_asound)( snd_timer_status_t*);
+void (*snd_timer_status_copy_dylibloader_wrapper_asound)( snd_timer_status_t*,const snd_timer_status_t*);
+snd_htimestamp_t (*snd_timer_status_get_timestamp_dylibloader_wrapper_asound)( snd_timer_status_t*);
+long (*snd_timer_status_get_resolution_dylibloader_wrapper_asound)( snd_timer_status_t*);
+long (*snd_timer_status_get_lost_dylibloader_wrapper_asound)( snd_timer_status_t*);
+long (*snd_timer_status_get_overrun_dylibloader_wrapper_asound)( snd_timer_status_t*);
+long (*snd_timer_status_get_queue_dylibloader_wrapper_asound)( snd_timer_status_t*);
+long (*snd_timer_info_get_ticks_dylibloader_wrapper_asound)( snd_timer_info_t*);
+int (*snd_hwdep_open_dylibloader_wrapper_asound)( snd_hwdep_t**,const char*, int);
+int (*snd_hwdep_close_dylibloader_wrapper_asound)( snd_hwdep_t*);
+int (*snd_hwdep_poll_descriptors_dylibloader_wrapper_asound)( snd_hwdep_t*,struct pollfd*, unsigned int);
+int (*snd_hwdep_poll_descriptors_count_dylibloader_wrapper_asound)( snd_hwdep_t*);
+int (*snd_hwdep_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_hwdep_t*,struct pollfd*, unsigned int, unsigned short*);
+int (*snd_hwdep_nonblock_dylibloader_wrapper_asound)( snd_hwdep_t*, int);
+int (*snd_hwdep_info_dylibloader_wrapper_asound)( snd_hwdep_t*, snd_hwdep_info_t*);
+int (*snd_hwdep_dsp_status_dylibloader_wrapper_asound)( snd_hwdep_t*, snd_hwdep_dsp_status_t*);
+int (*snd_hwdep_dsp_load_dylibloader_wrapper_asound)( snd_hwdep_t*, snd_hwdep_dsp_image_t*);
+int (*snd_hwdep_ioctl_dylibloader_wrapper_asound)( snd_hwdep_t*, unsigned int, void*);
+ssize_t (*snd_hwdep_write_dylibloader_wrapper_asound)( snd_hwdep_t*,const void*, size_t);
+ssize_t (*snd_hwdep_read_dylibloader_wrapper_asound)( snd_hwdep_t*, void*, size_t);
+size_t (*snd_hwdep_info_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_hwdep_info_malloc_dylibloader_wrapper_asound)( snd_hwdep_info_t**);
+void (*snd_hwdep_info_free_dylibloader_wrapper_asound)( snd_hwdep_info_t*);
+void (*snd_hwdep_info_copy_dylibloader_wrapper_asound)( snd_hwdep_info_t*,const snd_hwdep_info_t*);
+unsigned int (*snd_hwdep_info_get_device_dylibloader_wrapper_asound)(const snd_hwdep_info_t*);
+int (*snd_hwdep_info_get_card_dylibloader_wrapper_asound)(const snd_hwdep_info_t*);
+const char* (*snd_hwdep_info_get_id_dylibloader_wrapper_asound)(const snd_hwdep_info_t*);
+const char* (*snd_hwdep_info_get_name_dylibloader_wrapper_asound)(const snd_hwdep_info_t*);
+snd_hwdep_iface_t (*snd_hwdep_info_get_iface_dylibloader_wrapper_asound)(const snd_hwdep_info_t*);
+void (*snd_hwdep_info_set_device_dylibloader_wrapper_asound)( snd_hwdep_info_t*, unsigned int);
+size_t (*snd_hwdep_dsp_status_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_hwdep_dsp_status_malloc_dylibloader_wrapper_asound)( snd_hwdep_dsp_status_t**);
+void (*snd_hwdep_dsp_status_free_dylibloader_wrapper_asound)( snd_hwdep_dsp_status_t*);
+void (*snd_hwdep_dsp_status_copy_dylibloader_wrapper_asound)( snd_hwdep_dsp_status_t*,const snd_hwdep_dsp_status_t*);
+unsigned int (*snd_hwdep_dsp_status_get_version_dylibloader_wrapper_asound)(const snd_hwdep_dsp_status_t*);
+const char* (*snd_hwdep_dsp_status_get_id_dylibloader_wrapper_asound)(const snd_hwdep_dsp_status_t*);
+unsigned int (*snd_hwdep_dsp_status_get_num_dsps_dylibloader_wrapper_asound)(const snd_hwdep_dsp_status_t*);
+unsigned int (*snd_hwdep_dsp_status_get_dsp_loaded_dylibloader_wrapper_asound)(const snd_hwdep_dsp_status_t*);
+unsigned int (*snd_hwdep_dsp_status_get_chip_ready_dylibloader_wrapper_asound)(const snd_hwdep_dsp_status_t*);
+size_t (*snd_hwdep_dsp_image_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_hwdep_dsp_image_malloc_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t**);
+void (*snd_hwdep_dsp_image_free_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*);
+void (*snd_hwdep_dsp_image_copy_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*,const snd_hwdep_dsp_image_t*);
+unsigned int (*snd_hwdep_dsp_image_get_index_dylibloader_wrapper_asound)(const snd_hwdep_dsp_image_t*);
+const char* (*snd_hwdep_dsp_image_get_name_dylibloader_wrapper_asound)(const snd_hwdep_dsp_image_t*);
+const void* (*snd_hwdep_dsp_image_get_image_dylibloader_wrapper_asound)(const snd_hwdep_dsp_image_t*);
+size_t (*snd_hwdep_dsp_image_get_length_dylibloader_wrapper_asound)(const snd_hwdep_dsp_image_t*);
+void (*snd_hwdep_dsp_image_set_index_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*, unsigned int);
+void (*snd_hwdep_dsp_image_set_name_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*,const char*);
+void (*snd_hwdep_dsp_image_set_image_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*, void*);
+void (*snd_hwdep_dsp_image_set_length_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*, size_t);
+int (*snd_card_load_dylibloader_wrapper_asound)( int);
+int (*snd_card_next_dylibloader_wrapper_asound)( int*);
+int (*snd_card_get_index_dylibloader_wrapper_asound)(const char*);
+int (*snd_card_get_name_dylibloader_wrapper_asound)( int, char**);
+int (*snd_card_get_longname_dylibloader_wrapper_asound)( int, char**);
+int (*snd_device_name_hint_dylibloader_wrapper_asound)( int,const char*, void***);
+int (*snd_device_name_free_hint_dylibloader_wrapper_asound)( void**);
+char* (*snd_device_name_get_hint_dylibloader_wrapper_asound)(const void*,const char*);
+int (*snd_ctl_open_dylibloader_wrapper_asound)( snd_ctl_t**,const char*, int);
+int (*snd_ctl_open_lconf_dylibloader_wrapper_asound)( snd_ctl_t**,const char*, int, snd_config_t*);
+int (*snd_ctl_open_fallback_dylibloader_wrapper_asound)( snd_ctl_t**, snd_config_t*,const char*,const char*, int);
+int (*snd_ctl_close_dylibloader_wrapper_asound)( snd_ctl_t*);
+int (*snd_ctl_nonblock_dylibloader_wrapper_asound)( snd_ctl_t*, int);
+int (*snd_async_add_ctl_handler_dylibloader_wrapper_asound)( snd_async_handler_t**, snd_ctl_t*, snd_async_callback_t, void*);
+snd_ctl_t* (*snd_async_handler_get_ctl_dylibloader_wrapper_asound)( snd_async_handler_t*);
+int (*snd_ctl_poll_descriptors_count_dylibloader_wrapper_asound)( snd_ctl_t*);
+int (*snd_ctl_poll_descriptors_dylibloader_wrapper_asound)( snd_ctl_t*,struct pollfd*, unsigned int);
+int (*snd_ctl_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_ctl_t*,struct pollfd*, unsigned int, unsigned short*);
+int (*snd_ctl_subscribe_events_dylibloader_wrapper_asound)( snd_ctl_t*, int);
+int (*snd_ctl_card_info_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_card_info_t*);
+int (*snd_ctl_elem_list_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_list_t*);
+int (*snd_ctl_elem_info_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_read_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_value_t*);
+int (*snd_ctl_elem_write_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_value_t*);
+int (*snd_ctl_elem_lock_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_id_t*);
+int (*snd_ctl_elem_unlock_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_id_t*);
+int (*snd_ctl_elem_tlv_read_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, unsigned int*, unsigned int);
+int (*snd_ctl_elem_tlv_write_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*,const unsigned int*);
+int (*snd_ctl_elem_tlv_command_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*,const unsigned int*);
+int (*snd_ctl_hwdep_next_device_dylibloader_wrapper_asound)( snd_ctl_t*, int*);
+int (*snd_ctl_hwdep_info_dylibloader_wrapper_asound)( snd_ctl_t*, snd_hwdep_info_t*);
+int (*snd_ctl_pcm_next_device_dylibloader_wrapper_asound)( snd_ctl_t*, int*);
+int (*snd_ctl_pcm_info_dylibloader_wrapper_asound)( snd_ctl_t*, snd_pcm_info_t*);
+int (*snd_ctl_pcm_prefer_subdevice_dylibloader_wrapper_asound)( snd_ctl_t*, int);
+int (*snd_ctl_rawmidi_next_device_dylibloader_wrapper_asound)( snd_ctl_t*, int*);
+int (*snd_ctl_rawmidi_info_dylibloader_wrapper_asound)( snd_ctl_t*, snd_rawmidi_info_t*);
+int (*snd_ctl_rawmidi_prefer_subdevice_dylibloader_wrapper_asound)( snd_ctl_t*, int);
+int (*snd_ctl_set_power_state_dylibloader_wrapper_asound)( snd_ctl_t*, unsigned int);
+int (*snd_ctl_get_power_state_dylibloader_wrapper_asound)( snd_ctl_t*, unsigned int*);
+int (*snd_ctl_read_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_event_t*);
+int (*snd_ctl_wait_dylibloader_wrapper_asound)( snd_ctl_t*, int);
+const char* (*snd_ctl_name_dylibloader_wrapper_asound)( snd_ctl_t*);
+snd_ctl_type_t (*snd_ctl_type_dylibloader_wrapper_asound)( snd_ctl_t*);
+const char* (*snd_ctl_elem_type_name_dylibloader_wrapper_asound)( snd_ctl_elem_type_t);
+const char* (*snd_ctl_elem_iface_name_dylibloader_wrapper_asound)( snd_ctl_elem_iface_t);
+const char* (*snd_ctl_event_type_name_dylibloader_wrapper_asound)( snd_ctl_event_type_t);
+unsigned int (*snd_ctl_event_elem_get_mask_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+unsigned int (*snd_ctl_event_elem_get_numid_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+void (*snd_ctl_event_elem_get_id_dylibloader_wrapper_asound)(const snd_ctl_event_t*, snd_ctl_elem_id_t*);
+snd_ctl_elem_iface_t (*snd_ctl_event_elem_get_interface_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+unsigned int (*snd_ctl_event_elem_get_device_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+unsigned int (*snd_ctl_event_elem_get_subdevice_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+const char* (*snd_ctl_event_elem_get_name_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+unsigned int (*snd_ctl_event_elem_get_index_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+int (*snd_ctl_elem_list_alloc_space_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*, unsigned int);
+void (*snd_ctl_elem_list_free_space_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*);
+char* (*snd_ctl_ascii_elem_id_get_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*);
+int (*snd_ctl_ascii_elem_id_parse_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*,const char*);
+int (*snd_ctl_ascii_value_parse_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_value_t*, snd_ctl_elem_info_t*,const char*);
+size_t (*snd_ctl_elem_id_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_ctl_elem_id_malloc_dylibloader_wrapper_asound)( snd_ctl_elem_id_t**);
+void (*snd_ctl_elem_id_free_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*);
+void (*snd_ctl_elem_id_clear_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*);
+void (*snd_ctl_elem_id_copy_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*,const snd_ctl_elem_id_t*);
+unsigned int (*snd_ctl_elem_id_get_numid_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+snd_ctl_elem_iface_t (*snd_ctl_elem_id_get_interface_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+unsigned int (*snd_ctl_elem_id_get_device_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+unsigned int (*snd_ctl_elem_id_get_subdevice_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+const char* (*snd_ctl_elem_id_get_name_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+unsigned int (*snd_ctl_elem_id_get_index_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+void (*snd_ctl_elem_id_set_numid_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*, unsigned int);
+void (*snd_ctl_elem_id_set_interface_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*, snd_ctl_elem_iface_t);
+void (*snd_ctl_elem_id_set_device_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*, unsigned int);
+void (*snd_ctl_elem_id_set_subdevice_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*, unsigned int);
+void (*snd_ctl_elem_id_set_name_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*,const char*);
+void (*snd_ctl_elem_id_set_index_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*, unsigned int);
+size_t (*snd_ctl_card_info_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_ctl_card_info_malloc_dylibloader_wrapper_asound)( snd_ctl_card_info_t**);
+void (*snd_ctl_card_info_free_dylibloader_wrapper_asound)( snd_ctl_card_info_t*);
+void (*snd_ctl_card_info_clear_dylibloader_wrapper_asound)( snd_ctl_card_info_t*);
+void (*snd_ctl_card_info_copy_dylibloader_wrapper_asound)( snd_ctl_card_info_t*,const snd_ctl_card_info_t*);
+int (*snd_ctl_card_info_get_card_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+const char* (*snd_ctl_card_info_get_id_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+const char* (*snd_ctl_card_info_get_driver_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+const char* (*snd_ctl_card_info_get_name_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+const char* (*snd_ctl_card_info_get_longname_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+const char* (*snd_ctl_card_info_get_mixername_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+const char* (*snd_ctl_card_info_get_components_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+size_t (*snd_ctl_event_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_ctl_event_malloc_dylibloader_wrapper_asound)( snd_ctl_event_t**);
+void (*snd_ctl_event_free_dylibloader_wrapper_asound)( snd_ctl_event_t*);
+void (*snd_ctl_event_clear_dylibloader_wrapper_asound)( snd_ctl_event_t*);
+void (*snd_ctl_event_copy_dylibloader_wrapper_asound)( snd_ctl_event_t*,const snd_ctl_event_t*);
+snd_ctl_event_type_t (*snd_ctl_event_get_type_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+size_t (*snd_ctl_elem_list_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_ctl_elem_list_malloc_dylibloader_wrapper_asound)( snd_ctl_elem_list_t**);
+void (*snd_ctl_elem_list_free_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*);
+void (*snd_ctl_elem_list_clear_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*);
+void (*snd_ctl_elem_list_copy_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*,const snd_ctl_elem_list_t*);
+void (*snd_ctl_elem_list_set_offset_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*, unsigned int);
+unsigned int (*snd_ctl_elem_list_get_used_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*);
+unsigned int (*snd_ctl_elem_list_get_count_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*);
+void (*snd_ctl_elem_list_get_id_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int, snd_ctl_elem_id_t*);
+unsigned int (*snd_ctl_elem_list_get_numid_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+snd_ctl_elem_iface_t (*snd_ctl_elem_list_get_interface_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+unsigned int (*snd_ctl_elem_list_get_device_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+unsigned int (*snd_ctl_elem_list_get_subdevice_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+const char* (*snd_ctl_elem_list_get_name_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+unsigned int (*snd_ctl_elem_list_get_index_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+size_t (*snd_ctl_elem_info_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_ctl_elem_info_malloc_dylibloader_wrapper_asound)( snd_ctl_elem_info_t**);
+void (*snd_ctl_elem_info_free_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*);
+void (*snd_ctl_elem_info_clear_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*);
+void (*snd_ctl_elem_info_copy_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*,const snd_ctl_elem_info_t*);
+snd_ctl_elem_type_t (*snd_ctl_elem_info_get_type_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_is_readable_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_is_writable_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_is_volatile_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_is_inactive_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_is_locked_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_is_tlv_readable_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_is_tlv_writable_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_is_tlv_commandable_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_is_owner_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_is_user_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+pid_t (*snd_ctl_elem_info_get_owner_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+unsigned int (*snd_ctl_elem_info_get_count_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+long (*snd_ctl_elem_info_get_min_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+long (*snd_ctl_elem_info_get_max_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+long (*snd_ctl_elem_info_get_step_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+long long (*snd_ctl_elem_info_get_min64_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+long long (*snd_ctl_elem_info_get_max64_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+long long (*snd_ctl_elem_info_get_step64_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+unsigned int (*snd_ctl_elem_info_get_items_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+void (*snd_ctl_elem_info_set_item_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, unsigned int);
+const char* (*snd_ctl_elem_info_get_item_name_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_get_dimensions_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+int (*snd_ctl_elem_info_get_dimension_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*, unsigned int);
+int (*snd_ctl_elem_info_set_dimension_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*,const int [4]);
+void (*snd_ctl_elem_info_get_id_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*, snd_ctl_elem_id_t*);
+unsigned int (*snd_ctl_elem_info_get_numid_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+snd_ctl_elem_iface_t (*snd_ctl_elem_info_get_interface_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+unsigned int (*snd_ctl_elem_info_get_device_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+unsigned int (*snd_ctl_elem_info_get_subdevice_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+const char* (*snd_ctl_elem_info_get_name_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+unsigned int (*snd_ctl_elem_info_get_index_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+void (*snd_ctl_elem_info_set_id_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*,const snd_ctl_elem_id_t*);
+void (*snd_ctl_elem_info_set_numid_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, unsigned int);
+void (*snd_ctl_elem_info_set_interface_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, snd_ctl_elem_iface_t);
+void (*snd_ctl_elem_info_set_device_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, unsigned int);
+void (*snd_ctl_elem_info_set_subdevice_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, unsigned int);
+void (*snd_ctl_elem_info_set_name_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*,const char*);
+void (*snd_ctl_elem_info_set_index_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, unsigned int);
+int (*snd_ctl_add_integer_elem_set_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*, unsigned int, unsigned int, long, long, long);
+int (*snd_ctl_add_integer64_elem_set_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*, unsigned int, unsigned int, long long, long long, long long);
+int (*snd_ctl_add_boolean_elem_set_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*, unsigned int, unsigned int);
+int (*snd_ctl_add_enumerated_elem_set_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*, unsigned int, unsigned int, unsigned int,const char* []);
+int (*snd_ctl_add_bytes_elem_set_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*, unsigned int, unsigned int);
+int (*snd_ctl_elem_add_integer_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, unsigned int, long, long, long);
+int (*snd_ctl_elem_add_integer64_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, unsigned int, long long, long long, long long);
+int (*snd_ctl_elem_add_boolean_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, unsigned int);
+int (*snd_ctl_elem_add_enumerated_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, unsigned int, unsigned int,const char* []);
+int (*snd_ctl_elem_add_iec958_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*);
+int (*snd_ctl_elem_remove_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_id_t*);
+size_t (*snd_ctl_elem_value_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_ctl_elem_value_malloc_dylibloader_wrapper_asound)( snd_ctl_elem_value_t**);
+void (*snd_ctl_elem_value_free_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*);
+void (*snd_ctl_elem_value_clear_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*);
+void (*snd_ctl_elem_value_copy_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*,const snd_ctl_elem_value_t*);
+int (*snd_ctl_elem_value_compare_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*,const snd_ctl_elem_value_t*);
+void (*snd_ctl_elem_value_get_id_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, snd_ctl_elem_id_t*);
+unsigned int (*snd_ctl_elem_value_get_numid_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+snd_ctl_elem_iface_t (*snd_ctl_elem_value_get_interface_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+unsigned int (*snd_ctl_elem_value_get_device_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+unsigned int (*snd_ctl_elem_value_get_subdevice_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+const char* (*snd_ctl_elem_value_get_name_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+unsigned int (*snd_ctl_elem_value_get_index_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+void (*snd_ctl_elem_value_set_id_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*,const snd_ctl_elem_id_t*);
+void (*snd_ctl_elem_value_set_numid_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int);
+void (*snd_ctl_elem_value_set_interface_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, snd_ctl_elem_iface_t);
+void (*snd_ctl_elem_value_set_device_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int);
+void (*snd_ctl_elem_value_set_subdevice_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int);
+void (*snd_ctl_elem_value_set_name_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*,const char*);
+void (*snd_ctl_elem_value_set_index_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int);
+int (*snd_ctl_elem_value_get_boolean_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, unsigned int);
+long (*snd_ctl_elem_value_get_integer_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, unsigned int);
+long long (*snd_ctl_elem_value_get_integer64_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, unsigned int);
+unsigned int (*snd_ctl_elem_value_get_enumerated_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, unsigned int);
+unsigned char (*snd_ctl_elem_value_get_byte_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, unsigned int);
+void (*snd_ctl_elem_value_set_boolean_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int, long);
+void (*snd_ctl_elem_value_set_integer_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int, long);
+void (*snd_ctl_elem_value_set_integer64_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int, long long);
+void (*snd_ctl_elem_value_set_enumerated_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int, unsigned int);
+void (*snd_ctl_elem_value_set_byte_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int, unsigned char);
+void (*snd_ctl_elem_set_bytes_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, void*, size_t);
+const void* (*snd_ctl_elem_value_get_bytes_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+void (*snd_ctl_elem_value_get_iec958_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, snd_aes_iec958_t*);
+void (*snd_ctl_elem_value_set_iec958_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*,const snd_aes_iec958_t*);
+int (*snd_tlv_parse_dB_info_dylibloader_wrapper_asound)( unsigned int*, unsigned int, unsigned int**);
+int (*snd_tlv_get_dB_range_dylibloader_wrapper_asound)( unsigned int*, long, long, long*, long*);
+int (*snd_tlv_convert_to_dB_dylibloader_wrapper_asound)( unsigned int*, long, long, long, long*);
+int (*snd_tlv_convert_from_dB_dylibloader_wrapper_asound)( unsigned int*, long, long, long, long*, int);
+int (*snd_ctl_get_dB_range_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, long*, long*);
+int (*snd_ctl_convert_to_dB_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, long, long*);
+int (*snd_ctl_convert_from_dB_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, long, long*, int);
+int (*snd_hctl_compare_fast_dylibloader_wrapper_asound)(const snd_hctl_elem_t*,const snd_hctl_elem_t*);
+int (*snd_hctl_open_dylibloader_wrapper_asound)( snd_hctl_t**,const char*, int);
+int (*snd_hctl_open_ctl_dylibloader_wrapper_asound)( snd_hctl_t**, snd_ctl_t*);
+int (*snd_hctl_close_dylibloader_wrapper_asound)( snd_hctl_t*);
+int (*snd_hctl_nonblock_dylibloader_wrapper_asound)( snd_hctl_t*, int);
+int (*snd_hctl_poll_descriptors_count_dylibloader_wrapper_asound)( snd_hctl_t*);
+int (*snd_hctl_poll_descriptors_dylibloader_wrapper_asound)( snd_hctl_t*,struct pollfd*, unsigned int);
+int (*snd_hctl_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_hctl_t*,struct pollfd*, unsigned int, unsigned short*);
+unsigned int (*snd_hctl_get_count_dylibloader_wrapper_asound)( snd_hctl_t*);
+int (*snd_hctl_set_compare_dylibloader_wrapper_asound)( snd_hctl_t*, snd_hctl_compare_t);
+snd_hctl_elem_t* (*snd_hctl_first_elem_dylibloader_wrapper_asound)( snd_hctl_t*);
+snd_hctl_elem_t* (*snd_hctl_last_elem_dylibloader_wrapper_asound)( snd_hctl_t*);
+snd_hctl_elem_t* (*snd_hctl_find_elem_dylibloader_wrapper_asound)( snd_hctl_t*,const snd_ctl_elem_id_t*);
+void (*snd_hctl_set_callback_dylibloader_wrapper_asound)( snd_hctl_t*, snd_hctl_callback_t);
+void (*snd_hctl_set_callback_private_dylibloader_wrapper_asound)( snd_hctl_t*, void*);
+void* (*snd_hctl_get_callback_private_dylibloader_wrapper_asound)( snd_hctl_t*);
+int (*snd_hctl_load_dylibloader_wrapper_asound)( snd_hctl_t*);
+int (*snd_hctl_free_dylibloader_wrapper_asound)( snd_hctl_t*);
+int (*snd_hctl_handle_events_dylibloader_wrapper_asound)( snd_hctl_t*);
+const char* (*snd_hctl_name_dylibloader_wrapper_asound)( snd_hctl_t*);
+int (*snd_hctl_wait_dylibloader_wrapper_asound)( snd_hctl_t*, int);
+snd_ctl_t* (*snd_hctl_ctl_dylibloader_wrapper_asound)( snd_hctl_t*);
+snd_hctl_elem_t* (*snd_hctl_elem_next_dylibloader_wrapper_asound)( snd_hctl_elem_t*);
+snd_hctl_elem_t* (*snd_hctl_elem_prev_dylibloader_wrapper_asound)( snd_hctl_elem_t*);
+int (*snd_hctl_elem_info_dylibloader_wrapper_asound)( snd_hctl_elem_t*, snd_ctl_elem_info_t*);
+int (*snd_hctl_elem_read_dylibloader_wrapper_asound)( snd_hctl_elem_t*, snd_ctl_elem_value_t*);
+int (*snd_hctl_elem_write_dylibloader_wrapper_asound)( snd_hctl_elem_t*, snd_ctl_elem_value_t*);
+int (*snd_hctl_elem_tlv_read_dylibloader_wrapper_asound)( snd_hctl_elem_t*, unsigned int*, unsigned int);
+int (*snd_hctl_elem_tlv_write_dylibloader_wrapper_asound)( snd_hctl_elem_t*,const unsigned int*);
+int (*snd_hctl_elem_tlv_command_dylibloader_wrapper_asound)( snd_hctl_elem_t*,const unsigned int*);
+snd_hctl_t* (*snd_hctl_elem_get_hctl_dylibloader_wrapper_asound)( snd_hctl_elem_t*);
+void (*snd_hctl_elem_get_id_dylibloader_wrapper_asound)(const snd_hctl_elem_t*, snd_ctl_elem_id_t*);
+unsigned int (*snd_hctl_elem_get_numid_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+snd_ctl_elem_iface_t (*snd_hctl_elem_get_interface_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+unsigned int (*snd_hctl_elem_get_device_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+unsigned int (*snd_hctl_elem_get_subdevice_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+const char* (*snd_hctl_elem_get_name_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+unsigned int (*snd_hctl_elem_get_index_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+void (*snd_hctl_elem_set_callback_dylibloader_wrapper_asound)( snd_hctl_elem_t*, snd_hctl_elem_callback_t);
+void* (*snd_hctl_elem_get_callback_private_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+void (*snd_hctl_elem_set_callback_private_dylibloader_wrapper_asound)( snd_hctl_elem_t*, void*);
+int (*snd_sctl_build_dylibloader_wrapper_asound)( snd_sctl_t**, snd_ctl_t*, snd_config_t*, snd_config_t*, int);
+int (*snd_sctl_free_dylibloader_wrapper_asound)( snd_sctl_t*);
+int (*snd_sctl_install_dylibloader_wrapper_asound)( snd_sctl_t*);
+int (*snd_sctl_remove_dylibloader_wrapper_asound)( snd_sctl_t*);
+int (*snd_mixer_open_dylibloader_wrapper_asound)( snd_mixer_t**, int);
+int (*snd_mixer_close_dylibloader_wrapper_asound)( snd_mixer_t*);
+snd_mixer_elem_t* (*snd_mixer_first_elem_dylibloader_wrapper_asound)( snd_mixer_t*);
+snd_mixer_elem_t* (*snd_mixer_last_elem_dylibloader_wrapper_asound)( snd_mixer_t*);
+int (*snd_mixer_handle_events_dylibloader_wrapper_asound)( snd_mixer_t*);
+int (*snd_mixer_attach_dylibloader_wrapper_asound)( snd_mixer_t*,const char*);
+int (*snd_mixer_attach_hctl_dylibloader_wrapper_asound)( snd_mixer_t*, snd_hctl_t*);
+int (*snd_mixer_detach_dylibloader_wrapper_asound)( snd_mixer_t*,const char*);
+int (*snd_mixer_detach_hctl_dylibloader_wrapper_asound)( snd_mixer_t*, snd_hctl_t*);
+int (*snd_mixer_get_hctl_dylibloader_wrapper_asound)( snd_mixer_t*,const char*, snd_hctl_t**);
+int (*snd_mixer_poll_descriptors_count_dylibloader_wrapper_asound)( snd_mixer_t*);
+int (*snd_mixer_poll_descriptors_dylibloader_wrapper_asound)( snd_mixer_t*,struct pollfd*, unsigned int);
+int (*snd_mixer_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_mixer_t*,struct pollfd*, unsigned int, unsigned short*);
+int (*snd_mixer_load_dylibloader_wrapper_asound)( snd_mixer_t*);
+void (*snd_mixer_free_dylibloader_wrapper_asound)( snd_mixer_t*);
+int (*snd_mixer_wait_dylibloader_wrapper_asound)( snd_mixer_t*, int);
+int (*snd_mixer_set_compare_dylibloader_wrapper_asound)( snd_mixer_t*, snd_mixer_compare_t);
+void (*snd_mixer_set_callback_dylibloader_wrapper_asound)( snd_mixer_t*, snd_mixer_callback_t);
+void* (*snd_mixer_get_callback_private_dylibloader_wrapper_asound)(const snd_mixer_t*);
+void (*snd_mixer_set_callback_private_dylibloader_wrapper_asound)( snd_mixer_t*, void*);
+unsigned int (*snd_mixer_get_count_dylibloader_wrapper_asound)(const snd_mixer_t*);
+int (*snd_mixer_class_unregister_dylibloader_wrapper_asound)( snd_mixer_class_t*);
+snd_mixer_elem_t* (*snd_mixer_elem_next_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+snd_mixer_elem_t* (*snd_mixer_elem_prev_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+void (*snd_mixer_elem_set_callback_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_elem_callback_t);
+void* (*snd_mixer_elem_get_callback_private_dylibloader_wrapper_asound)(const snd_mixer_elem_t*);
+void (*snd_mixer_elem_set_callback_private_dylibloader_wrapper_asound)( snd_mixer_elem_t*, void*);
+snd_mixer_elem_type_t (*snd_mixer_elem_get_type_dylibloader_wrapper_asound)(const snd_mixer_elem_t*);
+int (*snd_mixer_class_register_dylibloader_wrapper_asound)( snd_mixer_class_t*, snd_mixer_t*);
+int (*snd_mixer_elem_new_dylibloader_wrapper_asound)( snd_mixer_elem_t**, snd_mixer_elem_type_t, int, void*, void*);
+int (*snd_mixer_elem_add_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_class_t*);
+int (*snd_mixer_elem_remove_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+void (*snd_mixer_elem_free_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_elem_info_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_elem_value_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_elem_attach_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_hctl_elem_t*);
+int (*snd_mixer_elem_detach_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_hctl_elem_t*);
+int (*snd_mixer_elem_empty_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+void* (*snd_mixer_elem_get_private_dylibloader_wrapper_asound)(const snd_mixer_elem_t*);
+size_t (*snd_mixer_class_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_mixer_class_malloc_dylibloader_wrapper_asound)( snd_mixer_class_t**);
+void (*snd_mixer_class_free_dylibloader_wrapper_asound)( snd_mixer_class_t*);
+void (*snd_mixer_class_copy_dylibloader_wrapper_asound)( snd_mixer_class_t*,const snd_mixer_class_t*);
+snd_mixer_t* (*snd_mixer_class_get_mixer_dylibloader_wrapper_asound)(const snd_mixer_class_t*);
+snd_mixer_event_t (*snd_mixer_class_get_event_dylibloader_wrapper_asound)(const snd_mixer_class_t*);
+void* (*snd_mixer_class_get_private_dylibloader_wrapper_asound)(const snd_mixer_class_t*);
+snd_mixer_compare_t (*snd_mixer_class_get_compare_dylibloader_wrapper_asound)(const snd_mixer_class_t*);
+int (*snd_mixer_class_set_event_dylibloader_wrapper_asound)( snd_mixer_class_t*, snd_mixer_event_t);
+int (*snd_mixer_class_set_private_dylibloader_wrapper_asound)( snd_mixer_class_t*, void*);
+int (*snd_mixer_class_set_private_free_dylibloader_wrapper_asound)( snd_mixer_class_t*, void*);
+int (*snd_mixer_class_set_compare_dylibloader_wrapper_asound)( snd_mixer_class_t*, snd_mixer_compare_t);
+const char* (*snd_mixer_selem_channel_name_dylibloader_wrapper_asound)( snd_mixer_selem_channel_id_t);
+int (*snd_mixer_selem_register_dylibloader_wrapper_asound)( snd_mixer_t*,struct snd_mixer_selem_regopt*, snd_mixer_class_t**);
+void (*snd_mixer_selem_get_id_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_id_t*);
+const char* (*snd_mixer_selem_get_name_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+unsigned int (*snd_mixer_selem_get_index_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+snd_mixer_elem_t* (*snd_mixer_find_selem_dylibloader_wrapper_asound)( snd_mixer_t*,const snd_mixer_selem_id_t*);
+int (*snd_mixer_selem_is_active_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_is_playback_mono_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_playback_channel_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t);
+int (*snd_mixer_selem_is_capture_mono_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_capture_channel_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t);
+int (*snd_mixer_selem_get_capture_group_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_common_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_playback_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_playback_volume_joined_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_capture_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_capture_volume_joined_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_common_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_playback_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_playback_switch_joined_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_capture_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_capture_switch_joined_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_has_capture_switch_exclusive_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_ask_playback_vol_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, long*);
+int (*snd_mixer_selem_ask_capture_vol_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, long*);
+int (*snd_mixer_selem_ask_playback_dB_vol_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, int, long*);
+int (*snd_mixer_selem_ask_capture_dB_vol_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, int, long*);
+int (*snd_mixer_selem_get_playback_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long*);
+int (*snd_mixer_selem_get_capture_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long*);
+int (*snd_mixer_selem_get_playback_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long*);
+int (*snd_mixer_selem_get_capture_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long*);
+int (*snd_mixer_selem_get_playback_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, int*);
+int (*snd_mixer_selem_get_capture_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, int*);
+int (*snd_mixer_selem_set_playback_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long);
+int (*snd_mixer_selem_set_capture_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long);
+int (*snd_mixer_selem_set_playback_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long, int);
+int (*snd_mixer_selem_set_capture_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long, int);
+int (*snd_mixer_selem_set_playback_volume_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long);
+int (*snd_mixer_selem_set_capture_volume_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long);
+int (*snd_mixer_selem_set_playback_dB_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, int);
+int (*snd_mixer_selem_set_capture_dB_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, int);
+int (*snd_mixer_selem_set_playback_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, int);
+int (*snd_mixer_selem_set_capture_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, int);
+int (*snd_mixer_selem_set_playback_switch_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, int);
+int (*snd_mixer_selem_set_capture_switch_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, int);
+int (*snd_mixer_selem_get_playback_volume_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long*, long*);
+int (*snd_mixer_selem_get_playback_dB_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long*, long*);
+int (*snd_mixer_selem_set_playback_volume_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, long);
+int (*snd_mixer_selem_get_capture_volume_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long*, long*);
+int (*snd_mixer_selem_get_capture_dB_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long*, long*);
+int (*snd_mixer_selem_set_capture_volume_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, long);
+int (*snd_mixer_selem_is_enumerated_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_is_enum_playback_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_is_enum_capture_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_get_enum_items_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+int (*snd_mixer_selem_get_enum_item_name_dylibloader_wrapper_asound)( snd_mixer_elem_t*, unsigned int, size_t, char*);
+int (*snd_mixer_selem_get_enum_item_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, unsigned int*);
+int (*snd_mixer_selem_set_enum_item_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, unsigned int);
+size_t (*snd_mixer_selem_id_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_mixer_selem_id_malloc_dylibloader_wrapper_asound)( snd_mixer_selem_id_t**);
+void (*snd_mixer_selem_id_free_dylibloader_wrapper_asound)( snd_mixer_selem_id_t*);
+void (*snd_mixer_selem_id_copy_dylibloader_wrapper_asound)( snd_mixer_selem_id_t*,const snd_mixer_selem_id_t*);
+const char* (*snd_mixer_selem_id_get_name_dylibloader_wrapper_asound)(const snd_mixer_selem_id_t*);
+unsigned int (*snd_mixer_selem_id_get_index_dylibloader_wrapper_asound)(const snd_mixer_selem_id_t*);
+void (*snd_mixer_selem_id_set_name_dylibloader_wrapper_asound)( snd_mixer_selem_id_t*,const char*);
+void (*snd_mixer_selem_id_set_index_dylibloader_wrapper_asound)( snd_mixer_selem_id_t*, unsigned int);
+int (*snd_mixer_selem_id_parse_dylibloader_wrapper_asound)( snd_mixer_selem_id_t*,const char*);
+int (*snd_seq_open_dylibloader_wrapper_asound)( snd_seq_t**,const char*, int, int);
+int (*snd_seq_open_lconf_dylibloader_wrapper_asound)( snd_seq_t**,const char*, int, int, snd_config_t*);
+const char* (*snd_seq_name_dylibloader_wrapper_asound)( snd_seq_t*);
+snd_seq_type_t (*snd_seq_type_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_seq_close_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_seq_poll_descriptors_count_dylibloader_wrapper_asound)( snd_seq_t*, short);
+int (*snd_seq_poll_descriptors_dylibloader_wrapper_asound)( snd_seq_t*,struct pollfd*, unsigned int, short);
+int (*snd_seq_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_seq_t*,struct pollfd*, unsigned int, unsigned short*);
+int (*snd_seq_nonblock_dylibloader_wrapper_asound)( snd_seq_t*, int);
+int (*snd_seq_client_id_dylibloader_wrapper_asound)( snd_seq_t*);
+size_t (*snd_seq_get_output_buffer_size_dylibloader_wrapper_asound)( snd_seq_t*);
+size_t (*snd_seq_get_input_buffer_size_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_seq_set_output_buffer_size_dylibloader_wrapper_asound)( snd_seq_t*, size_t);
+int (*snd_seq_set_input_buffer_size_dylibloader_wrapper_asound)( snd_seq_t*, size_t);
+size_t (*snd_seq_system_info_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_seq_system_info_malloc_dylibloader_wrapper_asound)( snd_seq_system_info_t**);
+void (*snd_seq_system_info_free_dylibloader_wrapper_asound)( snd_seq_system_info_t*);
+void (*snd_seq_system_info_copy_dylibloader_wrapper_asound)( snd_seq_system_info_t*,const snd_seq_system_info_t*);
+int (*snd_seq_system_info_get_queues_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+int (*snd_seq_system_info_get_clients_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+int (*snd_seq_system_info_get_ports_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+int (*snd_seq_system_info_get_channels_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+int (*snd_seq_system_info_get_cur_clients_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+int (*snd_seq_system_info_get_cur_queues_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+int (*snd_seq_system_info_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_system_info_t*);
+size_t (*snd_seq_client_info_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_seq_client_info_malloc_dylibloader_wrapper_asound)( snd_seq_client_info_t**);
+void (*snd_seq_client_info_free_dylibloader_wrapper_asound)( snd_seq_client_info_t*);
+void (*snd_seq_client_info_copy_dylibloader_wrapper_asound)( snd_seq_client_info_t*,const snd_seq_client_info_t*);
+int (*snd_seq_client_info_get_client_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+snd_seq_client_type_t (*snd_seq_client_info_get_type_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+const char* (*snd_seq_client_info_get_name_dylibloader_wrapper_asound)( snd_seq_client_info_t*);
+int (*snd_seq_client_info_get_broadcast_filter_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+int (*snd_seq_client_info_get_error_bounce_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+int (*snd_seq_client_info_get_card_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+int (*snd_seq_client_info_get_pid_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+const unsigned char* (*snd_seq_client_info_get_event_filter_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+int (*snd_seq_client_info_get_num_ports_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+int (*snd_seq_client_info_get_event_lost_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+void (*snd_seq_client_info_set_client_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+void (*snd_seq_client_info_set_name_dylibloader_wrapper_asound)( snd_seq_client_info_t*,const char*);
+void (*snd_seq_client_info_set_broadcast_filter_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+void (*snd_seq_client_info_set_error_bounce_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+void (*snd_seq_client_info_set_event_filter_dylibloader_wrapper_asound)( snd_seq_client_info_t*, unsigned char*);
+void (*snd_seq_client_info_event_filter_clear_dylibloader_wrapper_asound)( snd_seq_client_info_t*);
+void (*snd_seq_client_info_event_filter_add_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+void (*snd_seq_client_info_event_filter_del_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+int (*snd_seq_client_info_event_filter_check_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+int (*snd_seq_get_client_info_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_client_info_t*);
+int (*snd_seq_get_any_client_info_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_client_info_t*);
+int (*snd_seq_set_client_info_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_client_info_t*);
+int (*snd_seq_query_next_client_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_client_info_t*);
+size_t (*snd_seq_client_pool_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_seq_client_pool_malloc_dylibloader_wrapper_asound)( snd_seq_client_pool_t**);
+void (*snd_seq_client_pool_free_dylibloader_wrapper_asound)( snd_seq_client_pool_t*);
+void (*snd_seq_client_pool_copy_dylibloader_wrapper_asound)( snd_seq_client_pool_t*,const snd_seq_client_pool_t*);
+int (*snd_seq_client_pool_get_client_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+size_t (*snd_seq_client_pool_get_output_pool_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+size_t (*snd_seq_client_pool_get_input_pool_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+size_t (*snd_seq_client_pool_get_output_room_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+size_t (*snd_seq_client_pool_get_output_free_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+size_t (*snd_seq_client_pool_get_input_free_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+void (*snd_seq_client_pool_set_output_pool_dylibloader_wrapper_asound)( snd_seq_client_pool_t*, size_t);
+void (*snd_seq_client_pool_set_input_pool_dylibloader_wrapper_asound)( snd_seq_client_pool_t*, size_t);
+void (*snd_seq_client_pool_set_output_room_dylibloader_wrapper_asound)( snd_seq_client_pool_t*, size_t);
+int (*snd_seq_get_client_pool_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_client_pool_t*);
+int (*snd_seq_set_client_pool_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_client_pool_t*);
+size_t (*snd_seq_port_info_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_seq_port_info_malloc_dylibloader_wrapper_asound)( snd_seq_port_info_t**);
+void (*snd_seq_port_info_free_dylibloader_wrapper_asound)( snd_seq_port_info_t*);
+void (*snd_seq_port_info_copy_dylibloader_wrapper_asound)( snd_seq_port_info_t*,const snd_seq_port_info_t*);
+int (*snd_seq_port_info_get_client_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+int (*snd_seq_port_info_get_port_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+const snd_seq_addr_t* (*snd_seq_port_info_get_addr_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+const char* (*snd_seq_port_info_get_name_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+unsigned int (*snd_seq_port_info_get_capability_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+unsigned int (*snd_seq_port_info_get_type_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+int (*snd_seq_port_info_get_midi_channels_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+int (*snd_seq_port_info_get_midi_voices_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+int (*snd_seq_port_info_get_synth_voices_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+int (*snd_seq_port_info_get_read_use_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+int (*snd_seq_port_info_get_write_use_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+int (*snd_seq_port_info_get_port_specified_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+int (*snd_seq_port_info_get_timestamping_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+int (*snd_seq_port_info_get_timestamp_real_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+int (*snd_seq_port_info_get_timestamp_queue_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+void (*snd_seq_port_info_set_client_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+void (*snd_seq_port_info_set_port_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+void (*snd_seq_port_info_set_addr_dylibloader_wrapper_asound)( snd_seq_port_info_t*,const snd_seq_addr_t*);
+void (*snd_seq_port_info_set_name_dylibloader_wrapper_asound)( snd_seq_port_info_t*,const char*);
+void (*snd_seq_port_info_set_capability_dylibloader_wrapper_asound)( snd_seq_port_info_t*, unsigned int);
+void (*snd_seq_port_info_set_type_dylibloader_wrapper_asound)( snd_seq_port_info_t*, unsigned int);
+void (*snd_seq_port_info_set_midi_channels_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+void (*snd_seq_port_info_set_midi_voices_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+void (*snd_seq_port_info_set_synth_voices_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+void (*snd_seq_port_info_set_port_specified_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+void (*snd_seq_port_info_set_timestamping_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+void (*snd_seq_port_info_set_timestamp_real_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+void (*snd_seq_port_info_set_timestamp_queue_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+int (*snd_seq_create_port_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_port_info_t*);
+int (*snd_seq_delete_port_dylibloader_wrapper_asound)( snd_seq_t*, int);
+int (*snd_seq_get_port_info_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_port_info_t*);
+int (*snd_seq_get_any_port_info_dylibloader_wrapper_asound)( snd_seq_t*, int, int, snd_seq_port_info_t*);
+int (*snd_seq_set_port_info_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_port_info_t*);
+int (*snd_seq_query_next_port_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_port_info_t*);
+size_t (*snd_seq_port_subscribe_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_seq_port_subscribe_malloc_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t**);
+void (*snd_seq_port_subscribe_free_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*);
+void (*snd_seq_port_subscribe_copy_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*,const snd_seq_port_subscribe_t*);
+const snd_seq_addr_t* (*snd_seq_port_subscribe_get_sender_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+const snd_seq_addr_t* (*snd_seq_port_subscribe_get_dest_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+int (*snd_seq_port_subscribe_get_queue_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+int (*snd_seq_port_subscribe_get_exclusive_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+int (*snd_seq_port_subscribe_get_time_update_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+int (*snd_seq_port_subscribe_get_time_real_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+void (*snd_seq_port_subscribe_set_sender_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*,const snd_seq_addr_t*);
+void (*snd_seq_port_subscribe_set_dest_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*,const snd_seq_addr_t*);
+void (*snd_seq_port_subscribe_set_queue_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*, int);
+void (*snd_seq_port_subscribe_set_exclusive_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*, int);
+void (*snd_seq_port_subscribe_set_time_update_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*, int);
+void (*snd_seq_port_subscribe_set_time_real_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*, int);
+int (*snd_seq_get_port_subscription_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_port_subscribe_t*);
+int (*snd_seq_subscribe_port_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_port_subscribe_t*);
+int (*snd_seq_unsubscribe_port_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_port_subscribe_t*);
+size_t (*snd_seq_query_subscribe_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_seq_query_subscribe_malloc_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t**);
+void (*snd_seq_query_subscribe_free_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*);
+void (*snd_seq_query_subscribe_copy_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*,const snd_seq_query_subscribe_t*);
+int (*snd_seq_query_subscribe_get_client_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+int (*snd_seq_query_subscribe_get_port_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+const snd_seq_addr_t* (*snd_seq_query_subscribe_get_root_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+snd_seq_query_subs_type_t (*snd_seq_query_subscribe_get_type_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+int (*snd_seq_query_subscribe_get_index_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+int (*snd_seq_query_subscribe_get_num_subs_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+const snd_seq_addr_t* (*snd_seq_query_subscribe_get_addr_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+int (*snd_seq_query_subscribe_get_queue_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+int (*snd_seq_query_subscribe_get_exclusive_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+int (*snd_seq_query_subscribe_get_time_update_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+int (*snd_seq_query_subscribe_get_time_real_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+void (*snd_seq_query_subscribe_set_client_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*, int);
+void (*snd_seq_query_subscribe_set_port_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*, int);
+void (*snd_seq_query_subscribe_set_root_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*,const snd_seq_addr_t*);
+void (*snd_seq_query_subscribe_set_type_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*, snd_seq_query_subs_type_t);
+void (*snd_seq_query_subscribe_set_index_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*, int);
+int (*snd_seq_query_port_subscribers_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_query_subscribe_t*);
+size_t (*snd_seq_queue_info_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_seq_queue_info_malloc_dylibloader_wrapper_asound)( snd_seq_queue_info_t**);
+void (*snd_seq_queue_info_free_dylibloader_wrapper_asound)( snd_seq_queue_info_t*);
+void (*snd_seq_queue_info_copy_dylibloader_wrapper_asound)( snd_seq_queue_info_t*,const snd_seq_queue_info_t*);
+int (*snd_seq_queue_info_get_queue_dylibloader_wrapper_asound)(const snd_seq_queue_info_t*);
+const char* (*snd_seq_queue_info_get_name_dylibloader_wrapper_asound)(const snd_seq_queue_info_t*);
+int (*snd_seq_queue_info_get_owner_dylibloader_wrapper_asound)(const snd_seq_queue_info_t*);
+int (*snd_seq_queue_info_get_locked_dylibloader_wrapper_asound)(const snd_seq_queue_info_t*);
+unsigned int (*snd_seq_queue_info_get_flags_dylibloader_wrapper_asound)(const snd_seq_queue_info_t*);
+void (*snd_seq_queue_info_set_name_dylibloader_wrapper_asound)( snd_seq_queue_info_t*,const char*);
+void (*snd_seq_queue_info_set_owner_dylibloader_wrapper_asound)( snd_seq_queue_info_t*, int);
+void (*snd_seq_queue_info_set_locked_dylibloader_wrapper_asound)( snd_seq_queue_info_t*, int);
+void (*snd_seq_queue_info_set_flags_dylibloader_wrapper_asound)( snd_seq_queue_info_t*, unsigned int);
+int (*snd_seq_create_queue_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_queue_info_t*);
+int (*snd_seq_alloc_named_queue_dylibloader_wrapper_asound)( snd_seq_t*,const char*);
+int (*snd_seq_alloc_queue_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_seq_free_queue_dylibloader_wrapper_asound)( snd_seq_t*, int);
+int (*snd_seq_get_queue_info_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_info_t*);
+int (*snd_seq_set_queue_info_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_info_t*);
+int (*snd_seq_query_named_queue_dylibloader_wrapper_asound)( snd_seq_t*,const char*);
+int (*snd_seq_get_queue_usage_dylibloader_wrapper_asound)( snd_seq_t*, int);
+int (*snd_seq_set_queue_usage_dylibloader_wrapper_asound)( snd_seq_t*, int, int);
+size_t (*snd_seq_queue_status_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_seq_queue_status_malloc_dylibloader_wrapper_asound)( snd_seq_queue_status_t**);
+void (*snd_seq_queue_status_free_dylibloader_wrapper_asound)( snd_seq_queue_status_t*);
+void (*snd_seq_queue_status_copy_dylibloader_wrapper_asound)( snd_seq_queue_status_t*,const snd_seq_queue_status_t*);
+int (*snd_seq_queue_status_get_queue_dylibloader_wrapper_asound)(const snd_seq_queue_status_t*);
+int (*snd_seq_queue_status_get_events_dylibloader_wrapper_asound)(const snd_seq_queue_status_t*);
+snd_seq_tick_time_t (*snd_seq_queue_status_get_tick_time_dylibloader_wrapper_asound)(const snd_seq_queue_status_t*);
+const snd_seq_real_time_t* (*snd_seq_queue_status_get_real_time_dylibloader_wrapper_asound)(const snd_seq_queue_status_t*);
+unsigned int (*snd_seq_queue_status_get_status_dylibloader_wrapper_asound)(const snd_seq_queue_status_t*);
+int (*snd_seq_get_queue_status_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_status_t*);
+size_t (*snd_seq_queue_tempo_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_seq_queue_tempo_malloc_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t**);
+void (*snd_seq_queue_tempo_free_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*);
+void (*snd_seq_queue_tempo_copy_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*,const snd_seq_queue_tempo_t*);
+int (*snd_seq_queue_tempo_get_queue_dylibloader_wrapper_asound)(const snd_seq_queue_tempo_t*);
+unsigned int (*snd_seq_queue_tempo_get_tempo_dylibloader_wrapper_asound)(const snd_seq_queue_tempo_t*);
+int (*snd_seq_queue_tempo_get_ppq_dylibloader_wrapper_asound)(const snd_seq_queue_tempo_t*);
+unsigned int (*snd_seq_queue_tempo_get_skew_dylibloader_wrapper_asound)(const snd_seq_queue_tempo_t*);
+unsigned int (*snd_seq_queue_tempo_get_skew_base_dylibloader_wrapper_asound)(const snd_seq_queue_tempo_t*);
+void (*snd_seq_queue_tempo_set_tempo_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*, unsigned int);
+void (*snd_seq_queue_tempo_set_ppq_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*, int);
+void (*snd_seq_queue_tempo_set_skew_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*, unsigned int);
+void (*snd_seq_queue_tempo_set_skew_base_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*, unsigned int);
+int (*snd_seq_get_queue_tempo_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_tempo_t*);
+int (*snd_seq_set_queue_tempo_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_tempo_t*);
+size_t (*snd_seq_queue_timer_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_seq_queue_timer_malloc_dylibloader_wrapper_asound)( snd_seq_queue_timer_t**);
+void (*snd_seq_queue_timer_free_dylibloader_wrapper_asound)( snd_seq_queue_timer_t*);
+void (*snd_seq_queue_timer_copy_dylibloader_wrapper_asound)( snd_seq_queue_timer_t*,const snd_seq_queue_timer_t*);
+int (*snd_seq_queue_timer_get_queue_dylibloader_wrapper_asound)(const snd_seq_queue_timer_t*);
+snd_seq_queue_timer_type_t (*snd_seq_queue_timer_get_type_dylibloader_wrapper_asound)(const snd_seq_queue_timer_t*);
+const snd_timer_id_t* (*snd_seq_queue_timer_get_id_dylibloader_wrapper_asound)(const snd_seq_queue_timer_t*);
+unsigned int (*snd_seq_queue_timer_get_resolution_dylibloader_wrapper_asound)(const snd_seq_queue_timer_t*);
+void (*snd_seq_queue_timer_set_type_dylibloader_wrapper_asound)( snd_seq_queue_timer_t*, snd_seq_queue_timer_type_t);
+void (*snd_seq_queue_timer_set_id_dylibloader_wrapper_asound)( snd_seq_queue_timer_t*,const snd_timer_id_t*);
+void (*snd_seq_queue_timer_set_resolution_dylibloader_wrapper_asound)( snd_seq_queue_timer_t*, unsigned int);
+int (*snd_seq_get_queue_timer_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_timer_t*);
+int (*snd_seq_set_queue_timer_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_timer_t*);
+int (*snd_seq_free_event_dylibloader_wrapper_asound)( snd_seq_event_t*);
+ssize_t (*snd_seq_event_length_dylibloader_wrapper_asound)( snd_seq_event_t*);
+int (*snd_seq_event_output_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_event_t*);
+int (*snd_seq_event_output_buffer_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_event_t*);
+int (*snd_seq_event_output_direct_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_event_t*);
+int (*snd_seq_event_input_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_event_t**);
+int (*snd_seq_event_input_pending_dylibloader_wrapper_asound)( snd_seq_t*, int);
+int (*snd_seq_drain_output_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_seq_event_output_pending_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_seq_extract_output_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_event_t**);
+int (*snd_seq_drop_output_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_seq_drop_output_buffer_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_seq_drop_input_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_seq_drop_input_buffer_dylibloader_wrapper_asound)( snd_seq_t*);
+size_t (*snd_seq_remove_events_sizeof_dylibloader_wrapper_asound)( void);
+int (*snd_seq_remove_events_malloc_dylibloader_wrapper_asound)( snd_seq_remove_events_t**);
+void (*snd_seq_remove_events_free_dylibloader_wrapper_asound)( snd_seq_remove_events_t*);
+void (*snd_seq_remove_events_copy_dylibloader_wrapper_asound)( snd_seq_remove_events_t*,const snd_seq_remove_events_t*);
+unsigned int (*snd_seq_remove_events_get_condition_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+int (*snd_seq_remove_events_get_queue_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+const snd_seq_timestamp_t* (*snd_seq_remove_events_get_time_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+const snd_seq_addr_t* (*snd_seq_remove_events_get_dest_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+int (*snd_seq_remove_events_get_channel_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+int (*snd_seq_remove_events_get_event_type_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+int (*snd_seq_remove_events_get_tag_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+void (*snd_seq_remove_events_set_condition_dylibloader_wrapper_asound)( snd_seq_remove_events_t*, unsigned int);
+void (*snd_seq_remove_events_set_queue_dylibloader_wrapper_asound)( snd_seq_remove_events_t*, int);
+void (*snd_seq_remove_events_set_time_dylibloader_wrapper_asound)( snd_seq_remove_events_t*,const snd_seq_timestamp_t*);
+void (*snd_seq_remove_events_set_dest_dylibloader_wrapper_asound)( snd_seq_remove_events_t*,const snd_seq_addr_t*);
+void (*snd_seq_remove_events_set_channel_dylibloader_wrapper_asound)( snd_seq_remove_events_t*, int);
+void (*snd_seq_remove_events_set_event_type_dylibloader_wrapper_asound)( snd_seq_remove_events_t*, int);
+void (*snd_seq_remove_events_set_tag_dylibloader_wrapper_asound)( snd_seq_remove_events_t*, int);
+int (*snd_seq_remove_events_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_remove_events_t*);
+void (*snd_seq_set_bit_dylibloader_wrapper_asound)( int, void*);
+void (*snd_seq_unset_bit_dylibloader_wrapper_asound)( int, void*);
+int (*snd_seq_change_bit_dylibloader_wrapper_asound)( int, void*);
+int (*snd_seq_get_bit_dylibloader_wrapper_asound)( int, void*);
+int (*snd_seq_control_queue_dylibloader_wrapper_asound)( snd_seq_t*, int, int, int, snd_seq_event_t*);
+int (*snd_seq_create_simple_port_dylibloader_wrapper_asound)( snd_seq_t*,const char*, unsigned int, unsigned int);
+int (*snd_seq_delete_simple_port_dylibloader_wrapper_asound)( snd_seq_t*, int);
+int (*snd_seq_connect_from_dylibloader_wrapper_asound)( snd_seq_t*, int, int, int);
+int (*snd_seq_connect_to_dylibloader_wrapper_asound)( snd_seq_t*, int, int, int);
+int (*snd_seq_disconnect_from_dylibloader_wrapper_asound)( snd_seq_t*, int, int, int);
+int (*snd_seq_disconnect_to_dylibloader_wrapper_asound)( snd_seq_t*, int, int, int);
+int (*snd_seq_set_client_name_dylibloader_wrapper_asound)( snd_seq_t*,const char*);
+int (*snd_seq_set_client_event_filter_dylibloader_wrapper_asound)( snd_seq_t*, int);
+int (*snd_seq_set_client_pool_output_dylibloader_wrapper_asound)( snd_seq_t*, size_t);
+int (*snd_seq_set_client_pool_output_room_dylibloader_wrapper_asound)( snd_seq_t*, size_t);
+int (*snd_seq_set_client_pool_input_dylibloader_wrapper_asound)( snd_seq_t*, size_t);
+int (*snd_seq_sync_output_queue_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_seq_parse_address_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_addr_t*,const char*);
+int (*snd_seq_reset_pool_output_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_seq_reset_pool_input_dylibloader_wrapper_asound)( snd_seq_t*);
+int (*snd_midi_event_new_dylibloader_wrapper_asound)( size_t, snd_midi_event_t**);
+int (*snd_midi_event_resize_buffer_dylibloader_wrapper_asound)( snd_midi_event_t*, size_t);
+void (*snd_midi_event_free_dylibloader_wrapper_asound)( snd_midi_event_t*);
+void (*snd_midi_event_init_dylibloader_wrapper_asound)( snd_midi_event_t*);
+void (*snd_midi_event_reset_encode_dylibloader_wrapper_asound)( snd_midi_event_t*);
+void (*snd_midi_event_reset_decode_dylibloader_wrapper_asound)( snd_midi_event_t*);
+void (*snd_midi_event_no_status_dylibloader_wrapper_asound)( snd_midi_event_t*, int);
+long (*snd_midi_event_encode_dylibloader_wrapper_asound)( snd_midi_event_t*,const unsigned char*, long, snd_seq_event_t*);
+int (*snd_midi_event_encode_byte_dylibloader_wrapper_asound)( snd_midi_event_t*, int, snd_seq_event_t*);
+long (*snd_midi_event_decode_dylibloader_wrapper_asound)( snd_midi_event_t*, unsigned char*, long,const snd_seq_event_t*);
+int initialize_asound(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libasound.so.2", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// snd_asoundlib_version
+ *(void **) (&snd_asoundlib_version_dylibloader_wrapper_asound) = dlsym(handle, "snd_asoundlib_version");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_dlpath
+ *(void **) (&snd_dlpath_dylibloader_wrapper_asound) = dlsym(handle, "snd_dlpath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_dlopen
+ *(void **) (&snd_dlopen_dylibloader_wrapper_asound) = dlsym(handle, "snd_dlopen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_dlsym
+ *(void **) (&snd_dlsym_dylibloader_wrapper_asound) = dlsym(handle, "snd_dlsym");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_dlclose
+ *(void **) (&snd_dlclose_dylibloader_wrapper_asound) = dlsym(handle, "snd_dlclose");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_async_add_handler
+ *(void **) (&snd_async_add_handler_dylibloader_wrapper_asound) = dlsym(handle, "snd_async_add_handler");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_async_del_handler
+ *(void **) (&snd_async_del_handler_dylibloader_wrapper_asound) = dlsym(handle, "snd_async_del_handler");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_async_handler_get_fd
+ *(void **) (&snd_async_handler_get_fd_dylibloader_wrapper_asound) = dlsym(handle, "snd_async_handler_get_fd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_async_handler_get_signo
+ *(void **) (&snd_async_handler_get_signo_dylibloader_wrapper_asound) = dlsym(handle, "snd_async_handler_get_signo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_async_handler_get_callback_private
+ *(void **) (&snd_async_handler_get_callback_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_async_handler_get_callback_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_shm_area_create
+ *(void **) (&snd_shm_area_create_dylibloader_wrapper_asound) = dlsym(handle, "snd_shm_area_create");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_shm_area_share
+ *(void **) (&snd_shm_area_share_dylibloader_wrapper_asound) = dlsym(handle, "snd_shm_area_share");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_shm_area_destroy
+ *(void **) (&snd_shm_area_destroy_dylibloader_wrapper_asound) = dlsym(handle, "snd_shm_area_destroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_user_file
+ *(void **) (&snd_user_file_dylibloader_wrapper_asound) = dlsym(handle, "snd_user_file");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_input_stdio_open
+ *(void **) (&snd_input_stdio_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_input_stdio_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_input_stdio_attach
+ *(void **) (&snd_input_stdio_attach_dylibloader_wrapper_asound) = dlsym(handle, "snd_input_stdio_attach");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_input_buffer_open
+ *(void **) (&snd_input_buffer_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_input_buffer_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_input_close
+ *(void **) (&snd_input_close_dylibloader_wrapper_asound) = dlsym(handle, "snd_input_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_input_scanf
+ *(void **) (&snd_input_scanf_dylibloader_wrapper_asound) = dlsym(handle, "snd_input_scanf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_input_gets
+ *(void **) (&snd_input_gets_dylibloader_wrapper_asound) = dlsym(handle, "snd_input_gets");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_input_getc
+ *(void **) (&snd_input_getc_dylibloader_wrapper_asound) = dlsym(handle, "snd_input_getc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_input_ungetc
+ *(void **) (&snd_input_ungetc_dylibloader_wrapper_asound) = dlsym(handle, "snd_input_ungetc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_output_stdio_open
+ *(void **) (&snd_output_stdio_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_output_stdio_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_output_stdio_attach
+ *(void **) (&snd_output_stdio_attach_dylibloader_wrapper_asound) = dlsym(handle, "snd_output_stdio_attach");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_output_buffer_open
+ *(void **) (&snd_output_buffer_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_output_buffer_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_output_buffer_string
+ *(void **) (&snd_output_buffer_string_dylibloader_wrapper_asound) = dlsym(handle, "snd_output_buffer_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_output_close
+ *(void **) (&snd_output_close_dylibloader_wrapper_asound) = dlsym(handle, "snd_output_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_output_printf
+ *(void **) (&snd_output_printf_dylibloader_wrapper_asound) = dlsym(handle, "snd_output_printf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_output_vprintf
+ *(void **) (&snd_output_vprintf_dylibloader_wrapper_asound) = dlsym(handle, "snd_output_vprintf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_output_puts
+ *(void **) (&snd_output_puts_dylibloader_wrapper_asound) = dlsym(handle, "snd_output_puts");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_output_putc
+ *(void **) (&snd_output_putc_dylibloader_wrapper_asound) = dlsym(handle, "snd_output_putc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_output_flush
+ *(void **) (&snd_output_flush_dylibloader_wrapper_asound) = dlsym(handle, "snd_output_flush");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_strerror
+ *(void **) (&snd_strerror_dylibloader_wrapper_asound) = dlsym(handle, "snd_strerror");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_lib_error_set_handler
+ *(void **) (&snd_lib_error_set_handler_dylibloader_wrapper_asound) = dlsym(handle, "snd_lib_error_set_handler");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_lib_error_set_local
+ *(void **) (&snd_lib_error_set_local_dylibloader_wrapper_asound) = dlsym(handle, "snd_lib_error_set_local");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_topdir
+ *(void **) (&snd_config_topdir_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_topdir");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_top
+ *(void **) (&snd_config_top_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_top");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_load
+ *(void **) (&snd_config_load_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_load");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_load_override
+ *(void **) (&snd_config_load_override_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_load_override");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_save
+ *(void **) (&snd_config_save_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_save");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_update
+ *(void **) (&snd_config_update_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_update");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_update_r
+ *(void **) (&snd_config_update_r_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_update_r");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_update_free
+ *(void **) (&snd_config_update_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_update_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_update_free_global
+ *(void **) (&snd_config_update_free_global_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_update_free_global");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_update_ref
+ *(void **) (&snd_config_update_ref_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_update_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_ref
+ *(void **) (&snd_config_ref_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_unref
+ *(void **) (&snd_config_unref_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_search
+ *(void **) (&snd_config_search_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_search");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_searchv
+ *(void **) (&snd_config_searchv_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_searchv");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_search_definition
+ *(void **) (&snd_config_search_definition_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_search_definition");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_expand
+ *(void **) (&snd_config_expand_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_expand");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_evaluate
+ *(void **) (&snd_config_evaluate_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_evaluate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_add
+ *(void **) (&snd_config_add_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_add");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_add_before
+ *(void **) (&snd_config_add_before_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_add_before");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_add_after
+ *(void **) (&snd_config_add_after_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_add_after");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_remove
+ *(void **) (&snd_config_remove_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_remove");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_delete
+ *(void **) (&snd_config_delete_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_delete");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_delete_compound_members
+ *(void **) (&snd_config_delete_compound_members_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_delete_compound_members");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_copy
+ *(void **) (&snd_config_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_make
+ *(void **) (&snd_config_make_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_make");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_make_integer
+ *(void **) (&snd_config_make_integer_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_make_integer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_make_integer64
+ *(void **) (&snd_config_make_integer64_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_make_integer64");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_make_real
+ *(void **) (&snd_config_make_real_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_make_real");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_make_string
+ *(void **) (&snd_config_make_string_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_make_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_make_pointer
+ *(void **) (&snd_config_make_pointer_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_make_pointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_make_compound
+ *(void **) (&snd_config_make_compound_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_make_compound");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_imake_integer
+ *(void **) (&snd_config_imake_integer_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_imake_integer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_imake_integer64
+ *(void **) (&snd_config_imake_integer64_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_imake_integer64");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_imake_real
+ *(void **) (&snd_config_imake_real_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_imake_real");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_imake_string
+ *(void **) (&snd_config_imake_string_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_imake_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_imake_safe_string
+ *(void **) (&snd_config_imake_safe_string_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_imake_safe_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_imake_pointer
+ *(void **) (&snd_config_imake_pointer_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_imake_pointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_type
+ *(void **) (&snd_config_get_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_is_array
+ *(void **) (&snd_config_is_array_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_is_array");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_set_id
+ *(void **) (&snd_config_set_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_set_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_set_integer
+ *(void **) (&snd_config_set_integer_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_set_integer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_set_integer64
+ *(void **) (&snd_config_set_integer64_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_set_integer64");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_set_real
+ *(void **) (&snd_config_set_real_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_set_real");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_set_string
+ *(void **) (&snd_config_set_string_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_set_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_set_ascii
+ *(void **) (&snd_config_set_ascii_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_set_ascii");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_set_pointer
+ *(void **) (&snd_config_set_pointer_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_set_pointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_id
+ *(void **) (&snd_config_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_integer
+ *(void **) (&snd_config_get_integer_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_integer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_integer64
+ *(void **) (&snd_config_get_integer64_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_integer64");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_real
+ *(void **) (&snd_config_get_real_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_real");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_ireal
+ *(void **) (&snd_config_get_ireal_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_ireal");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_string
+ *(void **) (&snd_config_get_string_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_ascii
+ *(void **) (&snd_config_get_ascii_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_ascii");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_pointer
+ *(void **) (&snd_config_get_pointer_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_pointer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_test_id
+ *(void **) (&snd_config_test_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_test_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_iterator_first
+ *(void **) (&snd_config_iterator_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_iterator_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_iterator_next
+ *(void **) (&snd_config_iterator_next_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_iterator_next");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_iterator_end
+ *(void **) (&snd_config_iterator_end_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_iterator_end");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_iterator_entry
+ *(void **) (&snd_config_iterator_entry_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_iterator_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_bool_ascii
+ *(void **) (&snd_config_get_bool_ascii_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_bool_ascii");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_bool
+ *(void **) (&snd_config_get_bool_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_bool");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_ctl_iface_ascii
+ *(void **) (&snd_config_get_ctl_iface_ascii_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_ctl_iface_ascii");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_config_get_ctl_iface
+ *(void **) (&snd_config_get_ctl_iface_dylibloader_wrapper_asound) = dlsym(handle, "snd_config_get_ctl_iface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_names_list
+ *(void **) (&snd_names_list_dylibloader_wrapper_asound) = dlsym(handle, "snd_names_list");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_names_list_free
+ *(void **) (&snd_names_list_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_names_list_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_open
+ *(void **) (&snd_pcm_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_open_lconf
+ *(void **) (&snd_pcm_open_lconf_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_open_lconf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_open_fallback
+ *(void **) (&snd_pcm_open_fallback_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_open_fallback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_close
+ *(void **) (&snd_pcm_close_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_name
+ *(void **) (&snd_pcm_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_type
+ *(void **) (&snd_pcm_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_stream
+ *(void **) (&snd_pcm_stream_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_stream");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_poll_descriptors_count
+ *(void **) (&snd_pcm_poll_descriptors_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_poll_descriptors_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_poll_descriptors
+ *(void **) (&snd_pcm_poll_descriptors_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_poll_descriptors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_poll_descriptors_revents
+ *(void **) (&snd_pcm_poll_descriptors_revents_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_poll_descriptors_revents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_nonblock
+ *(void **) (&snd_pcm_nonblock_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_nonblock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_async_add_pcm_handler
+ *(void **) (&snd_async_add_pcm_handler_dylibloader_wrapper_asound) = dlsym(handle, "snd_async_add_pcm_handler");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_async_handler_get_pcm
+ *(void **) (&snd_async_handler_get_pcm_dylibloader_wrapper_asound) = dlsym(handle, "snd_async_handler_get_pcm");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info
+ *(void **) (&snd_pcm_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_current
+ *(void **) (&snd_pcm_hw_params_current_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_current");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params
+ *(void **) (&snd_pcm_hw_params_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_free
+ *(void **) (&snd_pcm_hw_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_current
+ *(void **) (&snd_pcm_sw_params_current_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_current");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params
+ *(void **) (&snd_pcm_sw_params_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_prepare
+ *(void **) (&snd_pcm_prepare_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_prepare");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_reset
+ *(void **) (&snd_pcm_reset_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_reset");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status
+ *(void **) (&snd_pcm_status_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_start
+ *(void **) (&snd_pcm_start_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_start");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_drop
+ *(void **) (&snd_pcm_drop_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_drop");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_drain
+ *(void **) (&snd_pcm_drain_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_drain");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_pause
+ *(void **) (&snd_pcm_pause_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_pause");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_state
+ *(void **) (&snd_pcm_state_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_state");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hwsync
+ *(void **) (&snd_pcm_hwsync_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hwsync");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_delay
+ *(void **) (&snd_pcm_delay_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_delay");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_resume
+ *(void **) (&snd_pcm_resume_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_resume");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_htimestamp
+ *(void **) (&snd_pcm_htimestamp_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_htimestamp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_avail
+ *(void **) (&snd_pcm_avail_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_avail");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_avail_update
+ *(void **) (&snd_pcm_avail_update_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_avail_update");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_avail_delay
+ *(void **) (&snd_pcm_avail_delay_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_avail_delay");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_rewindable
+ *(void **) (&snd_pcm_rewindable_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_rewindable");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_rewind
+ *(void **) (&snd_pcm_rewind_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_rewind");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_forwardable
+ *(void **) (&snd_pcm_forwardable_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_forwardable");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_forward
+ *(void **) (&snd_pcm_forward_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_forward");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_writei
+ *(void **) (&snd_pcm_writei_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_writei");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_readi
+ *(void **) (&snd_pcm_readi_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_readi");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_writen
+ *(void **) (&snd_pcm_writen_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_writen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_readn
+ *(void **) (&snd_pcm_readn_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_readn");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_wait
+ *(void **) (&snd_pcm_wait_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_wait");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_link
+ *(void **) (&snd_pcm_link_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_link");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_unlink
+ *(void **) (&snd_pcm_unlink_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_unlink");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_query_chmaps
+ *(void **) (&snd_pcm_query_chmaps_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_query_chmaps");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_query_chmaps_from_hw
+ *(void **) (&snd_pcm_query_chmaps_from_hw_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_query_chmaps_from_hw");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_free_chmaps
+ *(void **) (&snd_pcm_free_chmaps_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_free_chmaps");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_get_chmap
+ *(void **) (&snd_pcm_get_chmap_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_get_chmap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_set_chmap
+ *(void **) (&snd_pcm_set_chmap_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_set_chmap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_chmap_type_name
+ *(void **) (&snd_pcm_chmap_type_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_chmap_type_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_chmap_name
+ *(void **) (&snd_pcm_chmap_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_chmap_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_chmap_long_name
+ *(void **) (&snd_pcm_chmap_long_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_chmap_long_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_chmap_print
+ *(void **) (&snd_pcm_chmap_print_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_chmap_print");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_chmap_from_string
+ *(void **) (&snd_pcm_chmap_from_string_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_chmap_from_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_chmap_parse_string
+ *(void **) (&snd_pcm_chmap_parse_string_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_chmap_parse_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_recover
+ *(void **) (&snd_pcm_recover_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_recover");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_set_params
+ *(void **) (&snd_pcm_set_params_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_set_params");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_get_params
+ *(void **) (&snd_pcm_get_params_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_get_params");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_sizeof
+ *(void **) (&snd_pcm_info_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_malloc
+ *(void **) (&snd_pcm_info_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_free
+ *(void **) (&snd_pcm_info_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_copy
+ *(void **) (&snd_pcm_info_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_device
+ *(void **) (&snd_pcm_info_get_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_subdevice
+ *(void **) (&snd_pcm_info_get_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_stream
+ *(void **) (&snd_pcm_info_get_stream_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_stream");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_card
+ *(void **) (&snd_pcm_info_get_card_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_card");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_id
+ *(void **) (&snd_pcm_info_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_name
+ *(void **) (&snd_pcm_info_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_subdevice_name
+ *(void **) (&snd_pcm_info_get_subdevice_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_subdevice_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_class
+ *(void **) (&snd_pcm_info_get_class_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_class");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_subclass
+ *(void **) (&snd_pcm_info_get_subclass_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_subclass");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_subdevices_count
+ *(void **) (&snd_pcm_info_get_subdevices_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_subdevices_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_subdevices_avail
+ *(void **) (&snd_pcm_info_get_subdevices_avail_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_subdevices_avail");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_get_sync
+ *(void **) (&snd_pcm_info_get_sync_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_get_sync");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_set_device
+ *(void **) (&snd_pcm_info_set_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_set_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_set_subdevice
+ *(void **) (&snd_pcm_info_set_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_set_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_info_set_stream
+ *(void **) (&snd_pcm_info_set_stream_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_info_set_stream");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_any
+ *(void **) (&snd_pcm_hw_params_any_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_any");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_can_mmap_sample_resolution
+ *(void **) (&snd_pcm_hw_params_can_mmap_sample_resolution_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_can_mmap_sample_resolution");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_is_double
+ *(void **) (&snd_pcm_hw_params_is_double_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_is_double");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_is_batch
+ *(void **) (&snd_pcm_hw_params_is_batch_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_is_batch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_is_block_transfer
+ *(void **) (&snd_pcm_hw_params_is_block_transfer_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_is_block_transfer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_is_monotonic
+ *(void **) (&snd_pcm_hw_params_is_monotonic_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_is_monotonic");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_can_overrange
+ *(void **) (&snd_pcm_hw_params_can_overrange_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_can_overrange");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_can_pause
+ *(void **) (&snd_pcm_hw_params_can_pause_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_can_pause");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_can_resume
+ *(void **) (&snd_pcm_hw_params_can_resume_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_can_resume");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_is_half_duplex
+ *(void **) (&snd_pcm_hw_params_is_half_duplex_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_is_half_duplex");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_is_joint_duplex
+ *(void **) (&snd_pcm_hw_params_is_joint_duplex_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_is_joint_duplex");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_can_sync_start
+ *(void **) (&snd_pcm_hw_params_can_sync_start_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_can_sync_start");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_can_disable_period_wakeup
+ *(void **) (&snd_pcm_hw_params_can_disable_period_wakeup_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_can_disable_period_wakeup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_supports_audio_wallclock_ts
+ *(void **) (&snd_pcm_hw_params_supports_audio_wallclock_ts_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_supports_audio_wallclock_ts");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_supports_audio_ts_type
+ *(void **) (&snd_pcm_hw_params_supports_audio_ts_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_supports_audio_ts_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_rate_numden
+ *(void **) (&snd_pcm_hw_params_get_rate_numden_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_rate_numden");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_sbits
+ *(void **) (&snd_pcm_hw_params_get_sbits_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_sbits");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_fifo_size
+ *(void **) (&snd_pcm_hw_params_get_fifo_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_fifo_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_sizeof
+ *(void **) (&snd_pcm_hw_params_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_malloc
+ *(void **) (&snd_pcm_hw_params_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_free
+ *(void **) (&snd_pcm_hw_params_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_copy
+ *(void **) (&snd_pcm_hw_params_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_access
+ *(void **) (&snd_pcm_hw_params_get_access_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_access");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_test_access
+ *(void **) (&snd_pcm_hw_params_test_access_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_test_access");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_access
+ *(void **) (&snd_pcm_hw_params_set_access_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_access");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_access_first
+ *(void **) (&snd_pcm_hw_params_set_access_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_access_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_access_last
+ *(void **) (&snd_pcm_hw_params_set_access_last_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_access_last");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_access_mask
+ *(void **) (&snd_pcm_hw_params_set_access_mask_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_access_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_access_mask
+ *(void **) (&snd_pcm_hw_params_get_access_mask_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_access_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_format
+ *(void **) (&snd_pcm_hw_params_get_format_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_format");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_test_format
+ *(void **) (&snd_pcm_hw_params_test_format_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_test_format");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_format
+ *(void **) (&snd_pcm_hw_params_set_format_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_format");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_format_first
+ *(void **) (&snd_pcm_hw_params_set_format_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_format_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_format_last
+ *(void **) (&snd_pcm_hw_params_set_format_last_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_format_last");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_format_mask
+ *(void **) (&snd_pcm_hw_params_set_format_mask_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_format_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_format_mask
+ *(void **) (&snd_pcm_hw_params_get_format_mask_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_format_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_subformat
+ *(void **) (&snd_pcm_hw_params_get_subformat_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_subformat");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_test_subformat
+ *(void **) (&snd_pcm_hw_params_test_subformat_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_test_subformat");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_subformat
+ *(void **) (&snd_pcm_hw_params_set_subformat_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_subformat");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_subformat_first
+ *(void **) (&snd_pcm_hw_params_set_subformat_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_subformat_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_subformat_last
+ *(void **) (&snd_pcm_hw_params_set_subformat_last_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_subformat_last");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_subformat_mask
+ *(void **) (&snd_pcm_hw_params_set_subformat_mask_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_subformat_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_subformat_mask
+ *(void **) (&snd_pcm_hw_params_get_subformat_mask_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_subformat_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_channels
+ *(void **) (&snd_pcm_hw_params_get_channels_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_channels");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_channels_min
+ *(void **) (&snd_pcm_hw_params_get_channels_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_channels_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_channels_max
+ *(void **) (&snd_pcm_hw_params_get_channels_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_channels_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_test_channels
+ *(void **) (&snd_pcm_hw_params_test_channels_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_test_channels");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_channels
+ *(void **) (&snd_pcm_hw_params_set_channels_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_channels");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_channels_min
+ *(void **) (&snd_pcm_hw_params_set_channels_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_channels_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_channels_max
+ *(void **) (&snd_pcm_hw_params_set_channels_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_channels_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_channels_minmax
+ *(void **) (&snd_pcm_hw_params_set_channels_minmax_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_channels_minmax");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_channels_near
+ *(void **) (&snd_pcm_hw_params_set_channels_near_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_channels_near");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_channels_first
+ *(void **) (&snd_pcm_hw_params_set_channels_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_channels_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_channels_last
+ *(void **) (&snd_pcm_hw_params_set_channels_last_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_channels_last");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_rate
+ *(void **) (&snd_pcm_hw_params_get_rate_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_rate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_rate_min
+ *(void **) (&snd_pcm_hw_params_get_rate_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_rate_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_rate_max
+ *(void **) (&snd_pcm_hw_params_get_rate_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_rate_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_test_rate
+ *(void **) (&snd_pcm_hw_params_test_rate_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_test_rate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_rate
+ *(void **) (&snd_pcm_hw_params_set_rate_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_rate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_rate_min
+ *(void **) (&snd_pcm_hw_params_set_rate_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_rate_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_rate_max
+ *(void **) (&snd_pcm_hw_params_set_rate_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_rate_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_rate_minmax
+ *(void **) (&snd_pcm_hw_params_set_rate_minmax_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_rate_minmax");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_rate_near
+ *(void **) (&snd_pcm_hw_params_set_rate_near_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_rate_near");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_rate_first
+ *(void **) (&snd_pcm_hw_params_set_rate_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_rate_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_rate_last
+ *(void **) (&snd_pcm_hw_params_set_rate_last_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_rate_last");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_rate_resample
+ *(void **) (&snd_pcm_hw_params_set_rate_resample_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_rate_resample");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_rate_resample
+ *(void **) (&snd_pcm_hw_params_get_rate_resample_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_rate_resample");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_export_buffer
+ *(void **) (&snd_pcm_hw_params_set_export_buffer_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_export_buffer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_export_buffer
+ *(void **) (&snd_pcm_hw_params_get_export_buffer_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_export_buffer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_wakeup
+ *(void **) (&snd_pcm_hw_params_set_period_wakeup_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_wakeup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_period_wakeup
+ *(void **) (&snd_pcm_hw_params_get_period_wakeup_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_period_wakeup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_period_time
+ *(void **) (&snd_pcm_hw_params_get_period_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_period_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_period_time_min
+ *(void **) (&snd_pcm_hw_params_get_period_time_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_period_time_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_period_time_max
+ *(void **) (&snd_pcm_hw_params_get_period_time_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_period_time_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_test_period_time
+ *(void **) (&snd_pcm_hw_params_test_period_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_test_period_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_time
+ *(void **) (&snd_pcm_hw_params_set_period_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_time_min
+ *(void **) (&snd_pcm_hw_params_set_period_time_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_time_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_time_max
+ *(void **) (&snd_pcm_hw_params_set_period_time_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_time_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_time_minmax
+ *(void **) (&snd_pcm_hw_params_set_period_time_minmax_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_time_minmax");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_time_near
+ *(void **) (&snd_pcm_hw_params_set_period_time_near_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_time_near");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_time_first
+ *(void **) (&snd_pcm_hw_params_set_period_time_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_time_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_time_last
+ *(void **) (&snd_pcm_hw_params_set_period_time_last_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_time_last");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_period_size
+ *(void **) (&snd_pcm_hw_params_get_period_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_period_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_period_size_min
+ *(void **) (&snd_pcm_hw_params_get_period_size_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_period_size_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_period_size_max
+ *(void **) (&snd_pcm_hw_params_get_period_size_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_period_size_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_test_period_size
+ *(void **) (&snd_pcm_hw_params_test_period_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_test_period_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_size
+ *(void **) (&snd_pcm_hw_params_set_period_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_size_min
+ *(void **) (&snd_pcm_hw_params_set_period_size_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_size_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_size_max
+ *(void **) (&snd_pcm_hw_params_set_period_size_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_size_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_size_minmax
+ *(void **) (&snd_pcm_hw_params_set_period_size_minmax_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_size_minmax");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_size_near
+ *(void **) (&snd_pcm_hw_params_set_period_size_near_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_size_near");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_size_first
+ *(void **) (&snd_pcm_hw_params_set_period_size_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_size_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_size_last
+ *(void **) (&snd_pcm_hw_params_set_period_size_last_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_size_last");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_period_size_integer
+ *(void **) (&snd_pcm_hw_params_set_period_size_integer_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_period_size_integer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_periods
+ *(void **) (&snd_pcm_hw_params_get_periods_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_periods");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_periods_min
+ *(void **) (&snd_pcm_hw_params_get_periods_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_periods_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_periods_max
+ *(void **) (&snd_pcm_hw_params_get_periods_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_periods_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_test_periods
+ *(void **) (&snd_pcm_hw_params_test_periods_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_test_periods");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_periods
+ *(void **) (&snd_pcm_hw_params_set_periods_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_periods");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_periods_min
+ *(void **) (&snd_pcm_hw_params_set_periods_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_periods_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_periods_max
+ *(void **) (&snd_pcm_hw_params_set_periods_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_periods_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_periods_minmax
+ *(void **) (&snd_pcm_hw_params_set_periods_minmax_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_periods_minmax");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_periods_near
+ *(void **) (&snd_pcm_hw_params_set_periods_near_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_periods_near");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_periods_first
+ *(void **) (&snd_pcm_hw_params_set_periods_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_periods_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_periods_last
+ *(void **) (&snd_pcm_hw_params_set_periods_last_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_periods_last");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_periods_integer
+ *(void **) (&snd_pcm_hw_params_set_periods_integer_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_periods_integer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_buffer_time
+ *(void **) (&snd_pcm_hw_params_get_buffer_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_buffer_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_buffer_time_min
+ *(void **) (&snd_pcm_hw_params_get_buffer_time_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_buffer_time_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_buffer_time_max
+ *(void **) (&snd_pcm_hw_params_get_buffer_time_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_buffer_time_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_test_buffer_time
+ *(void **) (&snd_pcm_hw_params_test_buffer_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_test_buffer_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_time
+ *(void **) (&snd_pcm_hw_params_set_buffer_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_time_min
+ *(void **) (&snd_pcm_hw_params_set_buffer_time_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_time_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_time_max
+ *(void **) (&snd_pcm_hw_params_set_buffer_time_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_time_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_time_minmax
+ *(void **) (&snd_pcm_hw_params_set_buffer_time_minmax_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_time_minmax");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_time_near
+ *(void **) (&snd_pcm_hw_params_set_buffer_time_near_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_time_near");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_time_first
+ *(void **) (&snd_pcm_hw_params_set_buffer_time_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_time_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_time_last
+ *(void **) (&snd_pcm_hw_params_set_buffer_time_last_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_time_last");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_buffer_size
+ *(void **) (&snd_pcm_hw_params_get_buffer_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_buffer_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_buffer_size_min
+ *(void **) (&snd_pcm_hw_params_get_buffer_size_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_buffer_size_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_buffer_size_max
+ *(void **) (&snd_pcm_hw_params_get_buffer_size_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_buffer_size_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_test_buffer_size
+ *(void **) (&snd_pcm_hw_params_test_buffer_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_test_buffer_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_size
+ *(void **) (&snd_pcm_hw_params_set_buffer_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_size_min
+ *(void **) (&snd_pcm_hw_params_set_buffer_size_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_size_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_size_max
+ *(void **) (&snd_pcm_hw_params_set_buffer_size_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_size_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_size_minmax
+ *(void **) (&snd_pcm_hw_params_set_buffer_size_minmax_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_size_minmax");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_size_near
+ *(void **) (&snd_pcm_hw_params_set_buffer_size_near_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_size_near");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_size_first
+ *(void **) (&snd_pcm_hw_params_set_buffer_size_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_size_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_buffer_size_last
+ *(void **) (&snd_pcm_hw_params_set_buffer_size_last_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_buffer_size_last");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_min_align
+ *(void **) (&snd_pcm_hw_params_get_min_align_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_min_align");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_sizeof
+ *(void **) (&snd_pcm_sw_params_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_malloc
+ *(void **) (&snd_pcm_sw_params_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_free
+ *(void **) (&snd_pcm_sw_params_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_copy
+ *(void **) (&snd_pcm_sw_params_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_boundary
+ *(void **) (&snd_pcm_sw_params_get_boundary_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_boundary");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_set_tstamp_mode
+ *(void **) (&snd_pcm_sw_params_set_tstamp_mode_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_tstamp_mode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_tstamp_mode
+ *(void **) (&snd_pcm_sw_params_get_tstamp_mode_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_tstamp_mode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_set_avail_min
+ *(void **) (&snd_pcm_sw_params_set_avail_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_avail_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_avail_min
+ *(void **) (&snd_pcm_sw_params_get_avail_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_avail_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_set_period_event
+ *(void **) (&snd_pcm_sw_params_set_period_event_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_period_event");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_period_event
+ *(void **) (&snd_pcm_sw_params_get_period_event_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_period_event");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_set_start_threshold
+ *(void **) (&snd_pcm_sw_params_set_start_threshold_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_start_threshold");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_start_threshold
+ *(void **) (&snd_pcm_sw_params_get_start_threshold_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_start_threshold");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_set_stop_threshold
+ *(void **) (&snd_pcm_sw_params_set_stop_threshold_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_stop_threshold");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_stop_threshold
+ *(void **) (&snd_pcm_sw_params_get_stop_threshold_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_stop_threshold");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_set_silence_threshold
+ *(void **) (&snd_pcm_sw_params_set_silence_threshold_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_silence_threshold");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_silence_threshold
+ *(void **) (&snd_pcm_sw_params_get_silence_threshold_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_silence_threshold");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_set_silence_size
+ *(void **) (&snd_pcm_sw_params_set_silence_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_silence_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_silence_size
+ *(void **) (&snd_pcm_sw_params_get_silence_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_silence_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_access_mask_sizeof
+ *(void **) (&snd_pcm_access_mask_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_access_mask_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_access_mask_malloc
+ *(void **) (&snd_pcm_access_mask_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_access_mask_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_access_mask_free
+ *(void **) (&snd_pcm_access_mask_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_access_mask_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_access_mask_copy
+ *(void **) (&snd_pcm_access_mask_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_access_mask_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_access_mask_none
+ *(void **) (&snd_pcm_access_mask_none_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_access_mask_none");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_access_mask_any
+ *(void **) (&snd_pcm_access_mask_any_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_access_mask_any");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_access_mask_test
+ *(void **) (&snd_pcm_access_mask_test_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_access_mask_test");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_access_mask_empty
+ *(void **) (&snd_pcm_access_mask_empty_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_access_mask_empty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_access_mask_set
+ *(void **) (&snd_pcm_access_mask_set_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_access_mask_set");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_access_mask_reset
+ *(void **) (&snd_pcm_access_mask_reset_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_access_mask_reset");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_mask_sizeof
+ *(void **) (&snd_pcm_format_mask_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_mask_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_mask_malloc
+ *(void **) (&snd_pcm_format_mask_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_mask_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_mask_free
+ *(void **) (&snd_pcm_format_mask_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_mask_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_mask_copy
+ *(void **) (&snd_pcm_format_mask_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_mask_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_mask_none
+ *(void **) (&snd_pcm_format_mask_none_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_mask_none");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_mask_any
+ *(void **) (&snd_pcm_format_mask_any_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_mask_any");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_mask_test
+ *(void **) (&snd_pcm_format_mask_test_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_mask_test");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_mask_empty
+ *(void **) (&snd_pcm_format_mask_empty_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_mask_empty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_mask_set
+ *(void **) (&snd_pcm_format_mask_set_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_mask_set");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_mask_reset
+ *(void **) (&snd_pcm_format_mask_reset_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_mask_reset");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_mask_sizeof
+ *(void **) (&snd_pcm_subformat_mask_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_mask_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_mask_malloc
+ *(void **) (&snd_pcm_subformat_mask_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_mask_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_mask_free
+ *(void **) (&snd_pcm_subformat_mask_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_mask_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_mask_copy
+ *(void **) (&snd_pcm_subformat_mask_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_mask_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_mask_none
+ *(void **) (&snd_pcm_subformat_mask_none_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_mask_none");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_mask_any
+ *(void **) (&snd_pcm_subformat_mask_any_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_mask_any");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_mask_test
+ *(void **) (&snd_pcm_subformat_mask_test_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_mask_test");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_mask_empty
+ *(void **) (&snd_pcm_subformat_mask_empty_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_mask_empty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_mask_set
+ *(void **) (&snd_pcm_subformat_mask_set_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_mask_set");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_mask_reset
+ *(void **) (&snd_pcm_subformat_mask_reset_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_mask_reset");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_sizeof
+ *(void **) (&snd_pcm_status_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_malloc
+ *(void **) (&snd_pcm_status_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_free
+ *(void **) (&snd_pcm_status_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_copy
+ *(void **) (&snd_pcm_status_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_get_state
+ *(void **) (&snd_pcm_status_get_state_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_state");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_get_trigger_tstamp
+ *(void **) (&snd_pcm_status_get_trigger_tstamp_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_trigger_tstamp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_get_trigger_htstamp
+ *(void **) (&snd_pcm_status_get_trigger_htstamp_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_trigger_htstamp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_get_tstamp
+ *(void **) (&snd_pcm_status_get_tstamp_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_tstamp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_get_htstamp
+ *(void **) (&snd_pcm_status_get_htstamp_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_htstamp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_get_audio_htstamp
+ *(void **) (&snd_pcm_status_get_audio_htstamp_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_audio_htstamp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_get_driver_htstamp
+ *(void **) (&snd_pcm_status_get_driver_htstamp_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_driver_htstamp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_get_delay
+ *(void **) (&snd_pcm_status_get_delay_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_delay");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_get_avail
+ *(void **) (&snd_pcm_status_get_avail_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_avail");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_get_avail_max
+ *(void **) (&snd_pcm_status_get_avail_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_avail_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_get_overrange
+ *(void **) (&snd_pcm_status_get_overrange_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_overrange");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_type_name
+ *(void **) (&snd_pcm_type_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_type_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_stream_name
+ *(void **) (&snd_pcm_stream_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_stream_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_access_name
+ *(void **) (&snd_pcm_access_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_access_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_name
+ *(void **) (&snd_pcm_format_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_description
+ *(void **) (&snd_pcm_format_description_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_description");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_name
+ *(void **) (&snd_pcm_subformat_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_subformat_description
+ *(void **) (&snd_pcm_subformat_description_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_subformat_description");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_value
+ *(void **) (&snd_pcm_format_value_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_tstamp_mode_name
+ *(void **) (&snd_pcm_tstamp_mode_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_tstamp_mode_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_state_name
+ *(void **) (&snd_pcm_state_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_state_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_dump
+ *(void **) (&snd_pcm_dump_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_dump");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_dump_hw_setup
+ *(void **) (&snd_pcm_dump_hw_setup_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_dump_hw_setup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_dump_sw_setup
+ *(void **) (&snd_pcm_dump_sw_setup_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_dump_sw_setup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_dump_setup
+ *(void **) (&snd_pcm_dump_setup_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_dump_setup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_dump
+ *(void **) (&snd_pcm_hw_params_dump_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_dump");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_dump
+ *(void **) (&snd_pcm_sw_params_dump_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_dump");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_status_dump
+ *(void **) (&snd_pcm_status_dump_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_dump");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_mmap_begin
+ *(void **) (&snd_pcm_mmap_begin_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_mmap_begin");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_mmap_commit
+ *(void **) (&snd_pcm_mmap_commit_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_mmap_commit");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_mmap_writei
+ *(void **) (&snd_pcm_mmap_writei_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_mmap_writei");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_mmap_readi
+ *(void **) (&snd_pcm_mmap_readi_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_mmap_readi");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_mmap_writen
+ *(void **) (&snd_pcm_mmap_writen_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_mmap_writen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_mmap_readn
+ *(void **) (&snd_pcm_mmap_readn_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_mmap_readn");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_signed
+ *(void **) (&snd_pcm_format_signed_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_signed");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_unsigned
+ *(void **) (&snd_pcm_format_unsigned_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_unsigned");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_linear
+ *(void **) (&snd_pcm_format_linear_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_linear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_float
+ *(void **) (&snd_pcm_format_float_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_float");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_little_endian
+ *(void **) (&snd_pcm_format_little_endian_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_little_endian");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_big_endian
+ *(void **) (&snd_pcm_format_big_endian_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_big_endian");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_cpu_endian
+ *(void **) (&snd_pcm_format_cpu_endian_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_cpu_endian");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_width
+ *(void **) (&snd_pcm_format_width_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_width");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_physical_width
+ *(void **) (&snd_pcm_format_physical_width_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_physical_width");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_build_linear_format
+ *(void **) (&snd_pcm_build_linear_format_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_build_linear_format");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_size
+ *(void **) (&snd_pcm_format_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_silence
+ *(void **) (&snd_pcm_format_silence_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_silence");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_silence_16
+ *(void **) (&snd_pcm_format_silence_16_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_silence_16");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_silence_32
+ *(void **) (&snd_pcm_format_silence_32_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_silence_32");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_silence_64
+ *(void **) (&snd_pcm_format_silence_64_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_silence_64");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_format_set_silence
+ *(void **) (&snd_pcm_format_set_silence_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_format_set_silence");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_bytes_to_frames
+ *(void **) (&snd_pcm_bytes_to_frames_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_bytes_to_frames");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_frames_to_bytes
+ *(void **) (&snd_pcm_frames_to_bytes_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_frames_to_bytes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_bytes_to_samples
+ *(void **) (&snd_pcm_bytes_to_samples_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_bytes_to_samples");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_samples_to_bytes
+ *(void **) (&snd_pcm_samples_to_bytes_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_samples_to_bytes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_area_silence
+ *(void **) (&snd_pcm_area_silence_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_area_silence");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_areas_silence
+ *(void **) (&snd_pcm_areas_silence_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_areas_silence");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_area_copy
+ *(void **) (&snd_pcm_area_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_area_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_areas_copy
+ *(void **) (&snd_pcm_areas_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_areas_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_areas_copy_wrap
+ *(void **) (&snd_pcm_areas_copy_wrap_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_areas_copy_wrap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hook_get_pcm
+ *(void **) (&snd_pcm_hook_get_pcm_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hook_get_pcm");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hook_get_private
+ *(void **) (&snd_pcm_hook_get_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hook_get_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hook_set_private
+ *(void **) (&snd_pcm_hook_set_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hook_set_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hook_add
+ *(void **) (&snd_pcm_hook_add_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hook_add");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hook_remove
+ *(void **) (&snd_pcm_hook_remove_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hook_remove");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_meter_get_bufsize
+ *(void **) (&snd_pcm_meter_get_bufsize_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_meter_get_bufsize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_meter_get_channels
+ *(void **) (&snd_pcm_meter_get_channels_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_meter_get_channels");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_meter_get_rate
+ *(void **) (&snd_pcm_meter_get_rate_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_meter_get_rate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_meter_get_now
+ *(void **) (&snd_pcm_meter_get_now_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_meter_get_now");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_meter_get_boundary
+ *(void **) (&snd_pcm_meter_get_boundary_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_meter_get_boundary");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_meter_add_scope
+ *(void **) (&snd_pcm_meter_add_scope_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_meter_add_scope");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_meter_search_scope
+ *(void **) (&snd_pcm_meter_search_scope_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_meter_search_scope");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_scope_malloc
+ *(void **) (&snd_pcm_scope_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_scope_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_scope_set_ops
+ *(void **) (&snd_pcm_scope_set_ops_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_scope_set_ops");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_scope_set_name
+ *(void **) (&snd_pcm_scope_set_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_scope_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_scope_get_name
+ *(void **) (&snd_pcm_scope_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_scope_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_scope_get_callback_private
+ *(void **) (&snd_pcm_scope_get_callback_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_scope_get_callback_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_scope_set_callback_private
+ *(void **) (&snd_pcm_scope_set_callback_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_scope_set_callback_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_scope_s16_open
+ *(void **) (&snd_pcm_scope_s16_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_scope_s16_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_scope_s16_get_channel_buffer
+ *(void **) (&snd_pcm_scope_s16_get_channel_buffer_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_scope_s16_get_channel_buffer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_spcm_init
+ *(void **) (&snd_spcm_init_dylibloader_wrapper_asound) = dlsym(handle, "snd_spcm_init");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_spcm_init_duplex
+ *(void **) (&snd_spcm_init_duplex_dylibloader_wrapper_asound) = dlsym(handle, "snd_spcm_init_duplex");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_spcm_init_get_params
+ *(void **) (&snd_spcm_init_get_params_dylibloader_wrapper_asound) = dlsym(handle, "snd_spcm_init_get_params");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_start_mode_name
+ *(void **) (&snd_pcm_start_mode_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_start_mode_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_xrun_mode_name
+ *(void **) (&snd_pcm_xrun_mode_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_xrun_mode_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_set_start_mode
+ *(void **) (&snd_pcm_sw_params_set_start_mode_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_start_mode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_start_mode
+ *(void **) (&snd_pcm_sw_params_get_start_mode_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_start_mode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_set_xrun_mode
+ *(void **) (&snd_pcm_sw_params_set_xrun_mode_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_xrun_mode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_xrun_mode
+ *(void **) (&snd_pcm_sw_params_get_xrun_mode_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_xrun_mode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_set_xfer_align
+ *(void **) (&snd_pcm_sw_params_set_xfer_align_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_xfer_align");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_xfer_align
+ *(void **) (&snd_pcm_sw_params_get_xfer_align_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_xfer_align");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_set_sleep_min
+ *(void **) (&snd_pcm_sw_params_set_sleep_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_sleep_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_sw_params_get_sleep_min
+ *(void **) (&snd_pcm_sw_params_get_sleep_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_sleep_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_tick_time
+ *(void **) (&snd_pcm_hw_params_get_tick_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_tick_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_tick_time_min
+ *(void **) (&snd_pcm_hw_params_get_tick_time_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_tick_time_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_get_tick_time_max
+ *(void **) (&snd_pcm_hw_params_get_tick_time_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_get_tick_time_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_test_tick_time
+ *(void **) (&snd_pcm_hw_params_test_tick_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_test_tick_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_tick_time
+ *(void **) (&snd_pcm_hw_params_set_tick_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_tick_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_tick_time_min
+ *(void **) (&snd_pcm_hw_params_set_tick_time_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_tick_time_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_tick_time_max
+ *(void **) (&snd_pcm_hw_params_set_tick_time_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_tick_time_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_tick_time_minmax
+ *(void **) (&snd_pcm_hw_params_set_tick_time_minmax_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_tick_time_minmax");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_tick_time_near
+ *(void **) (&snd_pcm_hw_params_set_tick_time_near_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_tick_time_near");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_tick_time_first
+ *(void **) (&snd_pcm_hw_params_set_tick_time_first_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_tick_time_first");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_pcm_hw_params_set_tick_time_last
+ *(void **) (&snd_pcm_hw_params_set_tick_time_last_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_hw_params_set_tick_time_last");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_open
+ *(void **) (&snd_rawmidi_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_open_lconf
+ *(void **) (&snd_rawmidi_open_lconf_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_open_lconf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_close
+ *(void **) (&snd_rawmidi_close_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_poll_descriptors_count
+ *(void **) (&snd_rawmidi_poll_descriptors_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_poll_descriptors_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_poll_descriptors
+ *(void **) (&snd_rawmidi_poll_descriptors_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_poll_descriptors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_poll_descriptors_revents
+ *(void **) (&snd_rawmidi_poll_descriptors_revents_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_poll_descriptors_revents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_nonblock
+ *(void **) (&snd_rawmidi_nonblock_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_nonblock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_sizeof
+ *(void **) (&snd_rawmidi_info_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_malloc
+ *(void **) (&snd_rawmidi_info_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_free
+ *(void **) (&snd_rawmidi_info_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_copy
+ *(void **) (&snd_rawmidi_info_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_get_device
+ *(void **) (&snd_rawmidi_info_get_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_get_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_get_subdevice
+ *(void **) (&snd_rawmidi_info_get_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_get_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_get_stream
+ *(void **) (&snd_rawmidi_info_get_stream_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_get_stream");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_get_card
+ *(void **) (&snd_rawmidi_info_get_card_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_get_card");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_get_flags
+ *(void **) (&snd_rawmidi_info_get_flags_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_get_flags");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_get_id
+ *(void **) (&snd_rawmidi_info_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_get_name
+ *(void **) (&snd_rawmidi_info_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_get_subdevice_name
+ *(void **) (&snd_rawmidi_info_get_subdevice_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_get_subdevice_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_get_subdevices_count
+ *(void **) (&snd_rawmidi_info_get_subdevices_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_get_subdevices_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_get_subdevices_avail
+ *(void **) (&snd_rawmidi_info_get_subdevices_avail_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_get_subdevices_avail");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_set_device
+ *(void **) (&snd_rawmidi_info_set_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_set_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_set_subdevice
+ *(void **) (&snd_rawmidi_info_set_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_set_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info_set_stream
+ *(void **) (&snd_rawmidi_info_set_stream_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info_set_stream");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_info
+ *(void **) (&snd_rawmidi_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params_sizeof
+ *(void **) (&snd_rawmidi_params_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params_malloc
+ *(void **) (&snd_rawmidi_params_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params_free
+ *(void **) (&snd_rawmidi_params_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params_copy
+ *(void **) (&snd_rawmidi_params_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params_set_buffer_size
+ *(void **) (&snd_rawmidi_params_set_buffer_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params_set_buffer_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params_get_buffer_size
+ *(void **) (&snd_rawmidi_params_get_buffer_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params_get_buffer_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params_set_avail_min
+ *(void **) (&snd_rawmidi_params_set_avail_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params_set_avail_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params_get_avail_min
+ *(void **) (&snd_rawmidi_params_get_avail_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params_get_avail_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params_set_no_active_sensing
+ *(void **) (&snd_rawmidi_params_set_no_active_sensing_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params_set_no_active_sensing");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params_get_no_active_sensing
+ *(void **) (&snd_rawmidi_params_get_no_active_sensing_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params_get_no_active_sensing");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params
+ *(void **) (&snd_rawmidi_params_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_params_current
+ *(void **) (&snd_rawmidi_params_current_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_params_current");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_status_sizeof
+ *(void **) (&snd_rawmidi_status_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_status_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_status_malloc
+ *(void **) (&snd_rawmidi_status_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_status_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_status_free
+ *(void **) (&snd_rawmidi_status_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_status_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_status_copy
+ *(void **) (&snd_rawmidi_status_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_status_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_status_get_tstamp
+ *(void **) (&snd_rawmidi_status_get_tstamp_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_status_get_tstamp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_status_get_avail
+ *(void **) (&snd_rawmidi_status_get_avail_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_status_get_avail");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_status_get_xruns
+ *(void **) (&snd_rawmidi_status_get_xruns_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_status_get_xruns");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_status
+ *(void **) (&snd_rawmidi_status_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_status");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_drain
+ *(void **) (&snd_rawmidi_drain_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_drain");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_drop
+ *(void **) (&snd_rawmidi_drop_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_drop");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_write
+ *(void **) (&snd_rawmidi_write_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_write");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_read
+ *(void **) (&snd_rawmidi_read_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_read");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_name
+ *(void **) (&snd_rawmidi_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_type
+ *(void **) (&snd_rawmidi_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_rawmidi_stream
+ *(void **) (&snd_rawmidi_stream_dylibloader_wrapper_asound) = dlsym(handle, "snd_rawmidi_stream");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_query_open
+ *(void **) (&snd_timer_query_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_query_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_query_open_lconf
+ *(void **) (&snd_timer_query_open_lconf_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_query_open_lconf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_query_close
+ *(void **) (&snd_timer_query_close_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_query_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_query_next_device
+ *(void **) (&snd_timer_query_next_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_query_next_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_query_info
+ *(void **) (&snd_timer_query_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_query_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_query_params
+ *(void **) (&snd_timer_query_params_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_query_params");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_query_status
+ *(void **) (&snd_timer_query_status_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_query_status");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_open
+ *(void **) (&snd_timer_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_open_lconf
+ *(void **) (&snd_timer_open_lconf_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_open_lconf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_close
+ *(void **) (&snd_timer_close_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_async_add_timer_handler
+ *(void **) (&snd_async_add_timer_handler_dylibloader_wrapper_asound) = dlsym(handle, "snd_async_add_timer_handler");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_async_handler_get_timer
+ *(void **) (&snd_async_handler_get_timer_dylibloader_wrapper_asound) = dlsym(handle, "snd_async_handler_get_timer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_poll_descriptors_count
+ *(void **) (&snd_timer_poll_descriptors_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_poll_descriptors_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_poll_descriptors
+ *(void **) (&snd_timer_poll_descriptors_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_poll_descriptors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_poll_descriptors_revents
+ *(void **) (&snd_timer_poll_descriptors_revents_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_poll_descriptors_revents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_info
+ *(void **) (&snd_timer_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params
+ *(void **) (&snd_timer_params_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_status
+ *(void **) (&snd_timer_status_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_status");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_start
+ *(void **) (&snd_timer_start_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_start");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_stop
+ *(void **) (&snd_timer_stop_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_stop");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_continue
+ *(void **) (&snd_timer_continue_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_continue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_read
+ *(void **) (&snd_timer_read_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_read");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_sizeof
+ *(void **) (&snd_timer_id_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_malloc
+ *(void **) (&snd_timer_id_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_free
+ *(void **) (&snd_timer_id_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_copy
+ *(void **) (&snd_timer_id_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_set_class
+ *(void **) (&snd_timer_id_set_class_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_set_class");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_get_class
+ *(void **) (&snd_timer_id_get_class_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_get_class");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_set_sclass
+ *(void **) (&snd_timer_id_set_sclass_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_set_sclass");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_get_sclass
+ *(void **) (&snd_timer_id_get_sclass_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_get_sclass");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_set_card
+ *(void **) (&snd_timer_id_set_card_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_set_card");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_get_card
+ *(void **) (&snd_timer_id_get_card_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_get_card");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_set_device
+ *(void **) (&snd_timer_id_set_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_set_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_get_device
+ *(void **) (&snd_timer_id_get_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_get_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_set_subdevice
+ *(void **) (&snd_timer_id_set_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_set_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_id_get_subdevice
+ *(void **) (&snd_timer_id_get_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_id_get_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_sizeof
+ *(void **) (&snd_timer_ginfo_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_malloc
+ *(void **) (&snd_timer_ginfo_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_free
+ *(void **) (&snd_timer_ginfo_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_copy
+ *(void **) (&snd_timer_ginfo_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_set_tid
+ *(void **) (&snd_timer_ginfo_set_tid_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_set_tid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_get_tid
+ *(void **) (&snd_timer_ginfo_get_tid_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_get_tid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_get_flags
+ *(void **) (&snd_timer_ginfo_get_flags_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_get_flags");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_get_card
+ *(void **) (&snd_timer_ginfo_get_card_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_get_card");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_get_id
+ *(void **) (&snd_timer_ginfo_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_get_name
+ *(void **) (&snd_timer_ginfo_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_get_resolution
+ *(void **) (&snd_timer_ginfo_get_resolution_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_get_resolution");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_get_resolution_min
+ *(void **) (&snd_timer_ginfo_get_resolution_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_get_resolution_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_get_resolution_max
+ *(void **) (&snd_timer_ginfo_get_resolution_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_get_resolution_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_ginfo_get_clients
+ *(void **) (&snd_timer_ginfo_get_clients_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_ginfo_get_clients");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_info_sizeof
+ *(void **) (&snd_timer_info_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_info_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_info_malloc
+ *(void **) (&snd_timer_info_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_info_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_info_free
+ *(void **) (&snd_timer_info_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_info_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_info_copy
+ *(void **) (&snd_timer_info_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_info_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_info_is_slave
+ *(void **) (&snd_timer_info_is_slave_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_info_is_slave");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_info_get_card
+ *(void **) (&snd_timer_info_get_card_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_info_get_card");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_info_get_id
+ *(void **) (&snd_timer_info_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_info_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_info_get_name
+ *(void **) (&snd_timer_info_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_info_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_info_get_resolution
+ *(void **) (&snd_timer_info_get_resolution_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_info_get_resolution");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_sizeof
+ *(void **) (&snd_timer_params_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_malloc
+ *(void **) (&snd_timer_params_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_free
+ *(void **) (&snd_timer_params_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_copy
+ *(void **) (&snd_timer_params_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_set_auto_start
+ *(void **) (&snd_timer_params_set_auto_start_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_set_auto_start");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_get_auto_start
+ *(void **) (&snd_timer_params_get_auto_start_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_get_auto_start");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_set_exclusive
+ *(void **) (&snd_timer_params_set_exclusive_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_set_exclusive");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_get_exclusive
+ *(void **) (&snd_timer_params_get_exclusive_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_get_exclusive");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_set_early_event
+ *(void **) (&snd_timer_params_set_early_event_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_set_early_event");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_get_early_event
+ *(void **) (&snd_timer_params_get_early_event_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_get_early_event");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_set_ticks
+ *(void **) (&snd_timer_params_set_ticks_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_set_ticks");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_get_ticks
+ *(void **) (&snd_timer_params_get_ticks_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_get_ticks");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_set_queue_size
+ *(void **) (&snd_timer_params_set_queue_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_set_queue_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_get_queue_size
+ *(void **) (&snd_timer_params_get_queue_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_get_queue_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_set_filter
+ *(void **) (&snd_timer_params_set_filter_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_set_filter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_params_get_filter
+ *(void **) (&snd_timer_params_get_filter_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_params_get_filter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_status_sizeof
+ *(void **) (&snd_timer_status_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_status_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_status_malloc
+ *(void **) (&snd_timer_status_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_status_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_status_free
+ *(void **) (&snd_timer_status_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_status_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_status_copy
+ *(void **) (&snd_timer_status_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_status_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_status_get_timestamp
+ *(void **) (&snd_timer_status_get_timestamp_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_status_get_timestamp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_status_get_resolution
+ *(void **) (&snd_timer_status_get_resolution_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_status_get_resolution");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_status_get_lost
+ *(void **) (&snd_timer_status_get_lost_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_status_get_lost");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_status_get_overrun
+ *(void **) (&snd_timer_status_get_overrun_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_status_get_overrun");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_status_get_queue
+ *(void **) (&snd_timer_status_get_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_status_get_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_timer_info_get_ticks
+ *(void **) (&snd_timer_info_get_ticks_dylibloader_wrapper_asound) = dlsym(handle, "snd_timer_info_get_ticks");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_open
+ *(void **) (&snd_hwdep_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_close
+ *(void **) (&snd_hwdep_close_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_poll_descriptors
+ *(void **) (&snd_hwdep_poll_descriptors_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_poll_descriptors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_poll_descriptors_count
+ *(void **) (&snd_hwdep_poll_descriptors_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_poll_descriptors_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_poll_descriptors_revents
+ *(void **) (&snd_hwdep_poll_descriptors_revents_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_poll_descriptors_revents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_nonblock
+ *(void **) (&snd_hwdep_nonblock_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_nonblock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_info
+ *(void **) (&snd_hwdep_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_status
+ *(void **) (&snd_hwdep_dsp_status_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_status");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_load
+ *(void **) (&snd_hwdep_dsp_load_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_load");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_ioctl
+ *(void **) (&snd_hwdep_ioctl_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_ioctl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_write
+ *(void **) (&snd_hwdep_write_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_write");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_read
+ *(void **) (&snd_hwdep_read_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_read");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_info_sizeof
+ *(void **) (&snd_hwdep_info_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_info_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_info_malloc
+ *(void **) (&snd_hwdep_info_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_info_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_info_free
+ *(void **) (&snd_hwdep_info_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_info_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_info_copy
+ *(void **) (&snd_hwdep_info_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_info_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_info_get_device
+ *(void **) (&snd_hwdep_info_get_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_info_get_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_info_get_card
+ *(void **) (&snd_hwdep_info_get_card_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_info_get_card");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_info_get_id
+ *(void **) (&snd_hwdep_info_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_info_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_info_get_name
+ *(void **) (&snd_hwdep_info_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_info_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_info_get_iface
+ *(void **) (&snd_hwdep_info_get_iface_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_info_get_iface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_info_set_device
+ *(void **) (&snd_hwdep_info_set_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_info_set_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_status_sizeof
+ *(void **) (&snd_hwdep_dsp_status_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_status_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_status_malloc
+ *(void **) (&snd_hwdep_dsp_status_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_status_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_status_free
+ *(void **) (&snd_hwdep_dsp_status_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_status_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_status_copy
+ *(void **) (&snd_hwdep_dsp_status_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_status_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_status_get_version
+ *(void **) (&snd_hwdep_dsp_status_get_version_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_status_get_version");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_status_get_id
+ *(void **) (&snd_hwdep_dsp_status_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_status_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_status_get_num_dsps
+ *(void **) (&snd_hwdep_dsp_status_get_num_dsps_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_status_get_num_dsps");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_status_get_dsp_loaded
+ *(void **) (&snd_hwdep_dsp_status_get_dsp_loaded_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_status_get_dsp_loaded");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_status_get_chip_ready
+ *(void **) (&snd_hwdep_dsp_status_get_chip_ready_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_status_get_chip_ready");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_sizeof
+ *(void **) (&snd_hwdep_dsp_image_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_malloc
+ *(void **) (&snd_hwdep_dsp_image_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_free
+ *(void **) (&snd_hwdep_dsp_image_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_copy
+ *(void **) (&snd_hwdep_dsp_image_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_get_index
+ *(void **) (&snd_hwdep_dsp_image_get_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_get_name
+ *(void **) (&snd_hwdep_dsp_image_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_get_image
+ *(void **) (&snd_hwdep_dsp_image_get_image_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_get_image");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_get_length
+ *(void **) (&snd_hwdep_dsp_image_get_length_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_get_length");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_set_index
+ *(void **) (&snd_hwdep_dsp_image_set_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_set_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_set_name
+ *(void **) (&snd_hwdep_dsp_image_set_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_set_image
+ *(void **) (&snd_hwdep_dsp_image_set_image_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_set_image");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hwdep_dsp_image_set_length
+ *(void **) (&snd_hwdep_dsp_image_set_length_dylibloader_wrapper_asound) = dlsym(handle, "snd_hwdep_dsp_image_set_length");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_card_load
+ *(void **) (&snd_card_load_dylibloader_wrapper_asound) = dlsym(handle, "snd_card_load");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_card_next
+ *(void **) (&snd_card_next_dylibloader_wrapper_asound) = dlsym(handle, "snd_card_next");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_card_get_index
+ *(void **) (&snd_card_get_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_card_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_card_get_name
+ *(void **) (&snd_card_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_card_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_card_get_longname
+ *(void **) (&snd_card_get_longname_dylibloader_wrapper_asound) = dlsym(handle, "snd_card_get_longname");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_device_name_hint
+ *(void **) (&snd_device_name_hint_dylibloader_wrapper_asound) = dlsym(handle, "snd_device_name_hint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_device_name_free_hint
+ *(void **) (&snd_device_name_free_hint_dylibloader_wrapper_asound) = dlsym(handle, "snd_device_name_free_hint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_device_name_get_hint
+ *(void **) (&snd_device_name_get_hint_dylibloader_wrapper_asound) = dlsym(handle, "snd_device_name_get_hint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_open
+ *(void **) (&snd_ctl_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_open_lconf
+ *(void **) (&snd_ctl_open_lconf_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_open_lconf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_open_fallback
+ *(void **) (&snd_ctl_open_fallback_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_open_fallback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_close
+ *(void **) (&snd_ctl_close_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_nonblock
+ *(void **) (&snd_ctl_nonblock_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_nonblock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_async_add_ctl_handler
+ *(void **) (&snd_async_add_ctl_handler_dylibloader_wrapper_asound) = dlsym(handle, "snd_async_add_ctl_handler");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_async_handler_get_ctl
+ *(void **) (&snd_async_handler_get_ctl_dylibloader_wrapper_asound) = dlsym(handle, "snd_async_handler_get_ctl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_poll_descriptors_count
+ *(void **) (&snd_ctl_poll_descriptors_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_poll_descriptors_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_poll_descriptors
+ *(void **) (&snd_ctl_poll_descriptors_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_poll_descriptors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_poll_descriptors_revents
+ *(void **) (&snd_ctl_poll_descriptors_revents_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_poll_descriptors_revents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_subscribe_events
+ *(void **) (&snd_ctl_subscribe_events_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_subscribe_events");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info
+ *(void **) (&snd_ctl_card_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list
+ *(void **) (&snd_ctl_elem_list_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info
+ *(void **) (&snd_ctl_elem_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_read
+ *(void **) (&snd_ctl_elem_read_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_read");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_write
+ *(void **) (&snd_ctl_elem_write_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_write");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_lock
+ *(void **) (&snd_ctl_elem_lock_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_lock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_unlock
+ *(void **) (&snd_ctl_elem_unlock_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_unlock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_tlv_read
+ *(void **) (&snd_ctl_elem_tlv_read_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_tlv_read");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_tlv_write
+ *(void **) (&snd_ctl_elem_tlv_write_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_tlv_write");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_tlv_command
+ *(void **) (&snd_ctl_elem_tlv_command_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_tlv_command");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_hwdep_next_device
+ *(void **) (&snd_ctl_hwdep_next_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_hwdep_next_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_hwdep_info
+ *(void **) (&snd_ctl_hwdep_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_hwdep_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_pcm_next_device
+ *(void **) (&snd_ctl_pcm_next_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_pcm_next_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_pcm_info
+ *(void **) (&snd_ctl_pcm_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_pcm_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_pcm_prefer_subdevice
+ *(void **) (&snd_ctl_pcm_prefer_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_pcm_prefer_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_rawmidi_next_device
+ *(void **) (&snd_ctl_rawmidi_next_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_rawmidi_next_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_rawmidi_info
+ *(void **) (&snd_ctl_rawmidi_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_rawmidi_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_rawmidi_prefer_subdevice
+ *(void **) (&snd_ctl_rawmidi_prefer_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_rawmidi_prefer_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_set_power_state
+ *(void **) (&snd_ctl_set_power_state_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_set_power_state");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_get_power_state
+ *(void **) (&snd_ctl_get_power_state_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_get_power_state");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_read
+ *(void **) (&snd_ctl_read_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_read");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_wait
+ *(void **) (&snd_ctl_wait_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_wait");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_name
+ *(void **) (&snd_ctl_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_type
+ *(void **) (&snd_ctl_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_type_name
+ *(void **) (&snd_ctl_elem_type_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_type_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_iface_name
+ *(void **) (&snd_ctl_elem_iface_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_iface_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_type_name
+ *(void **) (&snd_ctl_event_type_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_type_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_elem_get_mask
+ *(void **) (&snd_ctl_event_elem_get_mask_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_elem_get_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_elem_get_numid
+ *(void **) (&snd_ctl_event_elem_get_numid_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_elem_get_numid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_elem_get_id
+ *(void **) (&snd_ctl_event_elem_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_elem_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_elem_get_interface
+ *(void **) (&snd_ctl_event_elem_get_interface_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_elem_get_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_elem_get_device
+ *(void **) (&snd_ctl_event_elem_get_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_elem_get_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_elem_get_subdevice
+ *(void **) (&snd_ctl_event_elem_get_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_elem_get_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_elem_get_name
+ *(void **) (&snd_ctl_event_elem_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_elem_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_elem_get_index
+ *(void **) (&snd_ctl_event_elem_get_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_elem_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_alloc_space
+ *(void **) (&snd_ctl_elem_list_alloc_space_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_alloc_space");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_free_space
+ *(void **) (&snd_ctl_elem_list_free_space_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_free_space");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_ascii_elem_id_get
+ *(void **) (&snd_ctl_ascii_elem_id_get_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_ascii_elem_id_get");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_ascii_elem_id_parse
+ *(void **) (&snd_ctl_ascii_elem_id_parse_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_ascii_elem_id_parse");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_ascii_value_parse
+ *(void **) (&snd_ctl_ascii_value_parse_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_ascii_value_parse");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_sizeof
+ *(void **) (&snd_ctl_elem_id_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_malloc
+ *(void **) (&snd_ctl_elem_id_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_free
+ *(void **) (&snd_ctl_elem_id_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_clear
+ *(void **) (&snd_ctl_elem_id_clear_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_clear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_copy
+ *(void **) (&snd_ctl_elem_id_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_get_numid
+ *(void **) (&snd_ctl_elem_id_get_numid_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_get_numid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_get_interface
+ *(void **) (&snd_ctl_elem_id_get_interface_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_get_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_get_device
+ *(void **) (&snd_ctl_elem_id_get_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_get_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_get_subdevice
+ *(void **) (&snd_ctl_elem_id_get_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_get_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_get_name
+ *(void **) (&snd_ctl_elem_id_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_get_index
+ *(void **) (&snd_ctl_elem_id_get_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_set_numid
+ *(void **) (&snd_ctl_elem_id_set_numid_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_set_numid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_set_interface
+ *(void **) (&snd_ctl_elem_id_set_interface_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_set_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_set_device
+ *(void **) (&snd_ctl_elem_id_set_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_set_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_set_subdevice
+ *(void **) (&snd_ctl_elem_id_set_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_set_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_set_name
+ *(void **) (&snd_ctl_elem_id_set_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_id_set_index
+ *(void **) (&snd_ctl_elem_id_set_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_id_set_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_sizeof
+ *(void **) (&snd_ctl_card_info_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_malloc
+ *(void **) (&snd_ctl_card_info_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_free
+ *(void **) (&snd_ctl_card_info_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_clear
+ *(void **) (&snd_ctl_card_info_clear_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_clear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_copy
+ *(void **) (&snd_ctl_card_info_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_get_card
+ *(void **) (&snd_ctl_card_info_get_card_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_get_card");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_get_id
+ *(void **) (&snd_ctl_card_info_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_get_driver
+ *(void **) (&snd_ctl_card_info_get_driver_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_get_driver");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_get_name
+ *(void **) (&snd_ctl_card_info_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_get_longname
+ *(void **) (&snd_ctl_card_info_get_longname_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_get_longname");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_get_mixername
+ *(void **) (&snd_ctl_card_info_get_mixername_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_get_mixername");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_card_info_get_components
+ *(void **) (&snd_ctl_card_info_get_components_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_card_info_get_components");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_sizeof
+ *(void **) (&snd_ctl_event_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_malloc
+ *(void **) (&snd_ctl_event_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_free
+ *(void **) (&snd_ctl_event_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_clear
+ *(void **) (&snd_ctl_event_clear_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_clear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_copy
+ *(void **) (&snd_ctl_event_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_event_get_type
+ *(void **) (&snd_ctl_event_get_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_event_get_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_sizeof
+ *(void **) (&snd_ctl_elem_list_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_malloc
+ *(void **) (&snd_ctl_elem_list_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_free
+ *(void **) (&snd_ctl_elem_list_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_clear
+ *(void **) (&snd_ctl_elem_list_clear_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_clear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_copy
+ *(void **) (&snd_ctl_elem_list_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_set_offset
+ *(void **) (&snd_ctl_elem_list_set_offset_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_set_offset");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_get_used
+ *(void **) (&snd_ctl_elem_list_get_used_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_get_used");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_get_count
+ *(void **) (&snd_ctl_elem_list_get_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_get_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_get_id
+ *(void **) (&snd_ctl_elem_list_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_get_numid
+ *(void **) (&snd_ctl_elem_list_get_numid_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_get_numid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_get_interface
+ *(void **) (&snd_ctl_elem_list_get_interface_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_get_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_get_device
+ *(void **) (&snd_ctl_elem_list_get_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_get_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_get_subdevice
+ *(void **) (&snd_ctl_elem_list_get_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_get_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_get_name
+ *(void **) (&snd_ctl_elem_list_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_list_get_index
+ *(void **) (&snd_ctl_elem_list_get_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_list_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_sizeof
+ *(void **) (&snd_ctl_elem_info_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_malloc
+ *(void **) (&snd_ctl_elem_info_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_free
+ *(void **) (&snd_ctl_elem_info_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_clear
+ *(void **) (&snd_ctl_elem_info_clear_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_clear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_copy
+ *(void **) (&snd_ctl_elem_info_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_type
+ *(void **) (&snd_ctl_elem_info_get_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_is_readable
+ *(void **) (&snd_ctl_elem_info_is_readable_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_is_readable");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_is_writable
+ *(void **) (&snd_ctl_elem_info_is_writable_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_is_writable");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_is_volatile
+ *(void **) (&snd_ctl_elem_info_is_volatile_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_is_volatile");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_is_inactive
+ *(void **) (&snd_ctl_elem_info_is_inactive_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_is_inactive");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_is_locked
+ *(void **) (&snd_ctl_elem_info_is_locked_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_is_locked");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_is_tlv_readable
+ *(void **) (&snd_ctl_elem_info_is_tlv_readable_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_is_tlv_readable");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_is_tlv_writable
+ *(void **) (&snd_ctl_elem_info_is_tlv_writable_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_is_tlv_writable");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_is_tlv_commandable
+ *(void **) (&snd_ctl_elem_info_is_tlv_commandable_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_is_tlv_commandable");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_is_owner
+ *(void **) (&snd_ctl_elem_info_is_owner_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_is_owner");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_is_user
+ *(void **) (&snd_ctl_elem_info_is_user_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_is_user");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_owner
+ *(void **) (&snd_ctl_elem_info_get_owner_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_owner");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_count
+ *(void **) (&snd_ctl_elem_info_get_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_min
+ *(void **) (&snd_ctl_elem_info_get_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_max
+ *(void **) (&snd_ctl_elem_info_get_max_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_step
+ *(void **) (&snd_ctl_elem_info_get_step_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_step");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_min64
+ *(void **) (&snd_ctl_elem_info_get_min64_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_min64");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_max64
+ *(void **) (&snd_ctl_elem_info_get_max64_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_max64");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_step64
+ *(void **) (&snd_ctl_elem_info_get_step64_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_step64");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_items
+ *(void **) (&snd_ctl_elem_info_get_items_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_items");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_set_item
+ *(void **) (&snd_ctl_elem_info_set_item_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_set_item");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_item_name
+ *(void **) (&snd_ctl_elem_info_get_item_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_item_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_dimensions
+ *(void **) (&snd_ctl_elem_info_get_dimensions_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_dimensions");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_dimension
+ *(void **) (&snd_ctl_elem_info_get_dimension_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_dimension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_set_dimension
+ *(void **) (&snd_ctl_elem_info_set_dimension_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_set_dimension");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_id
+ *(void **) (&snd_ctl_elem_info_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_numid
+ *(void **) (&snd_ctl_elem_info_get_numid_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_numid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_interface
+ *(void **) (&snd_ctl_elem_info_get_interface_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_device
+ *(void **) (&snd_ctl_elem_info_get_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_subdevice
+ *(void **) (&snd_ctl_elem_info_get_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_name
+ *(void **) (&snd_ctl_elem_info_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_get_index
+ *(void **) (&snd_ctl_elem_info_get_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_set_id
+ *(void **) (&snd_ctl_elem_info_set_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_set_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_set_numid
+ *(void **) (&snd_ctl_elem_info_set_numid_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_set_numid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_set_interface
+ *(void **) (&snd_ctl_elem_info_set_interface_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_set_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_set_device
+ *(void **) (&snd_ctl_elem_info_set_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_set_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_set_subdevice
+ *(void **) (&snd_ctl_elem_info_set_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_set_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_set_name
+ *(void **) (&snd_ctl_elem_info_set_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_info_set_index
+ *(void **) (&snd_ctl_elem_info_set_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_info_set_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_add_integer_elem_set
+ *(void **) (&snd_ctl_add_integer_elem_set_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_add_integer_elem_set");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_add_integer64_elem_set
+ *(void **) (&snd_ctl_add_integer64_elem_set_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_add_integer64_elem_set");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_add_boolean_elem_set
+ *(void **) (&snd_ctl_add_boolean_elem_set_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_add_boolean_elem_set");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_add_enumerated_elem_set
+ *(void **) (&snd_ctl_add_enumerated_elem_set_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_add_enumerated_elem_set");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_add_bytes_elem_set
+ *(void **) (&snd_ctl_add_bytes_elem_set_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_add_bytes_elem_set");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_add_integer
+ *(void **) (&snd_ctl_elem_add_integer_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_add_integer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_add_integer64
+ *(void **) (&snd_ctl_elem_add_integer64_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_add_integer64");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_add_boolean
+ *(void **) (&snd_ctl_elem_add_boolean_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_add_boolean");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_add_enumerated
+ *(void **) (&snd_ctl_elem_add_enumerated_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_add_enumerated");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_add_iec958
+ *(void **) (&snd_ctl_elem_add_iec958_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_add_iec958");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_remove
+ *(void **) (&snd_ctl_elem_remove_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_remove");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_sizeof
+ *(void **) (&snd_ctl_elem_value_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_malloc
+ *(void **) (&snd_ctl_elem_value_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_free
+ *(void **) (&snd_ctl_elem_value_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_clear
+ *(void **) (&snd_ctl_elem_value_clear_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_clear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_copy
+ *(void **) (&snd_ctl_elem_value_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_compare
+ *(void **) (&snd_ctl_elem_value_compare_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_compare");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_id
+ *(void **) (&snd_ctl_elem_value_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_numid
+ *(void **) (&snd_ctl_elem_value_get_numid_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_numid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_interface
+ *(void **) (&snd_ctl_elem_value_get_interface_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_device
+ *(void **) (&snd_ctl_elem_value_get_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_subdevice
+ *(void **) (&snd_ctl_elem_value_get_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_name
+ *(void **) (&snd_ctl_elem_value_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_index
+ *(void **) (&snd_ctl_elem_value_get_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_id
+ *(void **) (&snd_ctl_elem_value_set_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_numid
+ *(void **) (&snd_ctl_elem_value_set_numid_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_numid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_interface
+ *(void **) (&snd_ctl_elem_value_set_interface_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_device
+ *(void **) (&snd_ctl_elem_value_set_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_subdevice
+ *(void **) (&snd_ctl_elem_value_set_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_name
+ *(void **) (&snd_ctl_elem_value_set_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_index
+ *(void **) (&snd_ctl_elem_value_set_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_boolean
+ *(void **) (&snd_ctl_elem_value_get_boolean_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_boolean");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_integer
+ *(void **) (&snd_ctl_elem_value_get_integer_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_integer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_integer64
+ *(void **) (&snd_ctl_elem_value_get_integer64_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_integer64");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_enumerated
+ *(void **) (&snd_ctl_elem_value_get_enumerated_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_enumerated");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_byte
+ *(void **) (&snd_ctl_elem_value_get_byte_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_byte");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_boolean
+ *(void **) (&snd_ctl_elem_value_set_boolean_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_boolean");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_integer
+ *(void **) (&snd_ctl_elem_value_set_integer_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_integer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_integer64
+ *(void **) (&snd_ctl_elem_value_set_integer64_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_integer64");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_enumerated
+ *(void **) (&snd_ctl_elem_value_set_enumerated_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_enumerated");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_byte
+ *(void **) (&snd_ctl_elem_value_set_byte_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_byte");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_set_bytes
+ *(void **) (&snd_ctl_elem_set_bytes_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_set_bytes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_bytes
+ *(void **) (&snd_ctl_elem_value_get_bytes_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_bytes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_get_iec958
+ *(void **) (&snd_ctl_elem_value_get_iec958_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_get_iec958");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_elem_value_set_iec958
+ *(void **) (&snd_ctl_elem_value_set_iec958_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_elem_value_set_iec958");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_tlv_parse_dB_info
+ *(void **) (&snd_tlv_parse_dB_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_tlv_parse_dB_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_tlv_get_dB_range
+ *(void **) (&snd_tlv_get_dB_range_dylibloader_wrapper_asound) = dlsym(handle, "snd_tlv_get_dB_range");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_tlv_convert_to_dB
+ *(void **) (&snd_tlv_convert_to_dB_dylibloader_wrapper_asound) = dlsym(handle, "snd_tlv_convert_to_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_tlv_convert_from_dB
+ *(void **) (&snd_tlv_convert_from_dB_dylibloader_wrapper_asound) = dlsym(handle, "snd_tlv_convert_from_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_get_dB_range
+ *(void **) (&snd_ctl_get_dB_range_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_get_dB_range");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_convert_to_dB
+ *(void **) (&snd_ctl_convert_to_dB_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_convert_to_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_ctl_convert_from_dB
+ *(void **) (&snd_ctl_convert_from_dB_dylibloader_wrapper_asound) = dlsym(handle, "snd_ctl_convert_from_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_compare_fast
+ *(void **) (&snd_hctl_compare_fast_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_compare_fast");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_open
+ *(void **) (&snd_hctl_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_open_ctl
+ *(void **) (&snd_hctl_open_ctl_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_open_ctl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_close
+ *(void **) (&snd_hctl_close_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_nonblock
+ *(void **) (&snd_hctl_nonblock_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_nonblock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_poll_descriptors_count
+ *(void **) (&snd_hctl_poll_descriptors_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_poll_descriptors_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_poll_descriptors
+ *(void **) (&snd_hctl_poll_descriptors_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_poll_descriptors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_poll_descriptors_revents
+ *(void **) (&snd_hctl_poll_descriptors_revents_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_poll_descriptors_revents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_get_count
+ *(void **) (&snd_hctl_get_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_get_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_set_compare
+ *(void **) (&snd_hctl_set_compare_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_set_compare");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_first_elem
+ *(void **) (&snd_hctl_first_elem_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_first_elem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_last_elem
+ *(void **) (&snd_hctl_last_elem_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_last_elem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_find_elem
+ *(void **) (&snd_hctl_find_elem_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_find_elem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_set_callback
+ *(void **) (&snd_hctl_set_callback_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_set_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_set_callback_private
+ *(void **) (&snd_hctl_set_callback_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_set_callback_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_get_callback_private
+ *(void **) (&snd_hctl_get_callback_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_get_callback_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_load
+ *(void **) (&snd_hctl_load_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_load");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_free
+ *(void **) (&snd_hctl_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_handle_events
+ *(void **) (&snd_hctl_handle_events_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_handle_events");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_name
+ *(void **) (&snd_hctl_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_wait
+ *(void **) (&snd_hctl_wait_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_wait");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_ctl
+ *(void **) (&snd_hctl_ctl_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_ctl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_next
+ *(void **) (&snd_hctl_elem_next_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_next");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_prev
+ *(void **) (&snd_hctl_elem_prev_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_prev");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_info
+ *(void **) (&snd_hctl_elem_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_read
+ *(void **) (&snd_hctl_elem_read_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_read");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_write
+ *(void **) (&snd_hctl_elem_write_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_write");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_tlv_read
+ *(void **) (&snd_hctl_elem_tlv_read_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_tlv_read");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_tlv_write
+ *(void **) (&snd_hctl_elem_tlv_write_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_tlv_write");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_tlv_command
+ *(void **) (&snd_hctl_elem_tlv_command_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_tlv_command");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_get_hctl
+ *(void **) (&snd_hctl_elem_get_hctl_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_get_hctl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_get_id
+ *(void **) (&snd_hctl_elem_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_get_numid
+ *(void **) (&snd_hctl_elem_get_numid_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_get_numid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_get_interface
+ *(void **) (&snd_hctl_elem_get_interface_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_get_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_get_device
+ *(void **) (&snd_hctl_elem_get_device_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_get_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_get_subdevice
+ *(void **) (&snd_hctl_elem_get_subdevice_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_get_subdevice");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_get_name
+ *(void **) (&snd_hctl_elem_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_get_index
+ *(void **) (&snd_hctl_elem_get_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_set_callback
+ *(void **) (&snd_hctl_elem_set_callback_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_set_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_get_callback_private
+ *(void **) (&snd_hctl_elem_get_callback_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_get_callback_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_hctl_elem_set_callback_private
+ *(void **) (&snd_hctl_elem_set_callback_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_hctl_elem_set_callback_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_sctl_build
+ *(void **) (&snd_sctl_build_dylibloader_wrapper_asound) = dlsym(handle, "snd_sctl_build");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_sctl_free
+ *(void **) (&snd_sctl_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_sctl_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_sctl_install
+ *(void **) (&snd_sctl_install_dylibloader_wrapper_asound) = dlsym(handle, "snd_sctl_install");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_sctl_remove
+ *(void **) (&snd_sctl_remove_dylibloader_wrapper_asound) = dlsym(handle, "snd_sctl_remove");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_open
+ *(void **) (&snd_mixer_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_close
+ *(void **) (&snd_mixer_close_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_first_elem
+ *(void **) (&snd_mixer_first_elem_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_first_elem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_last_elem
+ *(void **) (&snd_mixer_last_elem_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_last_elem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_handle_events
+ *(void **) (&snd_mixer_handle_events_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_handle_events");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_attach
+ *(void **) (&snd_mixer_attach_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_attach");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_attach_hctl
+ *(void **) (&snd_mixer_attach_hctl_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_attach_hctl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_detach
+ *(void **) (&snd_mixer_detach_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_detach");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_detach_hctl
+ *(void **) (&snd_mixer_detach_hctl_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_detach_hctl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_get_hctl
+ *(void **) (&snd_mixer_get_hctl_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_get_hctl");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_poll_descriptors_count
+ *(void **) (&snd_mixer_poll_descriptors_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_poll_descriptors_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_poll_descriptors
+ *(void **) (&snd_mixer_poll_descriptors_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_poll_descriptors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_poll_descriptors_revents
+ *(void **) (&snd_mixer_poll_descriptors_revents_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_poll_descriptors_revents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_load
+ *(void **) (&snd_mixer_load_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_load");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_free
+ *(void **) (&snd_mixer_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_wait
+ *(void **) (&snd_mixer_wait_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_wait");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_set_compare
+ *(void **) (&snd_mixer_set_compare_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_set_compare");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_set_callback
+ *(void **) (&snd_mixer_set_callback_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_set_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_get_callback_private
+ *(void **) (&snd_mixer_get_callback_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_get_callback_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_set_callback_private
+ *(void **) (&snd_mixer_set_callback_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_set_callback_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_get_count
+ *(void **) (&snd_mixer_get_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_get_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_unregister
+ *(void **) (&snd_mixer_class_unregister_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_unregister");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_next
+ *(void **) (&snd_mixer_elem_next_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_next");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_prev
+ *(void **) (&snd_mixer_elem_prev_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_prev");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_set_callback
+ *(void **) (&snd_mixer_elem_set_callback_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_set_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_get_callback_private
+ *(void **) (&snd_mixer_elem_get_callback_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_get_callback_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_set_callback_private
+ *(void **) (&snd_mixer_elem_set_callback_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_set_callback_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_get_type
+ *(void **) (&snd_mixer_elem_get_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_get_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_register
+ *(void **) (&snd_mixer_class_register_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_register");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_new
+ *(void **) (&snd_mixer_elem_new_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_add
+ *(void **) (&snd_mixer_elem_add_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_add");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_remove
+ *(void **) (&snd_mixer_elem_remove_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_remove");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_free
+ *(void **) (&snd_mixer_elem_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_info
+ *(void **) (&snd_mixer_elem_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_value
+ *(void **) (&snd_mixer_elem_value_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_attach
+ *(void **) (&snd_mixer_elem_attach_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_attach");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_detach
+ *(void **) (&snd_mixer_elem_detach_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_detach");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_empty
+ *(void **) (&snd_mixer_elem_empty_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_empty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_elem_get_private
+ *(void **) (&snd_mixer_elem_get_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_elem_get_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_sizeof
+ *(void **) (&snd_mixer_class_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_malloc
+ *(void **) (&snd_mixer_class_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_free
+ *(void **) (&snd_mixer_class_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_copy
+ *(void **) (&snd_mixer_class_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_get_mixer
+ *(void **) (&snd_mixer_class_get_mixer_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_get_mixer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_get_event
+ *(void **) (&snd_mixer_class_get_event_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_get_event");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_get_private
+ *(void **) (&snd_mixer_class_get_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_get_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_get_compare
+ *(void **) (&snd_mixer_class_get_compare_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_get_compare");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_set_event
+ *(void **) (&snd_mixer_class_set_event_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_set_event");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_set_private
+ *(void **) (&snd_mixer_class_set_private_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_set_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_set_private_free
+ *(void **) (&snd_mixer_class_set_private_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_set_private_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_class_set_compare
+ *(void **) (&snd_mixer_class_set_compare_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_class_set_compare");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_channel_name
+ *(void **) (&snd_mixer_selem_channel_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_channel_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_register
+ *(void **) (&snd_mixer_selem_register_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_register");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_id
+ *(void **) (&snd_mixer_selem_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_name
+ *(void **) (&snd_mixer_selem_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_index
+ *(void **) (&snd_mixer_selem_get_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_find_selem
+ *(void **) (&snd_mixer_find_selem_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_find_selem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_is_active
+ *(void **) (&snd_mixer_selem_is_active_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_is_active");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_is_playback_mono
+ *(void **) (&snd_mixer_selem_is_playback_mono_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_is_playback_mono");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_playback_channel
+ *(void **) (&snd_mixer_selem_has_playback_channel_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_playback_channel");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_is_capture_mono
+ *(void **) (&snd_mixer_selem_is_capture_mono_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_is_capture_mono");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_capture_channel
+ *(void **) (&snd_mixer_selem_has_capture_channel_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_capture_channel");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_capture_group
+ *(void **) (&snd_mixer_selem_get_capture_group_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_capture_group");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_common_volume
+ *(void **) (&snd_mixer_selem_has_common_volume_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_common_volume");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_playback_volume
+ *(void **) (&snd_mixer_selem_has_playback_volume_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_playback_volume");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_playback_volume_joined
+ *(void **) (&snd_mixer_selem_has_playback_volume_joined_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_playback_volume_joined");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_capture_volume
+ *(void **) (&snd_mixer_selem_has_capture_volume_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_capture_volume");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_capture_volume_joined
+ *(void **) (&snd_mixer_selem_has_capture_volume_joined_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_capture_volume_joined");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_common_switch
+ *(void **) (&snd_mixer_selem_has_common_switch_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_common_switch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_playback_switch
+ *(void **) (&snd_mixer_selem_has_playback_switch_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_playback_switch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_playback_switch_joined
+ *(void **) (&snd_mixer_selem_has_playback_switch_joined_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_playback_switch_joined");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_capture_switch
+ *(void **) (&snd_mixer_selem_has_capture_switch_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_capture_switch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_capture_switch_joined
+ *(void **) (&snd_mixer_selem_has_capture_switch_joined_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_capture_switch_joined");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_has_capture_switch_exclusive
+ *(void **) (&snd_mixer_selem_has_capture_switch_exclusive_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_has_capture_switch_exclusive");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_ask_playback_vol_dB
+ *(void **) (&snd_mixer_selem_ask_playback_vol_dB_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_ask_playback_vol_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_ask_capture_vol_dB
+ *(void **) (&snd_mixer_selem_ask_capture_vol_dB_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_ask_capture_vol_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_ask_playback_dB_vol
+ *(void **) (&snd_mixer_selem_ask_playback_dB_vol_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_ask_playback_dB_vol");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_ask_capture_dB_vol
+ *(void **) (&snd_mixer_selem_ask_capture_dB_vol_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_ask_capture_dB_vol");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_playback_volume
+ *(void **) (&snd_mixer_selem_get_playback_volume_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_playback_volume");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_capture_volume
+ *(void **) (&snd_mixer_selem_get_capture_volume_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_capture_volume");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_playback_dB
+ *(void **) (&snd_mixer_selem_get_playback_dB_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_playback_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_capture_dB
+ *(void **) (&snd_mixer_selem_get_capture_dB_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_capture_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_playback_switch
+ *(void **) (&snd_mixer_selem_get_playback_switch_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_playback_switch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_capture_switch
+ *(void **) (&snd_mixer_selem_get_capture_switch_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_capture_switch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_playback_volume
+ *(void **) (&snd_mixer_selem_set_playback_volume_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_playback_volume");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_capture_volume
+ *(void **) (&snd_mixer_selem_set_capture_volume_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_capture_volume");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_playback_dB
+ *(void **) (&snd_mixer_selem_set_playback_dB_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_playback_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_capture_dB
+ *(void **) (&snd_mixer_selem_set_capture_dB_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_capture_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_playback_volume_all
+ *(void **) (&snd_mixer_selem_set_playback_volume_all_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_playback_volume_all");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_capture_volume_all
+ *(void **) (&snd_mixer_selem_set_capture_volume_all_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_capture_volume_all");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_playback_dB_all
+ *(void **) (&snd_mixer_selem_set_playback_dB_all_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_playback_dB_all");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_capture_dB_all
+ *(void **) (&snd_mixer_selem_set_capture_dB_all_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_capture_dB_all");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_playback_switch
+ *(void **) (&snd_mixer_selem_set_playback_switch_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_playback_switch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_capture_switch
+ *(void **) (&snd_mixer_selem_set_capture_switch_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_capture_switch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_playback_switch_all
+ *(void **) (&snd_mixer_selem_set_playback_switch_all_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_playback_switch_all");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_capture_switch_all
+ *(void **) (&snd_mixer_selem_set_capture_switch_all_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_capture_switch_all");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_playback_volume_range
+ *(void **) (&snd_mixer_selem_get_playback_volume_range_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_playback_volume_range");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_playback_dB_range
+ *(void **) (&snd_mixer_selem_get_playback_dB_range_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_playback_dB_range");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_playback_volume_range
+ *(void **) (&snd_mixer_selem_set_playback_volume_range_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_playback_volume_range");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_capture_volume_range
+ *(void **) (&snd_mixer_selem_get_capture_volume_range_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_capture_volume_range");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_capture_dB_range
+ *(void **) (&snd_mixer_selem_get_capture_dB_range_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_capture_dB_range");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_capture_volume_range
+ *(void **) (&snd_mixer_selem_set_capture_volume_range_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_capture_volume_range");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_is_enumerated
+ *(void **) (&snd_mixer_selem_is_enumerated_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_is_enumerated");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_is_enum_playback
+ *(void **) (&snd_mixer_selem_is_enum_playback_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_is_enum_playback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_is_enum_capture
+ *(void **) (&snd_mixer_selem_is_enum_capture_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_is_enum_capture");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_enum_items
+ *(void **) (&snd_mixer_selem_get_enum_items_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_enum_items");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_enum_item_name
+ *(void **) (&snd_mixer_selem_get_enum_item_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_enum_item_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_get_enum_item
+ *(void **) (&snd_mixer_selem_get_enum_item_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_get_enum_item");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_set_enum_item
+ *(void **) (&snd_mixer_selem_set_enum_item_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_set_enum_item");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_id_sizeof
+ *(void **) (&snd_mixer_selem_id_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_id_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_id_malloc
+ *(void **) (&snd_mixer_selem_id_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_id_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_id_free
+ *(void **) (&snd_mixer_selem_id_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_id_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_id_copy
+ *(void **) (&snd_mixer_selem_id_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_id_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_id_get_name
+ *(void **) (&snd_mixer_selem_id_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_id_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_id_get_index
+ *(void **) (&snd_mixer_selem_id_get_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_id_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_id_set_name
+ *(void **) (&snd_mixer_selem_id_set_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_id_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_id_set_index
+ *(void **) (&snd_mixer_selem_id_set_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_id_set_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_mixer_selem_id_parse
+ *(void **) (&snd_mixer_selem_id_parse_dylibloader_wrapper_asound) = dlsym(handle, "snd_mixer_selem_id_parse");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_open
+ *(void **) (&snd_seq_open_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_open_lconf
+ *(void **) (&snd_seq_open_lconf_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_open_lconf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_name
+ *(void **) (&snd_seq_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_type
+ *(void **) (&snd_seq_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_close
+ *(void **) (&snd_seq_close_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_poll_descriptors_count
+ *(void **) (&snd_seq_poll_descriptors_count_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_poll_descriptors_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_poll_descriptors
+ *(void **) (&snd_seq_poll_descriptors_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_poll_descriptors");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_poll_descriptors_revents
+ *(void **) (&snd_seq_poll_descriptors_revents_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_poll_descriptors_revents");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_nonblock
+ *(void **) (&snd_seq_nonblock_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_nonblock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_id
+ *(void **) (&snd_seq_client_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_output_buffer_size
+ *(void **) (&snd_seq_get_output_buffer_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_output_buffer_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_input_buffer_size
+ *(void **) (&snd_seq_get_input_buffer_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_input_buffer_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_output_buffer_size
+ *(void **) (&snd_seq_set_output_buffer_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_output_buffer_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_input_buffer_size
+ *(void **) (&snd_seq_set_input_buffer_size_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_input_buffer_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_system_info_sizeof
+ *(void **) (&snd_seq_system_info_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_system_info_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_system_info_malloc
+ *(void **) (&snd_seq_system_info_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_system_info_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_system_info_free
+ *(void **) (&snd_seq_system_info_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_system_info_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_system_info_copy
+ *(void **) (&snd_seq_system_info_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_system_info_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_system_info_get_queues
+ *(void **) (&snd_seq_system_info_get_queues_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_system_info_get_queues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_system_info_get_clients
+ *(void **) (&snd_seq_system_info_get_clients_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_system_info_get_clients");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_system_info_get_ports
+ *(void **) (&snd_seq_system_info_get_ports_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_system_info_get_ports");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_system_info_get_channels
+ *(void **) (&snd_seq_system_info_get_channels_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_system_info_get_channels");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_system_info_get_cur_clients
+ *(void **) (&snd_seq_system_info_get_cur_clients_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_system_info_get_cur_clients");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_system_info_get_cur_queues
+ *(void **) (&snd_seq_system_info_get_cur_queues_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_system_info_get_cur_queues");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_system_info
+ *(void **) (&snd_seq_system_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_system_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_sizeof
+ *(void **) (&snd_seq_client_info_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_malloc
+ *(void **) (&snd_seq_client_info_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_free
+ *(void **) (&snd_seq_client_info_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_copy
+ *(void **) (&snd_seq_client_info_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_get_client
+ *(void **) (&snd_seq_client_info_get_client_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_get_client");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_get_type
+ *(void **) (&snd_seq_client_info_get_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_get_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_get_name
+ *(void **) (&snd_seq_client_info_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_get_broadcast_filter
+ *(void **) (&snd_seq_client_info_get_broadcast_filter_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_get_broadcast_filter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_get_error_bounce
+ *(void **) (&snd_seq_client_info_get_error_bounce_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_get_error_bounce");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_get_card
+ *(void **) (&snd_seq_client_info_get_card_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_get_card");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_get_pid
+ *(void **) (&snd_seq_client_info_get_pid_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_get_pid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_get_event_filter
+ *(void **) (&snd_seq_client_info_get_event_filter_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_get_event_filter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_get_num_ports
+ *(void **) (&snd_seq_client_info_get_num_ports_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_get_num_ports");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_get_event_lost
+ *(void **) (&snd_seq_client_info_get_event_lost_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_get_event_lost");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_set_client
+ *(void **) (&snd_seq_client_info_set_client_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_set_client");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_set_name
+ *(void **) (&snd_seq_client_info_set_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_set_broadcast_filter
+ *(void **) (&snd_seq_client_info_set_broadcast_filter_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_set_broadcast_filter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_set_error_bounce
+ *(void **) (&snd_seq_client_info_set_error_bounce_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_set_error_bounce");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_set_event_filter
+ *(void **) (&snd_seq_client_info_set_event_filter_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_set_event_filter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_event_filter_clear
+ *(void **) (&snd_seq_client_info_event_filter_clear_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_event_filter_clear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_event_filter_add
+ *(void **) (&snd_seq_client_info_event_filter_add_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_event_filter_add");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_event_filter_del
+ *(void **) (&snd_seq_client_info_event_filter_del_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_event_filter_del");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_info_event_filter_check
+ *(void **) (&snd_seq_client_info_event_filter_check_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_info_event_filter_check");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_client_info
+ *(void **) (&snd_seq_get_client_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_client_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_any_client_info
+ *(void **) (&snd_seq_get_any_client_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_any_client_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_client_info
+ *(void **) (&snd_seq_set_client_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_client_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_next_client
+ *(void **) (&snd_seq_query_next_client_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_next_client");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_sizeof
+ *(void **) (&snd_seq_client_pool_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_malloc
+ *(void **) (&snd_seq_client_pool_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_free
+ *(void **) (&snd_seq_client_pool_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_copy
+ *(void **) (&snd_seq_client_pool_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_get_client
+ *(void **) (&snd_seq_client_pool_get_client_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_get_client");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_get_output_pool
+ *(void **) (&snd_seq_client_pool_get_output_pool_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_get_output_pool");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_get_input_pool
+ *(void **) (&snd_seq_client_pool_get_input_pool_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_get_input_pool");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_get_output_room
+ *(void **) (&snd_seq_client_pool_get_output_room_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_get_output_room");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_get_output_free
+ *(void **) (&snd_seq_client_pool_get_output_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_get_output_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_get_input_free
+ *(void **) (&snd_seq_client_pool_get_input_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_get_input_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_set_output_pool
+ *(void **) (&snd_seq_client_pool_set_output_pool_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_set_output_pool");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_set_input_pool
+ *(void **) (&snd_seq_client_pool_set_input_pool_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_set_input_pool");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_client_pool_set_output_room
+ *(void **) (&snd_seq_client_pool_set_output_room_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_client_pool_set_output_room");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_client_pool
+ *(void **) (&snd_seq_get_client_pool_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_client_pool");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_client_pool
+ *(void **) (&snd_seq_set_client_pool_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_client_pool");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_sizeof
+ *(void **) (&snd_seq_port_info_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_malloc
+ *(void **) (&snd_seq_port_info_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_free
+ *(void **) (&snd_seq_port_info_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_copy
+ *(void **) (&snd_seq_port_info_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_client
+ *(void **) (&snd_seq_port_info_get_client_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_client");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_port
+ *(void **) (&snd_seq_port_info_get_port_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_port");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_addr
+ *(void **) (&snd_seq_port_info_get_addr_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_addr");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_name
+ *(void **) (&snd_seq_port_info_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_capability
+ *(void **) (&snd_seq_port_info_get_capability_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_capability");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_type
+ *(void **) (&snd_seq_port_info_get_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_midi_channels
+ *(void **) (&snd_seq_port_info_get_midi_channels_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_midi_channels");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_midi_voices
+ *(void **) (&snd_seq_port_info_get_midi_voices_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_midi_voices");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_synth_voices
+ *(void **) (&snd_seq_port_info_get_synth_voices_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_synth_voices");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_read_use
+ *(void **) (&snd_seq_port_info_get_read_use_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_read_use");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_write_use
+ *(void **) (&snd_seq_port_info_get_write_use_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_write_use");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_port_specified
+ *(void **) (&snd_seq_port_info_get_port_specified_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_port_specified");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_timestamping
+ *(void **) (&snd_seq_port_info_get_timestamping_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_timestamping");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_timestamp_real
+ *(void **) (&snd_seq_port_info_get_timestamp_real_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_timestamp_real");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_get_timestamp_queue
+ *(void **) (&snd_seq_port_info_get_timestamp_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_get_timestamp_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_client
+ *(void **) (&snd_seq_port_info_set_client_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_client");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_port
+ *(void **) (&snd_seq_port_info_set_port_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_port");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_addr
+ *(void **) (&snd_seq_port_info_set_addr_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_addr");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_name
+ *(void **) (&snd_seq_port_info_set_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_capability
+ *(void **) (&snd_seq_port_info_set_capability_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_capability");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_type
+ *(void **) (&snd_seq_port_info_set_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_midi_channels
+ *(void **) (&snd_seq_port_info_set_midi_channels_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_midi_channels");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_midi_voices
+ *(void **) (&snd_seq_port_info_set_midi_voices_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_midi_voices");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_synth_voices
+ *(void **) (&snd_seq_port_info_set_synth_voices_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_synth_voices");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_port_specified
+ *(void **) (&snd_seq_port_info_set_port_specified_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_port_specified");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_timestamping
+ *(void **) (&snd_seq_port_info_set_timestamping_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_timestamping");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_timestamp_real
+ *(void **) (&snd_seq_port_info_set_timestamp_real_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_timestamp_real");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_info_set_timestamp_queue
+ *(void **) (&snd_seq_port_info_set_timestamp_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_info_set_timestamp_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_create_port
+ *(void **) (&snd_seq_create_port_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_create_port");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_delete_port
+ *(void **) (&snd_seq_delete_port_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_delete_port");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_port_info
+ *(void **) (&snd_seq_get_port_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_port_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_any_port_info
+ *(void **) (&snd_seq_get_any_port_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_any_port_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_port_info
+ *(void **) (&snd_seq_set_port_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_port_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_next_port
+ *(void **) (&snd_seq_query_next_port_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_next_port");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_sizeof
+ *(void **) (&snd_seq_port_subscribe_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_malloc
+ *(void **) (&snd_seq_port_subscribe_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_free
+ *(void **) (&snd_seq_port_subscribe_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_copy
+ *(void **) (&snd_seq_port_subscribe_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_get_sender
+ *(void **) (&snd_seq_port_subscribe_get_sender_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_get_sender");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_get_dest
+ *(void **) (&snd_seq_port_subscribe_get_dest_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_get_dest");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_get_queue
+ *(void **) (&snd_seq_port_subscribe_get_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_get_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_get_exclusive
+ *(void **) (&snd_seq_port_subscribe_get_exclusive_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_get_exclusive");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_get_time_update
+ *(void **) (&snd_seq_port_subscribe_get_time_update_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_get_time_update");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_get_time_real
+ *(void **) (&snd_seq_port_subscribe_get_time_real_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_get_time_real");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_set_sender
+ *(void **) (&snd_seq_port_subscribe_set_sender_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_set_sender");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_set_dest
+ *(void **) (&snd_seq_port_subscribe_set_dest_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_set_dest");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_set_queue
+ *(void **) (&snd_seq_port_subscribe_set_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_set_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_set_exclusive
+ *(void **) (&snd_seq_port_subscribe_set_exclusive_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_set_exclusive");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_set_time_update
+ *(void **) (&snd_seq_port_subscribe_set_time_update_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_set_time_update");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_port_subscribe_set_time_real
+ *(void **) (&snd_seq_port_subscribe_set_time_real_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_port_subscribe_set_time_real");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_port_subscription
+ *(void **) (&snd_seq_get_port_subscription_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_port_subscription");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_subscribe_port
+ *(void **) (&snd_seq_subscribe_port_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_subscribe_port");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_unsubscribe_port
+ *(void **) (&snd_seq_unsubscribe_port_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_unsubscribe_port");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_sizeof
+ *(void **) (&snd_seq_query_subscribe_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_malloc
+ *(void **) (&snd_seq_query_subscribe_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_free
+ *(void **) (&snd_seq_query_subscribe_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_copy
+ *(void **) (&snd_seq_query_subscribe_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_get_client
+ *(void **) (&snd_seq_query_subscribe_get_client_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_get_client");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_get_port
+ *(void **) (&snd_seq_query_subscribe_get_port_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_get_port");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_get_root
+ *(void **) (&snd_seq_query_subscribe_get_root_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_get_root");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_get_type
+ *(void **) (&snd_seq_query_subscribe_get_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_get_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_get_index
+ *(void **) (&snd_seq_query_subscribe_get_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_get_num_subs
+ *(void **) (&snd_seq_query_subscribe_get_num_subs_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_get_num_subs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_get_addr
+ *(void **) (&snd_seq_query_subscribe_get_addr_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_get_addr");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_get_queue
+ *(void **) (&snd_seq_query_subscribe_get_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_get_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_get_exclusive
+ *(void **) (&snd_seq_query_subscribe_get_exclusive_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_get_exclusive");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_get_time_update
+ *(void **) (&snd_seq_query_subscribe_get_time_update_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_get_time_update");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_get_time_real
+ *(void **) (&snd_seq_query_subscribe_get_time_real_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_get_time_real");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_set_client
+ *(void **) (&snd_seq_query_subscribe_set_client_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_set_client");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_set_port
+ *(void **) (&snd_seq_query_subscribe_set_port_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_set_port");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_set_root
+ *(void **) (&snd_seq_query_subscribe_set_root_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_set_root");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_set_type
+ *(void **) (&snd_seq_query_subscribe_set_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_set_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_subscribe_set_index
+ *(void **) (&snd_seq_query_subscribe_set_index_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_subscribe_set_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_port_subscribers
+ *(void **) (&snd_seq_query_port_subscribers_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_port_subscribers");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_sizeof
+ *(void **) (&snd_seq_queue_info_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_malloc
+ *(void **) (&snd_seq_queue_info_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_free
+ *(void **) (&snd_seq_queue_info_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_copy
+ *(void **) (&snd_seq_queue_info_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_get_queue
+ *(void **) (&snd_seq_queue_info_get_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_get_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_get_name
+ *(void **) (&snd_seq_queue_info_get_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_get_owner
+ *(void **) (&snd_seq_queue_info_get_owner_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_get_owner");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_get_locked
+ *(void **) (&snd_seq_queue_info_get_locked_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_get_locked");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_get_flags
+ *(void **) (&snd_seq_queue_info_get_flags_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_get_flags");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_set_name
+ *(void **) (&snd_seq_queue_info_set_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_set_owner
+ *(void **) (&snd_seq_queue_info_set_owner_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_set_owner");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_set_locked
+ *(void **) (&snd_seq_queue_info_set_locked_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_set_locked");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_info_set_flags
+ *(void **) (&snd_seq_queue_info_set_flags_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_info_set_flags");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_create_queue
+ *(void **) (&snd_seq_create_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_create_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_alloc_named_queue
+ *(void **) (&snd_seq_alloc_named_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_alloc_named_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_alloc_queue
+ *(void **) (&snd_seq_alloc_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_alloc_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_free_queue
+ *(void **) (&snd_seq_free_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_free_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_queue_info
+ *(void **) (&snd_seq_get_queue_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_queue_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_queue_info
+ *(void **) (&snd_seq_set_queue_info_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_queue_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_query_named_queue
+ *(void **) (&snd_seq_query_named_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_query_named_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_queue_usage
+ *(void **) (&snd_seq_get_queue_usage_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_queue_usage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_queue_usage
+ *(void **) (&snd_seq_set_queue_usage_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_queue_usage");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_status_sizeof
+ *(void **) (&snd_seq_queue_status_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_status_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_status_malloc
+ *(void **) (&snd_seq_queue_status_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_status_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_status_free
+ *(void **) (&snd_seq_queue_status_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_status_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_status_copy
+ *(void **) (&snd_seq_queue_status_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_status_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_status_get_queue
+ *(void **) (&snd_seq_queue_status_get_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_status_get_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_status_get_events
+ *(void **) (&snd_seq_queue_status_get_events_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_status_get_events");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_status_get_tick_time
+ *(void **) (&snd_seq_queue_status_get_tick_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_status_get_tick_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_status_get_real_time
+ *(void **) (&snd_seq_queue_status_get_real_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_status_get_real_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_status_get_status
+ *(void **) (&snd_seq_queue_status_get_status_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_status_get_status");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_queue_status
+ *(void **) (&snd_seq_get_queue_status_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_queue_status");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_sizeof
+ *(void **) (&snd_seq_queue_tempo_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_malloc
+ *(void **) (&snd_seq_queue_tempo_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_free
+ *(void **) (&snd_seq_queue_tempo_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_copy
+ *(void **) (&snd_seq_queue_tempo_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_get_queue
+ *(void **) (&snd_seq_queue_tempo_get_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_get_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_get_tempo
+ *(void **) (&snd_seq_queue_tempo_get_tempo_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_get_tempo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_get_ppq
+ *(void **) (&snd_seq_queue_tempo_get_ppq_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_get_ppq");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_get_skew
+ *(void **) (&snd_seq_queue_tempo_get_skew_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_get_skew");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_get_skew_base
+ *(void **) (&snd_seq_queue_tempo_get_skew_base_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_get_skew_base");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_set_tempo
+ *(void **) (&snd_seq_queue_tempo_set_tempo_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_set_tempo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_set_ppq
+ *(void **) (&snd_seq_queue_tempo_set_ppq_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_set_ppq");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_set_skew
+ *(void **) (&snd_seq_queue_tempo_set_skew_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_set_skew");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_tempo_set_skew_base
+ *(void **) (&snd_seq_queue_tempo_set_skew_base_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_tempo_set_skew_base");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_queue_tempo
+ *(void **) (&snd_seq_get_queue_tempo_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_queue_tempo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_queue_tempo
+ *(void **) (&snd_seq_set_queue_tempo_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_queue_tempo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_timer_sizeof
+ *(void **) (&snd_seq_queue_timer_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_timer_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_timer_malloc
+ *(void **) (&snd_seq_queue_timer_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_timer_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_timer_free
+ *(void **) (&snd_seq_queue_timer_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_timer_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_timer_copy
+ *(void **) (&snd_seq_queue_timer_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_timer_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_timer_get_queue
+ *(void **) (&snd_seq_queue_timer_get_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_timer_get_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_timer_get_type
+ *(void **) (&snd_seq_queue_timer_get_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_timer_get_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_timer_get_id
+ *(void **) (&snd_seq_queue_timer_get_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_timer_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_timer_get_resolution
+ *(void **) (&snd_seq_queue_timer_get_resolution_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_timer_get_resolution");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_timer_set_type
+ *(void **) (&snd_seq_queue_timer_set_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_timer_set_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_timer_set_id
+ *(void **) (&snd_seq_queue_timer_set_id_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_timer_set_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_queue_timer_set_resolution
+ *(void **) (&snd_seq_queue_timer_set_resolution_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_queue_timer_set_resolution");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_queue_timer
+ *(void **) (&snd_seq_get_queue_timer_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_queue_timer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_queue_timer
+ *(void **) (&snd_seq_set_queue_timer_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_queue_timer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_free_event
+ *(void **) (&snd_seq_free_event_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_free_event");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_event_length
+ *(void **) (&snd_seq_event_length_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_event_length");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_event_output
+ *(void **) (&snd_seq_event_output_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_event_output");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_event_output_buffer
+ *(void **) (&snd_seq_event_output_buffer_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_event_output_buffer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_event_output_direct
+ *(void **) (&snd_seq_event_output_direct_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_event_output_direct");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_event_input
+ *(void **) (&snd_seq_event_input_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_event_input");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_event_input_pending
+ *(void **) (&snd_seq_event_input_pending_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_event_input_pending");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_drain_output
+ *(void **) (&snd_seq_drain_output_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_drain_output");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_event_output_pending
+ *(void **) (&snd_seq_event_output_pending_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_event_output_pending");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_extract_output
+ *(void **) (&snd_seq_extract_output_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_extract_output");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_drop_output
+ *(void **) (&snd_seq_drop_output_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_drop_output");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_drop_output_buffer
+ *(void **) (&snd_seq_drop_output_buffer_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_drop_output_buffer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_drop_input
+ *(void **) (&snd_seq_drop_input_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_drop_input");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_drop_input_buffer
+ *(void **) (&snd_seq_drop_input_buffer_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_drop_input_buffer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_sizeof
+ *(void **) (&snd_seq_remove_events_sizeof_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_sizeof");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_malloc
+ *(void **) (&snd_seq_remove_events_malloc_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_free
+ *(void **) (&snd_seq_remove_events_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_copy
+ *(void **) (&snd_seq_remove_events_copy_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_get_condition
+ *(void **) (&snd_seq_remove_events_get_condition_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_get_condition");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_get_queue
+ *(void **) (&snd_seq_remove_events_get_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_get_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_get_time
+ *(void **) (&snd_seq_remove_events_get_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_get_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_get_dest
+ *(void **) (&snd_seq_remove_events_get_dest_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_get_dest");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_get_channel
+ *(void **) (&snd_seq_remove_events_get_channel_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_get_channel");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_get_event_type
+ *(void **) (&snd_seq_remove_events_get_event_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_get_event_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_get_tag
+ *(void **) (&snd_seq_remove_events_get_tag_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_get_tag");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_set_condition
+ *(void **) (&snd_seq_remove_events_set_condition_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_set_condition");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_set_queue
+ *(void **) (&snd_seq_remove_events_set_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_set_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_set_time
+ *(void **) (&snd_seq_remove_events_set_time_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_set_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_set_dest
+ *(void **) (&snd_seq_remove_events_set_dest_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_set_dest");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_set_channel
+ *(void **) (&snd_seq_remove_events_set_channel_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_set_channel");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_set_event_type
+ *(void **) (&snd_seq_remove_events_set_event_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_set_event_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events_set_tag
+ *(void **) (&snd_seq_remove_events_set_tag_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events_set_tag");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_remove_events
+ *(void **) (&snd_seq_remove_events_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_remove_events");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_bit
+ *(void **) (&snd_seq_set_bit_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_bit");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_unset_bit
+ *(void **) (&snd_seq_unset_bit_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_unset_bit");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_change_bit
+ *(void **) (&snd_seq_change_bit_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_change_bit");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_get_bit
+ *(void **) (&snd_seq_get_bit_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_get_bit");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_control_queue
+ *(void **) (&snd_seq_control_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_control_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_create_simple_port
+ *(void **) (&snd_seq_create_simple_port_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_create_simple_port");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_delete_simple_port
+ *(void **) (&snd_seq_delete_simple_port_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_delete_simple_port");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_connect_from
+ *(void **) (&snd_seq_connect_from_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_connect_from");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_connect_to
+ *(void **) (&snd_seq_connect_to_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_connect_to");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_disconnect_from
+ *(void **) (&snd_seq_disconnect_from_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_disconnect_from");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_disconnect_to
+ *(void **) (&snd_seq_disconnect_to_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_disconnect_to");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_client_name
+ *(void **) (&snd_seq_set_client_name_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_client_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_client_event_filter
+ *(void **) (&snd_seq_set_client_event_filter_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_client_event_filter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_client_pool_output
+ *(void **) (&snd_seq_set_client_pool_output_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_client_pool_output");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_client_pool_output_room
+ *(void **) (&snd_seq_set_client_pool_output_room_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_client_pool_output_room");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_set_client_pool_input
+ *(void **) (&snd_seq_set_client_pool_input_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_set_client_pool_input");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_sync_output_queue
+ *(void **) (&snd_seq_sync_output_queue_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_sync_output_queue");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_parse_address
+ *(void **) (&snd_seq_parse_address_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_parse_address");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_reset_pool_output
+ *(void **) (&snd_seq_reset_pool_output_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_reset_pool_output");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_seq_reset_pool_input
+ *(void **) (&snd_seq_reset_pool_input_dylibloader_wrapper_asound) = dlsym(handle, "snd_seq_reset_pool_input");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_midi_event_new
+ *(void **) (&snd_midi_event_new_dylibloader_wrapper_asound) = dlsym(handle, "snd_midi_event_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_midi_event_resize_buffer
+ *(void **) (&snd_midi_event_resize_buffer_dylibloader_wrapper_asound) = dlsym(handle, "snd_midi_event_resize_buffer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_midi_event_free
+ *(void **) (&snd_midi_event_free_dylibloader_wrapper_asound) = dlsym(handle, "snd_midi_event_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_midi_event_init
+ *(void **) (&snd_midi_event_init_dylibloader_wrapper_asound) = dlsym(handle, "snd_midi_event_init");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_midi_event_reset_encode
+ *(void **) (&snd_midi_event_reset_encode_dylibloader_wrapper_asound) = dlsym(handle, "snd_midi_event_reset_encode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_midi_event_reset_decode
+ *(void **) (&snd_midi_event_reset_decode_dylibloader_wrapper_asound) = dlsym(handle, "snd_midi_event_reset_decode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_midi_event_no_status
+ *(void **) (&snd_midi_event_no_status_dylibloader_wrapper_asound) = dlsym(handle, "snd_midi_event_no_status");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_midi_event_encode
+ *(void **) (&snd_midi_event_encode_dylibloader_wrapper_asound) = dlsym(handle, "snd_midi_event_encode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_midi_event_encode_byte
+ *(void **) (&snd_midi_event_encode_byte_dylibloader_wrapper_asound) = dlsym(handle, "snd_midi_event_encode_byte");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// snd_midi_event_decode
+ *(void **) (&snd_midi_event_decode_dylibloader_wrapper_asound) = dlsym(handle, "snd_midi_event_decode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/drivers/alsa/asound-so_wrap.h b/drivers/alsa/asound-so_wrap.h
new file mode 100644
index 0000000000..5332d74152
--- /dev/null
+++ b/drivers/alsa/asound-so_wrap.h
@@ -0,0 +1,5134 @@
+#ifndef DYLIBLOAD_WRAPPER_ASOUND
+#define DYLIBLOAD_WRAPPER_ASOUND
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-22 19:22:12
+// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/alsa/asoundlib.h --sys-include <alsa/asoundlib.h> --soname libasound.so.2 --init-name asound --omit-prefix snd_pcm_sw_params_set_tstamp_type --omit-prefix snd_pcm_status_get_audio_htstamp_report --omit-prefix snd_pcm_sw_params_get_tstamp_type --omit-prefix snd_pcm_status_set_audio_htstamp_config --output-header asound-so_wrap.h --output-implementation asound-so_wrap.c
+//
+#include <stdint.h>
+
+#define snd_asoundlib_version snd_asoundlib_version_dylibloader_orig_asound
+#define snd_dlpath snd_dlpath_dylibloader_orig_asound
+#define snd_dlopen snd_dlopen_dylibloader_orig_asound
+#define snd_dlsym snd_dlsym_dylibloader_orig_asound
+#define snd_dlclose snd_dlclose_dylibloader_orig_asound
+#define snd_async_add_handler snd_async_add_handler_dylibloader_orig_asound
+#define snd_async_del_handler snd_async_del_handler_dylibloader_orig_asound
+#define snd_async_handler_get_fd snd_async_handler_get_fd_dylibloader_orig_asound
+#define snd_async_handler_get_signo snd_async_handler_get_signo_dylibloader_orig_asound
+#define snd_async_handler_get_callback_private snd_async_handler_get_callback_private_dylibloader_orig_asound
+#define snd_shm_area_create snd_shm_area_create_dylibloader_orig_asound
+#define snd_shm_area_share snd_shm_area_share_dylibloader_orig_asound
+#define snd_shm_area_destroy snd_shm_area_destroy_dylibloader_orig_asound
+#define snd_user_file snd_user_file_dylibloader_orig_asound
+#define snd_input_stdio_open snd_input_stdio_open_dylibloader_orig_asound
+#define snd_input_stdio_attach snd_input_stdio_attach_dylibloader_orig_asound
+#define snd_input_buffer_open snd_input_buffer_open_dylibloader_orig_asound
+#define snd_input_close snd_input_close_dylibloader_orig_asound
+#define snd_input_scanf snd_input_scanf_dylibloader_orig_asound
+#define snd_input_gets snd_input_gets_dylibloader_orig_asound
+#define snd_input_getc snd_input_getc_dylibloader_orig_asound
+#define snd_input_ungetc snd_input_ungetc_dylibloader_orig_asound
+#define snd_output_stdio_open snd_output_stdio_open_dylibloader_orig_asound
+#define snd_output_stdio_attach snd_output_stdio_attach_dylibloader_orig_asound
+#define snd_output_buffer_open snd_output_buffer_open_dylibloader_orig_asound
+#define snd_output_buffer_string snd_output_buffer_string_dylibloader_orig_asound
+#define snd_output_close snd_output_close_dylibloader_orig_asound
+#define snd_output_printf snd_output_printf_dylibloader_orig_asound
+#define snd_output_vprintf snd_output_vprintf_dylibloader_orig_asound
+#define snd_output_puts snd_output_puts_dylibloader_orig_asound
+#define snd_output_putc snd_output_putc_dylibloader_orig_asound
+#define snd_output_flush snd_output_flush_dylibloader_orig_asound
+#define snd_strerror snd_strerror_dylibloader_orig_asound
+#define snd_lib_error_set_handler snd_lib_error_set_handler_dylibloader_orig_asound
+#define snd_lib_error_set_local snd_lib_error_set_local_dylibloader_orig_asound
+#define snd_config_topdir snd_config_topdir_dylibloader_orig_asound
+#define snd_config_top snd_config_top_dylibloader_orig_asound
+#define snd_config_load snd_config_load_dylibloader_orig_asound
+#define snd_config_load_override snd_config_load_override_dylibloader_orig_asound
+#define snd_config_save snd_config_save_dylibloader_orig_asound
+#define snd_config_update snd_config_update_dylibloader_orig_asound
+#define snd_config_update_r snd_config_update_r_dylibloader_orig_asound
+#define snd_config_update_free snd_config_update_free_dylibloader_orig_asound
+#define snd_config_update_free_global snd_config_update_free_global_dylibloader_orig_asound
+#define snd_config_update_ref snd_config_update_ref_dylibloader_orig_asound
+#define snd_config_ref snd_config_ref_dylibloader_orig_asound
+#define snd_config_unref snd_config_unref_dylibloader_orig_asound
+#define snd_config_search snd_config_search_dylibloader_orig_asound
+#define snd_config_searchv snd_config_searchv_dylibloader_orig_asound
+#define snd_config_search_definition snd_config_search_definition_dylibloader_orig_asound
+#define snd_config_expand snd_config_expand_dylibloader_orig_asound
+#define snd_config_evaluate snd_config_evaluate_dylibloader_orig_asound
+#define snd_config_add snd_config_add_dylibloader_orig_asound
+#define snd_config_add_before snd_config_add_before_dylibloader_orig_asound
+#define snd_config_add_after snd_config_add_after_dylibloader_orig_asound
+#define snd_config_remove snd_config_remove_dylibloader_orig_asound
+#define snd_config_delete snd_config_delete_dylibloader_orig_asound
+#define snd_config_delete_compound_members snd_config_delete_compound_members_dylibloader_orig_asound
+#define snd_config_copy snd_config_copy_dylibloader_orig_asound
+#define snd_config_make snd_config_make_dylibloader_orig_asound
+#define snd_config_make_integer snd_config_make_integer_dylibloader_orig_asound
+#define snd_config_make_integer64 snd_config_make_integer64_dylibloader_orig_asound
+#define snd_config_make_real snd_config_make_real_dylibloader_orig_asound
+#define snd_config_make_string snd_config_make_string_dylibloader_orig_asound
+#define snd_config_make_pointer snd_config_make_pointer_dylibloader_orig_asound
+#define snd_config_make_compound snd_config_make_compound_dylibloader_orig_asound
+#define snd_config_imake_integer snd_config_imake_integer_dylibloader_orig_asound
+#define snd_config_imake_integer64 snd_config_imake_integer64_dylibloader_orig_asound
+#define snd_config_imake_real snd_config_imake_real_dylibloader_orig_asound
+#define snd_config_imake_string snd_config_imake_string_dylibloader_orig_asound
+#define snd_config_imake_safe_string snd_config_imake_safe_string_dylibloader_orig_asound
+#define snd_config_imake_pointer snd_config_imake_pointer_dylibloader_orig_asound
+#define snd_config_get_type snd_config_get_type_dylibloader_orig_asound
+#define snd_config_is_array snd_config_is_array_dylibloader_orig_asound
+#define snd_config_set_id snd_config_set_id_dylibloader_orig_asound
+#define snd_config_set_integer snd_config_set_integer_dylibloader_orig_asound
+#define snd_config_set_integer64 snd_config_set_integer64_dylibloader_orig_asound
+#define snd_config_set_real snd_config_set_real_dylibloader_orig_asound
+#define snd_config_set_string snd_config_set_string_dylibloader_orig_asound
+#define snd_config_set_ascii snd_config_set_ascii_dylibloader_orig_asound
+#define snd_config_set_pointer snd_config_set_pointer_dylibloader_orig_asound
+#define snd_config_get_id snd_config_get_id_dylibloader_orig_asound
+#define snd_config_get_integer snd_config_get_integer_dylibloader_orig_asound
+#define snd_config_get_integer64 snd_config_get_integer64_dylibloader_orig_asound
+#define snd_config_get_real snd_config_get_real_dylibloader_orig_asound
+#define snd_config_get_ireal snd_config_get_ireal_dylibloader_orig_asound
+#define snd_config_get_string snd_config_get_string_dylibloader_orig_asound
+#define snd_config_get_ascii snd_config_get_ascii_dylibloader_orig_asound
+#define snd_config_get_pointer snd_config_get_pointer_dylibloader_orig_asound
+#define snd_config_test_id snd_config_test_id_dylibloader_orig_asound
+#define snd_config_iterator_first snd_config_iterator_first_dylibloader_orig_asound
+#define snd_config_iterator_next snd_config_iterator_next_dylibloader_orig_asound
+#define snd_config_iterator_end snd_config_iterator_end_dylibloader_orig_asound
+#define snd_config_iterator_entry snd_config_iterator_entry_dylibloader_orig_asound
+#define snd_config_get_bool_ascii snd_config_get_bool_ascii_dylibloader_orig_asound
+#define snd_config_get_bool snd_config_get_bool_dylibloader_orig_asound
+#define snd_config_get_ctl_iface_ascii snd_config_get_ctl_iface_ascii_dylibloader_orig_asound
+#define snd_config_get_ctl_iface snd_config_get_ctl_iface_dylibloader_orig_asound
+#define snd_names_list snd_names_list_dylibloader_orig_asound
+#define snd_names_list_free snd_names_list_free_dylibloader_orig_asound
+#define snd_pcm_open snd_pcm_open_dylibloader_orig_asound
+#define snd_pcm_open_lconf snd_pcm_open_lconf_dylibloader_orig_asound
+#define snd_pcm_open_fallback snd_pcm_open_fallback_dylibloader_orig_asound
+#define snd_pcm_close snd_pcm_close_dylibloader_orig_asound
+#define snd_pcm_name snd_pcm_name_dylibloader_orig_asound
+#define snd_pcm_type snd_pcm_type_dylibloader_orig_asound
+#define snd_pcm_stream snd_pcm_stream_dylibloader_orig_asound
+#define snd_pcm_poll_descriptors_count snd_pcm_poll_descriptors_count_dylibloader_orig_asound
+#define snd_pcm_poll_descriptors snd_pcm_poll_descriptors_dylibloader_orig_asound
+#define snd_pcm_poll_descriptors_revents snd_pcm_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_pcm_nonblock snd_pcm_nonblock_dylibloader_orig_asound
+#define snd_async_add_pcm_handler snd_async_add_pcm_handler_dylibloader_orig_asound
+#define snd_async_handler_get_pcm snd_async_handler_get_pcm_dylibloader_orig_asound
+#define snd_pcm_info snd_pcm_info_dylibloader_orig_asound
+#define snd_pcm_hw_params_current snd_pcm_hw_params_current_dylibloader_orig_asound
+#define snd_pcm_hw_params snd_pcm_hw_params_dylibloader_orig_asound
+#define snd_pcm_hw_free snd_pcm_hw_free_dylibloader_orig_asound
+#define snd_pcm_sw_params_current snd_pcm_sw_params_current_dylibloader_orig_asound
+#define snd_pcm_sw_params snd_pcm_sw_params_dylibloader_orig_asound
+#define snd_pcm_prepare snd_pcm_prepare_dylibloader_orig_asound
+#define snd_pcm_reset snd_pcm_reset_dylibloader_orig_asound
+#define snd_pcm_status snd_pcm_status_dylibloader_orig_asound
+#define snd_pcm_start snd_pcm_start_dylibloader_orig_asound
+#define snd_pcm_drop snd_pcm_drop_dylibloader_orig_asound
+#define snd_pcm_drain snd_pcm_drain_dylibloader_orig_asound
+#define snd_pcm_pause snd_pcm_pause_dylibloader_orig_asound
+#define snd_pcm_state snd_pcm_state_dylibloader_orig_asound
+#define snd_pcm_hwsync snd_pcm_hwsync_dylibloader_orig_asound
+#define snd_pcm_delay snd_pcm_delay_dylibloader_orig_asound
+#define snd_pcm_resume snd_pcm_resume_dylibloader_orig_asound
+#define snd_pcm_htimestamp snd_pcm_htimestamp_dylibloader_orig_asound
+#define snd_pcm_avail snd_pcm_avail_dylibloader_orig_asound
+#define snd_pcm_avail_update snd_pcm_avail_update_dylibloader_orig_asound
+#define snd_pcm_avail_delay snd_pcm_avail_delay_dylibloader_orig_asound
+#define snd_pcm_rewindable snd_pcm_rewindable_dylibloader_orig_asound
+#define snd_pcm_rewind snd_pcm_rewind_dylibloader_orig_asound
+#define snd_pcm_forwardable snd_pcm_forwardable_dylibloader_orig_asound
+#define snd_pcm_forward snd_pcm_forward_dylibloader_orig_asound
+#define snd_pcm_writei snd_pcm_writei_dylibloader_orig_asound
+#define snd_pcm_readi snd_pcm_readi_dylibloader_orig_asound
+#define snd_pcm_writen snd_pcm_writen_dylibloader_orig_asound
+#define snd_pcm_readn snd_pcm_readn_dylibloader_orig_asound
+#define snd_pcm_wait snd_pcm_wait_dylibloader_orig_asound
+#define snd_pcm_link snd_pcm_link_dylibloader_orig_asound
+#define snd_pcm_unlink snd_pcm_unlink_dylibloader_orig_asound
+#define snd_pcm_query_chmaps snd_pcm_query_chmaps_dylibloader_orig_asound
+#define snd_pcm_query_chmaps_from_hw snd_pcm_query_chmaps_from_hw_dylibloader_orig_asound
+#define snd_pcm_free_chmaps snd_pcm_free_chmaps_dylibloader_orig_asound
+#define snd_pcm_get_chmap snd_pcm_get_chmap_dylibloader_orig_asound
+#define snd_pcm_set_chmap snd_pcm_set_chmap_dylibloader_orig_asound
+#define snd_pcm_chmap_type_name snd_pcm_chmap_type_name_dylibloader_orig_asound
+#define snd_pcm_chmap_name snd_pcm_chmap_name_dylibloader_orig_asound
+#define snd_pcm_chmap_long_name snd_pcm_chmap_long_name_dylibloader_orig_asound
+#define snd_pcm_chmap_print snd_pcm_chmap_print_dylibloader_orig_asound
+#define snd_pcm_chmap_from_string snd_pcm_chmap_from_string_dylibloader_orig_asound
+#define snd_pcm_chmap_parse_string snd_pcm_chmap_parse_string_dylibloader_orig_asound
+#define snd_pcm_recover snd_pcm_recover_dylibloader_orig_asound
+#define snd_pcm_set_params snd_pcm_set_params_dylibloader_orig_asound
+#define snd_pcm_get_params snd_pcm_get_params_dylibloader_orig_asound
+#define snd_pcm_info_sizeof snd_pcm_info_sizeof_dylibloader_orig_asound
+#define snd_pcm_info_malloc snd_pcm_info_malloc_dylibloader_orig_asound
+#define snd_pcm_info_free snd_pcm_info_free_dylibloader_orig_asound
+#define snd_pcm_info_copy snd_pcm_info_copy_dylibloader_orig_asound
+#define snd_pcm_info_get_device snd_pcm_info_get_device_dylibloader_orig_asound
+#define snd_pcm_info_get_subdevice snd_pcm_info_get_subdevice_dylibloader_orig_asound
+#define snd_pcm_info_get_stream snd_pcm_info_get_stream_dylibloader_orig_asound
+#define snd_pcm_info_get_card snd_pcm_info_get_card_dylibloader_orig_asound
+#define snd_pcm_info_get_id snd_pcm_info_get_id_dylibloader_orig_asound
+#define snd_pcm_info_get_name snd_pcm_info_get_name_dylibloader_orig_asound
+#define snd_pcm_info_get_subdevice_name snd_pcm_info_get_subdevice_name_dylibloader_orig_asound
+#define snd_pcm_info_get_class snd_pcm_info_get_class_dylibloader_orig_asound
+#define snd_pcm_info_get_subclass snd_pcm_info_get_subclass_dylibloader_orig_asound
+#define snd_pcm_info_get_subdevices_count snd_pcm_info_get_subdevices_count_dylibloader_orig_asound
+#define snd_pcm_info_get_subdevices_avail snd_pcm_info_get_subdevices_avail_dylibloader_orig_asound
+#define snd_pcm_info_get_sync snd_pcm_info_get_sync_dylibloader_orig_asound
+#define snd_pcm_info_set_device snd_pcm_info_set_device_dylibloader_orig_asound
+#define snd_pcm_info_set_subdevice snd_pcm_info_set_subdevice_dylibloader_orig_asound
+#define snd_pcm_info_set_stream snd_pcm_info_set_stream_dylibloader_orig_asound
+#define snd_pcm_hw_params_any snd_pcm_hw_params_any_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_mmap_sample_resolution snd_pcm_hw_params_can_mmap_sample_resolution_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_double snd_pcm_hw_params_is_double_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_batch snd_pcm_hw_params_is_batch_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_block_transfer snd_pcm_hw_params_is_block_transfer_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_monotonic snd_pcm_hw_params_is_monotonic_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_overrange snd_pcm_hw_params_can_overrange_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_pause snd_pcm_hw_params_can_pause_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_resume snd_pcm_hw_params_can_resume_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_half_duplex snd_pcm_hw_params_is_half_duplex_dylibloader_orig_asound
+#define snd_pcm_hw_params_is_joint_duplex snd_pcm_hw_params_is_joint_duplex_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_sync_start snd_pcm_hw_params_can_sync_start_dylibloader_orig_asound
+#define snd_pcm_hw_params_can_disable_period_wakeup snd_pcm_hw_params_can_disable_period_wakeup_dylibloader_orig_asound
+#define snd_pcm_hw_params_supports_audio_wallclock_ts snd_pcm_hw_params_supports_audio_wallclock_ts_dylibloader_orig_asound
+#define snd_pcm_hw_params_supports_audio_ts_type snd_pcm_hw_params_supports_audio_ts_type_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_rate_numden snd_pcm_hw_params_get_rate_numden_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_sbits snd_pcm_hw_params_get_sbits_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_fifo_size snd_pcm_hw_params_get_fifo_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_sizeof snd_pcm_hw_params_sizeof_dylibloader_orig_asound
+#define snd_pcm_hw_params_malloc snd_pcm_hw_params_malloc_dylibloader_orig_asound
+#define snd_pcm_hw_params_free snd_pcm_hw_params_free_dylibloader_orig_asound
+#define snd_pcm_hw_params_copy snd_pcm_hw_params_copy_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_access snd_pcm_hw_params_get_access_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_access snd_pcm_hw_params_test_access_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_access snd_pcm_hw_params_set_access_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_access_first snd_pcm_hw_params_set_access_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_access_last snd_pcm_hw_params_set_access_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_access_mask snd_pcm_hw_params_set_access_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_access_mask snd_pcm_hw_params_get_access_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_format snd_pcm_hw_params_get_format_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_format snd_pcm_hw_params_test_format_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_format snd_pcm_hw_params_set_format_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_format_first snd_pcm_hw_params_set_format_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_format_last snd_pcm_hw_params_set_format_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_format_mask snd_pcm_hw_params_set_format_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_format_mask snd_pcm_hw_params_get_format_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_subformat snd_pcm_hw_params_get_subformat_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_subformat snd_pcm_hw_params_test_subformat_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_subformat snd_pcm_hw_params_set_subformat_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_subformat_first snd_pcm_hw_params_set_subformat_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_subformat_last snd_pcm_hw_params_set_subformat_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_subformat_mask snd_pcm_hw_params_set_subformat_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_subformat_mask snd_pcm_hw_params_get_subformat_mask_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_channels snd_pcm_hw_params_get_channels_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_channels_min snd_pcm_hw_params_get_channels_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_channels_max snd_pcm_hw_params_get_channels_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_channels snd_pcm_hw_params_test_channels_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels snd_pcm_hw_params_set_channels_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_min snd_pcm_hw_params_set_channels_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_max snd_pcm_hw_params_set_channels_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_minmax snd_pcm_hw_params_set_channels_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_near snd_pcm_hw_params_set_channels_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_first snd_pcm_hw_params_set_channels_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_channels_last snd_pcm_hw_params_set_channels_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_rate snd_pcm_hw_params_get_rate_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_rate_min snd_pcm_hw_params_get_rate_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_rate_max snd_pcm_hw_params_get_rate_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_rate snd_pcm_hw_params_test_rate_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate snd_pcm_hw_params_set_rate_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_min snd_pcm_hw_params_set_rate_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_max snd_pcm_hw_params_set_rate_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_minmax snd_pcm_hw_params_set_rate_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_near snd_pcm_hw_params_set_rate_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_first snd_pcm_hw_params_set_rate_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_last snd_pcm_hw_params_set_rate_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_rate_resample snd_pcm_hw_params_set_rate_resample_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_rate_resample snd_pcm_hw_params_get_rate_resample_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_export_buffer snd_pcm_hw_params_set_export_buffer_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_export_buffer snd_pcm_hw_params_get_export_buffer_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_wakeup snd_pcm_hw_params_set_period_wakeup_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_wakeup snd_pcm_hw_params_get_period_wakeup_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_time snd_pcm_hw_params_get_period_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_time_min snd_pcm_hw_params_get_period_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_time_max snd_pcm_hw_params_get_period_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_period_time snd_pcm_hw_params_test_period_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time snd_pcm_hw_params_set_period_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_min snd_pcm_hw_params_set_period_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_max snd_pcm_hw_params_set_period_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_minmax snd_pcm_hw_params_set_period_time_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_near snd_pcm_hw_params_set_period_time_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_first snd_pcm_hw_params_set_period_time_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_time_last snd_pcm_hw_params_set_period_time_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_size snd_pcm_hw_params_get_period_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_size_min snd_pcm_hw_params_get_period_size_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_period_size_max snd_pcm_hw_params_get_period_size_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_period_size snd_pcm_hw_params_test_period_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size snd_pcm_hw_params_set_period_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_min snd_pcm_hw_params_set_period_size_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_max snd_pcm_hw_params_set_period_size_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_minmax snd_pcm_hw_params_set_period_size_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_near snd_pcm_hw_params_set_period_size_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_first snd_pcm_hw_params_set_period_size_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_last snd_pcm_hw_params_set_period_size_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_period_size_integer snd_pcm_hw_params_set_period_size_integer_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_periods snd_pcm_hw_params_get_periods_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_periods_min snd_pcm_hw_params_get_periods_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_periods_max snd_pcm_hw_params_get_periods_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_periods snd_pcm_hw_params_test_periods_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods snd_pcm_hw_params_set_periods_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_min snd_pcm_hw_params_set_periods_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_max snd_pcm_hw_params_set_periods_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_minmax snd_pcm_hw_params_set_periods_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_near snd_pcm_hw_params_set_periods_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_first snd_pcm_hw_params_set_periods_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_last snd_pcm_hw_params_set_periods_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_periods_integer snd_pcm_hw_params_set_periods_integer_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_time snd_pcm_hw_params_get_buffer_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_time_min snd_pcm_hw_params_get_buffer_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_time_max snd_pcm_hw_params_get_buffer_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_buffer_time snd_pcm_hw_params_test_buffer_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time snd_pcm_hw_params_set_buffer_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_min snd_pcm_hw_params_set_buffer_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_max snd_pcm_hw_params_set_buffer_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_minmax snd_pcm_hw_params_set_buffer_time_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_near snd_pcm_hw_params_set_buffer_time_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_first snd_pcm_hw_params_set_buffer_time_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_time_last snd_pcm_hw_params_set_buffer_time_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_size snd_pcm_hw_params_get_buffer_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_size_min snd_pcm_hw_params_get_buffer_size_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_buffer_size_max snd_pcm_hw_params_get_buffer_size_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_buffer_size snd_pcm_hw_params_test_buffer_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size snd_pcm_hw_params_set_buffer_size_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_min snd_pcm_hw_params_set_buffer_size_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_max snd_pcm_hw_params_set_buffer_size_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_minmax snd_pcm_hw_params_set_buffer_size_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_near snd_pcm_hw_params_set_buffer_size_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_first snd_pcm_hw_params_set_buffer_size_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_buffer_size_last snd_pcm_hw_params_set_buffer_size_last_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_min_align snd_pcm_hw_params_get_min_align_dylibloader_orig_asound
+#define snd_pcm_sw_params_sizeof snd_pcm_sw_params_sizeof_dylibloader_orig_asound
+#define snd_pcm_sw_params_malloc snd_pcm_sw_params_malloc_dylibloader_orig_asound
+#define snd_pcm_sw_params_free snd_pcm_sw_params_free_dylibloader_orig_asound
+#define snd_pcm_sw_params_copy snd_pcm_sw_params_copy_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_boundary snd_pcm_sw_params_get_boundary_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_tstamp_mode snd_pcm_sw_params_set_tstamp_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_tstamp_mode snd_pcm_sw_params_get_tstamp_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_avail_min snd_pcm_sw_params_set_avail_min_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_avail_min snd_pcm_sw_params_get_avail_min_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_period_event snd_pcm_sw_params_set_period_event_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_period_event snd_pcm_sw_params_get_period_event_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_start_threshold snd_pcm_sw_params_set_start_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_start_threshold snd_pcm_sw_params_get_start_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_stop_threshold snd_pcm_sw_params_set_stop_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_stop_threshold snd_pcm_sw_params_get_stop_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_silence_threshold snd_pcm_sw_params_set_silence_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_silence_threshold snd_pcm_sw_params_get_silence_threshold_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_silence_size snd_pcm_sw_params_set_silence_size_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_silence_size snd_pcm_sw_params_get_silence_size_dylibloader_orig_asound
+#define snd_pcm_access_mask_sizeof snd_pcm_access_mask_sizeof_dylibloader_orig_asound
+#define snd_pcm_access_mask_malloc snd_pcm_access_mask_malloc_dylibloader_orig_asound
+#define snd_pcm_access_mask_free snd_pcm_access_mask_free_dylibloader_orig_asound
+#define snd_pcm_access_mask_copy snd_pcm_access_mask_copy_dylibloader_orig_asound
+#define snd_pcm_access_mask_none snd_pcm_access_mask_none_dylibloader_orig_asound
+#define snd_pcm_access_mask_any snd_pcm_access_mask_any_dylibloader_orig_asound
+#define snd_pcm_access_mask_test snd_pcm_access_mask_test_dylibloader_orig_asound
+#define snd_pcm_access_mask_empty snd_pcm_access_mask_empty_dylibloader_orig_asound
+#define snd_pcm_access_mask_set snd_pcm_access_mask_set_dylibloader_orig_asound
+#define snd_pcm_access_mask_reset snd_pcm_access_mask_reset_dylibloader_orig_asound
+#define snd_pcm_format_mask_sizeof snd_pcm_format_mask_sizeof_dylibloader_orig_asound
+#define snd_pcm_format_mask_malloc snd_pcm_format_mask_malloc_dylibloader_orig_asound
+#define snd_pcm_format_mask_free snd_pcm_format_mask_free_dylibloader_orig_asound
+#define snd_pcm_format_mask_copy snd_pcm_format_mask_copy_dylibloader_orig_asound
+#define snd_pcm_format_mask_none snd_pcm_format_mask_none_dylibloader_orig_asound
+#define snd_pcm_format_mask_any snd_pcm_format_mask_any_dylibloader_orig_asound
+#define snd_pcm_format_mask_test snd_pcm_format_mask_test_dylibloader_orig_asound
+#define snd_pcm_format_mask_empty snd_pcm_format_mask_empty_dylibloader_orig_asound
+#define snd_pcm_format_mask_set snd_pcm_format_mask_set_dylibloader_orig_asound
+#define snd_pcm_format_mask_reset snd_pcm_format_mask_reset_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_sizeof snd_pcm_subformat_mask_sizeof_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_malloc snd_pcm_subformat_mask_malloc_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_free snd_pcm_subformat_mask_free_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_copy snd_pcm_subformat_mask_copy_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_none snd_pcm_subformat_mask_none_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_any snd_pcm_subformat_mask_any_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_test snd_pcm_subformat_mask_test_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_empty snd_pcm_subformat_mask_empty_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_set snd_pcm_subformat_mask_set_dylibloader_orig_asound
+#define snd_pcm_subformat_mask_reset snd_pcm_subformat_mask_reset_dylibloader_orig_asound
+#define snd_pcm_status_sizeof snd_pcm_status_sizeof_dylibloader_orig_asound
+#define snd_pcm_status_malloc snd_pcm_status_malloc_dylibloader_orig_asound
+#define snd_pcm_status_free snd_pcm_status_free_dylibloader_orig_asound
+#define snd_pcm_status_copy snd_pcm_status_copy_dylibloader_orig_asound
+#define snd_pcm_status_get_state snd_pcm_status_get_state_dylibloader_orig_asound
+#define snd_pcm_status_get_trigger_tstamp snd_pcm_status_get_trigger_tstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_trigger_htstamp snd_pcm_status_get_trigger_htstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_tstamp snd_pcm_status_get_tstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_htstamp snd_pcm_status_get_htstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_audio_htstamp snd_pcm_status_get_audio_htstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_driver_htstamp snd_pcm_status_get_driver_htstamp_dylibloader_orig_asound
+#define snd_pcm_status_get_delay snd_pcm_status_get_delay_dylibloader_orig_asound
+#define snd_pcm_status_get_avail snd_pcm_status_get_avail_dylibloader_orig_asound
+#define snd_pcm_status_get_avail_max snd_pcm_status_get_avail_max_dylibloader_orig_asound
+#define snd_pcm_status_get_overrange snd_pcm_status_get_overrange_dylibloader_orig_asound
+#define snd_pcm_type_name snd_pcm_type_name_dylibloader_orig_asound
+#define snd_pcm_stream_name snd_pcm_stream_name_dylibloader_orig_asound
+#define snd_pcm_access_name snd_pcm_access_name_dylibloader_orig_asound
+#define snd_pcm_format_name snd_pcm_format_name_dylibloader_orig_asound
+#define snd_pcm_format_description snd_pcm_format_description_dylibloader_orig_asound
+#define snd_pcm_subformat_name snd_pcm_subformat_name_dylibloader_orig_asound
+#define snd_pcm_subformat_description snd_pcm_subformat_description_dylibloader_orig_asound
+#define snd_pcm_format_value snd_pcm_format_value_dylibloader_orig_asound
+#define snd_pcm_tstamp_mode_name snd_pcm_tstamp_mode_name_dylibloader_orig_asound
+#define snd_pcm_state_name snd_pcm_state_name_dylibloader_orig_asound
+#define snd_pcm_dump snd_pcm_dump_dylibloader_orig_asound
+#define snd_pcm_dump_hw_setup snd_pcm_dump_hw_setup_dylibloader_orig_asound
+#define snd_pcm_dump_sw_setup snd_pcm_dump_sw_setup_dylibloader_orig_asound
+#define snd_pcm_dump_setup snd_pcm_dump_setup_dylibloader_orig_asound
+#define snd_pcm_hw_params_dump snd_pcm_hw_params_dump_dylibloader_orig_asound
+#define snd_pcm_sw_params_dump snd_pcm_sw_params_dump_dylibloader_orig_asound
+#define snd_pcm_status_dump snd_pcm_status_dump_dylibloader_orig_asound
+#define snd_pcm_mmap_begin snd_pcm_mmap_begin_dylibloader_orig_asound
+#define snd_pcm_mmap_commit snd_pcm_mmap_commit_dylibloader_orig_asound
+#define snd_pcm_mmap_writei snd_pcm_mmap_writei_dylibloader_orig_asound
+#define snd_pcm_mmap_readi snd_pcm_mmap_readi_dylibloader_orig_asound
+#define snd_pcm_mmap_writen snd_pcm_mmap_writen_dylibloader_orig_asound
+#define snd_pcm_mmap_readn snd_pcm_mmap_readn_dylibloader_orig_asound
+#define snd_pcm_format_signed snd_pcm_format_signed_dylibloader_orig_asound
+#define snd_pcm_format_unsigned snd_pcm_format_unsigned_dylibloader_orig_asound
+#define snd_pcm_format_linear snd_pcm_format_linear_dylibloader_orig_asound
+#define snd_pcm_format_float snd_pcm_format_float_dylibloader_orig_asound
+#define snd_pcm_format_little_endian snd_pcm_format_little_endian_dylibloader_orig_asound
+#define snd_pcm_format_big_endian snd_pcm_format_big_endian_dylibloader_orig_asound
+#define snd_pcm_format_cpu_endian snd_pcm_format_cpu_endian_dylibloader_orig_asound
+#define snd_pcm_format_width snd_pcm_format_width_dylibloader_orig_asound
+#define snd_pcm_format_physical_width snd_pcm_format_physical_width_dylibloader_orig_asound
+#define snd_pcm_build_linear_format snd_pcm_build_linear_format_dylibloader_orig_asound
+#define snd_pcm_format_size snd_pcm_format_size_dylibloader_orig_asound
+#define snd_pcm_format_silence snd_pcm_format_silence_dylibloader_orig_asound
+#define snd_pcm_format_silence_16 snd_pcm_format_silence_16_dylibloader_orig_asound
+#define snd_pcm_format_silence_32 snd_pcm_format_silence_32_dylibloader_orig_asound
+#define snd_pcm_format_silence_64 snd_pcm_format_silence_64_dylibloader_orig_asound
+#define snd_pcm_format_set_silence snd_pcm_format_set_silence_dylibloader_orig_asound
+#define snd_pcm_bytes_to_frames snd_pcm_bytes_to_frames_dylibloader_orig_asound
+#define snd_pcm_frames_to_bytes snd_pcm_frames_to_bytes_dylibloader_orig_asound
+#define snd_pcm_bytes_to_samples snd_pcm_bytes_to_samples_dylibloader_orig_asound
+#define snd_pcm_samples_to_bytes snd_pcm_samples_to_bytes_dylibloader_orig_asound
+#define snd_pcm_area_silence snd_pcm_area_silence_dylibloader_orig_asound
+#define snd_pcm_areas_silence snd_pcm_areas_silence_dylibloader_orig_asound
+#define snd_pcm_area_copy snd_pcm_area_copy_dylibloader_orig_asound
+#define snd_pcm_areas_copy snd_pcm_areas_copy_dylibloader_orig_asound
+#define snd_pcm_areas_copy_wrap snd_pcm_areas_copy_wrap_dylibloader_orig_asound
+#define snd_pcm_hook_get_pcm snd_pcm_hook_get_pcm_dylibloader_orig_asound
+#define snd_pcm_hook_get_private snd_pcm_hook_get_private_dylibloader_orig_asound
+#define snd_pcm_hook_set_private snd_pcm_hook_set_private_dylibloader_orig_asound
+#define snd_pcm_hook_add snd_pcm_hook_add_dylibloader_orig_asound
+#define snd_pcm_hook_remove snd_pcm_hook_remove_dylibloader_orig_asound
+#define snd_pcm_meter_get_bufsize snd_pcm_meter_get_bufsize_dylibloader_orig_asound
+#define snd_pcm_meter_get_channels snd_pcm_meter_get_channels_dylibloader_orig_asound
+#define snd_pcm_meter_get_rate snd_pcm_meter_get_rate_dylibloader_orig_asound
+#define snd_pcm_meter_get_now snd_pcm_meter_get_now_dylibloader_orig_asound
+#define snd_pcm_meter_get_boundary snd_pcm_meter_get_boundary_dylibloader_orig_asound
+#define snd_pcm_meter_add_scope snd_pcm_meter_add_scope_dylibloader_orig_asound
+#define snd_pcm_meter_search_scope snd_pcm_meter_search_scope_dylibloader_orig_asound
+#define snd_pcm_scope_malloc snd_pcm_scope_malloc_dylibloader_orig_asound
+#define snd_pcm_scope_set_ops snd_pcm_scope_set_ops_dylibloader_orig_asound
+#define snd_pcm_scope_set_name snd_pcm_scope_set_name_dylibloader_orig_asound
+#define snd_pcm_scope_get_name snd_pcm_scope_get_name_dylibloader_orig_asound
+#define snd_pcm_scope_get_callback_private snd_pcm_scope_get_callback_private_dylibloader_orig_asound
+#define snd_pcm_scope_set_callback_private snd_pcm_scope_set_callback_private_dylibloader_orig_asound
+#define snd_pcm_scope_s16_open snd_pcm_scope_s16_open_dylibloader_orig_asound
+#define snd_pcm_scope_s16_get_channel_buffer snd_pcm_scope_s16_get_channel_buffer_dylibloader_orig_asound
+#define snd_spcm_init snd_spcm_init_dylibloader_orig_asound
+#define snd_spcm_init_duplex snd_spcm_init_duplex_dylibloader_orig_asound
+#define snd_spcm_init_get_params snd_spcm_init_get_params_dylibloader_orig_asound
+#define snd_pcm_start_mode_name snd_pcm_start_mode_name_dylibloader_orig_asound
+#define snd_pcm_xrun_mode_name snd_pcm_xrun_mode_name_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_start_mode snd_pcm_sw_params_set_start_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_start_mode snd_pcm_sw_params_get_start_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_xrun_mode snd_pcm_sw_params_set_xrun_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_xrun_mode snd_pcm_sw_params_get_xrun_mode_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_xfer_align snd_pcm_sw_params_set_xfer_align_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_xfer_align snd_pcm_sw_params_get_xfer_align_dylibloader_orig_asound
+#define snd_pcm_sw_params_set_sleep_min snd_pcm_sw_params_set_sleep_min_dylibloader_orig_asound
+#define snd_pcm_sw_params_get_sleep_min snd_pcm_sw_params_get_sleep_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_tick_time snd_pcm_hw_params_get_tick_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_tick_time_min snd_pcm_hw_params_get_tick_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_get_tick_time_max snd_pcm_hw_params_get_tick_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_test_tick_time snd_pcm_hw_params_test_tick_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time snd_pcm_hw_params_set_tick_time_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_min snd_pcm_hw_params_set_tick_time_min_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_max snd_pcm_hw_params_set_tick_time_max_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_minmax snd_pcm_hw_params_set_tick_time_minmax_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_near snd_pcm_hw_params_set_tick_time_near_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_first snd_pcm_hw_params_set_tick_time_first_dylibloader_orig_asound
+#define snd_pcm_hw_params_set_tick_time_last snd_pcm_hw_params_set_tick_time_last_dylibloader_orig_asound
+#define snd_rawmidi_open snd_rawmidi_open_dylibloader_orig_asound
+#define snd_rawmidi_open_lconf snd_rawmidi_open_lconf_dylibloader_orig_asound
+#define snd_rawmidi_close snd_rawmidi_close_dylibloader_orig_asound
+#define snd_rawmidi_poll_descriptors_count snd_rawmidi_poll_descriptors_count_dylibloader_orig_asound
+#define snd_rawmidi_poll_descriptors snd_rawmidi_poll_descriptors_dylibloader_orig_asound
+#define snd_rawmidi_poll_descriptors_revents snd_rawmidi_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_rawmidi_nonblock snd_rawmidi_nonblock_dylibloader_orig_asound
+#define snd_rawmidi_info_sizeof snd_rawmidi_info_sizeof_dylibloader_orig_asound
+#define snd_rawmidi_info_malloc snd_rawmidi_info_malloc_dylibloader_orig_asound
+#define snd_rawmidi_info_free snd_rawmidi_info_free_dylibloader_orig_asound
+#define snd_rawmidi_info_copy snd_rawmidi_info_copy_dylibloader_orig_asound
+#define snd_rawmidi_info_get_device snd_rawmidi_info_get_device_dylibloader_orig_asound
+#define snd_rawmidi_info_get_subdevice snd_rawmidi_info_get_subdevice_dylibloader_orig_asound
+#define snd_rawmidi_info_get_stream snd_rawmidi_info_get_stream_dylibloader_orig_asound
+#define snd_rawmidi_info_get_card snd_rawmidi_info_get_card_dylibloader_orig_asound
+#define snd_rawmidi_info_get_flags snd_rawmidi_info_get_flags_dylibloader_orig_asound
+#define snd_rawmidi_info_get_id snd_rawmidi_info_get_id_dylibloader_orig_asound
+#define snd_rawmidi_info_get_name snd_rawmidi_info_get_name_dylibloader_orig_asound
+#define snd_rawmidi_info_get_subdevice_name snd_rawmidi_info_get_subdevice_name_dylibloader_orig_asound
+#define snd_rawmidi_info_get_subdevices_count snd_rawmidi_info_get_subdevices_count_dylibloader_orig_asound
+#define snd_rawmidi_info_get_subdevices_avail snd_rawmidi_info_get_subdevices_avail_dylibloader_orig_asound
+#define snd_rawmidi_info_set_device snd_rawmidi_info_set_device_dylibloader_orig_asound
+#define snd_rawmidi_info_set_subdevice snd_rawmidi_info_set_subdevice_dylibloader_orig_asound
+#define snd_rawmidi_info_set_stream snd_rawmidi_info_set_stream_dylibloader_orig_asound
+#define snd_rawmidi_info snd_rawmidi_info_dylibloader_orig_asound
+#define snd_rawmidi_params_sizeof snd_rawmidi_params_sizeof_dylibloader_orig_asound
+#define snd_rawmidi_params_malloc snd_rawmidi_params_malloc_dylibloader_orig_asound
+#define snd_rawmidi_params_free snd_rawmidi_params_free_dylibloader_orig_asound
+#define snd_rawmidi_params_copy snd_rawmidi_params_copy_dylibloader_orig_asound
+#define snd_rawmidi_params_set_buffer_size snd_rawmidi_params_set_buffer_size_dylibloader_orig_asound
+#define snd_rawmidi_params_get_buffer_size snd_rawmidi_params_get_buffer_size_dylibloader_orig_asound
+#define snd_rawmidi_params_set_avail_min snd_rawmidi_params_set_avail_min_dylibloader_orig_asound
+#define snd_rawmidi_params_get_avail_min snd_rawmidi_params_get_avail_min_dylibloader_orig_asound
+#define snd_rawmidi_params_set_no_active_sensing snd_rawmidi_params_set_no_active_sensing_dylibloader_orig_asound
+#define snd_rawmidi_params_get_no_active_sensing snd_rawmidi_params_get_no_active_sensing_dylibloader_orig_asound
+#define snd_rawmidi_params snd_rawmidi_params_dylibloader_orig_asound
+#define snd_rawmidi_params_current snd_rawmidi_params_current_dylibloader_orig_asound
+#define snd_rawmidi_status_sizeof snd_rawmidi_status_sizeof_dylibloader_orig_asound
+#define snd_rawmidi_status_malloc snd_rawmidi_status_malloc_dylibloader_orig_asound
+#define snd_rawmidi_status_free snd_rawmidi_status_free_dylibloader_orig_asound
+#define snd_rawmidi_status_copy snd_rawmidi_status_copy_dylibloader_orig_asound
+#define snd_rawmidi_status_get_tstamp snd_rawmidi_status_get_tstamp_dylibloader_orig_asound
+#define snd_rawmidi_status_get_avail snd_rawmidi_status_get_avail_dylibloader_orig_asound
+#define snd_rawmidi_status_get_xruns snd_rawmidi_status_get_xruns_dylibloader_orig_asound
+#define snd_rawmidi_status snd_rawmidi_status_dylibloader_orig_asound
+#define snd_rawmidi_drain snd_rawmidi_drain_dylibloader_orig_asound
+#define snd_rawmidi_drop snd_rawmidi_drop_dylibloader_orig_asound
+#define snd_rawmidi_write snd_rawmidi_write_dylibloader_orig_asound
+#define snd_rawmidi_read snd_rawmidi_read_dylibloader_orig_asound
+#define snd_rawmidi_name snd_rawmidi_name_dylibloader_orig_asound
+#define snd_rawmidi_type snd_rawmidi_type_dylibloader_orig_asound
+#define snd_rawmidi_stream snd_rawmidi_stream_dylibloader_orig_asound
+#define snd_timer_query_open snd_timer_query_open_dylibloader_orig_asound
+#define snd_timer_query_open_lconf snd_timer_query_open_lconf_dylibloader_orig_asound
+#define snd_timer_query_close snd_timer_query_close_dylibloader_orig_asound
+#define snd_timer_query_next_device snd_timer_query_next_device_dylibloader_orig_asound
+#define snd_timer_query_info snd_timer_query_info_dylibloader_orig_asound
+#define snd_timer_query_params snd_timer_query_params_dylibloader_orig_asound
+#define snd_timer_query_status snd_timer_query_status_dylibloader_orig_asound
+#define snd_timer_open snd_timer_open_dylibloader_orig_asound
+#define snd_timer_open_lconf snd_timer_open_lconf_dylibloader_orig_asound
+#define snd_timer_close snd_timer_close_dylibloader_orig_asound
+#define snd_async_add_timer_handler snd_async_add_timer_handler_dylibloader_orig_asound
+#define snd_async_handler_get_timer snd_async_handler_get_timer_dylibloader_orig_asound
+#define snd_timer_poll_descriptors_count snd_timer_poll_descriptors_count_dylibloader_orig_asound
+#define snd_timer_poll_descriptors snd_timer_poll_descriptors_dylibloader_orig_asound
+#define snd_timer_poll_descriptors_revents snd_timer_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_timer_info snd_timer_info_dylibloader_orig_asound
+#define snd_timer_params snd_timer_params_dylibloader_orig_asound
+#define snd_timer_status snd_timer_status_dylibloader_orig_asound
+#define snd_timer_start snd_timer_start_dylibloader_orig_asound
+#define snd_timer_stop snd_timer_stop_dylibloader_orig_asound
+#define snd_timer_continue snd_timer_continue_dylibloader_orig_asound
+#define snd_timer_read snd_timer_read_dylibloader_orig_asound
+#define snd_timer_id_sizeof snd_timer_id_sizeof_dylibloader_orig_asound
+#define snd_timer_id_malloc snd_timer_id_malloc_dylibloader_orig_asound
+#define snd_timer_id_free snd_timer_id_free_dylibloader_orig_asound
+#define snd_timer_id_copy snd_timer_id_copy_dylibloader_orig_asound
+#define snd_timer_id_set_class snd_timer_id_set_class_dylibloader_orig_asound
+#define snd_timer_id_get_class snd_timer_id_get_class_dylibloader_orig_asound
+#define snd_timer_id_set_sclass snd_timer_id_set_sclass_dylibloader_orig_asound
+#define snd_timer_id_get_sclass snd_timer_id_get_sclass_dylibloader_orig_asound
+#define snd_timer_id_set_card snd_timer_id_set_card_dylibloader_orig_asound
+#define snd_timer_id_get_card snd_timer_id_get_card_dylibloader_orig_asound
+#define snd_timer_id_set_device snd_timer_id_set_device_dylibloader_orig_asound
+#define snd_timer_id_get_device snd_timer_id_get_device_dylibloader_orig_asound
+#define snd_timer_id_set_subdevice snd_timer_id_set_subdevice_dylibloader_orig_asound
+#define snd_timer_id_get_subdevice snd_timer_id_get_subdevice_dylibloader_orig_asound
+#define snd_timer_ginfo_sizeof snd_timer_ginfo_sizeof_dylibloader_orig_asound
+#define snd_timer_ginfo_malloc snd_timer_ginfo_malloc_dylibloader_orig_asound
+#define snd_timer_ginfo_free snd_timer_ginfo_free_dylibloader_orig_asound
+#define snd_timer_ginfo_copy snd_timer_ginfo_copy_dylibloader_orig_asound
+#define snd_timer_ginfo_set_tid snd_timer_ginfo_set_tid_dylibloader_orig_asound
+#define snd_timer_ginfo_get_tid snd_timer_ginfo_get_tid_dylibloader_orig_asound
+#define snd_timer_ginfo_get_flags snd_timer_ginfo_get_flags_dylibloader_orig_asound
+#define snd_timer_ginfo_get_card snd_timer_ginfo_get_card_dylibloader_orig_asound
+#define snd_timer_ginfo_get_id snd_timer_ginfo_get_id_dylibloader_orig_asound
+#define snd_timer_ginfo_get_name snd_timer_ginfo_get_name_dylibloader_orig_asound
+#define snd_timer_ginfo_get_resolution snd_timer_ginfo_get_resolution_dylibloader_orig_asound
+#define snd_timer_ginfo_get_resolution_min snd_timer_ginfo_get_resolution_min_dylibloader_orig_asound
+#define snd_timer_ginfo_get_resolution_max snd_timer_ginfo_get_resolution_max_dylibloader_orig_asound
+#define snd_timer_ginfo_get_clients snd_timer_ginfo_get_clients_dylibloader_orig_asound
+#define snd_timer_info_sizeof snd_timer_info_sizeof_dylibloader_orig_asound
+#define snd_timer_info_malloc snd_timer_info_malloc_dylibloader_orig_asound
+#define snd_timer_info_free snd_timer_info_free_dylibloader_orig_asound
+#define snd_timer_info_copy snd_timer_info_copy_dylibloader_orig_asound
+#define snd_timer_info_is_slave snd_timer_info_is_slave_dylibloader_orig_asound
+#define snd_timer_info_get_card snd_timer_info_get_card_dylibloader_orig_asound
+#define snd_timer_info_get_id snd_timer_info_get_id_dylibloader_orig_asound
+#define snd_timer_info_get_name snd_timer_info_get_name_dylibloader_orig_asound
+#define snd_timer_info_get_resolution snd_timer_info_get_resolution_dylibloader_orig_asound
+#define snd_timer_params_sizeof snd_timer_params_sizeof_dylibloader_orig_asound
+#define snd_timer_params_malloc snd_timer_params_malloc_dylibloader_orig_asound
+#define snd_timer_params_free snd_timer_params_free_dylibloader_orig_asound
+#define snd_timer_params_copy snd_timer_params_copy_dylibloader_orig_asound
+#define snd_timer_params_set_auto_start snd_timer_params_set_auto_start_dylibloader_orig_asound
+#define snd_timer_params_get_auto_start snd_timer_params_get_auto_start_dylibloader_orig_asound
+#define snd_timer_params_set_exclusive snd_timer_params_set_exclusive_dylibloader_orig_asound
+#define snd_timer_params_get_exclusive snd_timer_params_get_exclusive_dylibloader_orig_asound
+#define snd_timer_params_set_early_event snd_timer_params_set_early_event_dylibloader_orig_asound
+#define snd_timer_params_get_early_event snd_timer_params_get_early_event_dylibloader_orig_asound
+#define snd_timer_params_set_ticks snd_timer_params_set_ticks_dylibloader_orig_asound
+#define snd_timer_params_get_ticks snd_timer_params_get_ticks_dylibloader_orig_asound
+#define snd_timer_params_set_queue_size snd_timer_params_set_queue_size_dylibloader_orig_asound
+#define snd_timer_params_get_queue_size snd_timer_params_get_queue_size_dylibloader_orig_asound
+#define snd_timer_params_set_filter snd_timer_params_set_filter_dylibloader_orig_asound
+#define snd_timer_params_get_filter snd_timer_params_get_filter_dylibloader_orig_asound
+#define snd_timer_status_sizeof snd_timer_status_sizeof_dylibloader_orig_asound
+#define snd_timer_status_malloc snd_timer_status_malloc_dylibloader_orig_asound
+#define snd_timer_status_free snd_timer_status_free_dylibloader_orig_asound
+#define snd_timer_status_copy snd_timer_status_copy_dylibloader_orig_asound
+#define snd_timer_status_get_timestamp snd_timer_status_get_timestamp_dylibloader_orig_asound
+#define snd_timer_status_get_resolution snd_timer_status_get_resolution_dylibloader_orig_asound
+#define snd_timer_status_get_lost snd_timer_status_get_lost_dylibloader_orig_asound
+#define snd_timer_status_get_overrun snd_timer_status_get_overrun_dylibloader_orig_asound
+#define snd_timer_status_get_queue snd_timer_status_get_queue_dylibloader_orig_asound
+#define snd_timer_info_get_ticks snd_timer_info_get_ticks_dylibloader_orig_asound
+#define snd_hwdep_open snd_hwdep_open_dylibloader_orig_asound
+#define snd_hwdep_close snd_hwdep_close_dylibloader_orig_asound
+#define snd_hwdep_poll_descriptors snd_hwdep_poll_descriptors_dylibloader_orig_asound
+#define snd_hwdep_poll_descriptors_count snd_hwdep_poll_descriptors_count_dylibloader_orig_asound
+#define snd_hwdep_poll_descriptors_revents snd_hwdep_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_hwdep_nonblock snd_hwdep_nonblock_dylibloader_orig_asound
+#define snd_hwdep_info snd_hwdep_info_dylibloader_orig_asound
+#define snd_hwdep_dsp_status snd_hwdep_dsp_status_dylibloader_orig_asound
+#define snd_hwdep_dsp_load snd_hwdep_dsp_load_dylibloader_orig_asound
+#define snd_hwdep_ioctl snd_hwdep_ioctl_dylibloader_orig_asound
+#define snd_hwdep_write snd_hwdep_write_dylibloader_orig_asound
+#define snd_hwdep_read snd_hwdep_read_dylibloader_orig_asound
+#define snd_hwdep_info_sizeof snd_hwdep_info_sizeof_dylibloader_orig_asound
+#define snd_hwdep_info_malloc snd_hwdep_info_malloc_dylibloader_orig_asound
+#define snd_hwdep_info_free snd_hwdep_info_free_dylibloader_orig_asound
+#define snd_hwdep_info_copy snd_hwdep_info_copy_dylibloader_orig_asound
+#define snd_hwdep_info_get_device snd_hwdep_info_get_device_dylibloader_orig_asound
+#define snd_hwdep_info_get_card snd_hwdep_info_get_card_dylibloader_orig_asound
+#define snd_hwdep_info_get_id snd_hwdep_info_get_id_dylibloader_orig_asound
+#define snd_hwdep_info_get_name snd_hwdep_info_get_name_dylibloader_orig_asound
+#define snd_hwdep_info_get_iface snd_hwdep_info_get_iface_dylibloader_orig_asound
+#define snd_hwdep_info_set_device snd_hwdep_info_set_device_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_sizeof snd_hwdep_dsp_status_sizeof_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_malloc snd_hwdep_dsp_status_malloc_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_free snd_hwdep_dsp_status_free_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_copy snd_hwdep_dsp_status_copy_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_get_version snd_hwdep_dsp_status_get_version_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_get_id snd_hwdep_dsp_status_get_id_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_get_num_dsps snd_hwdep_dsp_status_get_num_dsps_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_get_dsp_loaded snd_hwdep_dsp_status_get_dsp_loaded_dylibloader_orig_asound
+#define snd_hwdep_dsp_status_get_chip_ready snd_hwdep_dsp_status_get_chip_ready_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_sizeof snd_hwdep_dsp_image_sizeof_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_malloc snd_hwdep_dsp_image_malloc_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_free snd_hwdep_dsp_image_free_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_copy snd_hwdep_dsp_image_copy_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_get_index snd_hwdep_dsp_image_get_index_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_get_name snd_hwdep_dsp_image_get_name_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_get_image snd_hwdep_dsp_image_get_image_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_get_length snd_hwdep_dsp_image_get_length_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_set_index snd_hwdep_dsp_image_set_index_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_set_name snd_hwdep_dsp_image_set_name_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_set_image snd_hwdep_dsp_image_set_image_dylibloader_orig_asound
+#define snd_hwdep_dsp_image_set_length snd_hwdep_dsp_image_set_length_dylibloader_orig_asound
+#define snd_card_load snd_card_load_dylibloader_orig_asound
+#define snd_card_next snd_card_next_dylibloader_orig_asound
+#define snd_card_get_index snd_card_get_index_dylibloader_orig_asound
+#define snd_card_get_name snd_card_get_name_dylibloader_orig_asound
+#define snd_card_get_longname snd_card_get_longname_dylibloader_orig_asound
+#define snd_device_name_hint snd_device_name_hint_dylibloader_orig_asound
+#define snd_device_name_free_hint snd_device_name_free_hint_dylibloader_orig_asound
+#define snd_device_name_get_hint snd_device_name_get_hint_dylibloader_orig_asound
+#define snd_ctl_open snd_ctl_open_dylibloader_orig_asound
+#define snd_ctl_open_lconf snd_ctl_open_lconf_dylibloader_orig_asound
+#define snd_ctl_open_fallback snd_ctl_open_fallback_dylibloader_orig_asound
+#define snd_ctl_close snd_ctl_close_dylibloader_orig_asound
+#define snd_ctl_nonblock snd_ctl_nonblock_dylibloader_orig_asound
+#define snd_async_add_ctl_handler snd_async_add_ctl_handler_dylibloader_orig_asound
+#define snd_async_handler_get_ctl snd_async_handler_get_ctl_dylibloader_orig_asound
+#define snd_ctl_poll_descriptors_count snd_ctl_poll_descriptors_count_dylibloader_orig_asound
+#define snd_ctl_poll_descriptors snd_ctl_poll_descriptors_dylibloader_orig_asound
+#define snd_ctl_poll_descriptors_revents snd_ctl_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_ctl_subscribe_events snd_ctl_subscribe_events_dylibloader_orig_asound
+#define snd_ctl_card_info snd_ctl_card_info_dylibloader_orig_asound
+#define snd_ctl_elem_list snd_ctl_elem_list_dylibloader_orig_asound
+#define snd_ctl_elem_info snd_ctl_elem_info_dylibloader_orig_asound
+#define snd_ctl_elem_read snd_ctl_elem_read_dylibloader_orig_asound
+#define snd_ctl_elem_write snd_ctl_elem_write_dylibloader_orig_asound
+#define snd_ctl_elem_lock snd_ctl_elem_lock_dylibloader_orig_asound
+#define snd_ctl_elem_unlock snd_ctl_elem_unlock_dylibloader_orig_asound
+#define snd_ctl_elem_tlv_read snd_ctl_elem_tlv_read_dylibloader_orig_asound
+#define snd_ctl_elem_tlv_write snd_ctl_elem_tlv_write_dylibloader_orig_asound
+#define snd_ctl_elem_tlv_command snd_ctl_elem_tlv_command_dylibloader_orig_asound
+#define snd_ctl_hwdep_next_device snd_ctl_hwdep_next_device_dylibloader_orig_asound
+#define snd_ctl_hwdep_info snd_ctl_hwdep_info_dylibloader_orig_asound
+#define snd_ctl_pcm_next_device snd_ctl_pcm_next_device_dylibloader_orig_asound
+#define snd_ctl_pcm_info snd_ctl_pcm_info_dylibloader_orig_asound
+#define snd_ctl_pcm_prefer_subdevice snd_ctl_pcm_prefer_subdevice_dylibloader_orig_asound
+#define snd_ctl_rawmidi_next_device snd_ctl_rawmidi_next_device_dylibloader_orig_asound
+#define snd_ctl_rawmidi_info snd_ctl_rawmidi_info_dylibloader_orig_asound
+#define snd_ctl_rawmidi_prefer_subdevice snd_ctl_rawmidi_prefer_subdevice_dylibloader_orig_asound
+#define snd_ctl_set_power_state snd_ctl_set_power_state_dylibloader_orig_asound
+#define snd_ctl_get_power_state snd_ctl_get_power_state_dylibloader_orig_asound
+#define snd_ctl_read snd_ctl_read_dylibloader_orig_asound
+#define snd_ctl_wait snd_ctl_wait_dylibloader_orig_asound
+#define snd_ctl_name snd_ctl_name_dylibloader_orig_asound
+#define snd_ctl_type snd_ctl_type_dylibloader_orig_asound
+#define snd_ctl_elem_type_name snd_ctl_elem_type_name_dylibloader_orig_asound
+#define snd_ctl_elem_iface_name snd_ctl_elem_iface_name_dylibloader_orig_asound
+#define snd_ctl_event_type_name snd_ctl_event_type_name_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_mask snd_ctl_event_elem_get_mask_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_numid snd_ctl_event_elem_get_numid_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_id snd_ctl_event_elem_get_id_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_interface snd_ctl_event_elem_get_interface_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_device snd_ctl_event_elem_get_device_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_subdevice snd_ctl_event_elem_get_subdevice_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_name snd_ctl_event_elem_get_name_dylibloader_orig_asound
+#define snd_ctl_event_elem_get_index snd_ctl_event_elem_get_index_dylibloader_orig_asound
+#define snd_ctl_elem_list_alloc_space snd_ctl_elem_list_alloc_space_dylibloader_orig_asound
+#define snd_ctl_elem_list_free_space snd_ctl_elem_list_free_space_dylibloader_orig_asound
+#define snd_ctl_ascii_elem_id_get snd_ctl_ascii_elem_id_get_dylibloader_orig_asound
+#define snd_ctl_ascii_elem_id_parse snd_ctl_ascii_elem_id_parse_dylibloader_orig_asound
+#define snd_ctl_ascii_value_parse snd_ctl_ascii_value_parse_dylibloader_orig_asound
+#define snd_ctl_elem_id_sizeof snd_ctl_elem_id_sizeof_dylibloader_orig_asound
+#define snd_ctl_elem_id_malloc snd_ctl_elem_id_malloc_dylibloader_orig_asound
+#define snd_ctl_elem_id_free snd_ctl_elem_id_free_dylibloader_orig_asound
+#define snd_ctl_elem_id_clear snd_ctl_elem_id_clear_dylibloader_orig_asound
+#define snd_ctl_elem_id_copy snd_ctl_elem_id_copy_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_numid snd_ctl_elem_id_get_numid_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_interface snd_ctl_elem_id_get_interface_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_device snd_ctl_elem_id_get_device_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_subdevice snd_ctl_elem_id_get_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_name snd_ctl_elem_id_get_name_dylibloader_orig_asound
+#define snd_ctl_elem_id_get_index snd_ctl_elem_id_get_index_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_numid snd_ctl_elem_id_set_numid_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_interface snd_ctl_elem_id_set_interface_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_device snd_ctl_elem_id_set_device_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_subdevice snd_ctl_elem_id_set_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_name snd_ctl_elem_id_set_name_dylibloader_orig_asound
+#define snd_ctl_elem_id_set_index snd_ctl_elem_id_set_index_dylibloader_orig_asound
+#define snd_ctl_card_info_sizeof snd_ctl_card_info_sizeof_dylibloader_orig_asound
+#define snd_ctl_card_info_malloc snd_ctl_card_info_malloc_dylibloader_orig_asound
+#define snd_ctl_card_info_free snd_ctl_card_info_free_dylibloader_orig_asound
+#define snd_ctl_card_info_clear snd_ctl_card_info_clear_dylibloader_orig_asound
+#define snd_ctl_card_info_copy snd_ctl_card_info_copy_dylibloader_orig_asound
+#define snd_ctl_card_info_get_card snd_ctl_card_info_get_card_dylibloader_orig_asound
+#define snd_ctl_card_info_get_id snd_ctl_card_info_get_id_dylibloader_orig_asound
+#define snd_ctl_card_info_get_driver snd_ctl_card_info_get_driver_dylibloader_orig_asound
+#define snd_ctl_card_info_get_name snd_ctl_card_info_get_name_dylibloader_orig_asound
+#define snd_ctl_card_info_get_longname snd_ctl_card_info_get_longname_dylibloader_orig_asound
+#define snd_ctl_card_info_get_mixername snd_ctl_card_info_get_mixername_dylibloader_orig_asound
+#define snd_ctl_card_info_get_components snd_ctl_card_info_get_components_dylibloader_orig_asound
+#define snd_ctl_event_sizeof snd_ctl_event_sizeof_dylibloader_orig_asound
+#define snd_ctl_event_malloc snd_ctl_event_malloc_dylibloader_orig_asound
+#define snd_ctl_event_free snd_ctl_event_free_dylibloader_orig_asound
+#define snd_ctl_event_clear snd_ctl_event_clear_dylibloader_orig_asound
+#define snd_ctl_event_copy snd_ctl_event_copy_dylibloader_orig_asound
+#define snd_ctl_event_get_type snd_ctl_event_get_type_dylibloader_orig_asound
+#define snd_ctl_elem_list_sizeof snd_ctl_elem_list_sizeof_dylibloader_orig_asound
+#define snd_ctl_elem_list_malloc snd_ctl_elem_list_malloc_dylibloader_orig_asound
+#define snd_ctl_elem_list_free snd_ctl_elem_list_free_dylibloader_orig_asound
+#define snd_ctl_elem_list_clear snd_ctl_elem_list_clear_dylibloader_orig_asound
+#define snd_ctl_elem_list_copy snd_ctl_elem_list_copy_dylibloader_orig_asound
+#define snd_ctl_elem_list_set_offset snd_ctl_elem_list_set_offset_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_used snd_ctl_elem_list_get_used_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_count snd_ctl_elem_list_get_count_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_id snd_ctl_elem_list_get_id_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_numid snd_ctl_elem_list_get_numid_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_interface snd_ctl_elem_list_get_interface_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_device snd_ctl_elem_list_get_device_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_subdevice snd_ctl_elem_list_get_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_name snd_ctl_elem_list_get_name_dylibloader_orig_asound
+#define snd_ctl_elem_list_get_index snd_ctl_elem_list_get_index_dylibloader_orig_asound
+#define snd_ctl_elem_info_sizeof snd_ctl_elem_info_sizeof_dylibloader_orig_asound
+#define snd_ctl_elem_info_malloc snd_ctl_elem_info_malloc_dylibloader_orig_asound
+#define snd_ctl_elem_info_free snd_ctl_elem_info_free_dylibloader_orig_asound
+#define snd_ctl_elem_info_clear snd_ctl_elem_info_clear_dylibloader_orig_asound
+#define snd_ctl_elem_info_copy snd_ctl_elem_info_copy_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_type snd_ctl_elem_info_get_type_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_readable snd_ctl_elem_info_is_readable_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_writable snd_ctl_elem_info_is_writable_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_volatile snd_ctl_elem_info_is_volatile_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_inactive snd_ctl_elem_info_is_inactive_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_locked snd_ctl_elem_info_is_locked_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_tlv_readable snd_ctl_elem_info_is_tlv_readable_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_tlv_writable snd_ctl_elem_info_is_tlv_writable_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_tlv_commandable snd_ctl_elem_info_is_tlv_commandable_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_owner snd_ctl_elem_info_is_owner_dylibloader_orig_asound
+#define snd_ctl_elem_info_is_user snd_ctl_elem_info_is_user_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_owner snd_ctl_elem_info_get_owner_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_count snd_ctl_elem_info_get_count_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_min snd_ctl_elem_info_get_min_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_max snd_ctl_elem_info_get_max_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_step snd_ctl_elem_info_get_step_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_min64 snd_ctl_elem_info_get_min64_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_max64 snd_ctl_elem_info_get_max64_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_step64 snd_ctl_elem_info_get_step64_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_items snd_ctl_elem_info_get_items_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_item snd_ctl_elem_info_set_item_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_item_name snd_ctl_elem_info_get_item_name_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_dimensions snd_ctl_elem_info_get_dimensions_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_dimension snd_ctl_elem_info_get_dimension_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_dimension snd_ctl_elem_info_set_dimension_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_id snd_ctl_elem_info_get_id_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_numid snd_ctl_elem_info_get_numid_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_interface snd_ctl_elem_info_get_interface_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_device snd_ctl_elem_info_get_device_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_subdevice snd_ctl_elem_info_get_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_name snd_ctl_elem_info_get_name_dylibloader_orig_asound
+#define snd_ctl_elem_info_get_index snd_ctl_elem_info_get_index_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_id snd_ctl_elem_info_set_id_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_numid snd_ctl_elem_info_set_numid_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_interface snd_ctl_elem_info_set_interface_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_device snd_ctl_elem_info_set_device_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_subdevice snd_ctl_elem_info_set_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_name snd_ctl_elem_info_set_name_dylibloader_orig_asound
+#define snd_ctl_elem_info_set_index snd_ctl_elem_info_set_index_dylibloader_orig_asound
+#define snd_ctl_add_integer_elem_set snd_ctl_add_integer_elem_set_dylibloader_orig_asound
+#define snd_ctl_add_integer64_elem_set snd_ctl_add_integer64_elem_set_dylibloader_orig_asound
+#define snd_ctl_add_boolean_elem_set snd_ctl_add_boolean_elem_set_dylibloader_orig_asound
+#define snd_ctl_add_enumerated_elem_set snd_ctl_add_enumerated_elem_set_dylibloader_orig_asound
+#define snd_ctl_add_bytes_elem_set snd_ctl_add_bytes_elem_set_dylibloader_orig_asound
+#define snd_ctl_elem_add_integer snd_ctl_elem_add_integer_dylibloader_orig_asound
+#define snd_ctl_elem_add_integer64 snd_ctl_elem_add_integer64_dylibloader_orig_asound
+#define snd_ctl_elem_add_boolean snd_ctl_elem_add_boolean_dylibloader_orig_asound
+#define snd_ctl_elem_add_enumerated snd_ctl_elem_add_enumerated_dylibloader_orig_asound
+#define snd_ctl_elem_add_iec958 snd_ctl_elem_add_iec958_dylibloader_orig_asound
+#define snd_ctl_elem_remove snd_ctl_elem_remove_dylibloader_orig_asound
+#define snd_ctl_elem_value_sizeof snd_ctl_elem_value_sizeof_dylibloader_orig_asound
+#define snd_ctl_elem_value_malloc snd_ctl_elem_value_malloc_dylibloader_orig_asound
+#define snd_ctl_elem_value_free snd_ctl_elem_value_free_dylibloader_orig_asound
+#define snd_ctl_elem_value_clear snd_ctl_elem_value_clear_dylibloader_orig_asound
+#define snd_ctl_elem_value_copy snd_ctl_elem_value_copy_dylibloader_orig_asound
+#define snd_ctl_elem_value_compare snd_ctl_elem_value_compare_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_id snd_ctl_elem_value_get_id_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_numid snd_ctl_elem_value_get_numid_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_interface snd_ctl_elem_value_get_interface_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_device snd_ctl_elem_value_get_device_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_subdevice snd_ctl_elem_value_get_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_name snd_ctl_elem_value_get_name_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_index snd_ctl_elem_value_get_index_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_id snd_ctl_elem_value_set_id_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_numid snd_ctl_elem_value_set_numid_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_interface snd_ctl_elem_value_set_interface_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_device snd_ctl_elem_value_set_device_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_subdevice snd_ctl_elem_value_set_subdevice_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_name snd_ctl_elem_value_set_name_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_index snd_ctl_elem_value_set_index_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_boolean snd_ctl_elem_value_get_boolean_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_integer snd_ctl_elem_value_get_integer_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_integer64 snd_ctl_elem_value_get_integer64_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_enumerated snd_ctl_elem_value_get_enumerated_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_byte snd_ctl_elem_value_get_byte_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_boolean snd_ctl_elem_value_set_boolean_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_integer snd_ctl_elem_value_set_integer_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_integer64 snd_ctl_elem_value_set_integer64_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_enumerated snd_ctl_elem_value_set_enumerated_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_byte snd_ctl_elem_value_set_byte_dylibloader_orig_asound
+#define snd_ctl_elem_set_bytes snd_ctl_elem_set_bytes_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_bytes snd_ctl_elem_value_get_bytes_dylibloader_orig_asound
+#define snd_ctl_elem_value_get_iec958 snd_ctl_elem_value_get_iec958_dylibloader_orig_asound
+#define snd_ctl_elem_value_set_iec958 snd_ctl_elem_value_set_iec958_dylibloader_orig_asound
+#define snd_tlv_parse_dB_info snd_tlv_parse_dB_info_dylibloader_orig_asound
+#define snd_tlv_get_dB_range snd_tlv_get_dB_range_dylibloader_orig_asound
+#define snd_tlv_convert_to_dB snd_tlv_convert_to_dB_dylibloader_orig_asound
+#define snd_tlv_convert_from_dB snd_tlv_convert_from_dB_dylibloader_orig_asound
+#define snd_ctl_get_dB_range snd_ctl_get_dB_range_dylibloader_orig_asound
+#define snd_ctl_convert_to_dB snd_ctl_convert_to_dB_dylibloader_orig_asound
+#define snd_ctl_convert_from_dB snd_ctl_convert_from_dB_dylibloader_orig_asound
+#define snd_hctl_compare_fast snd_hctl_compare_fast_dylibloader_orig_asound
+#define snd_hctl_open snd_hctl_open_dylibloader_orig_asound
+#define snd_hctl_open_ctl snd_hctl_open_ctl_dylibloader_orig_asound
+#define snd_hctl_close snd_hctl_close_dylibloader_orig_asound
+#define snd_hctl_nonblock snd_hctl_nonblock_dylibloader_orig_asound
+#define snd_hctl_poll_descriptors_count snd_hctl_poll_descriptors_count_dylibloader_orig_asound
+#define snd_hctl_poll_descriptors snd_hctl_poll_descriptors_dylibloader_orig_asound
+#define snd_hctl_poll_descriptors_revents snd_hctl_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_hctl_get_count snd_hctl_get_count_dylibloader_orig_asound
+#define snd_hctl_set_compare snd_hctl_set_compare_dylibloader_orig_asound
+#define snd_hctl_first_elem snd_hctl_first_elem_dylibloader_orig_asound
+#define snd_hctl_last_elem snd_hctl_last_elem_dylibloader_orig_asound
+#define snd_hctl_find_elem snd_hctl_find_elem_dylibloader_orig_asound
+#define snd_hctl_set_callback snd_hctl_set_callback_dylibloader_orig_asound
+#define snd_hctl_set_callback_private snd_hctl_set_callback_private_dylibloader_orig_asound
+#define snd_hctl_get_callback_private snd_hctl_get_callback_private_dylibloader_orig_asound
+#define snd_hctl_load snd_hctl_load_dylibloader_orig_asound
+#define snd_hctl_free snd_hctl_free_dylibloader_orig_asound
+#define snd_hctl_handle_events snd_hctl_handle_events_dylibloader_orig_asound
+#define snd_hctl_name snd_hctl_name_dylibloader_orig_asound
+#define snd_hctl_wait snd_hctl_wait_dylibloader_orig_asound
+#define snd_hctl_ctl snd_hctl_ctl_dylibloader_orig_asound
+#define snd_hctl_elem_next snd_hctl_elem_next_dylibloader_orig_asound
+#define snd_hctl_elem_prev snd_hctl_elem_prev_dylibloader_orig_asound
+#define snd_hctl_elem_info snd_hctl_elem_info_dylibloader_orig_asound
+#define snd_hctl_elem_read snd_hctl_elem_read_dylibloader_orig_asound
+#define snd_hctl_elem_write snd_hctl_elem_write_dylibloader_orig_asound
+#define snd_hctl_elem_tlv_read snd_hctl_elem_tlv_read_dylibloader_orig_asound
+#define snd_hctl_elem_tlv_write snd_hctl_elem_tlv_write_dylibloader_orig_asound
+#define snd_hctl_elem_tlv_command snd_hctl_elem_tlv_command_dylibloader_orig_asound
+#define snd_hctl_elem_get_hctl snd_hctl_elem_get_hctl_dylibloader_orig_asound
+#define snd_hctl_elem_get_id snd_hctl_elem_get_id_dylibloader_orig_asound
+#define snd_hctl_elem_get_numid snd_hctl_elem_get_numid_dylibloader_orig_asound
+#define snd_hctl_elem_get_interface snd_hctl_elem_get_interface_dylibloader_orig_asound
+#define snd_hctl_elem_get_device snd_hctl_elem_get_device_dylibloader_orig_asound
+#define snd_hctl_elem_get_subdevice snd_hctl_elem_get_subdevice_dylibloader_orig_asound
+#define snd_hctl_elem_get_name snd_hctl_elem_get_name_dylibloader_orig_asound
+#define snd_hctl_elem_get_index snd_hctl_elem_get_index_dylibloader_orig_asound
+#define snd_hctl_elem_set_callback snd_hctl_elem_set_callback_dylibloader_orig_asound
+#define snd_hctl_elem_get_callback_private snd_hctl_elem_get_callback_private_dylibloader_orig_asound
+#define snd_hctl_elem_set_callback_private snd_hctl_elem_set_callback_private_dylibloader_orig_asound
+#define snd_sctl_build snd_sctl_build_dylibloader_orig_asound
+#define snd_sctl_free snd_sctl_free_dylibloader_orig_asound
+#define snd_sctl_install snd_sctl_install_dylibloader_orig_asound
+#define snd_sctl_remove snd_sctl_remove_dylibloader_orig_asound
+#define snd_mixer_open snd_mixer_open_dylibloader_orig_asound
+#define snd_mixer_close snd_mixer_close_dylibloader_orig_asound
+#define snd_mixer_first_elem snd_mixer_first_elem_dylibloader_orig_asound
+#define snd_mixer_last_elem snd_mixer_last_elem_dylibloader_orig_asound
+#define snd_mixer_handle_events snd_mixer_handle_events_dylibloader_orig_asound
+#define snd_mixer_attach snd_mixer_attach_dylibloader_orig_asound
+#define snd_mixer_attach_hctl snd_mixer_attach_hctl_dylibloader_orig_asound
+#define snd_mixer_detach snd_mixer_detach_dylibloader_orig_asound
+#define snd_mixer_detach_hctl snd_mixer_detach_hctl_dylibloader_orig_asound
+#define snd_mixer_get_hctl snd_mixer_get_hctl_dylibloader_orig_asound
+#define snd_mixer_poll_descriptors_count snd_mixer_poll_descriptors_count_dylibloader_orig_asound
+#define snd_mixer_poll_descriptors snd_mixer_poll_descriptors_dylibloader_orig_asound
+#define snd_mixer_poll_descriptors_revents snd_mixer_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_mixer_load snd_mixer_load_dylibloader_orig_asound
+#define snd_mixer_free snd_mixer_free_dylibloader_orig_asound
+#define snd_mixer_wait snd_mixer_wait_dylibloader_orig_asound
+#define snd_mixer_set_compare snd_mixer_set_compare_dylibloader_orig_asound
+#define snd_mixer_set_callback snd_mixer_set_callback_dylibloader_orig_asound
+#define snd_mixer_get_callback_private snd_mixer_get_callback_private_dylibloader_orig_asound
+#define snd_mixer_set_callback_private snd_mixer_set_callback_private_dylibloader_orig_asound
+#define snd_mixer_get_count snd_mixer_get_count_dylibloader_orig_asound
+#define snd_mixer_class_unregister snd_mixer_class_unregister_dylibloader_orig_asound
+#define snd_mixer_elem_next snd_mixer_elem_next_dylibloader_orig_asound
+#define snd_mixer_elem_prev snd_mixer_elem_prev_dylibloader_orig_asound
+#define snd_mixer_elem_set_callback snd_mixer_elem_set_callback_dylibloader_orig_asound
+#define snd_mixer_elem_get_callback_private snd_mixer_elem_get_callback_private_dylibloader_orig_asound
+#define snd_mixer_elem_set_callback_private snd_mixer_elem_set_callback_private_dylibloader_orig_asound
+#define snd_mixer_elem_get_type snd_mixer_elem_get_type_dylibloader_orig_asound
+#define snd_mixer_class_register snd_mixer_class_register_dylibloader_orig_asound
+#define snd_mixer_elem_new snd_mixer_elem_new_dylibloader_orig_asound
+#define snd_mixer_elem_add snd_mixer_elem_add_dylibloader_orig_asound
+#define snd_mixer_elem_remove snd_mixer_elem_remove_dylibloader_orig_asound
+#define snd_mixer_elem_free snd_mixer_elem_free_dylibloader_orig_asound
+#define snd_mixer_elem_info snd_mixer_elem_info_dylibloader_orig_asound
+#define snd_mixer_elem_value snd_mixer_elem_value_dylibloader_orig_asound
+#define snd_mixer_elem_attach snd_mixer_elem_attach_dylibloader_orig_asound
+#define snd_mixer_elem_detach snd_mixer_elem_detach_dylibloader_orig_asound
+#define snd_mixer_elem_empty snd_mixer_elem_empty_dylibloader_orig_asound
+#define snd_mixer_elem_get_private snd_mixer_elem_get_private_dylibloader_orig_asound
+#define snd_mixer_class_sizeof snd_mixer_class_sizeof_dylibloader_orig_asound
+#define snd_mixer_class_malloc snd_mixer_class_malloc_dylibloader_orig_asound
+#define snd_mixer_class_free snd_mixer_class_free_dylibloader_orig_asound
+#define snd_mixer_class_copy snd_mixer_class_copy_dylibloader_orig_asound
+#define snd_mixer_class_get_mixer snd_mixer_class_get_mixer_dylibloader_orig_asound
+#define snd_mixer_class_get_event snd_mixer_class_get_event_dylibloader_orig_asound
+#define snd_mixer_class_get_private snd_mixer_class_get_private_dylibloader_orig_asound
+#define snd_mixer_class_get_compare snd_mixer_class_get_compare_dylibloader_orig_asound
+#define snd_mixer_class_set_event snd_mixer_class_set_event_dylibloader_orig_asound
+#define snd_mixer_class_set_private snd_mixer_class_set_private_dylibloader_orig_asound
+#define snd_mixer_class_set_private_free snd_mixer_class_set_private_free_dylibloader_orig_asound
+#define snd_mixer_class_set_compare snd_mixer_class_set_compare_dylibloader_orig_asound
+#define snd_mixer_selem_channel_name snd_mixer_selem_channel_name_dylibloader_orig_asound
+#define snd_mixer_selem_register snd_mixer_selem_register_dylibloader_orig_asound
+#define snd_mixer_selem_get_id snd_mixer_selem_get_id_dylibloader_orig_asound
+#define snd_mixer_selem_get_name snd_mixer_selem_get_name_dylibloader_orig_asound
+#define snd_mixer_selem_get_index snd_mixer_selem_get_index_dylibloader_orig_asound
+#define snd_mixer_find_selem snd_mixer_find_selem_dylibloader_orig_asound
+#define snd_mixer_selem_is_active snd_mixer_selem_is_active_dylibloader_orig_asound
+#define snd_mixer_selem_is_playback_mono snd_mixer_selem_is_playback_mono_dylibloader_orig_asound
+#define snd_mixer_selem_has_playback_channel snd_mixer_selem_has_playback_channel_dylibloader_orig_asound
+#define snd_mixer_selem_is_capture_mono snd_mixer_selem_is_capture_mono_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_channel snd_mixer_selem_has_capture_channel_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_group snd_mixer_selem_get_capture_group_dylibloader_orig_asound
+#define snd_mixer_selem_has_common_volume snd_mixer_selem_has_common_volume_dylibloader_orig_asound
+#define snd_mixer_selem_has_playback_volume snd_mixer_selem_has_playback_volume_dylibloader_orig_asound
+#define snd_mixer_selem_has_playback_volume_joined snd_mixer_selem_has_playback_volume_joined_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_volume snd_mixer_selem_has_capture_volume_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_volume_joined snd_mixer_selem_has_capture_volume_joined_dylibloader_orig_asound
+#define snd_mixer_selem_has_common_switch snd_mixer_selem_has_common_switch_dylibloader_orig_asound
+#define snd_mixer_selem_has_playback_switch snd_mixer_selem_has_playback_switch_dylibloader_orig_asound
+#define snd_mixer_selem_has_playback_switch_joined snd_mixer_selem_has_playback_switch_joined_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_switch snd_mixer_selem_has_capture_switch_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_switch_joined snd_mixer_selem_has_capture_switch_joined_dylibloader_orig_asound
+#define snd_mixer_selem_has_capture_switch_exclusive snd_mixer_selem_has_capture_switch_exclusive_dylibloader_orig_asound
+#define snd_mixer_selem_ask_playback_vol_dB snd_mixer_selem_ask_playback_vol_dB_dylibloader_orig_asound
+#define snd_mixer_selem_ask_capture_vol_dB snd_mixer_selem_ask_capture_vol_dB_dylibloader_orig_asound
+#define snd_mixer_selem_ask_playback_dB_vol snd_mixer_selem_ask_playback_dB_vol_dylibloader_orig_asound
+#define snd_mixer_selem_ask_capture_dB_vol snd_mixer_selem_ask_capture_dB_vol_dylibloader_orig_asound
+#define snd_mixer_selem_get_playback_volume snd_mixer_selem_get_playback_volume_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_volume snd_mixer_selem_get_capture_volume_dylibloader_orig_asound
+#define snd_mixer_selem_get_playback_dB snd_mixer_selem_get_playback_dB_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_dB snd_mixer_selem_get_capture_dB_dylibloader_orig_asound
+#define snd_mixer_selem_get_playback_switch snd_mixer_selem_get_playback_switch_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_switch snd_mixer_selem_get_capture_switch_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_volume snd_mixer_selem_set_playback_volume_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_volume snd_mixer_selem_set_capture_volume_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_dB snd_mixer_selem_set_playback_dB_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_dB snd_mixer_selem_set_capture_dB_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_volume_all snd_mixer_selem_set_playback_volume_all_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_volume_all snd_mixer_selem_set_capture_volume_all_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_dB_all snd_mixer_selem_set_playback_dB_all_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_dB_all snd_mixer_selem_set_capture_dB_all_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_switch snd_mixer_selem_set_playback_switch_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_switch snd_mixer_selem_set_capture_switch_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_switch_all snd_mixer_selem_set_playback_switch_all_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_switch_all snd_mixer_selem_set_capture_switch_all_dylibloader_orig_asound
+#define snd_mixer_selem_get_playback_volume_range snd_mixer_selem_get_playback_volume_range_dylibloader_orig_asound
+#define snd_mixer_selem_get_playback_dB_range snd_mixer_selem_get_playback_dB_range_dylibloader_orig_asound
+#define snd_mixer_selem_set_playback_volume_range snd_mixer_selem_set_playback_volume_range_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_volume_range snd_mixer_selem_get_capture_volume_range_dylibloader_orig_asound
+#define snd_mixer_selem_get_capture_dB_range snd_mixer_selem_get_capture_dB_range_dylibloader_orig_asound
+#define snd_mixer_selem_set_capture_volume_range snd_mixer_selem_set_capture_volume_range_dylibloader_orig_asound
+#define snd_mixer_selem_is_enumerated snd_mixer_selem_is_enumerated_dylibloader_orig_asound
+#define snd_mixer_selem_is_enum_playback snd_mixer_selem_is_enum_playback_dylibloader_orig_asound
+#define snd_mixer_selem_is_enum_capture snd_mixer_selem_is_enum_capture_dylibloader_orig_asound
+#define snd_mixer_selem_get_enum_items snd_mixer_selem_get_enum_items_dylibloader_orig_asound
+#define snd_mixer_selem_get_enum_item_name snd_mixer_selem_get_enum_item_name_dylibloader_orig_asound
+#define snd_mixer_selem_get_enum_item snd_mixer_selem_get_enum_item_dylibloader_orig_asound
+#define snd_mixer_selem_set_enum_item snd_mixer_selem_set_enum_item_dylibloader_orig_asound
+#define snd_mixer_selem_id_sizeof snd_mixer_selem_id_sizeof_dylibloader_orig_asound
+#define snd_mixer_selem_id_malloc snd_mixer_selem_id_malloc_dylibloader_orig_asound
+#define snd_mixer_selem_id_free snd_mixer_selem_id_free_dylibloader_orig_asound
+#define snd_mixer_selem_id_copy snd_mixer_selem_id_copy_dylibloader_orig_asound
+#define snd_mixer_selem_id_get_name snd_mixer_selem_id_get_name_dylibloader_orig_asound
+#define snd_mixer_selem_id_get_index snd_mixer_selem_id_get_index_dylibloader_orig_asound
+#define snd_mixer_selem_id_set_name snd_mixer_selem_id_set_name_dylibloader_orig_asound
+#define snd_mixer_selem_id_set_index snd_mixer_selem_id_set_index_dylibloader_orig_asound
+#define snd_mixer_selem_id_parse snd_mixer_selem_id_parse_dylibloader_orig_asound
+#define snd_seq_open snd_seq_open_dylibloader_orig_asound
+#define snd_seq_open_lconf snd_seq_open_lconf_dylibloader_orig_asound
+#define snd_seq_name snd_seq_name_dylibloader_orig_asound
+#define snd_seq_type snd_seq_type_dylibloader_orig_asound
+#define snd_seq_close snd_seq_close_dylibloader_orig_asound
+#define snd_seq_poll_descriptors_count snd_seq_poll_descriptors_count_dylibloader_orig_asound
+#define snd_seq_poll_descriptors snd_seq_poll_descriptors_dylibloader_orig_asound
+#define snd_seq_poll_descriptors_revents snd_seq_poll_descriptors_revents_dylibloader_orig_asound
+#define snd_seq_nonblock snd_seq_nonblock_dylibloader_orig_asound
+#define snd_seq_client_id snd_seq_client_id_dylibloader_orig_asound
+#define snd_seq_get_output_buffer_size snd_seq_get_output_buffer_size_dylibloader_orig_asound
+#define snd_seq_get_input_buffer_size snd_seq_get_input_buffer_size_dylibloader_orig_asound
+#define snd_seq_set_output_buffer_size snd_seq_set_output_buffer_size_dylibloader_orig_asound
+#define snd_seq_set_input_buffer_size snd_seq_set_input_buffer_size_dylibloader_orig_asound
+#define snd_seq_system_info_sizeof snd_seq_system_info_sizeof_dylibloader_orig_asound
+#define snd_seq_system_info_malloc snd_seq_system_info_malloc_dylibloader_orig_asound
+#define snd_seq_system_info_free snd_seq_system_info_free_dylibloader_orig_asound
+#define snd_seq_system_info_copy snd_seq_system_info_copy_dylibloader_orig_asound
+#define snd_seq_system_info_get_queues snd_seq_system_info_get_queues_dylibloader_orig_asound
+#define snd_seq_system_info_get_clients snd_seq_system_info_get_clients_dylibloader_orig_asound
+#define snd_seq_system_info_get_ports snd_seq_system_info_get_ports_dylibloader_orig_asound
+#define snd_seq_system_info_get_channels snd_seq_system_info_get_channels_dylibloader_orig_asound
+#define snd_seq_system_info_get_cur_clients snd_seq_system_info_get_cur_clients_dylibloader_orig_asound
+#define snd_seq_system_info_get_cur_queues snd_seq_system_info_get_cur_queues_dylibloader_orig_asound
+#define snd_seq_system_info snd_seq_system_info_dylibloader_orig_asound
+#define snd_seq_client_info_sizeof snd_seq_client_info_sizeof_dylibloader_orig_asound
+#define snd_seq_client_info_malloc snd_seq_client_info_malloc_dylibloader_orig_asound
+#define snd_seq_client_info_free snd_seq_client_info_free_dylibloader_orig_asound
+#define snd_seq_client_info_copy snd_seq_client_info_copy_dylibloader_orig_asound
+#define snd_seq_client_info_get_client snd_seq_client_info_get_client_dylibloader_orig_asound
+#define snd_seq_client_info_get_type snd_seq_client_info_get_type_dylibloader_orig_asound
+#define snd_seq_client_info_get_name snd_seq_client_info_get_name_dylibloader_orig_asound
+#define snd_seq_client_info_get_broadcast_filter snd_seq_client_info_get_broadcast_filter_dylibloader_orig_asound
+#define snd_seq_client_info_get_error_bounce snd_seq_client_info_get_error_bounce_dylibloader_orig_asound
+#define snd_seq_client_info_get_card snd_seq_client_info_get_card_dylibloader_orig_asound
+#define snd_seq_client_info_get_pid snd_seq_client_info_get_pid_dylibloader_orig_asound
+#define snd_seq_client_info_get_event_filter snd_seq_client_info_get_event_filter_dylibloader_orig_asound
+#define snd_seq_client_info_get_num_ports snd_seq_client_info_get_num_ports_dylibloader_orig_asound
+#define snd_seq_client_info_get_event_lost snd_seq_client_info_get_event_lost_dylibloader_orig_asound
+#define snd_seq_client_info_set_client snd_seq_client_info_set_client_dylibloader_orig_asound
+#define snd_seq_client_info_set_name snd_seq_client_info_set_name_dylibloader_orig_asound
+#define snd_seq_client_info_set_broadcast_filter snd_seq_client_info_set_broadcast_filter_dylibloader_orig_asound
+#define snd_seq_client_info_set_error_bounce snd_seq_client_info_set_error_bounce_dylibloader_orig_asound
+#define snd_seq_client_info_set_event_filter snd_seq_client_info_set_event_filter_dylibloader_orig_asound
+#define snd_seq_client_info_event_filter_clear snd_seq_client_info_event_filter_clear_dylibloader_orig_asound
+#define snd_seq_client_info_event_filter_add snd_seq_client_info_event_filter_add_dylibloader_orig_asound
+#define snd_seq_client_info_event_filter_del snd_seq_client_info_event_filter_del_dylibloader_orig_asound
+#define snd_seq_client_info_event_filter_check snd_seq_client_info_event_filter_check_dylibloader_orig_asound
+#define snd_seq_get_client_info snd_seq_get_client_info_dylibloader_orig_asound
+#define snd_seq_get_any_client_info snd_seq_get_any_client_info_dylibloader_orig_asound
+#define snd_seq_set_client_info snd_seq_set_client_info_dylibloader_orig_asound
+#define snd_seq_query_next_client snd_seq_query_next_client_dylibloader_orig_asound
+#define snd_seq_client_pool_sizeof snd_seq_client_pool_sizeof_dylibloader_orig_asound
+#define snd_seq_client_pool_malloc snd_seq_client_pool_malloc_dylibloader_orig_asound
+#define snd_seq_client_pool_free snd_seq_client_pool_free_dylibloader_orig_asound
+#define snd_seq_client_pool_copy snd_seq_client_pool_copy_dylibloader_orig_asound
+#define snd_seq_client_pool_get_client snd_seq_client_pool_get_client_dylibloader_orig_asound
+#define snd_seq_client_pool_get_output_pool snd_seq_client_pool_get_output_pool_dylibloader_orig_asound
+#define snd_seq_client_pool_get_input_pool snd_seq_client_pool_get_input_pool_dylibloader_orig_asound
+#define snd_seq_client_pool_get_output_room snd_seq_client_pool_get_output_room_dylibloader_orig_asound
+#define snd_seq_client_pool_get_output_free snd_seq_client_pool_get_output_free_dylibloader_orig_asound
+#define snd_seq_client_pool_get_input_free snd_seq_client_pool_get_input_free_dylibloader_orig_asound
+#define snd_seq_client_pool_set_output_pool snd_seq_client_pool_set_output_pool_dylibloader_orig_asound
+#define snd_seq_client_pool_set_input_pool snd_seq_client_pool_set_input_pool_dylibloader_orig_asound
+#define snd_seq_client_pool_set_output_room snd_seq_client_pool_set_output_room_dylibloader_orig_asound
+#define snd_seq_get_client_pool snd_seq_get_client_pool_dylibloader_orig_asound
+#define snd_seq_set_client_pool snd_seq_set_client_pool_dylibloader_orig_asound
+#define snd_seq_port_info_sizeof snd_seq_port_info_sizeof_dylibloader_orig_asound
+#define snd_seq_port_info_malloc snd_seq_port_info_malloc_dylibloader_orig_asound
+#define snd_seq_port_info_free snd_seq_port_info_free_dylibloader_orig_asound
+#define snd_seq_port_info_copy snd_seq_port_info_copy_dylibloader_orig_asound
+#define snd_seq_port_info_get_client snd_seq_port_info_get_client_dylibloader_orig_asound
+#define snd_seq_port_info_get_port snd_seq_port_info_get_port_dylibloader_orig_asound
+#define snd_seq_port_info_get_addr snd_seq_port_info_get_addr_dylibloader_orig_asound
+#define snd_seq_port_info_get_name snd_seq_port_info_get_name_dylibloader_orig_asound
+#define snd_seq_port_info_get_capability snd_seq_port_info_get_capability_dylibloader_orig_asound
+#define snd_seq_port_info_get_type snd_seq_port_info_get_type_dylibloader_orig_asound
+#define snd_seq_port_info_get_midi_channels snd_seq_port_info_get_midi_channels_dylibloader_orig_asound
+#define snd_seq_port_info_get_midi_voices snd_seq_port_info_get_midi_voices_dylibloader_orig_asound
+#define snd_seq_port_info_get_synth_voices snd_seq_port_info_get_synth_voices_dylibloader_orig_asound
+#define snd_seq_port_info_get_read_use snd_seq_port_info_get_read_use_dylibloader_orig_asound
+#define snd_seq_port_info_get_write_use snd_seq_port_info_get_write_use_dylibloader_orig_asound
+#define snd_seq_port_info_get_port_specified snd_seq_port_info_get_port_specified_dylibloader_orig_asound
+#define snd_seq_port_info_get_timestamping snd_seq_port_info_get_timestamping_dylibloader_orig_asound
+#define snd_seq_port_info_get_timestamp_real snd_seq_port_info_get_timestamp_real_dylibloader_orig_asound
+#define snd_seq_port_info_get_timestamp_queue snd_seq_port_info_get_timestamp_queue_dylibloader_orig_asound
+#define snd_seq_port_info_set_client snd_seq_port_info_set_client_dylibloader_orig_asound
+#define snd_seq_port_info_set_port snd_seq_port_info_set_port_dylibloader_orig_asound
+#define snd_seq_port_info_set_addr snd_seq_port_info_set_addr_dylibloader_orig_asound
+#define snd_seq_port_info_set_name snd_seq_port_info_set_name_dylibloader_orig_asound
+#define snd_seq_port_info_set_capability snd_seq_port_info_set_capability_dylibloader_orig_asound
+#define snd_seq_port_info_set_type snd_seq_port_info_set_type_dylibloader_orig_asound
+#define snd_seq_port_info_set_midi_channels snd_seq_port_info_set_midi_channels_dylibloader_orig_asound
+#define snd_seq_port_info_set_midi_voices snd_seq_port_info_set_midi_voices_dylibloader_orig_asound
+#define snd_seq_port_info_set_synth_voices snd_seq_port_info_set_synth_voices_dylibloader_orig_asound
+#define snd_seq_port_info_set_port_specified snd_seq_port_info_set_port_specified_dylibloader_orig_asound
+#define snd_seq_port_info_set_timestamping snd_seq_port_info_set_timestamping_dylibloader_orig_asound
+#define snd_seq_port_info_set_timestamp_real snd_seq_port_info_set_timestamp_real_dylibloader_orig_asound
+#define snd_seq_port_info_set_timestamp_queue snd_seq_port_info_set_timestamp_queue_dylibloader_orig_asound
+#define snd_seq_create_port snd_seq_create_port_dylibloader_orig_asound
+#define snd_seq_delete_port snd_seq_delete_port_dylibloader_orig_asound
+#define snd_seq_get_port_info snd_seq_get_port_info_dylibloader_orig_asound
+#define snd_seq_get_any_port_info snd_seq_get_any_port_info_dylibloader_orig_asound
+#define snd_seq_set_port_info snd_seq_set_port_info_dylibloader_orig_asound
+#define snd_seq_query_next_port snd_seq_query_next_port_dylibloader_orig_asound
+#define snd_seq_port_subscribe_sizeof snd_seq_port_subscribe_sizeof_dylibloader_orig_asound
+#define snd_seq_port_subscribe_malloc snd_seq_port_subscribe_malloc_dylibloader_orig_asound
+#define snd_seq_port_subscribe_free snd_seq_port_subscribe_free_dylibloader_orig_asound
+#define snd_seq_port_subscribe_copy snd_seq_port_subscribe_copy_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_sender snd_seq_port_subscribe_get_sender_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_dest snd_seq_port_subscribe_get_dest_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_queue snd_seq_port_subscribe_get_queue_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_exclusive snd_seq_port_subscribe_get_exclusive_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_time_update snd_seq_port_subscribe_get_time_update_dylibloader_orig_asound
+#define snd_seq_port_subscribe_get_time_real snd_seq_port_subscribe_get_time_real_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_sender snd_seq_port_subscribe_set_sender_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_dest snd_seq_port_subscribe_set_dest_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_queue snd_seq_port_subscribe_set_queue_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_exclusive snd_seq_port_subscribe_set_exclusive_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_time_update snd_seq_port_subscribe_set_time_update_dylibloader_orig_asound
+#define snd_seq_port_subscribe_set_time_real snd_seq_port_subscribe_set_time_real_dylibloader_orig_asound
+#define snd_seq_get_port_subscription snd_seq_get_port_subscription_dylibloader_orig_asound
+#define snd_seq_subscribe_port snd_seq_subscribe_port_dylibloader_orig_asound
+#define snd_seq_unsubscribe_port snd_seq_unsubscribe_port_dylibloader_orig_asound
+#define snd_seq_query_subscribe_sizeof snd_seq_query_subscribe_sizeof_dylibloader_orig_asound
+#define snd_seq_query_subscribe_malloc snd_seq_query_subscribe_malloc_dylibloader_orig_asound
+#define snd_seq_query_subscribe_free snd_seq_query_subscribe_free_dylibloader_orig_asound
+#define snd_seq_query_subscribe_copy snd_seq_query_subscribe_copy_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_client snd_seq_query_subscribe_get_client_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_port snd_seq_query_subscribe_get_port_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_root snd_seq_query_subscribe_get_root_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_type snd_seq_query_subscribe_get_type_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_index snd_seq_query_subscribe_get_index_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_num_subs snd_seq_query_subscribe_get_num_subs_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_addr snd_seq_query_subscribe_get_addr_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_queue snd_seq_query_subscribe_get_queue_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_exclusive snd_seq_query_subscribe_get_exclusive_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_time_update snd_seq_query_subscribe_get_time_update_dylibloader_orig_asound
+#define snd_seq_query_subscribe_get_time_real snd_seq_query_subscribe_get_time_real_dylibloader_orig_asound
+#define snd_seq_query_subscribe_set_client snd_seq_query_subscribe_set_client_dylibloader_orig_asound
+#define snd_seq_query_subscribe_set_port snd_seq_query_subscribe_set_port_dylibloader_orig_asound
+#define snd_seq_query_subscribe_set_root snd_seq_query_subscribe_set_root_dylibloader_orig_asound
+#define snd_seq_query_subscribe_set_type snd_seq_query_subscribe_set_type_dylibloader_orig_asound
+#define snd_seq_query_subscribe_set_index snd_seq_query_subscribe_set_index_dylibloader_orig_asound
+#define snd_seq_query_port_subscribers snd_seq_query_port_subscribers_dylibloader_orig_asound
+#define snd_seq_queue_info_sizeof snd_seq_queue_info_sizeof_dylibloader_orig_asound
+#define snd_seq_queue_info_malloc snd_seq_queue_info_malloc_dylibloader_orig_asound
+#define snd_seq_queue_info_free snd_seq_queue_info_free_dylibloader_orig_asound
+#define snd_seq_queue_info_copy snd_seq_queue_info_copy_dylibloader_orig_asound
+#define snd_seq_queue_info_get_queue snd_seq_queue_info_get_queue_dylibloader_orig_asound
+#define snd_seq_queue_info_get_name snd_seq_queue_info_get_name_dylibloader_orig_asound
+#define snd_seq_queue_info_get_owner snd_seq_queue_info_get_owner_dylibloader_orig_asound
+#define snd_seq_queue_info_get_locked snd_seq_queue_info_get_locked_dylibloader_orig_asound
+#define snd_seq_queue_info_get_flags snd_seq_queue_info_get_flags_dylibloader_orig_asound
+#define snd_seq_queue_info_set_name snd_seq_queue_info_set_name_dylibloader_orig_asound
+#define snd_seq_queue_info_set_owner snd_seq_queue_info_set_owner_dylibloader_orig_asound
+#define snd_seq_queue_info_set_locked snd_seq_queue_info_set_locked_dylibloader_orig_asound
+#define snd_seq_queue_info_set_flags snd_seq_queue_info_set_flags_dylibloader_orig_asound
+#define snd_seq_create_queue snd_seq_create_queue_dylibloader_orig_asound
+#define snd_seq_alloc_named_queue snd_seq_alloc_named_queue_dylibloader_orig_asound
+#define snd_seq_alloc_queue snd_seq_alloc_queue_dylibloader_orig_asound
+#define snd_seq_free_queue snd_seq_free_queue_dylibloader_orig_asound
+#define snd_seq_get_queue_info snd_seq_get_queue_info_dylibloader_orig_asound
+#define snd_seq_set_queue_info snd_seq_set_queue_info_dylibloader_orig_asound
+#define snd_seq_query_named_queue snd_seq_query_named_queue_dylibloader_orig_asound
+#define snd_seq_get_queue_usage snd_seq_get_queue_usage_dylibloader_orig_asound
+#define snd_seq_set_queue_usage snd_seq_set_queue_usage_dylibloader_orig_asound
+#define snd_seq_queue_status_sizeof snd_seq_queue_status_sizeof_dylibloader_orig_asound
+#define snd_seq_queue_status_malloc snd_seq_queue_status_malloc_dylibloader_orig_asound
+#define snd_seq_queue_status_free snd_seq_queue_status_free_dylibloader_orig_asound
+#define snd_seq_queue_status_copy snd_seq_queue_status_copy_dylibloader_orig_asound
+#define snd_seq_queue_status_get_queue snd_seq_queue_status_get_queue_dylibloader_orig_asound
+#define snd_seq_queue_status_get_events snd_seq_queue_status_get_events_dylibloader_orig_asound
+#define snd_seq_queue_status_get_tick_time snd_seq_queue_status_get_tick_time_dylibloader_orig_asound
+#define snd_seq_queue_status_get_real_time snd_seq_queue_status_get_real_time_dylibloader_orig_asound
+#define snd_seq_queue_status_get_status snd_seq_queue_status_get_status_dylibloader_orig_asound
+#define snd_seq_get_queue_status snd_seq_get_queue_status_dylibloader_orig_asound
+#define snd_seq_queue_tempo_sizeof snd_seq_queue_tempo_sizeof_dylibloader_orig_asound
+#define snd_seq_queue_tempo_malloc snd_seq_queue_tempo_malloc_dylibloader_orig_asound
+#define snd_seq_queue_tempo_free snd_seq_queue_tempo_free_dylibloader_orig_asound
+#define snd_seq_queue_tempo_copy snd_seq_queue_tempo_copy_dylibloader_orig_asound
+#define snd_seq_queue_tempo_get_queue snd_seq_queue_tempo_get_queue_dylibloader_orig_asound
+#define snd_seq_queue_tempo_get_tempo snd_seq_queue_tempo_get_tempo_dylibloader_orig_asound
+#define snd_seq_queue_tempo_get_ppq snd_seq_queue_tempo_get_ppq_dylibloader_orig_asound
+#define snd_seq_queue_tempo_get_skew snd_seq_queue_tempo_get_skew_dylibloader_orig_asound
+#define snd_seq_queue_tempo_get_skew_base snd_seq_queue_tempo_get_skew_base_dylibloader_orig_asound
+#define snd_seq_queue_tempo_set_tempo snd_seq_queue_tempo_set_tempo_dylibloader_orig_asound
+#define snd_seq_queue_tempo_set_ppq snd_seq_queue_tempo_set_ppq_dylibloader_orig_asound
+#define snd_seq_queue_tempo_set_skew snd_seq_queue_tempo_set_skew_dylibloader_orig_asound
+#define snd_seq_queue_tempo_set_skew_base snd_seq_queue_tempo_set_skew_base_dylibloader_orig_asound
+#define snd_seq_get_queue_tempo snd_seq_get_queue_tempo_dylibloader_orig_asound
+#define snd_seq_set_queue_tempo snd_seq_set_queue_tempo_dylibloader_orig_asound
+#define snd_seq_queue_timer_sizeof snd_seq_queue_timer_sizeof_dylibloader_orig_asound
+#define snd_seq_queue_timer_malloc snd_seq_queue_timer_malloc_dylibloader_orig_asound
+#define snd_seq_queue_timer_free snd_seq_queue_timer_free_dylibloader_orig_asound
+#define snd_seq_queue_timer_copy snd_seq_queue_timer_copy_dylibloader_orig_asound
+#define snd_seq_queue_timer_get_queue snd_seq_queue_timer_get_queue_dylibloader_orig_asound
+#define snd_seq_queue_timer_get_type snd_seq_queue_timer_get_type_dylibloader_orig_asound
+#define snd_seq_queue_timer_get_id snd_seq_queue_timer_get_id_dylibloader_orig_asound
+#define snd_seq_queue_timer_get_resolution snd_seq_queue_timer_get_resolution_dylibloader_orig_asound
+#define snd_seq_queue_timer_set_type snd_seq_queue_timer_set_type_dylibloader_orig_asound
+#define snd_seq_queue_timer_set_id snd_seq_queue_timer_set_id_dylibloader_orig_asound
+#define snd_seq_queue_timer_set_resolution snd_seq_queue_timer_set_resolution_dylibloader_orig_asound
+#define snd_seq_get_queue_timer snd_seq_get_queue_timer_dylibloader_orig_asound
+#define snd_seq_set_queue_timer snd_seq_set_queue_timer_dylibloader_orig_asound
+#define snd_seq_free_event snd_seq_free_event_dylibloader_orig_asound
+#define snd_seq_event_length snd_seq_event_length_dylibloader_orig_asound
+#define snd_seq_event_output snd_seq_event_output_dylibloader_orig_asound
+#define snd_seq_event_output_buffer snd_seq_event_output_buffer_dylibloader_orig_asound
+#define snd_seq_event_output_direct snd_seq_event_output_direct_dylibloader_orig_asound
+#define snd_seq_event_input snd_seq_event_input_dylibloader_orig_asound
+#define snd_seq_event_input_pending snd_seq_event_input_pending_dylibloader_orig_asound
+#define snd_seq_drain_output snd_seq_drain_output_dylibloader_orig_asound
+#define snd_seq_event_output_pending snd_seq_event_output_pending_dylibloader_orig_asound
+#define snd_seq_extract_output snd_seq_extract_output_dylibloader_orig_asound
+#define snd_seq_drop_output snd_seq_drop_output_dylibloader_orig_asound
+#define snd_seq_drop_output_buffer snd_seq_drop_output_buffer_dylibloader_orig_asound
+#define snd_seq_drop_input snd_seq_drop_input_dylibloader_orig_asound
+#define snd_seq_drop_input_buffer snd_seq_drop_input_buffer_dylibloader_orig_asound
+#define snd_seq_remove_events_sizeof snd_seq_remove_events_sizeof_dylibloader_orig_asound
+#define snd_seq_remove_events_malloc snd_seq_remove_events_malloc_dylibloader_orig_asound
+#define snd_seq_remove_events_free snd_seq_remove_events_free_dylibloader_orig_asound
+#define snd_seq_remove_events_copy snd_seq_remove_events_copy_dylibloader_orig_asound
+#define snd_seq_remove_events_get_condition snd_seq_remove_events_get_condition_dylibloader_orig_asound
+#define snd_seq_remove_events_get_queue snd_seq_remove_events_get_queue_dylibloader_orig_asound
+#define snd_seq_remove_events_get_time snd_seq_remove_events_get_time_dylibloader_orig_asound
+#define snd_seq_remove_events_get_dest snd_seq_remove_events_get_dest_dylibloader_orig_asound
+#define snd_seq_remove_events_get_channel snd_seq_remove_events_get_channel_dylibloader_orig_asound
+#define snd_seq_remove_events_get_event_type snd_seq_remove_events_get_event_type_dylibloader_orig_asound
+#define snd_seq_remove_events_get_tag snd_seq_remove_events_get_tag_dylibloader_orig_asound
+#define snd_seq_remove_events_set_condition snd_seq_remove_events_set_condition_dylibloader_orig_asound
+#define snd_seq_remove_events_set_queue snd_seq_remove_events_set_queue_dylibloader_orig_asound
+#define snd_seq_remove_events_set_time snd_seq_remove_events_set_time_dylibloader_orig_asound
+#define snd_seq_remove_events_set_dest snd_seq_remove_events_set_dest_dylibloader_orig_asound
+#define snd_seq_remove_events_set_channel snd_seq_remove_events_set_channel_dylibloader_orig_asound
+#define snd_seq_remove_events_set_event_type snd_seq_remove_events_set_event_type_dylibloader_orig_asound
+#define snd_seq_remove_events_set_tag snd_seq_remove_events_set_tag_dylibloader_orig_asound
+#define snd_seq_remove_events snd_seq_remove_events_dylibloader_orig_asound
+#define snd_seq_set_bit snd_seq_set_bit_dylibloader_orig_asound
+#define snd_seq_unset_bit snd_seq_unset_bit_dylibloader_orig_asound
+#define snd_seq_change_bit snd_seq_change_bit_dylibloader_orig_asound
+#define snd_seq_get_bit snd_seq_get_bit_dylibloader_orig_asound
+#define snd_seq_control_queue snd_seq_control_queue_dylibloader_orig_asound
+#define snd_seq_create_simple_port snd_seq_create_simple_port_dylibloader_orig_asound
+#define snd_seq_delete_simple_port snd_seq_delete_simple_port_dylibloader_orig_asound
+#define snd_seq_connect_from snd_seq_connect_from_dylibloader_orig_asound
+#define snd_seq_connect_to snd_seq_connect_to_dylibloader_orig_asound
+#define snd_seq_disconnect_from snd_seq_disconnect_from_dylibloader_orig_asound
+#define snd_seq_disconnect_to snd_seq_disconnect_to_dylibloader_orig_asound
+#define snd_seq_set_client_name snd_seq_set_client_name_dylibloader_orig_asound
+#define snd_seq_set_client_event_filter snd_seq_set_client_event_filter_dylibloader_orig_asound
+#define snd_seq_set_client_pool_output snd_seq_set_client_pool_output_dylibloader_orig_asound
+#define snd_seq_set_client_pool_output_room snd_seq_set_client_pool_output_room_dylibloader_orig_asound
+#define snd_seq_set_client_pool_input snd_seq_set_client_pool_input_dylibloader_orig_asound
+#define snd_seq_sync_output_queue snd_seq_sync_output_queue_dylibloader_orig_asound
+#define snd_seq_parse_address snd_seq_parse_address_dylibloader_orig_asound
+#define snd_seq_reset_pool_output snd_seq_reset_pool_output_dylibloader_orig_asound
+#define snd_seq_reset_pool_input snd_seq_reset_pool_input_dylibloader_orig_asound
+#define snd_midi_event_new snd_midi_event_new_dylibloader_orig_asound
+#define snd_midi_event_resize_buffer snd_midi_event_resize_buffer_dylibloader_orig_asound
+#define snd_midi_event_free snd_midi_event_free_dylibloader_orig_asound
+#define snd_midi_event_init snd_midi_event_init_dylibloader_orig_asound
+#define snd_midi_event_reset_encode snd_midi_event_reset_encode_dylibloader_orig_asound
+#define snd_midi_event_reset_decode snd_midi_event_reset_decode_dylibloader_orig_asound
+#define snd_midi_event_no_status snd_midi_event_no_status_dylibloader_orig_asound
+#define snd_midi_event_encode snd_midi_event_encode_dylibloader_orig_asound
+#define snd_midi_event_encode_byte snd_midi_event_encode_byte_dylibloader_orig_asound
+#define snd_midi_event_decode snd_midi_event_decode_dylibloader_orig_asound
+#include <alsa/asoundlib.h>
+#undef snd_asoundlib_version
+#undef snd_dlpath
+#undef snd_dlopen
+#undef snd_dlsym
+#undef snd_dlclose
+#undef snd_async_add_handler
+#undef snd_async_del_handler
+#undef snd_async_handler_get_fd
+#undef snd_async_handler_get_signo
+#undef snd_async_handler_get_callback_private
+#undef snd_shm_area_create
+#undef snd_shm_area_share
+#undef snd_shm_area_destroy
+#undef snd_user_file
+#undef snd_input_stdio_open
+#undef snd_input_stdio_attach
+#undef snd_input_buffer_open
+#undef snd_input_close
+#undef snd_input_scanf
+#undef snd_input_gets
+#undef snd_input_getc
+#undef snd_input_ungetc
+#undef snd_output_stdio_open
+#undef snd_output_stdio_attach
+#undef snd_output_buffer_open
+#undef snd_output_buffer_string
+#undef snd_output_close
+#undef snd_output_printf
+#undef snd_output_vprintf
+#undef snd_output_puts
+#undef snd_output_putc
+#undef snd_output_flush
+#undef snd_strerror
+#undef snd_lib_error_set_handler
+#undef snd_lib_error_set_local
+#undef snd_config_topdir
+#undef snd_config_top
+#undef snd_config_load
+#undef snd_config_load_override
+#undef snd_config_save
+#undef snd_config_update
+#undef snd_config_update_r
+#undef snd_config_update_free
+#undef snd_config_update_free_global
+#undef snd_config_update_ref
+#undef snd_config_ref
+#undef snd_config_unref
+#undef snd_config_search
+#undef snd_config_searchv
+#undef snd_config_search_definition
+#undef snd_config_expand
+#undef snd_config_evaluate
+#undef snd_config_add
+#undef snd_config_add_before
+#undef snd_config_add_after
+#undef snd_config_remove
+#undef snd_config_delete
+#undef snd_config_delete_compound_members
+#undef snd_config_copy
+#undef snd_config_make
+#undef snd_config_make_integer
+#undef snd_config_make_integer64
+#undef snd_config_make_real
+#undef snd_config_make_string
+#undef snd_config_make_pointer
+#undef snd_config_make_compound
+#undef snd_config_imake_integer
+#undef snd_config_imake_integer64
+#undef snd_config_imake_real
+#undef snd_config_imake_string
+#undef snd_config_imake_safe_string
+#undef snd_config_imake_pointer
+#undef snd_config_get_type
+#undef snd_config_is_array
+#undef snd_config_set_id
+#undef snd_config_set_integer
+#undef snd_config_set_integer64
+#undef snd_config_set_real
+#undef snd_config_set_string
+#undef snd_config_set_ascii
+#undef snd_config_set_pointer
+#undef snd_config_get_id
+#undef snd_config_get_integer
+#undef snd_config_get_integer64
+#undef snd_config_get_real
+#undef snd_config_get_ireal
+#undef snd_config_get_string
+#undef snd_config_get_ascii
+#undef snd_config_get_pointer
+#undef snd_config_test_id
+#undef snd_config_iterator_first
+#undef snd_config_iterator_next
+#undef snd_config_iterator_end
+#undef snd_config_iterator_entry
+#undef snd_config_get_bool_ascii
+#undef snd_config_get_bool
+#undef snd_config_get_ctl_iface_ascii
+#undef snd_config_get_ctl_iface
+#undef snd_names_list
+#undef snd_names_list_free
+#undef snd_pcm_open
+#undef snd_pcm_open_lconf
+#undef snd_pcm_open_fallback
+#undef snd_pcm_close
+#undef snd_pcm_name
+#undef snd_pcm_type
+#undef snd_pcm_stream
+#undef snd_pcm_poll_descriptors_count
+#undef snd_pcm_poll_descriptors
+#undef snd_pcm_poll_descriptors_revents
+#undef snd_pcm_nonblock
+#undef snd_async_add_pcm_handler
+#undef snd_async_handler_get_pcm
+#undef snd_pcm_info
+#undef snd_pcm_hw_params_current
+#undef snd_pcm_hw_params
+#undef snd_pcm_hw_free
+#undef snd_pcm_sw_params_current
+#undef snd_pcm_sw_params
+#undef snd_pcm_prepare
+#undef snd_pcm_reset
+#undef snd_pcm_status
+#undef snd_pcm_start
+#undef snd_pcm_drop
+#undef snd_pcm_drain
+#undef snd_pcm_pause
+#undef snd_pcm_state
+#undef snd_pcm_hwsync
+#undef snd_pcm_delay
+#undef snd_pcm_resume
+#undef snd_pcm_htimestamp
+#undef snd_pcm_avail
+#undef snd_pcm_avail_update
+#undef snd_pcm_avail_delay
+#undef snd_pcm_rewindable
+#undef snd_pcm_rewind
+#undef snd_pcm_forwardable
+#undef snd_pcm_forward
+#undef snd_pcm_writei
+#undef snd_pcm_readi
+#undef snd_pcm_writen
+#undef snd_pcm_readn
+#undef snd_pcm_wait
+#undef snd_pcm_link
+#undef snd_pcm_unlink
+#undef snd_pcm_query_chmaps
+#undef snd_pcm_query_chmaps_from_hw
+#undef snd_pcm_free_chmaps
+#undef snd_pcm_get_chmap
+#undef snd_pcm_set_chmap
+#undef snd_pcm_chmap_type_name
+#undef snd_pcm_chmap_name
+#undef snd_pcm_chmap_long_name
+#undef snd_pcm_chmap_print
+#undef snd_pcm_chmap_from_string
+#undef snd_pcm_chmap_parse_string
+#undef snd_pcm_recover
+#undef snd_pcm_set_params
+#undef snd_pcm_get_params
+#undef snd_pcm_info_sizeof
+#undef snd_pcm_info_malloc
+#undef snd_pcm_info_free
+#undef snd_pcm_info_copy
+#undef snd_pcm_info_get_device
+#undef snd_pcm_info_get_subdevice
+#undef snd_pcm_info_get_stream
+#undef snd_pcm_info_get_card
+#undef snd_pcm_info_get_id
+#undef snd_pcm_info_get_name
+#undef snd_pcm_info_get_subdevice_name
+#undef snd_pcm_info_get_class
+#undef snd_pcm_info_get_subclass
+#undef snd_pcm_info_get_subdevices_count
+#undef snd_pcm_info_get_subdevices_avail
+#undef snd_pcm_info_get_sync
+#undef snd_pcm_info_set_device
+#undef snd_pcm_info_set_subdevice
+#undef snd_pcm_info_set_stream
+#undef snd_pcm_hw_params_any
+#undef snd_pcm_hw_params_can_mmap_sample_resolution
+#undef snd_pcm_hw_params_is_double
+#undef snd_pcm_hw_params_is_batch
+#undef snd_pcm_hw_params_is_block_transfer
+#undef snd_pcm_hw_params_is_monotonic
+#undef snd_pcm_hw_params_can_overrange
+#undef snd_pcm_hw_params_can_pause
+#undef snd_pcm_hw_params_can_resume
+#undef snd_pcm_hw_params_is_half_duplex
+#undef snd_pcm_hw_params_is_joint_duplex
+#undef snd_pcm_hw_params_can_sync_start
+#undef snd_pcm_hw_params_can_disable_period_wakeup
+#undef snd_pcm_hw_params_supports_audio_wallclock_ts
+#undef snd_pcm_hw_params_supports_audio_ts_type
+#undef snd_pcm_hw_params_get_rate_numden
+#undef snd_pcm_hw_params_get_sbits
+#undef snd_pcm_hw_params_get_fifo_size
+#undef snd_pcm_hw_params_sizeof
+#undef snd_pcm_hw_params_malloc
+#undef snd_pcm_hw_params_free
+#undef snd_pcm_hw_params_copy
+#undef snd_pcm_hw_params_get_access
+#undef snd_pcm_hw_params_test_access
+#undef snd_pcm_hw_params_set_access
+#undef snd_pcm_hw_params_set_access_first
+#undef snd_pcm_hw_params_set_access_last
+#undef snd_pcm_hw_params_set_access_mask
+#undef snd_pcm_hw_params_get_access_mask
+#undef snd_pcm_hw_params_get_format
+#undef snd_pcm_hw_params_test_format
+#undef snd_pcm_hw_params_set_format
+#undef snd_pcm_hw_params_set_format_first
+#undef snd_pcm_hw_params_set_format_last
+#undef snd_pcm_hw_params_set_format_mask
+#undef snd_pcm_hw_params_get_format_mask
+#undef snd_pcm_hw_params_get_subformat
+#undef snd_pcm_hw_params_test_subformat
+#undef snd_pcm_hw_params_set_subformat
+#undef snd_pcm_hw_params_set_subformat_first
+#undef snd_pcm_hw_params_set_subformat_last
+#undef snd_pcm_hw_params_set_subformat_mask
+#undef snd_pcm_hw_params_get_subformat_mask
+#undef snd_pcm_hw_params_get_channels
+#undef snd_pcm_hw_params_get_channels_min
+#undef snd_pcm_hw_params_get_channels_max
+#undef snd_pcm_hw_params_test_channels
+#undef snd_pcm_hw_params_set_channels
+#undef snd_pcm_hw_params_set_channels_min
+#undef snd_pcm_hw_params_set_channels_max
+#undef snd_pcm_hw_params_set_channels_minmax
+#undef snd_pcm_hw_params_set_channels_near
+#undef snd_pcm_hw_params_set_channels_first
+#undef snd_pcm_hw_params_set_channels_last
+#undef snd_pcm_hw_params_get_rate
+#undef snd_pcm_hw_params_get_rate_min
+#undef snd_pcm_hw_params_get_rate_max
+#undef snd_pcm_hw_params_test_rate
+#undef snd_pcm_hw_params_set_rate
+#undef snd_pcm_hw_params_set_rate_min
+#undef snd_pcm_hw_params_set_rate_max
+#undef snd_pcm_hw_params_set_rate_minmax
+#undef snd_pcm_hw_params_set_rate_near
+#undef snd_pcm_hw_params_set_rate_first
+#undef snd_pcm_hw_params_set_rate_last
+#undef snd_pcm_hw_params_set_rate_resample
+#undef snd_pcm_hw_params_get_rate_resample
+#undef snd_pcm_hw_params_set_export_buffer
+#undef snd_pcm_hw_params_get_export_buffer
+#undef snd_pcm_hw_params_set_period_wakeup
+#undef snd_pcm_hw_params_get_period_wakeup
+#undef snd_pcm_hw_params_get_period_time
+#undef snd_pcm_hw_params_get_period_time_min
+#undef snd_pcm_hw_params_get_period_time_max
+#undef snd_pcm_hw_params_test_period_time
+#undef snd_pcm_hw_params_set_period_time
+#undef snd_pcm_hw_params_set_period_time_min
+#undef snd_pcm_hw_params_set_period_time_max
+#undef snd_pcm_hw_params_set_period_time_minmax
+#undef snd_pcm_hw_params_set_period_time_near
+#undef snd_pcm_hw_params_set_period_time_first
+#undef snd_pcm_hw_params_set_period_time_last
+#undef snd_pcm_hw_params_get_period_size
+#undef snd_pcm_hw_params_get_period_size_min
+#undef snd_pcm_hw_params_get_period_size_max
+#undef snd_pcm_hw_params_test_period_size
+#undef snd_pcm_hw_params_set_period_size
+#undef snd_pcm_hw_params_set_period_size_min
+#undef snd_pcm_hw_params_set_period_size_max
+#undef snd_pcm_hw_params_set_period_size_minmax
+#undef snd_pcm_hw_params_set_period_size_near
+#undef snd_pcm_hw_params_set_period_size_first
+#undef snd_pcm_hw_params_set_period_size_last
+#undef snd_pcm_hw_params_set_period_size_integer
+#undef snd_pcm_hw_params_get_periods
+#undef snd_pcm_hw_params_get_periods_min
+#undef snd_pcm_hw_params_get_periods_max
+#undef snd_pcm_hw_params_test_periods
+#undef snd_pcm_hw_params_set_periods
+#undef snd_pcm_hw_params_set_periods_min
+#undef snd_pcm_hw_params_set_periods_max
+#undef snd_pcm_hw_params_set_periods_minmax
+#undef snd_pcm_hw_params_set_periods_near
+#undef snd_pcm_hw_params_set_periods_first
+#undef snd_pcm_hw_params_set_periods_last
+#undef snd_pcm_hw_params_set_periods_integer
+#undef snd_pcm_hw_params_get_buffer_time
+#undef snd_pcm_hw_params_get_buffer_time_min
+#undef snd_pcm_hw_params_get_buffer_time_max
+#undef snd_pcm_hw_params_test_buffer_time
+#undef snd_pcm_hw_params_set_buffer_time
+#undef snd_pcm_hw_params_set_buffer_time_min
+#undef snd_pcm_hw_params_set_buffer_time_max
+#undef snd_pcm_hw_params_set_buffer_time_minmax
+#undef snd_pcm_hw_params_set_buffer_time_near
+#undef snd_pcm_hw_params_set_buffer_time_first
+#undef snd_pcm_hw_params_set_buffer_time_last
+#undef snd_pcm_hw_params_get_buffer_size
+#undef snd_pcm_hw_params_get_buffer_size_min
+#undef snd_pcm_hw_params_get_buffer_size_max
+#undef snd_pcm_hw_params_test_buffer_size
+#undef snd_pcm_hw_params_set_buffer_size
+#undef snd_pcm_hw_params_set_buffer_size_min
+#undef snd_pcm_hw_params_set_buffer_size_max
+#undef snd_pcm_hw_params_set_buffer_size_minmax
+#undef snd_pcm_hw_params_set_buffer_size_near
+#undef snd_pcm_hw_params_set_buffer_size_first
+#undef snd_pcm_hw_params_set_buffer_size_last
+#undef snd_pcm_hw_params_get_min_align
+#undef snd_pcm_sw_params_sizeof
+#undef snd_pcm_sw_params_malloc
+#undef snd_pcm_sw_params_free
+#undef snd_pcm_sw_params_copy
+#undef snd_pcm_sw_params_get_boundary
+#undef snd_pcm_sw_params_set_tstamp_mode
+#undef snd_pcm_sw_params_get_tstamp_mode
+#undef snd_pcm_sw_params_set_avail_min
+#undef snd_pcm_sw_params_get_avail_min
+#undef snd_pcm_sw_params_set_period_event
+#undef snd_pcm_sw_params_get_period_event
+#undef snd_pcm_sw_params_set_start_threshold
+#undef snd_pcm_sw_params_get_start_threshold
+#undef snd_pcm_sw_params_set_stop_threshold
+#undef snd_pcm_sw_params_get_stop_threshold
+#undef snd_pcm_sw_params_set_silence_threshold
+#undef snd_pcm_sw_params_get_silence_threshold
+#undef snd_pcm_sw_params_set_silence_size
+#undef snd_pcm_sw_params_get_silence_size
+#undef snd_pcm_access_mask_sizeof
+#undef snd_pcm_access_mask_malloc
+#undef snd_pcm_access_mask_free
+#undef snd_pcm_access_mask_copy
+#undef snd_pcm_access_mask_none
+#undef snd_pcm_access_mask_any
+#undef snd_pcm_access_mask_test
+#undef snd_pcm_access_mask_empty
+#undef snd_pcm_access_mask_set
+#undef snd_pcm_access_mask_reset
+#undef snd_pcm_format_mask_sizeof
+#undef snd_pcm_format_mask_malloc
+#undef snd_pcm_format_mask_free
+#undef snd_pcm_format_mask_copy
+#undef snd_pcm_format_mask_none
+#undef snd_pcm_format_mask_any
+#undef snd_pcm_format_mask_test
+#undef snd_pcm_format_mask_empty
+#undef snd_pcm_format_mask_set
+#undef snd_pcm_format_mask_reset
+#undef snd_pcm_subformat_mask_sizeof
+#undef snd_pcm_subformat_mask_malloc
+#undef snd_pcm_subformat_mask_free
+#undef snd_pcm_subformat_mask_copy
+#undef snd_pcm_subformat_mask_none
+#undef snd_pcm_subformat_mask_any
+#undef snd_pcm_subformat_mask_test
+#undef snd_pcm_subformat_mask_empty
+#undef snd_pcm_subformat_mask_set
+#undef snd_pcm_subformat_mask_reset
+#undef snd_pcm_status_sizeof
+#undef snd_pcm_status_malloc
+#undef snd_pcm_status_free
+#undef snd_pcm_status_copy
+#undef snd_pcm_status_get_state
+#undef snd_pcm_status_get_trigger_tstamp
+#undef snd_pcm_status_get_trigger_htstamp
+#undef snd_pcm_status_get_tstamp
+#undef snd_pcm_status_get_htstamp
+#undef snd_pcm_status_get_audio_htstamp
+#undef snd_pcm_status_get_driver_htstamp
+#undef snd_pcm_status_get_delay
+#undef snd_pcm_status_get_avail
+#undef snd_pcm_status_get_avail_max
+#undef snd_pcm_status_get_overrange
+#undef snd_pcm_type_name
+#undef snd_pcm_stream_name
+#undef snd_pcm_access_name
+#undef snd_pcm_format_name
+#undef snd_pcm_format_description
+#undef snd_pcm_subformat_name
+#undef snd_pcm_subformat_description
+#undef snd_pcm_format_value
+#undef snd_pcm_tstamp_mode_name
+#undef snd_pcm_state_name
+#undef snd_pcm_dump
+#undef snd_pcm_dump_hw_setup
+#undef snd_pcm_dump_sw_setup
+#undef snd_pcm_dump_setup
+#undef snd_pcm_hw_params_dump
+#undef snd_pcm_sw_params_dump
+#undef snd_pcm_status_dump
+#undef snd_pcm_mmap_begin
+#undef snd_pcm_mmap_commit
+#undef snd_pcm_mmap_writei
+#undef snd_pcm_mmap_readi
+#undef snd_pcm_mmap_writen
+#undef snd_pcm_mmap_readn
+#undef snd_pcm_format_signed
+#undef snd_pcm_format_unsigned
+#undef snd_pcm_format_linear
+#undef snd_pcm_format_float
+#undef snd_pcm_format_little_endian
+#undef snd_pcm_format_big_endian
+#undef snd_pcm_format_cpu_endian
+#undef snd_pcm_format_width
+#undef snd_pcm_format_physical_width
+#undef snd_pcm_build_linear_format
+#undef snd_pcm_format_size
+#undef snd_pcm_format_silence
+#undef snd_pcm_format_silence_16
+#undef snd_pcm_format_silence_32
+#undef snd_pcm_format_silence_64
+#undef snd_pcm_format_set_silence
+#undef snd_pcm_bytes_to_frames
+#undef snd_pcm_frames_to_bytes
+#undef snd_pcm_bytes_to_samples
+#undef snd_pcm_samples_to_bytes
+#undef snd_pcm_area_silence
+#undef snd_pcm_areas_silence
+#undef snd_pcm_area_copy
+#undef snd_pcm_areas_copy
+#undef snd_pcm_areas_copy_wrap
+#undef snd_pcm_hook_get_pcm
+#undef snd_pcm_hook_get_private
+#undef snd_pcm_hook_set_private
+#undef snd_pcm_hook_add
+#undef snd_pcm_hook_remove
+#undef snd_pcm_meter_get_bufsize
+#undef snd_pcm_meter_get_channels
+#undef snd_pcm_meter_get_rate
+#undef snd_pcm_meter_get_now
+#undef snd_pcm_meter_get_boundary
+#undef snd_pcm_meter_add_scope
+#undef snd_pcm_meter_search_scope
+#undef snd_pcm_scope_malloc
+#undef snd_pcm_scope_set_ops
+#undef snd_pcm_scope_set_name
+#undef snd_pcm_scope_get_name
+#undef snd_pcm_scope_get_callback_private
+#undef snd_pcm_scope_set_callback_private
+#undef snd_pcm_scope_s16_open
+#undef snd_pcm_scope_s16_get_channel_buffer
+#undef snd_spcm_init
+#undef snd_spcm_init_duplex
+#undef snd_spcm_init_get_params
+#undef snd_pcm_start_mode_name
+#undef snd_pcm_xrun_mode_name
+#undef snd_pcm_sw_params_set_start_mode
+#undef snd_pcm_sw_params_get_start_mode
+#undef snd_pcm_sw_params_set_xrun_mode
+#undef snd_pcm_sw_params_get_xrun_mode
+#undef snd_pcm_sw_params_set_xfer_align
+#undef snd_pcm_sw_params_get_xfer_align
+#undef snd_pcm_sw_params_set_sleep_min
+#undef snd_pcm_sw_params_get_sleep_min
+#undef snd_pcm_hw_params_get_tick_time
+#undef snd_pcm_hw_params_get_tick_time_min
+#undef snd_pcm_hw_params_get_tick_time_max
+#undef snd_pcm_hw_params_test_tick_time
+#undef snd_pcm_hw_params_set_tick_time
+#undef snd_pcm_hw_params_set_tick_time_min
+#undef snd_pcm_hw_params_set_tick_time_max
+#undef snd_pcm_hw_params_set_tick_time_minmax
+#undef snd_pcm_hw_params_set_tick_time_near
+#undef snd_pcm_hw_params_set_tick_time_first
+#undef snd_pcm_hw_params_set_tick_time_last
+#undef snd_rawmidi_open
+#undef snd_rawmidi_open_lconf
+#undef snd_rawmidi_close
+#undef snd_rawmidi_poll_descriptors_count
+#undef snd_rawmidi_poll_descriptors
+#undef snd_rawmidi_poll_descriptors_revents
+#undef snd_rawmidi_nonblock
+#undef snd_rawmidi_info_sizeof
+#undef snd_rawmidi_info_malloc
+#undef snd_rawmidi_info_free
+#undef snd_rawmidi_info_copy
+#undef snd_rawmidi_info_get_device
+#undef snd_rawmidi_info_get_subdevice
+#undef snd_rawmidi_info_get_stream
+#undef snd_rawmidi_info_get_card
+#undef snd_rawmidi_info_get_flags
+#undef snd_rawmidi_info_get_id
+#undef snd_rawmidi_info_get_name
+#undef snd_rawmidi_info_get_subdevice_name
+#undef snd_rawmidi_info_get_subdevices_count
+#undef snd_rawmidi_info_get_subdevices_avail
+#undef snd_rawmidi_info_set_device
+#undef snd_rawmidi_info_set_subdevice
+#undef snd_rawmidi_info_set_stream
+#undef snd_rawmidi_info
+#undef snd_rawmidi_params_sizeof
+#undef snd_rawmidi_params_malloc
+#undef snd_rawmidi_params_free
+#undef snd_rawmidi_params_copy
+#undef snd_rawmidi_params_set_buffer_size
+#undef snd_rawmidi_params_get_buffer_size
+#undef snd_rawmidi_params_set_avail_min
+#undef snd_rawmidi_params_get_avail_min
+#undef snd_rawmidi_params_set_no_active_sensing
+#undef snd_rawmidi_params_get_no_active_sensing
+#undef snd_rawmidi_params
+#undef snd_rawmidi_params_current
+#undef snd_rawmidi_status_sizeof
+#undef snd_rawmidi_status_malloc
+#undef snd_rawmidi_status_free
+#undef snd_rawmidi_status_copy
+#undef snd_rawmidi_status_get_tstamp
+#undef snd_rawmidi_status_get_avail
+#undef snd_rawmidi_status_get_xruns
+#undef snd_rawmidi_status
+#undef snd_rawmidi_drain
+#undef snd_rawmidi_drop
+#undef snd_rawmidi_write
+#undef snd_rawmidi_read
+#undef snd_rawmidi_name
+#undef snd_rawmidi_type
+#undef snd_rawmidi_stream
+#undef snd_timer_query_open
+#undef snd_timer_query_open_lconf
+#undef snd_timer_query_close
+#undef snd_timer_query_next_device
+#undef snd_timer_query_info
+#undef snd_timer_query_params
+#undef snd_timer_query_status
+#undef snd_timer_open
+#undef snd_timer_open_lconf
+#undef snd_timer_close
+#undef snd_async_add_timer_handler
+#undef snd_async_handler_get_timer
+#undef snd_timer_poll_descriptors_count
+#undef snd_timer_poll_descriptors
+#undef snd_timer_poll_descriptors_revents
+#undef snd_timer_info
+#undef snd_timer_params
+#undef snd_timer_status
+#undef snd_timer_start
+#undef snd_timer_stop
+#undef snd_timer_continue
+#undef snd_timer_read
+#undef snd_timer_id_sizeof
+#undef snd_timer_id_malloc
+#undef snd_timer_id_free
+#undef snd_timer_id_copy
+#undef snd_timer_id_set_class
+#undef snd_timer_id_get_class
+#undef snd_timer_id_set_sclass
+#undef snd_timer_id_get_sclass
+#undef snd_timer_id_set_card
+#undef snd_timer_id_get_card
+#undef snd_timer_id_set_device
+#undef snd_timer_id_get_device
+#undef snd_timer_id_set_subdevice
+#undef snd_timer_id_get_subdevice
+#undef snd_timer_ginfo_sizeof
+#undef snd_timer_ginfo_malloc
+#undef snd_timer_ginfo_free
+#undef snd_timer_ginfo_copy
+#undef snd_timer_ginfo_set_tid
+#undef snd_timer_ginfo_get_tid
+#undef snd_timer_ginfo_get_flags
+#undef snd_timer_ginfo_get_card
+#undef snd_timer_ginfo_get_id
+#undef snd_timer_ginfo_get_name
+#undef snd_timer_ginfo_get_resolution
+#undef snd_timer_ginfo_get_resolution_min
+#undef snd_timer_ginfo_get_resolution_max
+#undef snd_timer_ginfo_get_clients
+#undef snd_timer_info_sizeof
+#undef snd_timer_info_malloc
+#undef snd_timer_info_free
+#undef snd_timer_info_copy
+#undef snd_timer_info_is_slave
+#undef snd_timer_info_get_card
+#undef snd_timer_info_get_id
+#undef snd_timer_info_get_name
+#undef snd_timer_info_get_resolution
+#undef snd_timer_params_sizeof
+#undef snd_timer_params_malloc
+#undef snd_timer_params_free
+#undef snd_timer_params_copy
+#undef snd_timer_params_set_auto_start
+#undef snd_timer_params_get_auto_start
+#undef snd_timer_params_set_exclusive
+#undef snd_timer_params_get_exclusive
+#undef snd_timer_params_set_early_event
+#undef snd_timer_params_get_early_event
+#undef snd_timer_params_set_ticks
+#undef snd_timer_params_get_ticks
+#undef snd_timer_params_set_queue_size
+#undef snd_timer_params_get_queue_size
+#undef snd_timer_params_set_filter
+#undef snd_timer_params_get_filter
+#undef snd_timer_status_sizeof
+#undef snd_timer_status_malloc
+#undef snd_timer_status_free
+#undef snd_timer_status_copy
+#undef snd_timer_status_get_timestamp
+#undef snd_timer_status_get_resolution
+#undef snd_timer_status_get_lost
+#undef snd_timer_status_get_overrun
+#undef snd_timer_status_get_queue
+#undef snd_timer_info_get_ticks
+#undef snd_hwdep_open
+#undef snd_hwdep_close
+#undef snd_hwdep_poll_descriptors
+#undef snd_hwdep_poll_descriptors_count
+#undef snd_hwdep_poll_descriptors_revents
+#undef snd_hwdep_nonblock
+#undef snd_hwdep_info
+#undef snd_hwdep_dsp_status
+#undef snd_hwdep_dsp_load
+#undef snd_hwdep_ioctl
+#undef snd_hwdep_write
+#undef snd_hwdep_read
+#undef snd_hwdep_info_sizeof
+#undef snd_hwdep_info_malloc
+#undef snd_hwdep_info_free
+#undef snd_hwdep_info_copy
+#undef snd_hwdep_info_get_device
+#undef snd_hwdep_info_get_card
+#undef snd_hwdep_info_get_id
+#undef snd_hwdep_info_get_name
+#undef snd_hwdep_info_get_iface
+#undef snd_hwdep_info_set_device
+#undef snd_hwdep_dsp_status_sizeof
+#undef snd_hwdep_dsp_status_malloc
+#undef snd_hwdep_dsp_status_free
+#undef snd_hwdep_dsp_status_copy
+#undef snd_hwdep_dsp_status_get_version
+#undef snd_hwdep_dsp_status_get_id
+#undef snd_hwdep_dsp_status_get_num_dsps
+#undef snd_hwdep_dsp_status_get_dsp_loaded
+#undef snd_hwdep_dsp_status_get_chip_ready
+#undef snd_hwdep_dsp_image_sizeof
+#undef snd_hwdep_dsp_image_malloc
+#undef snd_hwdep_dsp_image_free
+#undef snd_hwdep_dsp_image_copy
+#undef snd_hwdep_dsp_image_get_index
+#undef snd_hwdep_dsp_image_get_name
+#undef snd_hwdep_dsp_image_get_image
+#undef snd_hwdep_dsp_image_get_length
+#undef snd_hwdep_dsp_image_set_index
+#undef snd_hwdep_dsp_image_set_name
+#undef snd_hwdep_dsp_image_set_image
+#undef snd_hwdep_dsp_image_set_length
+#undef snd_card_load
+#undef snd_card_next
+#undef snd_card_get_index
+#undef snd_card_get_name
+#undef snd_card_get_longname
+#undef snd_device_name_hint
+#undef snd_device_name_free_hint
+#undef snd_device_name_get_hint
+#undef snd_ctl_open
+#undef snd_ctl_open_lconf
+#undef snd_ctl_open_fallback
+#undef snd_ctl_close
+#undef snd_ctl_nonblock
+#undef snd_async_add_ctl_handler
+#undef snd_async_handler_get_ctl
+#undef snd_ctl_poll_descriptors_count
+#undef snd_ctl_poll_descriptors
+#undef snd_ctl_poll_descriptors_revents
+#undef snd_ctl_subscribe_events
+#undef snd_ctl_card_info
+#undef snd_ctl_elem_list
+#undef snd_ctl_elem_info
+#undef snd_ctl_elem_read
+#undef snd_ctl_elem_write
+#undef snd_ctl_elem_lock
+#undef snd_ctl_elem_unlock
+#undef snd_ctl_elem_tlv_read
+#undef snd_ctl_elem_tlv_write
+#undef snd_ctl_elem_tlv_command
+#undef snd_ctl_hwdep_next_device
+#undef snd_ctl_hwdep_info
+#undef snd_ctl_pcm_next_device
+#undef snd_ctl_pcm_info
+#undef snd_ctl_pcm_prefer_subdevice
+#undef snd_ctl_rawmidi_next_device
+#undef snd_ctl_rawmidi_info
+#undef snd_ctl_rawmidi_prefer_subdevice
+#undef snd_ctl_set_power_state
+#undef snd_ctl_get_power_state
+#undef snd_ctl_read
+#undef snd_ctl_wait
+#undef snd_ctl_name
+#undef snd_ctl_type
+#undef snd_ctl_elem_type_name
+#undef snd_ctl_elem_iface_name
+#undef snd_ctl_event_type_name
+#undef snd_ctl_event_elem_get_mask
+#undef snd_ctl_event_elem_get_numid
+#undef snd_ctl_event_elem_get_id
+#undef snd_ctl_event_elem_get_interface
+#undef snd_ctl_event_elem_get_device
+#undef snd_ctl_event_elem_get_subdevice
+#undef snd_ctl_event_elem_get_name
+#undef snd_ctl_event_elem_get_index
+#undef snd_ctl_elem_list_alloc_space
+#undef snd_ctl_elem_list_free_space
+#undef snd_ctl_ascii_elem_id_get
+#undef snd_ctl_ascii_elem_id_parse
+#undef snd_ctl_ascii_value_parse
+#undef snd_ctl_elem_id_sizeof
+#undef snd_ctl_elem_id_malloc
+#undef snd_ctl_elem_id_free
+#undef snd_ctl_elem_id_clear
+#undef snd_ctl_elem_id_copy
+#undef snd_ctl_elem_id_get_numid
+#undef snd_ctl_elem_id_get_interface
+#undef snd_ctl_elem_id_get_device
+#undef snd_ctl_elem_id_get_subdevice
+#undef snd_ctl_elem_id_get_name
+#undef snd_ctl_elem_id_get_index
+#undef snd_ctl_elem_id_set_numid
+#undef snd_ctl_elem_id_set_interface
+#undef snd_ctl_elem_id_set_device
+#undef snd_ctl_elem_id_set_subdevice
+#undef snd_ctl_elem_id_set_name
+#undef snd_ctl_elem_id_set_index
+#undef snd_ctl_card_info_sizeof
+#undef snd_ctl_card_info_malloc
+#undef snd_ctl_card_info_free
+#undef snd_ctl_card_info_clear
+#undef snd_ctl_card_info_copy
+#undef snd_ctl_card_info_get_card
+#undef snd_ctl_card_info_get_id
+#undef snd_ctl_card_info_get_driver
+#undef snd_ctl_card_info_get_name
+#undef snd_ctl_card_info_get_longname
+#undef snd_ctl_card_info_get_mixername
+#undef snd_ctl_card_info_get_components
+#undef snd_ctl_event_sizeof
+#undef snd_ctl_event_malloc
+#undef snd_ctl_event_free
+#undef snd_ctl_event_clear
+#undef snd_ctl_event_copy
+#undef snd_ctl_event_get_type
+#undef snd_ctl_elem_list_sizeof
+#undef snd_ctl_elem_list_malloc
+#undef snd_ctl_elem_list_free
+#undef snd_ctl_elem_list_clear
+#undef snd_ctl_elem_list_copy
+#undef snd_ctl_elem_list_set_offset
+#undef snd_ctl_elem_list_get_used
+#undef snd_ctl_elem_list_get_count
+#undef snd_ctl_elem_list_get_id
+#undef snd_ctl_elem_list_get_numid
+#undef snd_ctl_elem_list_get_interface
+#undef snd_ctl_elem_list_get_device
+#undef snd_ctl_elem_list_get_subdevice
+#undef snd_ctl_elem_list_get_name
+#undef snd_ctl_elem_list_get_index
+#undef snd_ctl_elem_info_sizeof
+#undef snd_ctl_elem_info_malloc
+#undef snd_ctl_elem_info_free
+#undef snd_ctl_elem_info_clear
+#undef snd_ctl_elem_info_copy
+#undef snd_ctl_elem_info_get_type
+#undef snd_ctl_elem_info_is_readable
+#undef snd_ctl_elem_info_is_writable
+#undef snd_ctl_elem_info_is_volatile
+#undef snd_ctl_elem_info_is_inactive
+#undef snd_ctl_elem_info_is_locked
+#undef snd_ctl_elem_info_is_tlv_readable
+#undef snd_ctl_elem_info_is_tlv_writable
+#undef snd_ctl_elem_info_is_tlv_commandable
+#undef snd_ctl_elem_info_is_owner
+#undef snd_ctl_elem_info_is_user
+#undef snd_ctl_elem_info_get_owner
+#undef snd_ctl_elem_info_get_count
+#undef snd_ctl_elem_info_get_min
+#undef snd_ctl_elem_info_get_max
+#undef snd_ctl_elem_info_get_step
+#undef snd_ctl_elem_info_get_min64
+#undef snd_ctl_elem_info_get_max64
+#undef snd_ctl_elem_info_get_step64
+#undef snd_ctl_elem_info_get_items
+#undef snd_ctl_elem_info_set_item
+#undef snd_ctl_elem_info_get_item_name
+#undef snd_ctl_elem_info_get_dimensions
+#undef snd_ctl_elem_info_get_dimension
+#undef snd_ctl_elem_info_set_dimension
+#undef snd_ctl_elem_info_get_id
+#undef snd_ctl_elem_info_get_numid
+#undef snd_ctl_elem_info_get_interface
+#undef snd_ctl_elem_info_get_device
+#undef snd_ctl_elem_info_get_subdevice
+#undef snd_ctl_elem_info_get_name
+#undef snd_ctl_elem_info_get_index
+#undef snd_ctl_elem_info_set_id
+#undef snd_ctl_elem_info_set_numid
+#undef snd_ctl_elem_info_set_interface
+#undef snd_ctl_elem_info_set_device
+#undef snd_ctl_elem_info_set_subdevice
+#undef snd_ctl_elem_info_set_name
+#undef snd_ctl_elem_info_set_index
+#undef snd_ctl_add_integer_elem_set
+#undef snd_ctl_add_integer64_elem_set
+#undef snd_ctl_add_boolean_elem_set
+#undef snd_ctl_add_enumerated_elem_set
+#undef snd_ctl_add_bytes_elem_set
+#undef snd_ctl_elem_add_integer
+#undef snd_ctl_elem_add_integer64
+#undef snd_ctl_elem_add_boolean
+#undef snd_ctl_elem_add_enumerated
+#undef snd_ctl_elem_add_iec958
+#undef snd_ctl_elem_remove
+#undef snd_ctl_elem_value_sizeof
+#undef snd_ctl_elem_value_malloc
+#undef snd_ctl_elem_value_free
+#undef snd_ctl_elem_value_clear
+#undef snd_ctl_elem_value_copy
+#undef snd_ctl_elem_value_compare
+#undef snd_ctl_elem_value_get_id
+#undef snd_ctl_elem_value_get_numid
+#undef snd_ctl_elem_value_get_interface
+#undef snd_ctl_elem_value_get_device
+#undef snd_ctl_elem_value_get_subdevice
+#undef snd_ctl_elem_value_get_name
+#undef snd_ctl_elem_value_get_index
+#undef snd_ctl_elem_value_set_id
+#undef snd_ctl_elem_value_set_numid
+#undef snd_ctl_elem_value_set_interface
+#undef snd_ctl_elem_value_set_device
+#undef snd_ctl_elem_value_set_subdevice
+#undef snd_ctl_elem_value_set_name
+#undef snd_ctl_elem_value_set_index
+#undef snd_ctl_elem_value_get_boolean
+#undef snd_ctl_elem_value_get_integer
+#undef snd_ctl_elem_value_get_integer64
+#undef snd_ctl_elem_value_get_enumerated
+#undef snd_ctl_elem_value_get_byte
+#undef snd_ctl_elem_value_set_boolean
+#undef snd_ctl_elem_value_set_integer
+#undef snd_ctl_elem_value_set_integer64
+#undef snd_ctl_elem_value_set_enumerated
+#undef snd_ctl_elem_value_set_byte
+#undef snd_ctl_elem_set_bytes
+#undef snd_ctl_elem_value_get_bytes
+#undef snd_ctl_elem_value_get_iec958
+#undef snd_ctl_elem_value_set_iec958
+#undef snd_tlv_parse_dB_info
+#undef snd_tlv_get_dB_range
+#undef snd_tlv_convert_to_dB
+#undef snd_tlv_convert_from_dB
+#undef snd_ctl_get_dB_range
+#undef snd_ctl_convert_to_dB
+#undef snd_ctl_convert_from_dB
+#undef snd_hctl_compare_fast
+#undef snd_hctl_open
+#undef snd_hctl_open_ctl
+#undef snd_hctl_close
+#undef snd_hctl_nonblock
+#undef snd_hctl_poll_descriptors_count
+#undef snd_hctl_poll_descriptors
+#undef snd_hctl_poll_descriptors_revents
+#undef snd_hctl_get_count
+#undef snd_hctl_set_compare
+#undef snd_hctl_first_elem
+#undef snd_hctl_last_elem
+#undef snd_hctl_find_elem
+#undef snd_hctl_set_callback
+#undef snd_hctl_set_callback_private
+#undef snd_hctl_get_callback_private
+#undef snd_hctl_load
+#undef snd_hctl_free
+#undef snd_hctl_handle_events
+#undef snd_hctl_name
+#undef snd_hctl_wait
+#undef snd_hctl_ctl
+#undef snd_hctl_elem_next
+#undef snd_hctl_elem_prev
+#undef snd_hctl_elem_info
+#undef snd_hctl_elem_read
+#undef snd_hctl_elem_write
+#undef snd_hctl_elem_tlv_read
+#undef snd_hctl_elem_tlv_write
+#undef snd_hctl_elem_tlv_command
+#undef snd_hctl_elem_get_hctl
+#undef snd_hctl_elem_get_id
+#undef snd_hctl_elem_get_numid
+#undef snd_hctl_elem_get_interface
+#undef snd_hctl_elem_get_device
+#undef snd_hctl_elem_get_subdevice
+#undef snd_hctl_elem_get_name
+#undef snd_hctl_elem_get_index
+#undef snd_hctl_elem_set_callback
+#undef snd_hctl_elem_get_callback_private
+#undef snd_hctl_elem_set_callback_private
+#undef snd_sctl_build
+#undef snd_sctl_free
+#undef snd_sctl_install
+#undef snd_sctl_remove
+#undef snd_mixer_open
+#undef snd_mixer_close
+#undef snd_mixer_first_elem
+#undef snd_mixer_last_elem
+#undef snd_mixer_handle_events
+#undef snd_mixer_attach
+#undef snd_mixer_attach_hctl
+#undef snd_mixer_detach
+#undef snd_mixer_detach_hctl
+#undef snd_mixer_get_hctl
+#undef snd_mixer_poll_descriptors_count
+#undef snd_mixer_poll_descriptors
+#undef snd_mixer_poll_descriptors_revents
+#undef snd_mixer_load
+#undef snd_mixer_free
+#undef snd_mixer_wait
+#undef snd_mixer_set_compare
+#undef snd_mixer_set_callback
+#undef snd_mixer_get_callback_private
+#undef snd_mixer_set_callback_private
+#undef snd_mixer_get_count
+#undef snd_mixer_class_unregister
+#undef snd_mixer_elem_next
+#undef snd_mixer_elem_prev
+#undef snd_mixer_elem_set_callback
+#undef snd_mixer_elem_get_callback_private
+#undef snd_mixer_elem_set_callback_private
+#undef snd_mixer_elem_get_type
+#undef snd_mixer_class_register
+#undef snd_mixer_elem_new
+#undef snd_mixer_elem_add
+#undef snd_mixer_elem_remove
+#undef snd_mixer_elem_free
+#undef snd_mixer_elem_info
+#undef snd_mixer_elem_value
+#undef snd_mixer_elem_attach
+#undef snd_mixer_elem_detach
+#undef snd_mixer_elem_empty
+#undef snd_mixer_elem_get_private
+#undef snd_mixer_class_sizeof
+#undef snd_mixer_class_malloc
+#undef snd_mixer_class_free
+#undef snd_mixer_class_copy
+#undef snd_mixer_class_get_mixer
+#undef snd_mixer_class_get_event
+#undef snd_mixer_class_get_private
+#undef snd_mixer_class_get_compare
+#undef snd_mixer_class_set_event
+#undef snd_mixer_class_set_private
+#undef snd_mixer_class_set_private_free
+#undef snd_mixer_class_set_compare
+#undef snd_mixer_selem_channel_name
+#undef snd_mixer_selem_register
+#undef snd_mixer_selem_get_id
+#undef snd_mixer_selem_get_name
+#undef snd_mixer_selem_get_index
+#undef snd_mixer_find_selem
+#undef snd_mixer_selem_is_active
+#undef snd_mixer_selem_is_playback_mono
+#undef snd_mixer_selem_has_playback_channel
+#undef snd_mixer_selem_is_capture_mono
+#undef snd_mixer_selem_has_capture_channel
+#undef snd_mixer_selem_get_capture_group
+#undef snd_mixer_selem_has_common_volume
+#undef snd_mixer_selem_has_playback_volume
+#undef snd_mixer_selem_has_playback_volume_joined
+#undef snd_mixer_selem_has_capture_volume
+#undef snd_mixer_selem_has_capture_volume_joined
+#undef snd_mixer_selem_has_common_switch
+#undef snd_mixer_selem_has_playback_switch
+#undef snd_mixer_selem_has_playback_switch_joined
+#undef snd_mixer_selem_has_capture_switch
+#undef snd_mixer_selem_has_capture_switch_joined
+#undef snd_mixer_selem_has_capture_switch_exclusive
+#undef snd_mixer_selem_ask_playback_vol_dB
+#undef snd_mixer_selem_ask_capture_vol_dB
+#undef snd_mixer_selem_ask_playback_dB_vol
+#undef snd_mixer_selem_ask_capture_dB_vol
+#undef snd_mixer_selem_get_playback_volume
+#undef snd_mixer_selem_get_capture_volume
+#undef snd_mixer_selem_get_playback_dB
+#undef snd_mixer_selem_get_capture_dB
+#undef snd_mixer_selem_get_playback_switch
+#undef snd_mixer_selem_get_capture_switch
+#undef snd_mixer_selem_set_playback_volume
+#undef snd_mixer_selem_set_capture_volume
+#undef snd_mixer_selem_set_playback_dB
+#undef snd_mixer_selem_set_capture_dB
+#undef snd_mixer_selem_set_playback_volume_all
+#undef snd_mixer_selem_set_capture_volume_all
+#undef snd_mixer_selem_set_playback_dB_all
+#undef snd_mixer_selem_set_capture_dB_all
+#undef snd_mixer_selem_set_playback_switch
+#undef snd_mixer_selem_set_capture_switch
+#undef snd_mixer_selem_set_playback_switch_all
+#undef snd_mixer_selem_set_capture_switch_all
+#undef snd_mixer_selem_get_playback_volume_range
+#undef snd_mixer_selem_get_playback_dB_range
+#undef snd_mixer_selem_set_playback_volume_range
+#undef snd_mixer_selem_get_capture_volume_range
+#undef snd_mixer_selem_get_capture_dB_range
+#undef snd_mixer_selem_set_capture_volume_range
+#undef snd_mixer_selem_is_enumerated
+#undef snd_mixer_selem_is_enum_playback
+#undef snd_mixer_selem_is_enum_capture
+#undef snd_mixer_selem_get_enum_items
+#undef snd_mixer_selem_get_enum_item_name
+#undef snd_mixer_selem_get_enum_item
+#undef snd_mixer_selem_set_enum_item
+#undef snd_mixer_selem_id_sizeof
+#undef snd_mixer_selem_id_malloc
+#undef snd_mixer_selem_id_free
+#undef snd_mixer_selem_id_copy
+#undef snd_mixer_selem_id_get_name
+#undef snd_mixer_selem_id_get_index
+#undef snd_mixer_selem_id_set_name
+#undef snd_mixer_selem_id_set_index
+#undef snd_mixer_selem_id_parse
+#undef snd_seq_open
+#undef snd_seq_open_lconf
+#undef snd_seq_name
+#undef snd_seq_type
+#undef snd_seq_close
+#undef snd_seq_poll_descriptors_count
+#undef snd_seq_poll_descriptors
+#undef snd_seq_poll_descriptors_revents
+#undef snd_seq_nonblock
+#undef snd_seq_client_id
+#undef snd_seq_get_output_buffer_size
+#undef snd_seq_get_input_buffer_size
+#undef snd_seq_set_output_buffer_size
+#undef snd_seq_set_input_buffer_size
+#undef snd_seq_system_info_sizeof
+#undef snd_seq_system_info_malloc
+#undef snd_seq_system_info_free
+#undef snd_seq_system_info_copy
+#undef snd_seq_system_info_get_queues
+#undef snd_seq_system_info_get_clients
+#undef snd_seq_system_info_get_ports
+#undef snd_seq_system_info_get_channels
+#undef snd_seq_system_info_get_cur_clients
+#undef snd_seq_system_info_get_cur_queues
+#undef snd_seq_system_info
+#undef snd_seq_client_info_sizeof
+#undef snd_seq_client_info_malloc
+#undef snd_seq_client_info_free
+#undef snd_seq_client_info_copy
+#undef snd_seq_client_info_get_client
+#undef snd_seq_client_info_get_type
+#undef snd_seq_client_info_get_name
+#undef snd_seq_client_info_get_broadcast_filter
+#undef snd_seq_client_info_get_error_bounce
+#undef snd_seq_client_info_get_card
+#undef snd_seq_client_info_get_pid
+#undef snd_seq_client_info_get_event_filter
+#undef snd_seq_client_info_get_num_ports
+#undef snd_seq_client_info_get_event_lost
+#undef snd_seq_client_info_set_client
+#undef snd_seq_client_info_set_name
+#undef snd_seq_client_info_set_broadcast_filter
+#undef snd_seq_client_info_set_error_bounce
+#undef snd_seq_client_info_set_event_filter
+#undef snd_seq_client_info_event_filter_clear
+#undef snd_seq_client_info_event_filter_add
+#undef snd_seq_client_info_event_filter_del
+#undef snd_seq_client_info_event_filter_check
+#undef snd_seq_get_client_info
+#undef snd_seq_get_any_client_info
+#undef snd_seq_set_client_info
+#undef snd_seq_query_next_client
+#undef snd_seq_client_pool_sizeof
+#undef snd_seq_client_pool_malloc
+#undef snd_seq_client_pool_free
+#undef snd_seq_client_pool_copy
+#undef snd_seq_client_pool_get_client
+#undef snd_seq_client_pool_get_output_pool
+#undef snd_seq_client_pool_get_input_pool
+#undef snd_seq_client_pool_get_output_room
+#undef snd_seq_client_pool_get_output_free
+#undef snd_seq_client_pool_get_input_free
+#undef snd_seq_client_pool_set_output_pool
+#undef snd_seq_client_pool_set_input_pool
+#undef snd_seq_client_pool_set_output_room
+#undef snd_seq_get_client_pool
+#undef snd_seq_set_client_pool
+#undef snd_seq_port_info_sizeof
+#undef snd_seq_port_info_malloc
+#undef snd_seq_port_info_free
+#undef snd_seq_port_info_copy
+#undef snd_seq_port_info_get_client
+#undef snd_seq_port_info_get_port
+#undef snd_seq_port_info_get_addr
+#undef snd_seq_port_info_get_name
+#undef snd_seq_port_info_get_capability
+#undef snd_seq_port_info_get_type
+#undef snd_seq_port_info_get_midi_channels
+#undef snd_seq_port_info_get_midi_voices
+#undef snd_seq_port_info_get_synth_voices
+#undef snd_seq_port_info_get_read_use
+#undef snd_seq_port_info_get_write_use
+#undef snd_seq_port_info_get_port_specified
+#undef snd_seq_port_info_get_timestamping
+#undef snd_seq_port_info_get_timestamp_real
+#undef snd_seq_port_info_get_timestamp_queue
+#undef snd_seq_port_info_set_client
+#undef snd_seq_port_info_set_port
+#undef snd_seq_port_info_set_addr
+#undef snd_seq_port_info_set_name
+#undef snd_seq_port_info_set_capability
+#undef snd_seq_port_info_set_type
+#undef snd_seq_port_info_set_midi_channels
+#undef snd_seq_port_info_set_midi_voices
+#undef snd_seq_port_info_set_synth_voices
+#undef snd_seq_port_info_set_port_specified
+#undef snd_seq_port_info_set_timestamping
+#undef snd_seq_port_info_set_timestamp_real
+#undef snd_seq_port_info_set_timestamp_queue
+#undef snd_seq_create_port
+#undef snd_seq_delete_port
+#undef snd_seq_get_port_info
+#undef snd_seq_get_any_port_info
+#undef snd_seq_set_port_info
+#undef snd_seq_query_next_port
+#undef snd_seq_port_subscribe_sizeof
+#undef snd_seq_port_subscribe_malloc
+#undef snd_seq_port_subscribe_free
+#undef snd_seq_port_subscribe_copy
+#undef snd_seq_port_subscribe_get_sender
+#undef snd_seq_port_subscribe_get_dest
+#undef snd_seq_port_subscribe_get_queue
+#undef snd_seq_port_subscribe_get_exclusive
+#undef snd_seq_port_subscribe_get_time_update
+#undef snd_seq_port_subscribe_get_time_real
+#undef snd_seq_port_subscribe_set_sender
+#undef snd_seq_port_subscribe_set_dest
+#undef snd_seq_port_subscribe_set_queue
+#undef snd_seq_port_subscribe_set_exclusive
+#undef snd_seq_port_subscribe_set_time_update
+#undef snd_seq_port_subscribe_set_time_real
+#undef snd_seq_get_port_subscription
+#undef snd_seq_subscribe_port
+#undef snd_seq_unsubscribe_port
+#undef snd_seq_query_subscribe_sizeof
+#undef snd_seq_query_subscribe_malloc
+#undef snd_seq_query_subscribe_free
+#undef snd_seq_query_subscribe_copy
+#undef snd_seq_query_subscribe_get_client
+#undef snd_seq_query_subscribe_get_port
+#undef snd_seq_query_subscribe_get_root
+#undef snd_seq_query_subscribe_get_type
+#undef snd_seq_query_subscribe_get_index
+#undef snd_seq_query_subscribe_get_num_subs
+#undef snd_seq_query_subscribe_get_addr
+#undef snd_seq_query_subscribe_get_queue
+#undef snd_seq_query_subscribe_get_exclusive
+#undef snd_seq_query_subscribe_get_time_update
+#undef snd_seq_query_subscribe_get_time_real
+#undef snd_seq_query_subscribe_set_client
+#undef snd_seq_query_subscribe_set_port
+#undef snd_seq_query_subscribe_set_root
+#undef snd_seq_query_subscribe_set_type
+#undef snd_seq_query_subscribe_set_index
+#undef snd_seq_query_port_subscribers
+#undef snd_seq_queue_info_sizeof
+#undef snd_seq_queue_info_malloc
+#undef snd_seq_queue_info_free
+#undef snd_seq_queue_info_copy
+#undef snd_seq_queue_info_get_queue
+#undef snd_seq_queue_info_get_name
+#undef snd_seq_queue_info_get_owner
+#undef snd_seq_queue_info_get_locked
+#undef snd_seq_queue_info_get_flags
+#undef snd_seq_queue_info_set_name
+#undef snd_seq_queue_info_set_owner
+#undef snd_seq_queue_info_set_locked
+#undef snd_seq_queue_info_set_flags
+#undef snd_seq_create_queue
+#undef snd_seq_alloc_named_queue
+#undef snd_seq_alloc_queue
+#undef snd_seq_free_queue
+#undef snd_seq_get_queue_info
+#undef snd_seq_set_queue_info
+#undef snd_seq_query_named_queue
+#undef snd_seq_get_queue_usage
+#undef snd_seq_set_queue_usage
+#undef snd_seq_queue_status_sizeof
+#undef snd_seq_queue_status_malloc
+#undef snd_seq_queue_status_free
+#undef snd_seq_queue_status_copy
+#undef snd_seq_queue_status_get_queue
+#undef snd_seq_queue_status_get_events
+#undef snd_seq_queue_status_get_tick_time
+#undef snd_seq_queue_status_get_real_time
+#undef snd_seq_queue_status_get_status
+#undef snd_seq_get_queue_status
+#undef snd_seq_queue_tempo_sizeof
+#undef snd_seq_queue_tempo_malloc
+#undef snd_seq_queue_tempo_free
+#undef snd_seq_queue_tempo_copy
+#undef snd_seq_queue_tempo_get_queue
+#undef snd_seq_queue_tempo_get_tempo
+#undef snd_seq_queue_tempo_get_ppq
+#undef snd_seq_queue_tempo_get_skew
+#undef snd_seq_queue_tempo_get_skew_base
+#undef snd_seq_queue_tempo_set_tempo
+#undef snd_seq_queue_tempo_set_ppq
+#undef snd_seq_queue_tempo_set_skew
+#undef snd_seq_queue_tempo_set_skew_base
+#undef snd_seq_get_queue_tempo
+#undef snd_seq_set_queue_tempo
+#undef snd_seq_queue_timer_sizeof
+#undef snd_seq_queue_timer_malloc
+#undef snd_seq_queue_timer_free
+#undef snd_seq_queue_timer_copy
+#undef snd_seq_queue_timer_get_queue
+#undef snd_seq_queue_timer_get_type
+#undef snd_seq_queue_timer_get_id
+#undef snd_seq_queue_timer_get_resolution
+#undef snd_seq_queue_timer_set_type
+#undef snd_seq_queue_timer_set_id
+#undef snd_seq_queue_timer_set_resolution
+#undef snd_seq_get_queue_timer
+#undef snd_seq_set_queue_timer
+#undef snd_seq_free_event
+#undef snd_seq_event_length
+#undef snd_seq_event_output
+#undef snd_seq_event_output_buffer
+#undef snd_seq_event_output_direct
+#undef snd_seq_event_input
+#undef snd_seq_event_input_pending
+#undef snd_seq_drain_output
+#undef snd_seq_event_output_pending
+#undef snd_seq_extract_output
+#undef snd_seq_drop_output
+#undef snd_seq_drop_output_buffer
+#undef snd_seq_drop_input
+#undef snd_seq_drop_input_buffer
+#undef snd_seq_remove_events_sizeof
+#undef snd_seq_remove_events_malloc
+#undef snd_seq_remove_events_free
+#undef snd_seq_remove_events_copy
+#undef snd_seq_remove_events_get_condition
+#undef snd_seq_remove_events_get_queue
+#undef snd_seq_remove_events_get_time
+#undef snd_seq_remove_events_get_dest
+#undef snd_seq_remove_events_get_channel
+#undef snd_seq_remove_events_get_event_type
+#undef snd_seq_remove_events_get_tag
+#undef snd_seq_remove_events_set_condition
+#undef snd_seq_remove_events_set_queue
+#undef snd_seq_remove_events_set_time
+#undef snd_seq_remove_events_set_dest
+#undef snd_seq_remove_events_set_channel
+#undef snd_seq_remove_events_set_event_type
+#undef snd_seq_remove_events_set_tag
+#undef snd_seq_remove_events
+#undef snd_seq_set_bit
+#undef snd_seq_unset_bit
+#undef snd_seq_change_bit
+#undef snd_seq_get_bit
+#undef snd_seq_control_queue
+#undef snd_seq_create_simple_port
+#undef snd_seq_delete_simple_port
+#undef snd_seq_connect_from
+#undef snd_seq_connect_to
+#undef snd_seq_disconnect_from
+#undef snd_seq_disconnect_to
+#undef snd_seq_set_client_name
+#undef snd_seq_set_client_event_filter
+#undef snd_seq_set_client_pool_output
+#undef snd_seq_set_client_pool_output_room
+#undef snd_seq_set_client_pool_input
+#undef snd_seq_sync_output_queue
+#undef snd_seq_parse_address
+#undef snd_seq_reset_pool_output
+#undef snd_seq_reset_pool_input
+#undef snd_midi_event_new
+#undef snd_midi_event_resize_buffer
+#undef snd_midi_event_free
+#undef snd_midi_event_init
+#undef snd_midi_event_reset_encode
+#undef snd_midi_event_reset_decode
+#undef snd_midi_event_no_status
+#undef snd_midi_event_encode
+#undef snd_midi_event_encode_byte
+#undef snd_midi_event_decode
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define snd_asoundlib_version snd_asoundlib_version_dylibloader_wrapper_asound
+#define snd_dlpath snd_dlpath_dylibloader_wrapper_asound
+#define snd_dlopen snd_dlopen_dylibloader_wrapper_asound
+#define snd_dlsym snd_dlsym_dylibloader_wrapper_asound
+#define snd_dlclose snd_dlclose_dylibloader_wrapper_asound
+#define snd_async_add_handler snd_async_add_handler_dylibloader_wrapper_asound
+#define snd_async_del_handler snd_async_del_handler_dylibloader_wrapper_asound
+#define snd_async_handler_get_fd snd_async_handler_get_fd_dylibloader_wrapper_asound
+#define snd_async_handler_get_signo snd_async_handler_get_signo_dylibloader_wrapper_asound
+#define snd_async_handler_get_callback_private snd_async_handler_get_callback_private_dylibloader_wrapper_asound
+#define snd_shm_area_create snd_shm_area_create_dylibloader_wrapper_asound
+#define snd_shm_area_share snd_shm_area_share_dylibloader_wrapper_asound
+#define snd_shm_area_destroy snd_shm_area_destroy_dylibloader_wrapper_asound
+#define snd_user_file snd_user_file_dylibloader_wrapper_asound
+#define snd_input_stdio_open snd_input_stdio_open_dylibloader_wrapper_asound
+#define snd_input_stdio_attach snd_input_stdio_attach_dylibloader_wrapper_asound
+#define snd_input_buffer_open snd_input_buffer_open_dylibloader_wrapper_asound
+#define snd_input_close snd_input_close_dylibloader_wrapper_asound
+#define snd_input_scanf snd_input_scanf_dylibloader_wrapper_asound
+#define snd_input_gets snd_input_gets_dylibloader_wrapper_asound
+#define snd_input_getc snd_input_getc_dylibloader_wrapper_asound
+#define snd_input_ungetc snd_input_ungetc_dylibloader_wrapper_asound
+#define snd_output_stdio_open snd_output_stdio_open_dylibloader_wrapper_asound
+#define snd_output_stdio_attach snd_output_stdio_attach_dylibloader_wrapper_asound
+#define snd_output_buffer_open snd_output_buffer_open_dylibloader_wrapper_asound
+#define snd_output_buffer_string snd_output_buffer_string_dylibloader_wrapper_asound
+#define snd_output_close snd_output_close_dylibloader_wrapper_asound
+#define snd_output_printf snd_output_printf_dylibloader_wrapper_asound
+#define snd_output_vprintf snd_output_vprintf_dylibloader_wrapper_asound
+#define snd_output_puts snd_output_puts_dylibloader_wrapper_asound
+#define snd_output_putc snd_output_putc_dylibloader_wrapper_asound
+#define snd_output_flush snd_output_flush_dylibloader_wrapper_asound
+#define snd_strerror snd_strerror_dylibloader_wrapper_asound
+#define snd_lib_error_set_handler snd_lib_error_set_handler_dylibloader_wrapper_asound
+#define snd_lib_error_set_local snd_lib_error_set_local_dylibloader_wrapper_asound
+#define snd_config_topdir snd_config_topdir_dylibloader_wrapper_asound
+#define snd_config_top snd_config_top_dylibloader_wrapper_asound
+#define snd_config_load snd_config_load_dylibloader_wrapper_asound
+#define snd_config_load_override snd_config_load_override_dylibloader_wrapper_asound
+#define snd_config_save snd_config_save_dylibloader_wrapper_asound
+#define snd_config_update snd_config_update_dylibloader_wrapper_asound
+#define snd_config_update_r snd_config_update_r_dylibloader_wrapper_asound
+#define snd_config_update_free snd_config_update_free_dylibloader_wrapper_asound
+#define snd_config_update_free_global snd_config_update_free_global_dylibloader_wrapper_asound
+#define snd_config_update_ref snd_config_update_ref_dylibloader_wrapper_asound
+#define snd_config_ref snd_config_ref_dylibloader_wrapper_asound
+#define snd_config_unref snd_config_unref_dylibloader_wrapper_asound
+#define snd_config_search snd_config_search_dylibloader_wrapper_asound
+#define snd_config_searchv snd_config_searchv_dylibloader_wrapper_asound
+#define snd_config_search_definition snd_config_search_definition_dylibloader_wrapper_asound
+#define snd_config_expand snd_config_expand_dylibloader_wrapper_asound
+#define snd_config_evaluate snd_config_evaluate_dylibloader_wrapper_asound
+#define snd_config_add snd_config_add_dylibloader_wrapper_asound
+#define snd_config_add_before snd_config_add_before_dylibloader_wrapper_asound
+#define snd_config_add_after snd_config_add_after_dylibloader_wrapper_asound
+#define snd_config_remove snd_config_remove_dylibloader_wrapper_asound
+#define snd_config_delete snd_config_delete_dylibloader_wrapper_asound
+#define snd_config_delete_compound_members snd_config_delete_compound_members_dylibloader_wrapper_asound
+#define snd_config_copy snd_config_copy_dylibloader_wrapper_asound
+#define snd_config_make snd_config_make_dylibloader_wrapper_asound
+#define snd_config_make_integer snd_config_make_integer_dylibloader_wrapper_asound
+#define snd_config_make_integer64 snd_config_make_integer64_dylibloader_wrapper_asound
+#define snd_config_make_real snd_config_make_real_dylibloader_wrapper_asound
+#define snd_config_make_string snd_config_make_string_dylibloader_wrapper_asound
+#define snd_config_make_pointer snd_config_make_pointer_dylibloader_wrapper_asound
+#define snd_config_make_compound snd_config_make_compound_dylibloader_wrapper_asound
+#define snd_config_imake_integer snd_config_imake_integer_dylibloader_wrapper_asound
+#define snd_config_imake_integer64 snd_config_imake_integer64_dylibloader_wrapper_asound
+#define snd_config_imake_real snd_config_imake_real_dylibloader_wrapper_asound
+#define snd_config_imake_string snd_config_imake_string_dylibloader_wrapper_asound
+#define snd_config_imake_safe_string snd_config_imake_safe_string_dylibloader_wrapper_asound
+#define snd_config_imake_pointer snd_config_imake_pointer_dylibloader_wrapper_asound
+#define snd_config_get_type snd_config_get_type_dylibloader_wrapper_asound
+#define snd_config_is_array snd_config_is_array_dylibloader_wrapper_asound
+#define snd_config_set_id snd_config_set_id_dylibloader_wrapper_asound
+#define snd_config_set_integer snd_config_set_integer_dylibloader_wrapper_asound
+#define snd_config_set_integer64 snd_config_set_integer64_dylibloader_wrapper_asound
+#define snd_config_set_real snd_config_set_real_dylibloader_wrapper_asound
+#define snd_config_set_string snd_config_set_string_dylibloader_wrapper_asound
+#define snd_config_set_ascii snd_config_set_ascii_dylibloader_wrapper_asound
+#define snd_config_set_pointer snd_config_set_pointer_dylibloader_wrapper_asound
+#define snd_config_get_id snd_config_get_id_dylibloader_wrapper_asound
+#define snd_config_get_integer snd_config_get_integer_dylibloader_wrapper_asound
+#define snd_config_get_integer64 snd_config_get_integer64_dylibloader_wrapper_asound
+#define snd_config_get_real snd_config_get_real_dylibloader_wrapper_asound
+#define snd_config_get_ireal snd_config_get_ireal_dylibloader_wrapper_asound
+#define snd_config_get_string snd_config_get_string_dylibloader_wrapper_asound
+#define snd_config_get_ascii snd_config_get_ascii_dylibloader_wrapper_asound
+#define snd_config_get_pointer snd_config_get_pointer_dylibloader_wrapper_asound
+#define snd_config_test_id snd_config_test_id_dylibloader_wrapper_asound
+#define snd_config_iterator_first snd_config_iterator_first_dylibloader_wrapper_asound
+#define snd_config_iterator_next snd_config_iterator_next_dylibloader_wrapper_asound
+#define snd_config_iterator_end snd_config_iterator_end_dylibloader_wrapper_asound
+#define snd_config_iterator_entry snd_config_iterator_entry_dylibloader_wrapper_asound
+#define snd_config_get_bool_ascii snd_config_get_bool_ascii_dylibloader_wrapper_asound
+#define snd_config_get_bool snd_config_get_bool_dylibloader_wrapper_asound
+#define snd_config_get_ctl_iface_ascii snd_config_get_ctl_iface_ascii_dylibloader_wrapper_asound
+#define snd_config_get_ctl_iface snd_config_get_ctl_iface_dylibloader_wrapper_asound
+#define snd_names_list snd_names_list_dylibloader_wrapper_asound
+#define snd_names_list_free snd_names_list_free_dylibloader_wrapper_asound
+#define snd_pcm_open snd_pcm_open_dylibloader_wrapper_asound
+#define snd_pcm_open_lconf snd_pcm_open_lconf_dylibloader_wrapper_asound
+#define snd_pcm_open_fallback snd_pcm_open_fallback_dylibloader_wrapper_asound
+#define snd_pcm_close snd_pcm_close_dylibloader_wrapper_asound
+#define snd_pcm_name snd_pcm_name_dylibloader_wrapper_asound
+#define snd_pcm_type snd_pcm_type_dylibloader_wrapper_asound
+#define snd_pcm_stream snd_pcm_stream_dylibloader_wrapper_asound
+#define snd_pcm_poll_descriptors_count snd_pcm_poll_descriptors_count_dylibloader_wrapper_asound
+#define snd_pcm_poll_descriptors snd_pcm_poll_descriptors_dylibloader_wrapper_asound
+#define snd_pcm_poll_descriptors_revents snd_pcm_poll_descriptors_revents_dylibloader_wrapper_asound
+#define snd_pcm_nonblock snd_pcm_nonblock_dylibloader_wrapper_asound
+#define snd_async_add_pcm_handler snd_async_add_pcm_handler_dylibloader_wrapper_asound
+#define snd_async_handler_get_pcm snd_async_handler_get_pcm_dylibloader_wrapper_asound
+#define snd_pcm_info snd_pcm_info_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_current snd_pcm_hw_params_current_dylibloader_wrapper_asound
+#define snd_pcm_hw_params snd_pcm_hw_params_dylibloader_wrapper_asound
+#define snd_pcm_hw_free snd_pcm_hw_free_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_current snd_pcm_sw_params_current_dylibloader_wrapper_asound
+#define snd_pcm_sw_params snd_pcm_sw_params_dylibloader_wrapper_asound
+#define snd_pcm_prepare snd_pcm_prepare_dylibloader_wrapper_asound
+#define snd_pcm_reset snd_pcm_reset_dylibloader_wrapper_asound
+#define snd_pcm_status snd_pcm_status_dylibloader_wrapper_asound
+#define snd_pcm_start snd_pcm_start_dylibloader_wrapper_asound
+#define snd_pcm_drop snd_pcm_drop_dylibloader_wrapper_asound
+#define snd_pcm_drain snd_pcm_drain_dylibloader_wrapper_asound
+#define snd_pcm_pause snd_pcm_pause_dylibloader_wrapper_asound
+#define snd_pcm_state snd_pcm_state_dylibloader_wrapper_asound
+#define snd_pcm_hwsync snd_pcm_hwsync_dylibloader_wrapper_asound
+#define snd_pcm_delay snd_pcm_delay_dylibloader_wrapper_asound
+#define snd_pcm_resume snd_pcm_resume_dylibloader_wrapper_asound
+#define snd_pcm_htimestamp snd_pcm_htimestamp_dylibloader_wrapper_asound
+#define snd_pcm_avail snd_pcm_avail_dylibloader_wrapper_asound
+#define snd_pcm_avail_update snd_pcm_avail_update_dylibloader_wrapper_asound
+#define snd_pcm_avail_delay snd_pcm_avail_delay_dylibloader_wrapper_asound
+#define snd_pcm_rewindable snd_pcm_rewindable_dylibloader_wrapper_asound
+#define snd_pcm_rewind snd_pcm_rewind_dylibloader_wrapper_asound
+#define snd_pcm_forwardable snd_pcm_forwardable_dylibloader_wrapper_asound
+#define snd_pcm_forward snd_pcm_forward_dylibloader_wrapper_asound
+#define snd_pcm_writei snd_pcm_writei_dylibloader_wrapper_asound
+#define snd_pcm_readi snd_pcm_readi_dylibloader_wrapper_asound
+#define snd_pcm_writen snd_pcm_writen_dylibloader_wrapper_asound
+#define snd_pcm_readn snd_pcm_readn_dylibloader_wrapper_asound
+#define snd_pcm_wait snd_pcm_wait_dylibloader_wrapper_asound
+#define snd_pcm_link snd_pcm_link_dylibloader_wrapper_asound
+#define snd_pcm_unlink snd_pcm_unlink_dylibloader_wrapper_asound
+#define snd_pcm_query_chmaps snd_pcm_query_chmaps_dylibloader_wrapper_asound
+#define snd_pcm_query_chmaps_from_hw snd_pcm_query_chmaps_from_hw_dylibloader_wrapper_asound
+#define snd_pcm_free_chmaps snd_pcm_free_chmaps_dylibloader_wrapper_asound
+#define snd_pcm_get_chmap snd_pcm_get_chmap_dylibloader_wrapper_asound
+#define snd_pcm_set_chmap snd_pcm_set_chmap_dylibloader_wrapper_asound
+#define snd_pcm_chmap_type_name snd_pcm_chmap_type_name_dylibloader_wrapper_asound
+#define snd_pcm_chmap_name snd_pcm_chmap_name_dylibloader_wrapper_asound
+#define snd_pcm_chmap_long_name snd_pcm_chmap_long_name_dylibloader_wrapper_asound
+#define snd_pcm_chmap_print snd_pcm_chmap_print_dylibloader_wrapper_asound
+#define snd_pcm_chmap_from_string snd_pcm_chmap_from_string_dylibloader_wrapper_asound
+#define snd_pcm_chmap_parse_string snd_pcm_chmap_parse_string_dylibloader_wrapper_asound
+#define snd_pcm_recover snd_pcm_recover_dylibloader_wrapper_asound
+#define snd_pcm_set_params snd_pcm_set_params_dylibloader_wrapper_asound
+#define snd_pcm_get_params snd_pcm_get_params_dylibloader_wrapper_asound
+#define snd_pcm_info_sizeof snd_pcm_info_sizeof_dylibloader_wrapper_asound
+#define snd_pcm_info_malloc snd_pcm_info_malloc_dylibloader_wrapper_asound
+#define snd_pcm_info_free snd_pcm_info_free_dylibloader_wrapper_asound
+#define snd_pcm_info_copy snd_pcm_info_copy_dylibloader_wrapper_asound
+#define snd_pcm_info_get_device snd_pcm_info_get_device_dylibloader_wrapper_asound
+#define snd_pcm_info_get_subdevice snd_pcm_info_get_subdevice_dylibloader_wrapper_asound
+#define snd_pcm_info_get_stream snd_pcm_info_get_stream_dylibloader_wrapper_asound
+#define snd_pcm_info_get_card snd_pcm_info_get_card_dylibloader_wrapper_asound
+#define snd_pcm_info_get_id snd_pcm_info_get_id_dylibloader_wrapper_asound
+#define snd_pcm_info_get_name snd_pcm_info_get_name_dylibloader_wrapper_asound
+#define snd_pcm_info_get_subdevice_name snd_pcm_info_get_subdevice_name_dylibloader_wrapper_asound
+#define snd_pcm_info_get_class snd_pcm_info_get_class_dylibloader_wrapper_asound
+#define snd_pcm_info_get_subclass snd_pcm_info_get_subclass_dylibloader_wrapper_asound
+#define snd_pcm_info_get_subdevices_count snd_pcm_info_get_subdevices_count_dylibloader_wrapper_asound
+#define snd_pcm_info_get_subdevices_avail snd_pcm_info_get_subdevices_avail_dylibloader_wrapper_asound
+#define snd_pcm_info_get_sync snd_pcm_info_get_sync_dylibloader_wrapper_asound
+#define snd_pcm_info_set_device snd_pcm_info_set_device_dylibloader_wrapper_asound
+#define snd_pcm_info_set_subdevice snd_pcm_info_set_subdevice_dylibloader_wrapper_asound
+#define snd_pcm_info_set_stream snd_pcm_info_set_stream_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_any snd_pcm_hw_params_any_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_can_mmap_sample_resolution snd_pcm_hw_params_can_mmap_sample_resolution_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_is_double snd_pcm_hw_params_is_double_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_is_batch snd_pcm_hw_params_is_batch_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_is_block_transfer snd_pcm_hw_params_is_block_transfer_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_is_monotonic snd_pcm_hw_params_is_monotonic_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_can_overrange snd_pcm_hw_params_can_overrange_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_can_pause snd_pcm_hw_params_can_pause_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_can_resume snd_pcm_hw_params_can_resume_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_is_half_duplex snd_pcm_hw_params_is_half_duplex_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_is_joint_duplex snd_pcm_hw_params_is_joint_duplex_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_can_sync_start snd_pcm_hw_params_can_sync_start_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_can_disable_period_wakeup snd_pcm_hw_params_can_disable_period_wakeup_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_supports_audio_wallclock_ts snd_pcm_hw_params_supports_audio_wallclock_ts_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_supports_audio_ts_type snd_pcm_hw_params_supports_audio_ts_type_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_rate_numden snd_pcm_hw_params_get_rate_numden_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_sbits snd_pcm_hw_params_get_sbits_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_fifo_size snd_pcm_hw_params_get_fifo_size_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_sizeof snd_pcm_hw_params_sizeof_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_malloc snd_pcm_hw_params_malloc_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_free snd_pcm_hw_params_free_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_copy snd_pcm_hw_params_copy_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_access snd_pcm_hw_params_get_access_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_test_access snd_pcm_hw_params_test_access_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_access snd_pcm_hw_params_set_access_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_access_first snd_pcm_hw_params_set_access_first_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_access_last snd_pcm_hw_params_set_access_last_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_access_mask snd_pcm_hw_params_set_access_mask_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_access_mask snd_pcm_hw_params_get_access_mask_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_format snd_pcm_hw_params_get_format_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_test_format snd_pcm_hw_params_test_format_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_format snd_pcm_hw_params_set_format_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_format_first snd_pcm_hw_params_set_format_first_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_format_last snd_pcm_hw_params_set_format_last_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_format_mask snd_pcm_hw_params_set_format_mask_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_format_mask snd_pcm_hw_params_get_format_mask_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_subformat snd_pcm_hw_params_get_subformat_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_test_subformat snd_pcm_hw_params_test_subformat_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_subformat snd_pcm_hw_params_set_subformat_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_subformat_first snd_pcm_hw_params_set_subformat_first_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_subformat_last snd_pcm_hw_params_set_subformat_last_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_subformat_mask snd_pcm_hw_params_set_subformat_mask_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_subformat_mask snd_pcm_hw_params_get_subformat_mask_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_channels snd_pcm_hw_params_get_channels_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_channels_min snd_pcm_hw_params_get_channels_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_channels_max snd_pcm_hw_params_get_channels_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_test_channels snd_pcm_hw_params_test_channels_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_channels snd_pcm_hw_params_set_channels_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_channels_min snd_pcm_hw_params_set_channels_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_channels_max snd_pcm_hw_params_set_channels_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_channels_minmax snd_pcm_hw_params_set_channels_minmax_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_channels_near snd_pcm_hw_params_set_channels_near_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_channels_first snd_pcm_hw_params_set_channels_first_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_channels_last snd_pcm_hw_params_set_channels_last_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_rate snd_pcm_hw_params_get_rate_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_rate_min snd_pcm_hw_params_get_rate_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_rate_max snd_pcm_hw_params_get_rate_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_test_rate snd_pcm_hw_params_test_rate_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_rate snd_pcm_hw_params_set_rate_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_rate_min snd_pcm_hw_params_set_rate_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_rate_max snd_pcm_hw_params_set_rate_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_rate_minmax snd_pcm_hw_params_set_rate_minmax_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_rate_near snd_pcm_hw_params_set_rate_near_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_rate_first snd_pcm_hw_params_set_rate_first_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_rate_last snd_pcm_hw_params_set_rate_last_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_rate_resample snd_pcm_hw_params_set_rate_resample_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_rate_resample snd_pcm_hw_params_get_rate_resample_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_export_buffer snd_pcm_hw_params_set_export_buffer_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_export_buffer snd_pcm_hw_params_get_export_buffer_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_wakeup snd_pcm_hw_params_set_period_wakeup_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_period_wakeup snd_pcm_hw_params_get_period_wakeup_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_period_time snd_pcm_hw_params_get_period_time_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_period_time_min snd_pcm_hw_params_get_period_time_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_period_time_max snd_pcm_hw_params_get_period_time_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_test_period_time snd_pcm_hw_params_test_period_time_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_time snd_pcm_hw_params_set_period_time_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_time_min snd_pcm_hw_params_set_period_time_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_time_max snd_pcm_hw_params_set_period_time_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_time_minmax snd_pcm_hw_params_set_period_time_minmax_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_time_near snd_pcm_hw_params_set_period_time_near_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_time_first snd_pcm_hw_params_set_period_time_first_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_time_last snd_pcm_hw_params_set_period_time_last_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_period_size snd_pcm_hw_params_get_period_size_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_period_size_min snd_pcm_hw_params_get_period_size_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_period_size_max snd_pcm_hw_params_get_period_size_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_test_period_size snd_pcm_hw_params_test_period_size_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_size snd_pcm_hw_params_set_period_size_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_size_min snd_pcm_hw_params_set_period_size_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_size_max snd_pcm_hw_params_set_period_size_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_size_minmax snd_pcm_hw_params_set_period_size_minmax_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_size_near snd_pcm_hw_params_set_period_size_near_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_size_first snd_pcm_hw_params_set_period_size_first_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_size_last snd_pcm_hw_params_set_period_size_last_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_period_size_integer snd_pcm_hw_params_set_period_size_integer_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_periods snd_pcm_hw_params_get_periods_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_periods_min snd_pcm_hw_params_get_periods_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_periods_max snd_pcm_hw_params_get_periods_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_test_periods snd_pcm_hw_params_test_periods_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_periods snd_pcm_hw_params_set_periods_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_periods_min snd_pcm_hw_params_set_periods_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_periods_max snd_pcm_hw_params_set_periods_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_periods_minmax snd_pcm_hw_params_set_periods_minmax_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_periods_near snd_pcm_hw_params_set_periods_near_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_periods_first snd_pcm_hw_params_set_periods_first_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_periods_last snd_pcm_hw_params_set_periods_last_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_periods_integer snd_pcm_hw_params_set_periods_integer_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_buffer_time snd_pcm_hw_params_get_buffer_time_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_buffer_time_min snd_pcm_hw_params_get_buffer_time_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_buffer_time_max snd_pcm_hw_params_get_buffer_time_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_test_buffer_time snd_pcm_hw_params_test_buffer_time_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_time snd_pcm_hw_params_set_buffer_time_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_time_min snd_pcm_hw_params_set_buffer_time_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_time_max snd_pcm_hw_params_set_buffer_time_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_time_minmax snd_pcm_hw_params_set_buffer_time_minmax_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_time_near snd_pcm_hw_params_set_buffer_time_near_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_time_first snd_pcm_hw_params_set_buffer_time_first_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_time_last snd_pcm_hw_params_set_buffer_time_last_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_buffer_size snd_pcm_hw_params_get_buffer_size_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_buffer_size_min snd_pcm_hw_params_get_buffer_size_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_buffer_size_max snd_pcm_hw_params_get_buffer_size_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_test_buffer_size snd_pcm_hw_params_test_buffer_size_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_size snd_pcm_hw_params_set_buffer_size_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_size_min snd_pcm_hw_params_set_buffer_size_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_size_max snd_pcm_hw_params_set_buffer_size_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_size_minmax snd_pcm_hw_params_set_buffer_size_minmax_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_size_near snd_pcm_hw_params_set_buffer_size_near_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_size_first snd_pcm_hw_params_set_buffer_size_first_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_buffer_size_last snd_pcm_hw_params_set_buffer_size_last_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_min_align snd_pcm_hw_params_get_min_align_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_sizeof snd_pcm_sw_params_sizeof_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_malloc snd_pcm_sw_params_malloc_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_free snd_pcm_sw_params_free_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_copy snd_pcm_sw_params_copy_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_boundary snd_pcm_sw_params_get_boundary_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_set_tstamp_mode snd_pcm_sw_params_set_tstamp_mode_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_tstamp_mode snd_pcm_sw_params_get_tstamp_mode_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_set_avail_min snd_pcm_sw_params_set_avail_min_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_avail_min snd_pcm_sw_params_get_avail_min_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_set_period_event snd_pcm_sw_params_set_period_event_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_period_event snd_pcm_sw_params_get_period_event_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_set_start_threshold snd_pcm_sw_params_set_start_threshold_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_start_threshold snd_pcm_sw_params_get_start_threshold_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_set_stop_threshold snd_pcm_sw_params_set_stop_threshold_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_stop_threshold snd_pcm_sw_params_get_stop_threshold_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_set_silence_threshold snd_pcm_sw_params_set_silence_threshold_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_silence_threshold snd_pcm_sw_params_get_silence_threshold_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_set_silence_size snd_pcm_sw_params_set_silence_size_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_silence_size snd_pcm_sw_params_get_silence_size_dylibloader_wrapper_asound
+#define snd_pcm_access_mask_sizeof snd_pcm_access_mask_sizeof_dylibloader_wrapper_asound
+#define snd_pcm_access_mask_malloc snd_pcm_access_mask_malloc_dylibloader_wrapper_asound
+#define snd_pcm_access_mask_free snd_pcm_access_mask_free_dylibloader_wrapper_asound
+#define snd_pcm_access_mask_copy snd_pcm_access_mask_copy_dylibloader_wrapper_asound
+#define snd_pcm_access_mask_none snd_pcm_access_mask_none_dylibloader_wrapper_asound
+#define snd_pcm_access_mask_any snd_pcm_access_mask_any_dylibloader_wrapper_asound
+#define snd_pcm_access_mask_test snd_pcm_access_mask_test_dylibloader_wrapper_asound
+#define snd_pcm_access_mask_empty snd_pcm_access_mask_empty_dylibloader_wrapper_asound
+#define snd_pcm_access_mask_set snd_pcm_access_mask_set_dylibloader_wrapper_asound
+#define snd_pcm_access_mask_reset snd_pcm_access_mask_reset_dylibloader_wrapper_asound
+#define snd_pcm_format_mask_sizeof snd_pcm_format_mask_sizeof_dylibloader_wrapper_asound
+#define snd_pcm_format_mask_malloc snd_pcm_format_mask_malloc_dylibloader_wrapper_asound
+#define snd_pcm_format_mask_free snd_pcm_format_mask_free_dylibloader_wrapper_asound
+#define snd_pcm_format_mask_copy snd_pcm_format_mask_copy_dylibloader_wrapper_asound
+#define snd_pcm_format_mask_none snd_pcm_format_mask_none_dylibloader_wrapper_asound
+#define snd_pcm_format_mask_any snd_pcm_format_mask_any_dylibloader_wrapper_asound
+#define snd_pcm_format_mask_test snd_pcm_format_mask_test_dylibloader_wrapper_asound
+#define snd_pcm_format_mask_empty snd_pcm_format_mask_empty_dylibloader_wrapper_asound
+#define snd_pcm_format_mask_set snd_pcm_format_mask_set_dylibloader_wrapper_asound
+#define snd_pcm_format_mask_reset snd_pcm_format_mask_reset_dylibloader_wrapper_asound
+#define snd_pcm_subformat_mask_sizeof snd_pcm_subformat_mask_sizeof_dylibloader_wrapper_asound
+#define snd_pcm_subformat_mask_malloc snd_pcm_subformat_mask_malloc_dylibloader_wrapper_asound
+#define snd_pcm_subformat_mask_free snd_pcm_subformat_mask_free_dylibloader_wrapper_asound
+#define snd_pcm_subformat_mask_copy snd_pcm_subformat_mask_copy_dylibloader_wrapper_asound
+#define snd_pcm_subformat_mask_none snd_pcm_subformat_mask_none_dylibloader_wrapper_asound
+#define snd_pcm_subformat_mask_any snd_pcm_subformat_mask_any_dylibloader_wrapper_asound
+#define snd_pcm_subformat_mask_test snd_pcm_subformat_mask_test_dylibloader_wrapper_asound
+#define snd_pcm_subformat_mask_empty snd_pcm_subformat_mask_empty_dylibloader_wrapper_asound
+#define snd_pcm_subformat_mask_set snd_pcm_subformat_mask_set_dylibloader_wrapper_asound
+#define snd_pcm_subformat_mask_reset snd_pcm_subformat_mask_reset_dylibloader_wrapper_asound
+#define snd_pcm_status_sizeof snd_pcm_status_sizeof_dylibloader_wrapper_asound
+#define snd_pcm_status_malloc snd_pcm_status_malloc_dylibloader_wrapper_asound
+#define snd_pcm_status_free snd_pcm_status_free_dylibloader_wrapper_asound
+#define snd_pcm_status_copy snd_pcm_status_copy_dylibloader_wrapper_asound
+#define snd_pcm_status_get_state snd_pcm_status_get_state_dylibloader_wrapper_asound
+#define snd_pcm_status_get_trigger_tstamp snd_pcm_status_get_trigger_tstamp_dylibloader_wrapper_asound
+#define snd_pcm_status_get_trigger_htstamp snd_pcm_status_get_trigger_htstamp_dylibloader_wrapper_asound
+#define snd_pcm_status_get_tstamp snd_pcm_status_get_tstamp_dylibloader_wrapper_asound
+#define snd_pcm_status_get_htstamp snd_pcm_status_get_htstamp_dylibloader_wrapper_asound
+#define snd_pcm_status_get_audio_htstamp snd_pcm_status_get_audio_htstamp_dylibloader_wrapper_asound
+#define snd_pcm_status_get_driver_htstamp snd_pcm_status_get_driver_htstamp_dylibloader_wrapper_asound
+#define snd_pcm_status_get_delay snd_pcm_status_get_delay_dylibloader_wrapper_asound
+#define snd_pcm_status_get_avail snd_pcm_status_get_avail_dylibloader_wrapper_asound
+#define snd_pcm_status_get_avail_max snd_pcm_status_get_avail_max_dylibloader_wrapper_asound
+#define snd_pcm_status_get_overrange snd_pcm_status_get_overrange_dylibloader_wrapper_asound
+#define snd_pcm_type_name snd_pcm_type_name_dylibloader_wrapper_asound
+#define snd_pcm_stream_name snd_pcm_stream_name_dylibloader_wrapper_asound
+#define snd_pcm_access_name snd_pcm_access_name_dylibloader_wrapper_asound
+#define snd_pcm_format_name snd_pcm_format_name_dylibloader_wrapper_asound
+#define snd_pcm_format_description snd_pcm_format_description_dylibloader_wrapper_asound
+#define snd_pcm_subformat_name snd_pcm_subformat_name_dylibloader_wrapper_asound
+#define snd_pcm_subformat_description snd_pcm_subformat_description_dylibloader_wrapper_asound
+#define snd_pcm_format_value snd_pcm_format_value_dylibloader_wrapper_asound
+#define snd_pcm_tstamp_mode_name snd_pcm_tstamp_mode_name_dylibloader_wrapper_asound
+#define snd_pcm_state_name snd_pcm_state_name_dylibloader_wrapper_asound
+#define snd_pcm_dump snd_pcm_dump_dylibloader_wrapper_asound
+#define snd_pcm_dump_hw_setup snd_pcm_dump_hw_setup_dylibloader_wrapper_asound
+#define snd_pcm_dump_sw_setup snd_pcm_dump_sw_setup_dylibloader_wrapper_asound
+#define snd_pcm_dump_setup snd_pcm_dump_setup_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_dump snd_pcm_hw_params_dump_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_dump snd_pcm_sw_params_dump_dylibloader_wrapper_asound
+#define snd_pcm_status_dump snd_pcm_status_dump_dylibloader_wrapper_asound
+#define snd_pcm_mmap_begin snd_pcm_mmap_begin_dylibloader_wrapper_asound
+#define snd_pcm_mmap_commit snd_pcm_mmap_commit_dylibloader_wrapper_asound
+#define snd_pcm_mmap_writei snd_pcm_mmap_writei_dylibloader_wrapper_asound
+#define snd_pcm_mmap_readi snd_pcm_mmap_readi_dylibloader_wrapper_asound
+#define snd_pcm_mmap_writen snd_pcm_mmap_writen_dylibloader_wrapper_asound
+#define snd_pcm_mmap_readn snd_pcm_mmap_readn_dylibloader_wrapper_asound
+#define snd_pcm_format_signed snd_pcm_format_signed_dylibloader_wrapper_asound
+#define snd_pcm_format_unsigned snd_pcm_format_unsigned_dylibloader_wrapper_asound
+#define snd_pcm_format_linear snd_pcm_format_linear_dylibloader_wrapper_asound
+#define snd_pcm_format_float snd_pcm_format_float_dylibloader_wrapper_asound
+#define snd_pcm_format_little_endian snd_pcm_format_little_endian_dylibloader_wrapper_asound
+#define snd_pcm_format_big_endian snd_pcm_format_big_endian_dylibloader_wrapper_asound
+#define snd_pcm_format_cpu_endian snd_pcm_format_cpu_endian_dylibloader_wrapper_asound
+#define snd_pcm_format_width snd_pcm_format_width_dylibloader_wrapper_asound
+#define snd_pcm_format_physical_width snd_pcm_format_physical_width_dylibloader_wrapper_asound
+#define snd_pcm_build_linear_format snd_pcm_build_linear_format_dylibloader_wrapper_asound
+#define snd_pcm_format_size snd_pcm_format_size_dylibloader_wrapper_asound
+#define snd_pcm_format_silence snd_pcm_format_silence_dylibloader_wrapper_asound
+#define snd_pcm_format_silence_16 snd_pcm_format_silence_16_dylibloader_wrapper_asound
+#define snd_pcm_format_silence_32 snd_pcm_format_silence_32_dylibloader_wrapper_asound
+#define snd_pcm_format_silence_64 snd_pcm_format_silence_64_dylibloader_wrapper_asound
+#define snd_pcm_format_set_silence snd_pcm_format_set_silence_dylibloader_wrapper_asound
+#define snd_pcm_bytes_to_frames snd_pcm_bytes_to_frames_dylibloader_wrapper_asound
+#define snd_pcm_frames_to_bytes snd_pcm_frames_to_bytes_dylibloader_wrapper_asound
+#define snd_pcm_bytes_to_samples snd_pcm_bytes_to_samples_dylibloader_wrapper_asound
+#define snd_pcm_samples_to_bytes snd_pcm_samples_to_bytes_dylibloader_wrapper_asound
+#define snd_pcm_area_silence snd_pcm_area_silence_dylibloader_wrapper_asound
+#define snd_pcm_areas_silence snd_pcm_areas_silence_dylibloader_wrapper_asound
+#define snd_pcm_area_copy snd_pcm_area_copy_dylibloader_wrapper_asound
+#define snd_pcm_areas_copy snd_pcm_areas_copy_dylibloader_wrapper_asound
+#define snd_pcm_areas_copy_wrap snd_pcm_areas_copy_wrap_dylibloader_wrapper_asound
+#define snd_pcm_hook_get_pcm snd_pcm_hook_get_pcm_dylibloader_wrapper_asound
+#define snd_pcm_hook_get_private snd_pcm_hook_get_private_dylibloader_wrapper_asound
+#define snd_pcm_hook_set_private snd_pcm_hook_set_private_dylibloader_wrapper_asound
+#define snd_pcm_hook_add snd_pcm_hook_add_dylibloader_wrapper_asound
+#define snd_pcm_hook_remove snd_pcm_hook_remove_dylibloader_wrapper_asound
+#define snd_pcm_meter_get_bufsize snd_pcm_meter_get_bufsize_dylibloader_wrapper_asound
+#define snd_pcm_meter_get_channels snd_pcm_meter_get_channels_dylibloader_wrapper_asound
+#define snd_pcm_meter_get_rate snd_pcm_meter_get_rate_dylibloader_wrapper_asound
+#define snd_pcm_meter_get_now snd_pcm_meter_get_now_dylibloader_wrapper_asound
+#define snd_pcm_meter_get_boundary snd_pcm_meter_get_boundary_dylibloader_wrapper_asound
+#define snd_pcm_meter_add_scope snd_pcm_meter_add_scope_dylibloader_wrapper_asound
+#define snd_pcm_meter_search_scope snd_pcm_meter_search_scope_dylibloader_wrapper_asound
+#define snd_pcm_scope_malloc snd_pcm_scope_malloc_dylibloader_wrapper_asound
+#define snd_pcm_scope_set_ops snd_pcm_scope_set_ops_dylibloader_wrapper_asound
+#define snd_pcm_scope_set_name snd_pcm_scope_set_name_dylibloader_wrapper_asound
+#define snd_pcm_scope_get_name snd_pcm_scope_get_name_dylibloader_wrapper_asound
+#define snd_pcm_scope_get_callback_private snd_pcm_scope_get_callback_private_dylibloader_wrapper_asound
+#define snd_pcm_scope_set_callback_private snd_pcm_scope_set_callback_private_dylibloader_wrapper_asound
+#define snd_pcm_scope_s16_open snd_pcm_scope_s16_open_dylibloader_wrapper_asound
+#define snd_pcm_scope_s16_get_channel_buffer snd_pcm_scope_s16_get_channel_buffer_dylibloader_wrapper_asound
+#define snd_spcm_init snd_spcm_init_dylibloader_wrapper_asound
+#define snd_spcm_init_duplex snd_spcm_init_duplex_dylibloader_wrapper_asound
+#define snd_spcm_init_get_params snd_spcm_init_get_params_dylibloader_wrapper_asound
+#define snd_pcm_start_mode_name snd_pcm_start_mode_name_dylibloader_wrapper_asound
+#define snd_pcm_xrun_mode_name snd_pcm_xrun_mode_name_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_set_start_mode snd_pcm_sw_params_set_start_mode_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_start_mode snd_pcm_sw_params_get_start_mode_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_set_xrun_mode snd_pcm_sw_params_set_xrun_mode_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_xrun_mode snd_pcm_sw_params_get_xrun_mode_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_set_xfer_align snd_pcm_sw_params_set_xfer_align_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_xfer_align snd_pcm_sw_params_get_xfer_align_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_set_sleep_min snd_pcm_sw_params_set_sleep_min_dylibloader_wrapper_asound
+#define snd_pcm_sw_params_get_sleep_min snd_pcm_sw_params_get_sleep_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_tick_time snd_pcm_hw_params_get_tick_time_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_tick_time_min snd_pcm_hw_params_get_tick_time_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_get_tick_time_max snd_pcm_hw_params_get_tick_time_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_test_tick_time snd_pcm_hw_params_test_tick_time_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_tick_time snd_pcm_hw_params_set_tick_time_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_tick_time_min snd_pcm_hw_params_set_tick_time_min_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_tick_time_max snd_pcm_hw_params_set_tick_time_max_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_tick_time_minmax snd_pcm_hw_params_set_tick_time_minmax_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_tick_time_near snd_pcm_hw_params_set_tick_time_near_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_tick_time_first snd_pcm_hw_params_set_tick_time_first_dylibloader_wrapper_asound
+#define snd_pcm_hw_params_set_tick_time_last snd_pcm_hw_params_set_tick_time_last_dylibloader_wrapper_asound
+#define snd_rawmidi_open snd_rawmidi_open_dylibloader_wrapper_asound
+#define snd_rawmidi_open_lconf snd_rawmidi_open_lconf_dylibloader_wrapper_asound
+#define snd_rawmidi_close snd_rawmidi_close_dylibloader_wrapper_asound
+#define snd_rawmidi_poll_descriptors_count snd_rawmidi_poll_descriptors_count_dylibloader_wrapper_asound
+#define snd_rawmidi_poll_descriptors snd_rawmidi_poll_descriptors_dylibloader_wrapper_asound
+#define snd_rawmidi_poll_descriptors_revents snd_rawmidi_poll_descriptors_revents_dylibloader_wrapper_asound
+#define snd_rawmidi_nonblock snd_rawmidi_nonblock_dylibloader_wrapper_asound
+#define snd_rawmidi_info_sizeof snd_rawmidi_info_sizeof_dylibloader_wrapper_asound
+#define snd_rawmidi_info_malloc snd_rawmidi_info_malloc_dylibloader_wrapper_asound
+#define snd_rawmidi_info_free snd_rawmidi_info_free_dylibloader_wrapper_asound
+#define snd_rawmidi_info_copy snd_rawmidi_info_copy_dylibloader_wrapper_asound
+#define snd_rawmidi_info_get_device snd_rawmidi_info_get_device_dylibloader_wrapper_asound
+#define snd_rawmidi_info_get_subdevice snd_rawmidi_info_get_subdevice_dylibloader_wrapper_asound
+#define snd_rawmidi_info_get_stream snd_rawmidi_info_get_stream_dylibloader_wrapper_asound
+#define snd_rawmidi_info_get_card snd_rawmidi_info_get_card_dylibloader_wrapper_asound
+#define snd_rawmidi_info_get_flags snd_rawmidi_info_get_flags_dylibloader_wrapper_asound
+#define snd_rawmidi_info_get_id snd_rawmidi_info_get_id_dylibloader_wrapper_asound
+#define snd_rawmidi_info_get_name snd_rawmidi_info_get_name_dylibloader_wrapper_asound
+#define snd_rawmidi_info_get_subdevice_name snd_rawmidi_info_get_subdevice_name_dylibloader_wrapper_asound
+#define snd_rawmidi_info_get_subdevices_count snd_rawmidi_info_get_subdevices_count_dylibloader_wrapper_asound
+#define snd_rawmidi_info_get_subdevices_avail snd_rawmidi_info_get_subdevices_avail_dylibloader_wrapper_asound
+#define snd_rawmidi_info_set_device snd_rawmidi_info_set_device_dylibloader_wrapper_asound
+#define snd_rawmidi_info_set_subdevice snd_rawmidi_info_set_subdevice_dylibloader_wrapper_asound
+#define snd_rawmidi_info_set_stream snd_rawmidi_info_set_stream_dylibloader_wrapper_asound
+#define snd_rawmidi_info snd_rawmidi_info_dylibloader_wrapper_asound
+#define snd_rawmidi_params_sizeof snd_rawmidi_params_sizeof_dylibloader_wrapper_asound
+#define snd_rawmidi_params_malloc snd_rawmidi_params_malloc_dylibloader_wrapper_asound
+#define snd_rawmidi_params_free snd_rawmidi_params_free_dylibloader_wrapper_asound
+#define snd_rawmidi_params_copy snd_rawmidi_params_copy_dylibloader_wrapper_asound
+#define snd_rawmidi_params_set_buffer_size snd_rawmidi_params_set_buffer_size_dylibloader_wrapper_asound
+#define snd_rawmidi_params_get_buffer_size snd_rawmidi_params_get_buffer_size_dylibloader_wrapper_asound
+#define snd_rawmidi_params_set_avail_min snd_rawmidi_params_set_avail_min_dylibloader_wrapper_asound
+#define snd_rawmidi_params_get_avail_min snd_rawmidi_params_get_avail_min_dylibloader_wrapper_asound
+#define snd_rawmidi_params_set_no_active_sensing snd_rawmidi_params_set_no_active_sensing_dylibloader_wrapper_asound
+#define snd_rawmidi_params_get_no_active_sensing snd_rawmidi_params_get_no_active_sensing_dylibloader_wrapper_asound
+#define snd_rawmidi_params snd_rawmidi_params_dylibloader_wrapper_asound
+#define snd_rawmidi_params_current snd_rawmidi_params_current_dylibloader_wrapper_asound
+#define snd_rawmidi_status_sizeof snd_rawmidi_status_sizeof_dylibloader_wrapper_asound
+#define snd_rawmidi_status_malloc snd_rawmidi_status_malloc_dylibloader_wrapper_asound
+#define snd_rawmidi_status_free snd_rawmidi_status_free_dylibloader_wrapper_asound
+#define snd_rawmidi_status_copy snd_rawmidi_status_copy_dylibloader_wrapper_asound
+#define snd_rawmidi_status_get_tstamp snd_rawmidi_status_get_tstamp_dylibloader_wrapper_asound
+#define snd_rawmidi_status_get_avail snd_rawmidi_status_get_avail_dylibloader_wrapper_asound
+#define snd_rawmidi_status_get_xruns snd_rawmidi_status_get_xruns_dylibloader_wrapper_asound
+#define snd_rawmidi_status snd_rawmidi_status_dylibloader_wrapper_asound
+#define snd_rawmidi_drain snd_rawmidi_drain_dylibloader_wrapper_asound
+#define snd_rawmidi_drop snd_rawmidi_drop_dylibloader_wrapper_asound
+#define snd_rawmidi_write snd_rawmidi_write_dylibloader_wrapper_asound
+#define snd_rawmidi_read snd_rawmidi_read_dylibloader_wrapper_asound
+#define snd_rawmidi_name snd_rawmidi_name_dylibloader_wrapper_asound
+#define snd_rawmidi_type snd_rawmidi_type_dylibloader_wrapper_asound
+#define snd_rawmidi_stream snd_rawmidi_stream_dylibloader_wrapper_asound
+#define snd_timer_query_open snd_timer_query_open_dylibloader_wrapper_asound
+#define snd_timer_query_open_lconf snd_timer_query_open_lconf_dylibloader_wrapper_asound
+#define snd_timer_query_close snd_timer_query_close_dylibloader_wrapper_asound
+#define snd_timer_query_next_device snd_timer_query_next_device_dylibloader_wrapper_asound
+#define snd_timer_query_info snd_timer_query_info_dylibloader_wrapper_asound
+#define snd_timer_query_params snd_timer_query_params_dylibloader_wrapper_asound
+#define snd_timer_query_status snd_timer_query_status_dylibloader_wrapper_asound
+#define snd_timer_open snd_timer_open_dylibloader_wrapper_asound
+#define snd_timer_open_lconf snd_timer_open_lconf_dylibloader_wrapper_asound
+#define snd_timer_close snd_timer_close_dylibloader_wrapper_asound
+#define snd_async_add_timer_handler snd_async_add_timer_handler_dylibloader_wrapper_asound
+#define snd_async_handler_get_timer snd_async_handler_get_timer_dylibloader_wrapper_asound
+#define snd_timer_poll_descriptors_count snd_timer_poll_descriptors_count_dylibloader_wrapper_asound
+#define snd_timer_poll_descriptors snd_timer_poll_descriptors_dylibloader_wrapper_asound
+#define snd_timer_poll_descriptors_revents snd_timer_poll_descriptors_revents_dylibloader_wrapper_asound
+#define snd_timer_info snd_timer_info_dylibloader_wrapper_asound
+#define snd_timer_params snd_timer_params_dylibloader_wrapper_asound
+#define snd_timer_status snd_timer_status_dylibloader_wrapper_asound
+#define snd_timer_start snd_timer_start_dylibloader_wrapper_asound
+#define snd_timer_stop snd_timer_stop_dylibloader_wrapper_asound
+#define snd_timer_continue snd_timer_continue_dylibloader_wrapper_asound
+#define snd_timer_read snd_timer_read_dylibloader_wrapper_asound
+#define snd_timer_id_sizeof snd_timer_id_sizeof_dylibloader_wrapper_asound
+#define snd_timer_id_malloc snd_timer_id_malloc_dylibloader_wrapper_asound
+#define snd_timer_id_free snd_timer_id_free_dylibloader_wrapper_asound
+#define snd_timer_id_copy snd_timer_id_copy_dylibloader_wrapper_asound
+#define snd_timer_id_set_class snd_timer_id_set_class_dylibloader_wrapper_asound
+#define snd_timer_id_get_class snd_timer_id_get_class_dylibloader_wrapper_asound
+#define snd_timer_id_set_sclass snd_timer_id_set_sclass_dylibloader_wrapper_asound
+#define snd_timer_id_get_sclass snd_timer_id_get_sclass_dylibloader_wrapper_asound
+#define snd_timer_id_set_card snd_timer_id_set_card_dylibloader_wrapper_asound
+#define snd_timer_id_get_card snd_timer_id_get_card_dylibloader_wrapper_asound
+#define snd_timer_id_set_device snd_timer_id_set_device_dylibloader_wrapper_asound
+#define snd_timer_id_get_device snd_timer_id_get_device_dylibloader_wrapper_asound
+#define snd_timer_id_set_subdevice snd_timer_id_set_subdevice_dylibloader_wrapper_asound
+#define snd_timer_id_get_subdevice snd_timer_id_get_subdevice_dylibloader_wrapper_asound
+#define snd_timer_ginfo_sizeof snd_timer_ginfo_sizeof_dylibloader_wrapper_asound
+#define snd_timer_ginfo_malloc snd_timer_ginfo_malloc_dylibloader_wrapper_asound
+#define snd_timer_ginfo_free snd_timer_ginfo_free_dylibloader_wrapper_asound
+#define snd_timer_ginfo_copy snd_timer_ginfo_copy_dylibloader_wrapper_asound
+#define snd_timer_ginfo_set_tid snd_timer_ginfo_set_tid_dylibloader_wrapper_asound
+#define snd_timer_ginfo_get_tid snd_timer_ginfo_get_tid_dylibloader_wrapper_asound
+#define snd_timer_ginfo_get_flags snd_timer_ginfo_get_flags_dylibloader_wrapper_asound
+#define snd_timer_ginfo_get_card snd_timer_ginfo_get_card_dylibloader_wrapper_asound
+#define snd_timer_ginfo_get_id snd_timer_ginfo_get_id_dylibloader_wrapper_asound
+#define snd_timer_ginfo_get_name snd_timer_ginfo_get_name_dylibloader_wrapper_asound
+#define snd_timer_ginfo_get_resolution snd_timer_ginfo_get_resolution_dylibloader_wrapper_asound
+#define snd_timer_ginfo_get_resolution_min snd_timer_ginfo_get_resolution_min_dylibloader_wrapper_asound
+#define snd_timer_ginfo_get_resolution_max snd_timer_ginfo_get_resolution_max_dylibloader_wrapper_asound
+#define snd_timer_ginfo_get_clients snd_timer_ginfo_get_clients_dylibloader_wrapper_asound
+#define snd_timer_info_sizeof snd_timer_info_sizeof_dylibloader_wrapper_asound
+#define snd_timer_info_malloc snd_timer_info_malloc_dylibloader_wrapper_asound
+#define snd_timer_info_free snd_timer_info_free_dylibloader_wrapper_asound
+#define snd_timer_info_copy snd_timer_info_copy_dylibloader_wrapper_asound
+#define snd_timer_info_is_slave snd_timer_info_is_slave_dylibloader_wrapper_asound
+#define snd_timer_info_get_card snd_timer_info_get_card_dylibloader_wrapper_asound
+#define snd_timer_info_get_id snd_timer_info_get_id_dylibloader_wrapper_asound
+#define snd_timer_info_get_name snd_timer_info_get_name_dylibloader_wrapper_asound
+#define snd_timer_info_get_resolution snd_timer_info_get_resolution_dylibloader_wrapper_asound
+#define snd_timer_params_sizeof snd_timer_params_sizeof_dylibloader_wrapper_asound
+#define snd_timer_params_malloc snd_timer_params_malloc_dylibloader_wrapper_asound
+#define snd_timer_params_free snd_timer_params_free_dylibloader_wrapper_asound
+#define snd_timer_params_copy snd_timer_params_copy_dylibloader_wrapper_asound
+#define snd_timer_params_set_auto_start snd_timer_params_set_auto_start_dylibloader_wrapper_asound
+#define snd_timer_params_get_auto_start snd_timer_params_get_auto_start_dylibloader_wrapper_asound
+#define snd_timer_params_set_exclusive snd_timer_params_set_exclusive_dylibloader_wrapper_asound
+#define snd_timer_params_get_exclusive snd_timer_params_get_exclusive_dylibloader_wrapper_asound
+#define snd_timer_params_set_early_event snd_timer_params_set_early_event_dylibloader_wrapper_asound
+#define snd_timer_params_get_early_event snd_timer_params_get_early_event_dylibloader_wrapper_asound
+#define snd_timer_params_set_ticks snd_timer_params_set_ticks_dylibloader_wrapper_asound
+#define snd_timer_params_get_ticks snd_timer_params_get_ticks_dylibloader_wrapper_asound
+#define snd_timer_params_set_queue_size snd_timer_params_set_queue_size_dylibloader_wrapper_asound
+#define snd_timer_params_get_queue_size snd_timer_params_get_queue_size_dylibloader_wrapper_asound
+#define snd_timer_params_set_filter snd_timer_params_set_filter_dylibloader_wrapper_asound
+#define snd_timer_params_get_filter snd_timer_params_get_filter_dylibloader_wrapper_asound
+#define snd_timer_status_sizeof snd_timer_status_sizeof_dylibloader_wrapper_asound
+#define snd_timer_status_malloc snd_timer_status_malloc_dylibloader_wrapper_asound
+#define snd_timer_status_free snd_timer_status_free_dylibloader_wrapper_asound
+#define snd_timer_status_copy snd_timer_status_copy_dylibloader_wrapper_asound
+#define snd_timer_status_get_timestamp snd_timer_status_get_timestamp_dylibloader_wrapper_asound
+#define snd_timer_status_get_resolution snd_timer_status_get_resolution_dylibloader_wrapper_asound
+#define snd_timer_status_get_lost snd_timer_status_get_lost_dylibloader_wrapper_asound
+#define snd_timer_status_get_overrun snd_timer_status_get_overrun_dylibloader_wrapper_asound
+#define snd_timer_status_get_queue snd_timer_status_get_queue_dylibloader_wrapper_asound
+#define snd_timer_info_get_ticks snd_timer_info_get_ticks_dylibloader_wrapper_asound
+#define snd_hwdep_open snd_hwdep_open_dylibloader_wrapper_asound
+#define snd_hwdep_close snd_hwdep_close_dylibloader_wrapper_asound
+#define snd_hwdep_poll_descriptors snd_hwdep_poll_descriptors_dylibloader_wrapper_asound
+#define snd_hwdep_poll_descriptors_count snd_hwdep_poll_descriptors_count_dylibloader_wrapper_asound
+#define snd_hwdep_poll_descriptors_revents snd_hwdep_poll_descriptors_revents_dylibloader_wrapper_asound
+#define snd_hwdep_nonblock snd_hwdep_nonblock_dylibloader_wrapper_asound
+#define snd_hwdep_info snd_hwdep_info_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_status snd_hwdep_dsp_status_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_load snd_hwdep_dsp_load_dylibloader_wrapper_asound
+#define snd_hwdep_ioctl snd_hwdep_ioctl_dylibloader_wrapper_asound
+#define snd_hwdep_write snd_hwdep_write_dylibloader_wrapper_asound
+#define snd_hwdep_read snd_hwdep_read_dylibloader_wrapper_asound
+#define snd_hwdep_info_sizeof snd_hwdep_info_sizeof_dylibloader_wrapper_asound
+#define snd_hwdep_info_malloc snd_hwdep_info_malloc_dylibloader_wrapper_asound
+#define snd_hwdep_info_free snd_hwdep_info_free_dylibloader_wrapper_asound
+#define snd_hwdep_info_copy snd_hwdep_info_copy_dylibloader_wrapper_asound
+#define snd_hwdep_info_get_device snd_hwdep_info_get_device_dylibloader_wrapper_asound
+#define snd_hwdep_info_get_card snd_hwdep_info_get_card_dylibloader_wrapper_asound
+#define snd_hwdep_info_get_id snd_hwdep_info_get_id_dylibloader_wrapper_asound
+#define snd_hwdep_info_get_name snd_hwdep_info_get_name_dylibloader_wrapper_asound
+#define snd_hwdep_info_get_iface snd_hwdep_info_get_iface_dylibloader_wrapper_asound
+#define snd_hwdep_info_set_device snd_hwdep_info_set_device_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_status_sizeof snd_hwdep_dsp_status_sizeof_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_status_malloc snd_hwdep_dsp_status_malloc_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_status_free snd_hwdep_dsp_status_free_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_status_copy snd_hwdep_dsp_status_copy_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_status_get_version snd_hwdep_dsp_status_get_version_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_status_get_id snd_hwdep_dsp_status_get_id_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_status_get_num_dsps snd_hwdep_dsp_status_get_num_dsps_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_status_get_dsp_loaded snd_hwdep_dsp_status_get_dsp_loaded_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_status_get_chip_ready snd_hwdep_dsp_status_get_chip_ready_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_sizeof snd_hwdep_dsp_image_sizeof_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_malloc snd_hwdep_dsp_image_malloc_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_free snd_hwdep_dsp_image_free_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_copy snd_hwdep_dsp_image_copy_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_get_index snd_hwdep_dsp_image_get_index_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_get_name snd_hwdep_dsp_image_get_name_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_get_image snd_hwdep_dsp_image_get_image_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_get_length snd_hwdep_dsp_image_get_length_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_set_index snd_hwdep_dsp_image_set_index_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_set_name snd_hwdep_dsp_image_set_name_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_set_image snd_hwdep_dsp_image_set_image_dylibloader_wrapper_asound
+#define snd_hwdep_dsp_image_set_length snd_hwdep_dsp_image_set_length_dylibloader_wrapper_asound
+#define snd_card_load snd_card_load_dylibloader_wrapper_asound
+#define snd_card_next snd_card_next_dylibloader_wrapper_asound
+#define snd_card_get_index snd_card_get_index_dylibloader_wrapper_asound
+#define snd_card_get_name snd_card_get_name_dylibloader_wrapper_asound
+#define snd_card_get_longname snd_card_get_longname_dylibloader_wrapper_asound
+#define snd_device_name_hint snd_device_name_hint_dylibloader_wrapper_asound
+#define snd_device_name_free_hint snd_device_name_free_hint_dylibloader_wrapper_asound
+#define snd_device_name_get_hint snd_device_name_get_hint_dylibloader_wrapper_asound
+#define snd_ctl_open snd_ctl_open_dylibloader_wrapper_asound
+#define snd_ctl_open_lconf snd_ctl_open_lconf_dylibloader_wrapper_asound
+#define snd_ctl_open_fallback snd_ctl_open_fallback_dylibloader_wrapper_asound
+#define snd_ctl_close snd_ctl_close_dylibloader_wrapper_asound
+#define snd_ctl_nonblock snd_ctl_nonblock_dylibloader_wrapper_asound
+#define snd_async_add_ctl_handler snd_async_add_ctl_handler_dylibloader_wrapper_asound
+#define snd_async_handler_get_ctl snd_async_handler_get_ctl_dylibloader_wrapper_asound
+#define snd_ctl_poll_descriptors_count snd_ctl_poll_descriptors_count_dylibloader_wrapper_asound
+#define snd_ctl_poll_descriptors snd_ctl_poll_descriptors_dylibloader_wrapper_asound
+#define snd_ctl_poll_descriptors_revents snd_ctl_poll_descriptors_revents_dylibloader_wrapper_asound
+#define snd_ctl_subscribe_events snd_ctl_subscribe_events_dylibloader_wrapper_asound
+#define snd_ctl_card_info snd_ctl_card_info_dylibloader_wrapper_asound
+#define snd_ctl_elem_list snd_ctl_elem_list_dylibloader_wrapper_asound
+#define snd_ctl_elem_info snd_ctl_elem_info_dylibloader_wrapper_asound
+#define snd_ctl_elem_read snd_ctl_elem_read_dylibloader_wrapper_asound
+#define snd_ctl_elem_write snd_ctl_elem_write_dylibloader_wrapper_asound
+#define snd_ctl_elem_lock snd_ctl_elem_lock_dylibloader_wrapper_asound
+#define snd_ctl_elem_unlock snd_ctl_elem_unlock_dylibloader_wrapper_asound
+#define snd_ctl_elem_tlv_read snd_ctl_elem_tlv_read_dylibloader_wrapper_asound
+#define snd_ctl_elem_tlv_write snd_ctl_elem_tlv_write_dylibloader_wrapper_asound
+#define snd_ctl_elem_tlv_command snd_ctl_elem_tlv_command_dylibloader_wrapper_asound
+#define snd_ctl_hwdep_next_device snd_ctl_hwdep_next_device_dylibloader_wrapper_asound
+#define snd_ctl_hwdep_info snd_ctl_hwdep_info_dylibloader_wrapper_asound
+#define snd_ctl_pcm_next_device snd_ctl_pcm_next_device_dylibloader_wrapper_asound
+#define snd_ctl_pcm_info snd_ctl_pcm_info_dylibloader_wrapper_asound
+#define snd_ctl_pcm_prefer_subdevice snd_ctl_pcm_prefer_subdevice_dylibloader_wrapper_asound
+#define snd_ctl_rawmidi_next_device snd_ctl_rawmidi_next_device_dylibloader_wrapper_asound
+#define snd_ctl_rawmidi_info snd_ctl_rawmidi_info_dylibloader_wrapper_asound
+#define snd_ctl_rawmidi_prefer_subdevice snd_ctl_rawmidi_prefer_subdevice_dylibloader_wrapper_asound
+#define snd_ctl_set_power_state snd_ctl_set_power_state_dylibloader_wrapper_asound
+#define snd_ctl_get_power_state snd_ctl_get_power_state_dylibloader_wrapper_asound
+#define snd_ctl_read snd_ctl_read_dylibloader_wrapper_asound
+#define snd_ctl_wait snd_ctl_wait_dylibloader_wrapper_asound
+#define snd_ctl_name snd_ctl_name_dylibloader_wrapper_asound
+#define snd_ctl_type snd_ctl_type_dylibloader_wrapper_asound
+#define snd_ctl_elem_type_name snd_ctl_elem_type_name_dylibloader_wrapper_asound
+#define snd_ctl_elem_iface_name snd_ctl_elem_iface_name_dylibloader_wrapper_asound
+#define snd_ctl_event_type_name snd_ctl_event_type_name_dylibloader_wrapper_asound
+#define snd_ctl_event_elem_get_mask snd_ctl_event_elem_get_mask_dylibloader_wrapper_asound
+#define snd_ctl_event_elem_get_numid snd_ctl_event_elem_get_numid_dylibloader_wrapper_asound
+#define snd_ctl_event_elem_get_id snd_ctl_event_elem_get_id_dylibloader_wrapper_asound
+#define snd_ctl_event_elem_get_interface snd_ctl_event_elem_get_interface_dylibloader_wrapper_asound
+#define snd_ctl_event_elem_get_device snd_ctl_event_elem_get_device_dylibloader_wrapper_asound
+#define snd_ctl_event_elem_get_subdevice snd_ctl_event_elem_get_subdevice_dylibloader_wrapper_asound
+#define snd_ctl_event_elem_get_name snd_ctl_event_elem_get_name_dylibloader_wrapper_asound
+#define snd_ctl_event_elem_get_index snd_ctl_event_elem_get_index_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_alloc_space snd_ctl_elem_list_alloc_space_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_free_space snd_ctl_elem_list_free_space_dylibloader_wrapper_asound
+#define snd_ctl_ascii_elem_id_get snd_ctl_ascii_elem_id_get_dylibloader_wrapper_asound
+#define snd_ctl_ascii_elem_id_parse snd_ctl_ascii_elem_id_parse_dylibloader_wrapper_asound
+#define snd_ctl_ascii_value_parse snd_ctl_ascii_value_parse_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_sizeof snd_ctl_elem_id_sizeof_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_malloc snd_ctl_elem_id_malloc_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_free snd_ctl_elem_id_free_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_clear snd_ctl_elem_id_clear_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_copy snd_ctl_elem_id_copy_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_get_numid snd_ctl_elem_id_get_numid_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_get_interface snd_ctl_elem_id_get_interface_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_get_device snd_ctl_elem_id_get_device_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_get_subdevice snd_ctl_elem_id_get_subdevice_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_get_name snd_ctl_elem_id_get_name_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_get_index snd_ctl_elem_id_get_index_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_set_numid snd_ctl_elem_id_set_numid_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_set_interface snd_ctl_elem_id_set_interface_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_set_device snd_ctl_elem_id_set_device_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_set_subdevice snd_ctl_elem_id_set_subdevice_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_set_name snd_ctl_elem_id_set_name_dylibloader_wrapper_asound
+#define snd_ctl_elem_id_set_index snd_ctl_elem_id_set_index_dylibloader_wrapper_asound
+#define snd_ctl_card_info_sizeof snd_ctl_card_info_sizeof_dylibloader_wrapper_asound
+#define snd_ctl_card_info_malloc snd_ctl_card_info_malloc_dylibloader_wrapper_asound
+#define snd_ctl_card_info_free snd_ctl_card_info_free_dylibloader_wrapper_asound
+#define snd_ctl_card_info_clear snd_ctl_card_info_clear_dylibloader_wrapper_asound
+#define snd_ctl_card_info_copy snd_ctl_card_info_copy_dylibloader_wrapper_asound
+#define snd_ctl_card_info_get_card snd_ctl_card_info_get_card_dylibloader_wrapper_asound
+#define snd_ctl_card_info_get_id snd_ctl_card_info_get_id_dylibloader_wrapper_asound
+#define snd_ctl_card_info_get_driver snd_ctl_card_info_get_driver_dylibloader_wrapper_asound
+#define snd_ctl_card_info_get_name snd_ctl_card_info_get_name_dylibloader_wrapper_asound
+#define snd_ctl_card_info_get_longname snd_ctl_card_info_get_longname_dylibloader_wrapper_asound
+#define snd_ctl_card_info_get_mixername snd_ctl_card_info_get_mixername_dylibloader_wrapper_asound
+#define snd_ctl_card_info_get_components snd_ctl_card_info_get_components_dylibloader_wrapper_asound
+#define snd_ctl_event_sizeof snd_ctl_event_sizeof_dylibloader_wrapper_asound
+#define snd_ctl_event_malloc snd_ctl_event_malloc_dylibloader_wrapper_asound
+#define snd_ctl_event_free snd_ctl_event_free_dylibloader_wrapper_asound
+#define snd_ctl_event_clear snd_ctl_event_clear_dylibloader_wrapper_asound
+#define snd_ctl_event_copy snd_ctl_event_copy_dylibloader_wrapper_asound
+#define snd_ctl_event_get_type snd_ctl_event_get_type_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_sizeof snd_ctl_elem_list_sizeof_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_malloc snd_ctl_elem_list_malloc_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_free snd_ctl_elem_list_free_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_clear snd_ctl_elem_list_clear_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_copy snd_ctl_elem_list_copy_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_set_offset snd_ctl_elem_list_set_offset_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_get_used snd_ctl_elem_list_get_used_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_get_count snd_ctl_elem_list_get_count_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_get_id snd_ctl_elem_list_get_id_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_get_numid snd_ctl_elem_list_get_numid_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_get_interface snd_ctl_elem_list_get_interface_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_get_device snd_ctl_elem_list_get_device_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_get_subdevice snd_ctl_elem_list_get_subdevice_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_get_name snd_ctl_elem_list_get_name_dylibloader_wrapper_asound
+#define snd_ctl_elem_list_get_index snd_ctl_elem_list_get_index_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_sizeof snd_ctl_elem_info_sizeof_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_malloc snd_ctl_elem_info_malloc_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_free snd_ctl_elem_info_free_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_clear snd_ctl_elem_info_clear_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_copy snd_ctl_elem_info_copy_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_type snd_ctl_elem_info_get_type_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_is_readable snd_ctl_elem_info_is_readable_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_is_writable snd_ctl_elem_info_is_writable_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_is_volatile snd_ctl_elem_info_is_volatile_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_is_inactive snd_ctl_elem_info_is_inactive_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_is_locked snd_ctl_elem_info_is_locked_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_is_tlv_readable snd_ctl_elem_info_is_tlv_readable_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_is_tlv_writable snd_ctl_elem_info_is_tlv_writable_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_is_tlv_commandable snd_ctl_elem_info_is_tlv_commandable_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_is_owner snd_ctl_elem_info_is_owner_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_is_user snd_ctl_elem_info_is_user_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_owner snd_ctl_elem_info_get_owner_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_count snd_ctl_elem_info_get_count_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_min snd_ctl_elem_info_get_min_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_max snd_ctl_elem_info_get_max_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_step snd_ctl_elem_info_get_step_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_min64 snd_ctl_elem_info_get_min64_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_max64 snd_ctl_elem_info_get_max64_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_step64 snd_ctl_elem_info_get_step64_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_items snd_ctl_elem_info_get_items_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_set_item snd_ctl_elem_info_set_item_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_item_name snd_ctl_elem_info_get_item_name_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_dimensions snd_ctl_elem_info_get_dimensions_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_dimension snd_ctl_elem_info_get_dimension_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_set_dimension snd_ctl_elem_info_set_dimension_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_id snd_ctl_elem_info_get_id_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_numid snd_ctl_elem_info_get_numid_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_interface snd_ctl_elem_info_get_interface_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_device snd_ctl_elem_info_get_device_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_subdevice snd_ctl_elem_info_get_subdevice_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_name snd_ctl_elem_info_get_name_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_get_index snd_ctl_elem_info_get_index_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_set_id snd_ctl_elem_info_set_id_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_set_numid snd_ctl_elem_info_set_numid_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_set_interface snd_ctl_elem_info_set_interface_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_set_device snd_ctl_elem_info_set_device_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_set_subdevice snd_ctl_elem_info_set_subdevice_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_set_name snd_ctl_elem_info_set_name_dylibloader_wrapper_asound
+#define snd_ctl_elem_info_set_index snd_ctl_elem_info_set_index_dylibloader_wrapper_asound
+#define snd_ctl_add_integer_elem_set snd_ctl_add_integer_elem_set_dylibloader_wrapper_asound
+#define snd_ctl_add_integer64_elem_set snd_ctl_add_integer64_elem_set_dylibloader_wrapper_asound
+#define snd_ctl_add_boolean_elem_set snd_ctl_add_boolean_elem_set_dylibloader_wrapper_asound
+#define snd_ctl_add_enumerated_elem_set snd_ctl_add_enumerated_elem_set_dylibloader_wrapper_asound
+#define snd_ctl_add_bytes_elem_set snd_ctl_add_bytes_elem_set_dylibloader_wrapper_asound
+#define snd_ctl_elem_add_integer snd_ctl_elem_add_integer_dylibloader_wrapper_asound
+#define snd_ctl_elem_add_integer64 snd_ctl_elem_add_integer64_dylibloader_wrapper_asound
+#define snd_ctl_elem_add_boolean snd_ctl_elem_add_boolean_dylibloader_wrapper_asound
+#define snd_ctl_elem_add_enumerated snd_ctl_elem_add_enumerated_dylibloader_wrapper_asound
+#define snd_ctl_elem_add_iec958 snd_ctl_elem_add_iec958_dylibloader_wrapper_asound
+#define snd_ctl_elem_remove snd_ctl_elem_remove_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_sizeof snd_ctl_elem_value_sizeof_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_malloc snd_ctl_elem_value_malloc_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_free snd_ctl_elem_value_free_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_clear snd_ctl_elem_value_clear_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_copy snd_ctl_elem_value_copy_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_compare snd_ctl_elem_value_compare_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_id snd_ctl_elem_value_get_id_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_numid snd_ctl_elem_value_get_numid_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_interface snd_ctl_elem_value_get_interface_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_device snd_ctl_elem_value_get_device_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_subdevice snd_ctl_elem_value_get_subdevice_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_name snd_ctl_elem_value_get_name_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_index snd_ctl_elem_value_get_index_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_id snd_ctl_elem_value_set_id_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_numid snd_ctl_elem_value_set_numid_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_interface snd_ctl_elem_value_set_interface_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_device snd_ctl_elem_value_set_device_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_subdevice snd_ctl_elem_value_set_subdevice_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_name snd_ctl_elem_value_set_name_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_index snd_ctl_elem_value_set_index_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_boolean snd_ctl_elem_value_get_boolean_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_integer snd_ctl_elem_value_get_integer_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_integer64 snd_ctl_elem_value_get_integer64_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_enumerated snd_ctl_elem_value_get_enumerated_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_byte snd_ctl_elem_value_get_byte_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_boolean snd_ctl_elem_value_set_boolean_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_integer snd_ctl_elem_value_set_integer_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_integer64 snd_ctl_elem_value_set_integer64_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_enumerated snd_ctl_elem_value_set_enumerated_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_byte snd_ctl_elem_value_set_byte_dylibloader_wrapper_asound
+#define snd_ctl_elem_set_bytes snd_ctl_elem_set_bytes_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_bytes snd_ctl_elem_value_get_bytes_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_get_iec958 snd_ctl_elem_value_get_iec958_dylibloader_wrapper_asound
+#define snd_ctl_elem_value_set_iec958 snd_ctl_elem_value_set_iec958_dylibloader_wrapper_asound
+#define snd_tlv_parse_dB_info snd_tlv_parse_dB_info_dylibloader_wrapper_asound
+#define snd_tlv_get_dB_range snd_tlv_get_dB_range_dylibloader_wrapper_asound
+#define snd_tlv_convert_to_dB snd_tlv_convert_to_dB_dylibloader_wrapper_asound
+#define snd_tlv_convert_from_dB snd_tlv_convert_from_dB_dylibloader_wrapper_asound
+#define snd_ctl_get_dB_range snd_ctl_get_dB_range_dylibloader_wrapper_asound
+#define snd_ctl_convert_to_dB snd_ctl_convert_to_dB_dylibloader_wrapper_asound
+#define snd_ctl_convert_from_dB snd_ctl_convert_from_dB_dylibloader_wrapper_asound
+#define snd_hctl_compare_fast snd_hctl_compare_fast_dylibloader_wrapper_asound
+#define snd_hctl_open snd_hctl_open_dylibloader_wrapper_asound
+#define snd_hctl_open_ctl snd_hctl_open_ctl_dylibloader_wrapper_asound
+#define snd_hctl_close snd_hctl_close_dylibloader_wrapper_asound
+#define snd_hctl_nonblock snd_hctl_nonblock_dylibloader_wrapper_asound
+#define snd_hctl_poll_descriptors_count snd_hctl_poll_descriptors_count_dylibloader_wrapper_asound
+#define snd_hctl_poll_descriptors snd_hctl_poll_descriptors_dylibloader_wrapper_asound
+#define snd_hctl_poll_descriptors_revents snd_hctl_poll_descriptors_revents_dylibloader_wrapper_asound
+#define snd_hctl_get_count snd_hctl_get_count_dylibloader_wrapper_asound
+#define snd_hctl_set_compare snd_hctl_set_compare_dylibloader_wrapper_asound
+#define snd_hctl_first_elem snd_hctl_first_elem_dylibloader_wrapper_asound
+#define snd_hctl_last_elem snd_hctl_last_elem_dylibloader_wrapper_asound
+#define snd_hctl_find_elem snd_hctl_find_elem_dylibloader_wrapper_asound
+#define snd_hctl_set_callback snd_hctl_set_callback_dylibloader_wrapper_asound
+#define snd_hctl_set_callback_private snd_hctl_set_callback_private_dylibloader_wrapper_asound
+#define snd_hctl_get_callback_private snd_hctl_get_callback_private_dylibloader_wrapper_asound
+#define snd_hctl_load snd_hctl_load_dylibloader_wrapper_asound
+#define snd_hctl_free snd_hctl_free_dylibloader_wrapper_asound
+#define snd_hctl_handle_events snd_hctl_handle_events_dylibloader_wrapper_asound
+#define snd_hctl_name snd_hctl_name_dylibloader_wrapper_asound
+#define snd_hctl_wait snd_hctl_wait_dylibloader_wrapper_asound
+#define snd_hctl_ctl snd_hctl_ctl_dylibloader_wrapper_asound
+#define snd_hctl_elem_next snd_hctl_elem_next_dylibloader_wrapper_asound
+#define snd_hctl_elem_prev snd_hctl_elem_prev_dylibloader_wrapper_asound
+#define snd_hctl_elem_info snd_hctl_elem_info_dylibloader_wrapper_asound
+#define snd_hctl_elem_read snd_hctl_elem_read_dylibloader_wrapper_asound
+#define snd_hctl_elem_write snd_hctl_elem_write_dylibloader_wrapper_asound
+#define snd_hctl_elem_tlv_read snd_hctl_elem_tlv_read_dylibloader_wrapper_asound
+#define snd_hctl_elem_tlv_write snd_hctl_elem_tlv_write_dylibloader_wrapper_asound
+#define snd_hctl_elem_tlv_command snd_hctl_elem_tlv_command_dylibloader_wrapper_asound
+#define snd_hctl_elem_get_hctl snd_hctl_elem_get_hctl_dylibloader_wrapper_asound
+#define snd_hctl_elem_get_id snd_hctl_elem_get_id_dylibloader_wrapper_asound
+#define snd_hctl_elem_get_numid snd_hctl_elem_get_numid_dylibloader_wrapper_asound
+#define snd_hctl_elem_get_interface snd_hctl_elem_get_interface_dylibloader_wrapper_asound
+#define snd_hctl_elem_get_device snd_hctl_elem_get_device_dylibloader_wrapper_asound
+#define snd_hctl_elem_get_subdevice snd_hctl_elem_get_subdevice_dylibloader_wrapper_asound
+#define snd_hctl_elem_get_name snd_hctl_elem_get_name_dylibloader_wrapper_asound
+#define snd_hctl_elem_get_index snd_hctl_elem_get_index_dylibloader_wrapper_asound
+#define snd_hctl_elem_set_callback snd_hctl_elem_set_callback_dylibloader_wrapper_asound
+#define snd_hctl_elem_get_callback_private snd_hctl_elem_get_callback_private_dylibloader_wrapper_asound
+#define snd_hctl_elem_set_callback_private snd_hctl_elem_set_callback_private_dylibloader_wrapper_asound
+#define snd_sctl_build snd_sctl_build_dylibloader_wrapper_asound
+#define snd_sctl_free snd_sctl_free_dylibloader_wrapper_asound
+#define snd_sctl_install snd_sctl_install_dylibloader_wrapper_asound
+#define snd_sctl_remove snd_sctl_remove_dylibloader_wrapper_asound
+#define snd_mixer_open snd_mixer_open_dylibloader_wrapper_asound
+#define snd_mixer_close snd_mixer_close_dylibloader_wrapper_asound
+#define snd_mixer_first_elem snd_mixer_first_elem_dylibloader_wrapper_asound
+#define snd_mixer_last_elem snd_mixer_last_elem_dylibloader_wrapper_asound
+#define snd_mixer_handle_events snd_mixer_handle_events_dylibloader_wrapper_asound
+#define snd_mixer_attach snd_mixer_attach_dylibloader_wrapper_asound
+#define snd_mixer_attach_hctl snd_mixer_attach_hctl_dylibloader_wrapper_asound
+#define snd_mixer_detach snd_mixer_detach_dylibloader_wrapper_asound
+#define snd_mixer_detach_hctl snd_mixer_detach_hctl_dylibloader_wrapper_asound
+#define snd_mixer_get_hctl snd_mixer_get_hctl_dylibloader_wrapper_asound
+#define snd_mixer_poll_descriptors_count snd_mixer_poll_descriptors_count_dylibloader_wrapper_asound
+#define snd_mixer_poll_descriptors snd_mixer_poll_descriptors_dylibloader_wrapper_asound
+#define snd_mixer_poll_descriptors_revents snd_mixer_poll_descriptors_revents_dylibloader_wrapper_asound
+#define snd_mixer_load snd_mixer_load_dylibloader_wrapper_asound
+#define snd_mixer_free snd_mixer_free_dylibloader_wrapper_asound
+#define snd_mixer_wait snd_mixer_wait_dylibloader_wrapper_asound
+#define snd_mixer_set_compare snd_mixer_set_compare_dylibloader_wrapper_asound
+#define snd_mixer_set_callback snd_mixer_set_callback_dylibloader_wrapper_asound
+#define snd_mixer_get_callback_private snd_mixer_get_callback_private_dylibloader_wrapper_asound
+#define snd_mixer_set_callback_private snd_mixer_set_callback_private_dylibloader_wrapper_asound
+#define snd_mixer_get_count snd_mixer_get_count_dylibloader_wrapper_asound
+#define snd_mixer_class_unregister snd_mixer_class_unregister_dylibloader_wrapper_asound
+#define snd_mixer_elem_next snd_mixer_elem_next_dylibloader_wrapper_asound
+#define snd_mixer_elem_prev snd_mixer_elem_prev_dylibloader_wrapper_asound
+#define snd_mixer_elem_set_callback snd_mixer_elem_set_callback_dylibloader_wrapper_asound
+#define snd_mixer_elem_get_callback_private snd_mixer_elem_get_callback_private_dylibloader_wrapper_asound
+#define snd_mixer_elem_set_callback_private snd_mixer_elem_set_callback_private_dylibloader_wrapper_asound
+#define snd_mixer_elem_get_type snd_mixer_elem_get_type_dylibloader_wrapper_asound
+#define snd_mixer_class_register snd_mixer_class_register_dylibloader_wrapper_asound
+#define snd_mixer_elem_new snd_mixer_elem_new_dylibloader_wrapper_asound
+#define snd_mixer_elem_add snd_mixer_elem_add_dylibloader_wrapper_asound
+#define snd_mixer_elem_remove snd_mixer_elem_remove_dylibloader_wrapper_asound
+#define snd_mixer_elem_free snd_mixer_elem_free_dylibloader_wrapper_asound
+#define snd_mixer_elem_info snd_mixer_elem_info_dylibloader_wrapper_asound
+#define snd_mixer_elem_value snd_mixer_elem_value_dylibloader_wrapper_asound
+#define snd_mixer_elem_attach snd_mixer_elem_attach_dylibloader_wrapper_asound
+#define snd_mixer_elem_detach snd_mixer_elem_detach_dylibloader_wrapper_asound
+#define snd_mixer_elem_empty snd_mixer_elem_empty_dylibloader_wrapper_asound
+#define snd_mixer_elem_get_private snd_mixer_elem_get_private_dylibloader_wrapper_asound
+#define snd_mixer_class_sizeof snd_mixer_class_sizeof_dylibloader_wrapper_asound
+#define snd_mixer_class_malloc snd_mixer_class_malloc_dylibloader_wrapper_asound
+#define snd_mixer_class_free snd_mixer_class_free_dylibloader_wrapper_asound
+#define snd_mixer_class_copy snd_mixer_class_copy_dylibloader_wrapper_asound
+#define snd_mixer_class_get_mixer snd_mixer_class_get_mixer_dylibloader_wrapper_asound
+#define snd_mixer_class_get_event snd_mixer_class_get_event_dylibloader_wrapper_asound
+#define snd_mixer_class_get_private snd_mixer_class_get_private_dylibloader_wrapper_asound
+#define snd_mixer_class_get_compare snd_mixer_class_get_compare_dylibloader_wrapper_asound
+#define snd_mixer_class_set_event snd_mixer_class_set_event_dylibloader_wrapper_asound
+#define snd_mixer_class_set_private snd_mixer_class_set_private_dylibloader_wrapper_asound
+#define snd_mixer_class_set_private_free snd_mixer_class_set_private_free_dylibloader_wrapper_asound
+#define snd_mixer_class_set_compare snd_mixer_class_set_compare_dylibloader_wrapper_asound
+#define snd_mixer_selem_channel_name snd_mixer_selem_channel_name_dylibloader_wrapper_asound
+#define snd_mixer_selem_register snd_mixer_selem_register_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_id snd_mixer_selem_get_id_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_name snd_mixer_selem_get_name_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_index snd_mixer_selem_get_index_dylibloader_wrapper_asound
+#define snd_mixer_find_selem snd_mixer_find_selem_dylibloader_wrapper_asound
+#define snd_mixer_selem_is_active snd_mixer_selem_is_active_dylibloader_wrapper_asound
+#define snd_mixer_selem_is_playback_mono snd_mixer_selem_is_playback_mono_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_playback_channel snd_mixer_selem_has_playback_channel_dylibloader_wrapper_asound
+#define snd_mixer_selem_is_capture_mono snd_mixer_selem_is_capture_mono_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_capture_channel snd_mixer_selem_has_capture_channel_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_capture_group snd_mixer_selem_get_capture_group_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_common_volume snd_mixer_selem_has_common_volume_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_playback_volume snd_mixer_selem_has_playback_volume_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_playback_volume_joined snd_mixer_selem_has_playback_volume_joined_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_capture_volume snd_mixer_selem_has_capture_volume_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_capture_volume_joined snd_mixer_selem_has_capture_volume_joined_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_common_switch snd_mixer_selem_has_common_switch_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_playback_switch snd_mixer_selem_has_playback_switch_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_playback_switch_joined snd_mixer_selem_has_playback_switch_joined_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_capture_switch snd_mixer_selem_has_capture_switch_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_capture_switch_joined snd_mixer_selem_has_capture_switch_joined_dylibloader_wrapper_asound
+#define snd_mixer_selem_has_capture_switch_exclusive snd_mixer_selem_has_capture_switch_exclusive_dylibloader_wrapper_asound
+#define snd_mixer_selem_ask_playback_vol_dB snd_mixer_selem_ask_playback_vol_dB_dylibloader_wrapper_asound
+#define snd_mixer_selem_ask_capture_vol_dB snd_mixer_selem_ask_capture_vol_dB_dylibloader_wrapper_asound
+#define snd_mixer_selem_ask_playback_dB_vol snd_mixer_selem_ask_playback_dB_vol_dylibloader_wrapper_asound
+#define snd_mixer_selem_ask_capture_dB_vol snd_mixer_selem_ask_capture_dB_vol_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_playback_volume snd_mixer_selem_get_playback_volume_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_capture_volume snd_mixer_selem_get_capture_volume_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_playback_dB snd_mixer_selem_get_playback_dB_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_capture_dB snd_mixer_selem_get_capture_dB_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_playback_switch snd_mixer_selem_get_playback_switch_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_capture_switch snd_mixer_selem_get_capture_switch_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_playback_volume snd_mixer_selem_set_playback_volume_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_capture_volume snd_mixer_selem_set_capture_volume_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_playback_dB snd_mixer_selem_set_playback_dB_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_capture_dB snd_mixer_selem_set_capture_dB_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_playback_volume_all snd_mixer_selem_set_playback_volume_all_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_capture_volume_all snd_mixer_selem_set_capture_volume_all_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_playback_dB_all snd_mixer_selem_set_playback_dB_all_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_capture_dB_all snd_mixer_selem_set_capture_dB_all_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_playback_switch snd_mixer_selem_set_playback_switch_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_capture_switch snd_mixer_selem_set_capture_switch_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_playback_switch_all snd_mixer_selem_set_playback_switch_all_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_capture_switch_all snd_mixer_selem_set_capture_switch_all_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_playback_volume_range snd_mixer_selem_get_playback_volume_range_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_playback_dB_range snd_mixer_selem_get_playback_dB_range_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_playback_volume_range snd_mixer_selem_set_playback_volume_range_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_capture_volume_range snd_mixer_selem_get_capture_volume_range_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_capture_dB_range snd_mixer_selem_get_capture_dB_range_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_capture_volume_range snd_mixer_selem_set_capture_volume_range_dylibloader_wrapper_asound
+#define snd_mixer_selem_is_enumerated snd_mixer_selem_is_enumerated_dylibloader_wrapper_asound
+#define snd_mixer_selem_is_enum_playback snd_mixer_selem_is_enum_playback_dylibloader_wrapper_asound
+#define snd_mixer_selem_is_enum_capture snd_mixer_selem_is_enum_capture_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_enum_items snd_mixer_selem_get_enum_items_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_enum_item_name snd_mixer_selem_get_enum_item_name_dylibloader_wrapper_asound
+#define snd_mixer_selem_get_enum_item snd_mixer_selem_get_enum_item_dylibloader_wrapper_asound
+#define snd_mixer_selem_set_enum_item snd_mixer_selem_set_enum_item_dylibloader_wrapper_asound
+#define snd_mixer_selem_id_sizeof snd_mixer_selem_id_sizeof_dylibloader_wrapper_asound
+#define snd_mixer_selem_id_malloc snd_mixer_selem_id_malloc_dylibloader_wrapper_asound
+#define snd_mixer_selem_id_free snd_mixer_selem_id_free_dylibloader_wrapper_asound
+#define snd_mixer_selem_id_copy snd_mixer_selem_id_copy_dylibloader_wrapper_asound
+#define snd_mixer_selem_id_get_name snd_mixer_selem_id_get_name_dylibloader_wrapper_asound
+#define snd_mixer_selem_id_get_index snd_mixer_selem_id_get_index_dylibloader_wrapper_asound
+#define snd_mixer_selem_id_set_name snd_mixer_selem_id_set_name_dylibloader_wrapper_asound
+#define snd_mixer_selem_id_set_index snd_mixer_selem_id_set_index_dylibloader_wrapper_asound
+#define snd_mixer_selem_id_parse snd_mixer_selem_id_parse_dylibloader_wrapper_asound
+#define snd_seq_open snd_seq_open_dylibloader_wrapper_asound
+#define snd_seq_open_lconf snd_seq_open_lconf_dylibloader_wrapper_asound
+#define snd_seq_name snd_seq_name_dylibloader_wrapper_asound
+#define snd_seq_type snd_seq_type_dylibloader_wrapper_asound
+#define snd_seq_close snd_seq_close_dylibloader_wrapper_asound
+#define snd_seq_poll_descriptors_count snd_seq_poll_descriptors_count_dylibloader_wrapper_asound
+#define snd_seq_poll_descriptors snd_seq_poll_descriptors_dylibloader_wrapper_asound
+#define snd_seq_poll_descriptors_revents snd_seq_poll_descriptors_revents_dylibloader_wrapper_asound
+#define snd_seq_nonblock snd_seq_nonblock_dylibloader_wrapper_asound
+#define snd_seq_client_id snd_seq_client_id_dylibloader_wrapper_asound
+#define snd_seq_get_output_buffer_size snd_seq_get_output_buffer_size_dylibloader_wrapper_asound
+#define snd_seq_get_input_buffer_size snd_seq_get_input_buffer_size_dylibloader_wrapper_asound
+#define snd_seq_set_output_buffer_size snd_seq_set_output_buffer_size_dylibloader_wrapper_asound
+#define snd_seq_set_input_buffer_size snd_seq_set_input_buffer_size_dylibloader_wrapper_asound
+#define snd_seq_system_info_sizeof snd_seq_system_info_sizeof_dylibloader_wrapper_asound
+#define snd_seq_system_info_malloc snd_seq_system_info_malloc_dylibloader_wrapper_asound
+#define snd_seq_system_info_free snd_seq_system_info_free_dylibloader_wrapper_asound
+#define snd_seq_system_info_copy snd_seq_system_info_copy_dylibloader_wrapper_asound
+#define snd_seq_system_info_get_queues snd_seq_system_info_get_queues_dylibloader_wrapper_asound
+#define snd_seq_system_info_get_clients snd_seq_system_info_get_clients_dylibloader_wrapper_asound
+#define snd_seq_system_info_get_ports snd_seq_system_info_get_ports_dylibloader_wrapper_asound
+#define snd_seq_system_info_get_channels snd_seq_system_info_get_channels_dylibloader_wrapper_asound
+#define snd_seq_system_info_get_cur_clients snd_seq_system_info_get_cur_clients_dylibloader_wrapper_asound
+#define snd_seq_system_info_get_cur_queues snd_seq_system_info_get_cur_queues_dylibloader_wrapper_asound
+#define snd_seq_system_info snd_seq_system_info_dylibloader_wrapper_asound
+#define snd_seq_client_info_sizeof snd_seq_client_info_sizeof_dylibloader_wrapper_asound
+#define snd_seq_client_info_malloc snd_seq_client_info_malloc_dylibloader_wrapper_asound
+#define snd_seq_client_info_free snd_seq_client_info_free_dylibloader_wrapper_asound
+#define snd_seq_client_info_copy snd_seq_client_info_copy_dylibloader_wrapper_asound
+#define snd_seq_client_info_get_client snd_seq_client_info_get_client_dylibloader_wrapper_asound
+#define snd_seq_client_info_get_type snd_seq_client_info_get_type_dylibloader_wrapper_asound
+#define snd_seq_client_info_get_name snd_seq_client_info_get_name_dylibloader_wrapper_asound
+#define snd_seq_client_info_get_broadcast_filter snd_seq_client_info_get_broadcast_filter_dylibloader_wrapper_asound
+#define snd_seq_client_info_get_error_bounce snd_seq_client_info_get_error_bounce_dylibloader_wrapper_asound
+#define snd_seq_client_info_get_card snd_seq_client_info_get_card_dylibloader_wrapper_asound
+#define snd_seq_client_info_get_pid snd_seq_client_info_get_pid_dylibloader_wrapper_asound
+#define snd_seq_client_info_get_event_filter snd_seq_client_info_get_event_filter_dylibloader_wrapper_asound
+#define snd_seq_client_info_get_num_ports snd_seq_client_info_get_num_ports_dylibloader_wrapper_asound
+#define snd_seq_client_info_get_event_lost snd_seq_client_info_get_event_lost_dylibloader_wrapper_asound
+#define snd_seq_client_info_set_client snd_seq_client_info_set_client_dylibloader_wrapper_asound
+#define snd_seq_client_info_set_name snd_seq_client_info_set_name_dylibloader_wrapper_asound
+#define snd_seq_client_info_set_broadcast_filter snd_seq_client_info_set_broadcast_filter_dylibloader_wrapper_asound
+#define snd_seq_client_info_set_error_bounce snd_seq_client_info_set_error_bounce_dylibloader_wrapper_asound
+#define snd_seq_client_info_set_event_filter snd_seq_client_info_set_event_filter_dylibloader_wrapper_asound
+#define snd_seq_client_info_event_filter_clear snd_seq_client_info_event_filter_clear_dylibloader_wrapper_asound
+#define snd_seq_client_info_event_filter_add snd_seq_client_info_event_filter_add_dylibloader_wrapper_asound
+#define snd_seq_client_info_event_filter_del snd_seq_client_info_event_filter_del_dylibloader_wrapper_asound
+#define snd_seq_client_info_event_filter_check snd_seq_client_info_event_filter_check_dylibloader_wrapper_asound
+#define snd_seq_get_client_info snd_seq_get_client_info_dylibloader_wrapper_asound
+#define snd_seq_get_any_client_info snd_seq_get_any_client_info_dylibloader_wrapper_asound
+#define snd_seq_set_client_info snd_seq_set_client_info_dylibloader_wrapper_asound
+#define snd_seq_query_next_client snd_seq_query_next_client_dylibloader_wrapper_asound
+#define snd_seq_client_pool_sizeof snd_seq_client_pool_sizeof_dylibloader_wrapper_asound
+#define snd_seq_client_pool_malloc snd_seq_client_pool_malloc_dylibloader_wrapper_asound
+#define snd_seq_client_pool_free snd_seq_client_pool_free_dylibloader_wrapper_asound
+#define snd_seq_client_pool_copy snd_seq_client_pool_copy_dylibloader_wrapper_asound
+#define snd_seq_client_pool_get_client snd_seq_client_pool_get_client_dylibloader_wrapper_asound
+#define snd_seq_client_pool_get_output_pool snd_seq_client_pool_get_output_pool_dylibloader_wrapper_asound
+#define snd_seq_client_pool_get_input_pool snd_seq_client_pool_get_input_pool_dylibloader_wrapper_asound
+#define snd_seq_client_pool_get_output_room snd_seq_client_pool_get_output_room_dylibloader_wrapper_asound
+#define snd_seq_client_pool_get_output_free snd_seq_client_pool_get_output_free_dylibloader_wrapper_asound
+#define snd_seq_client_pool_get_input_free snd_seq_client_pool_get_input_free_dylibloader_wrapper_asound
+#define snd_seq_client_pool_set_output_pool snd_seq_client_pool_set_output_pool_dylibloader_wrapper_asound
+#define snd_seq_client_pool_set_input_pool snd_seq_client_pool_set_input_pool_dylibloader_wrapper_asound
+#define snd_seq_client_pool_set_output_room snd_seq_client_pool_set_output_room_dylibloader_wrapper_asound
+#define snd_seq_get_client_pool snd_seq_get_client_pool_dylibloader_wrapper_asound
+#define snd_seq_set_client_pool snd_seq_set_client_pool_dylibloader_wrapper_asound
+#define snd_seq_port_info_sizeof snd_seq_port_info_sizeof_dylibloader_wrapper_asound
+#define snd_seq_port_info_malloc snd_seq_port_info_malloc_dylibloader_wrapper_asound
+#define snd_seq_port_info_free snd_seq_port_info_free_dylibloader_wrapper_asound
+#define snd_seq_port_info_copy snd_seq_port_info_copy_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_client snd_seq_port_info_get_client_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_port snd_seq_port_info_get_port_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_addr snd_seq_port_info_get_addr_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_name snd_seq_port_info_get_name_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_capability snd_seq_port_info_get_capability_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_type snd_seq_port_info_get_type_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_midi_channels snd_seq_port_info_get_midi_channels_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_midi_voices snd_seq_port_info_get_midi_voices_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_synth_voices snd_seq_port_info_get_synth_voices_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_read_use snd_seq_port_info_get_read_use_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_write_use snd_seq_port_info_get_write_use_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_port_specified snd_seq_port_info_get_port_specified_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_timestamping snd_seq_port_info_get_timestamping_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_timestamp_real snd_seq_port_info_get_timestamp_real_dylibloader_wrapper_asound
+#define snd_seq_port_info_get_timestamp_queue snd_seq_port_info_get_timestamp_queue_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_client snd_seq_port_info_set_client_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_port snd_seq_port_info_set_port_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_addr snd_seq_port_info_set_addr_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_name snd_seq_port_info_set_name_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_capability snd_seq_port_info_set_capability_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_type snd_seq_port_info_set_type_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_midi_channels snd_seq_port_info_set_midi_channels_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_midi_voices snd_seq_port_info_set_midi_voices_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_synth_voices snd_seq_port_info_set_synth_voices_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_port_specified snd_seq_port_info_set_port_specified_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_timestamping snd_seq_port_info_set_timestamping_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_timestamp_real snd_seq_port_info_set_timestamp_real_dylibloader_wrapper_asound
+#define snd_seq_port_info_set_timestamp_queue snd_seq_port_info_set_timestamp_queue_dylibloader_wrapper_asound
+#define snd_seq_create_port snd_seq_create_port_dylibloader_wrapper_asound
+#define snd_seq_delete_port snd_seq_delete_port_dylibloader_wrapper_asound
+#define snd_seq_get_port_info snd_seq_get_port_info_dylibloader_wrapper_asound
+#define snd_seq_get_any_port_info snd_seq_get_any_port_info_dylibloader_wrapper_asound
+#define snd_seq_set_port_info snd_seq_set_port_info_dylibloader_wrapper_asound
+#define snd_seq_query_next_port snd_seq_query_next_port_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_sizeof snd_seq_port_subscribe_sizeof_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_malloc snd_seq_port_subscribe_malloc_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_free snd_seq_port_subscribe_free_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_copy snd_seq_port_subscribe_copy_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_get_sender snd_seq_port_subscribe_get_sender_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_get_dest snd_seq_port_subscribe_get_dest_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_get_queue snd_seq_port_subscribe_get_queue_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_get_exclusive snd_seq_port_subscribe_get_exclusive_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_get_time_update snd_seq_port_subscribe_get_time_update_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_get_time_real snd_seq_port_subscribe_get_time_real_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_set_sender snd_seq_port_subscribe_set_sender_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_set_dest snd_seq_port_subscribe_set_dest_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_set_queue snd_seq_port_subscribe_set_queue_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_set_exclusive snd_seq_port_subscribe_set_exclusive_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_set_time_update snd_seq_port_subscribe_set_time_update_dylibloader_wrapper_asound
+#define snd_seq_port_subscribe_set_time_real snd_seq_port_subscribe_set_time_real_dylibloader_wrapper_asound
+#define snd_seq_get_port_subscription snd_seq_get_port_subscription_dylibloader_wrapper_asound
+#define snd_seq_subscribe_port snd_seq_subscribe_port_dylibloader_wrapper_asound
+#define snd_seq_unsubscribe_port snd_seq_unsubscribe_port_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_sizeof snd_seq_query_subscribe_sizeof_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_malloc snd_seq_query_subscribe_malloc_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_free snd_seq_query_subscribe_free_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_copy snd_seq_query_subscribe_copy_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_get_client snd_seq_query_subscribe_get_client_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_get_port snd_seq_query_subscribe_get_port_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_get_root snd_seq_query_subscribe_get_root_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_get_type snd_seq_query_subscribe_get_type_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_get_index snd_seq_query_subscribe_get_index_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_get_num_subs snd_seq_query_subscribe_get_num_subs_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_get_addr snd_seq_query_subscribe_get_addr_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_get_queue snd_seq_query_subscribe_get_queue_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_get_exclusive snd_seq_query_subscribe_get_exclusive_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_get_time_update snd_seq_query_subscribe_get_time_update_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_get_time_real snd_seq_query_subscribe_get_time_real_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_set_client snd_seq_query_subscribe_set_client_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_set_port snd_seq_query_subscribe_set_port_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_set_root snd_seq_query_subscribe_set_root_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_set_type snd_seq_query_subscribe_set_type_dylibloader_wrapper_asound
+#define snd_seq_query_subscribe_set_index snd_seq_query_subscribe_set_index_dylibloader_wrapper_asound
+#define snd_seq_query_port_subscribers snd_seq_query_port_subscribers_dylibloader_wrapper_asound
+#define snd_seq_queue_info_sizeof snd_seq_queue_info_sizeof_dylibloader_wrapper_asound
+#define snd_seq_queue_info_malloc snd_seq_queue_info_malloc_dylibloader_wrapper_asound
+#define snd_seq_queue_info_free snd_seq_queue_info_free_dylibloader_wrapper_asound
+#define snd_seq_queue_info_copy snd_seq_queue_info_copy_dylibloader_wrapper_asound
+#define snd_seq_queue_info_get_queue snd_seq_queue_info_get_queue_dylibloader_wrapper_asound
+#define snd_seq_queue_info_get_name snd_seq_queue_info_get_name_dylibloader_wrapper_asound
+#define snd_seq_queue_info_get_owner snd_seq_queue_info_get_owner_dylibloader_wrapper_asound
+#define snd_seq_queue_info_get_locked snd_seq_queue_info_get_locked_dylibloader_wrapper_asound
+#define snd_seq_queue_info_get_flags snd_seq_queue_info_get_flags_dylibloader_wrapper_asound
+#define snd_seq_queue_info_set_name snd_seq_queue_info_set_name_dylibloader_wrapper_asound
+#define snd_seq_queue_info_set_owner snd_seq_queue_info_set_owner_dylibloader_wrapper_asound
+#define snd_seq_queue_info_set_locked snd_seq_queue_info_set_locked_dylibloader_wrapper_asound
+#define snd_seq_queue_info_set_flags snd_seq_queue_info_set_flags_dylibloader_wrapper_asound
+#define snd_seq_create_queue snd_seq_create_queue_dylibloader_wrapper_asound
+#define snd_seq_alloc_named_queue snd_seq_alloc_named_queue_dylibloader_wrapper_asound
+#define snd_seq_alloc_queue snd_seq_alloc_queue_dylibloader_wrapper_asound
+#define snd_seq_free_queue snd_seq_free_queue_dylibloader_wrapper_asound
+#define snd_seq_get_queue_info snd_seq_get_queue_info_dylibloader_wrapper_asound
+#define snd_seq_set_queue_info snd_seq_set_queue_info_dylibloader_wrapper_asound
+#define snd_seq_query_named_queue snd_seq_query_named_queue_dylibloader_wrapper_asound
+#define snd_seq_get_queue_usage snd_seq_get_queue_usage_dylibloader_wrapper_asound
+#define snd_seq_set_queue_usage snd_seq_set_queue_usage_dylibloader_wrapper_asound
+#define snd_seq_queue_status_sizeof snd_seq_queue_status_sizeof_dylibloader_wrapper_asound
+#define snd_seq_queue_status_malloc snd_seq_queue_status_malloc_dylibloader_wrapper_asound
+#define snd_seq_queue_status_free snd_seq_queue_status_free_dylibloader_wrapper_asound
+#define snd_seq_queue_status_copy snd_seq_queue_status_copy_dylibloader_wrapper_asound
+#define snd_seq_queue_status_get_queue snd_seq_queue_status_get_queue_dylibloader_wrapper_asound
+#define snd_seq_queue_status_get_events snd_seq_queue_status_get_events_dylibloader_wrapper_asound
+#define snd_seq_queue_status_get_tick_time snd_seq_queue_status_get_tick_time_dylibloader_wrapper_asound
+#define snd_seq_queue_status_get_real_time snd_seq_queue_status_get_real_time_dylibloader_wrapper_asound
+#define snd_seq_queue_status_get_status snd_seq_queue_status_get_status_dylibloader_wrapper_asound
+#define snd_seq_get_queue_status snd_seq_get_queue_status_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_sizeof snd_seq_queue_tempo_sizeof_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_malloc snd_seq_queue_tempo_malloc_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_free snd_seq_queue_tempo_free_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_copy snd_seq_queue_tempo_copy_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_get_queue snd_seq_queue_tempo_get_queue_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_get_tempo snd_seq_queue_tempo_get_tempo_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_get_ppq snd_seq_queue_tempo_get_ppq_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_get_skew snd_seq_queue_tempo_get_skew_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_get_skew_base snd_seq_queue_tempo_get_skew_base_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_set_tempo snd_seq_queue_tempo_set_tempo_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_set_ppq snd_seq_queue_tempo_set_ppq_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_set_skew snd_seq_queue_tempo_set_skew_dylibloader_wrapper_asound
+#define snd_seq_queue_tempo_set_skew_base snd_seq_queue_tempo_set_skew_base_dylibloader_wrapper_asound
+#define snd_seq_get_queue_tempo snd_seq_get_queue_tempo_dylibloader_wrapper_asound
+#define snd_seq_set_queue_tempo snd_seq_set_queue_tempo_dylibloader_wrapper_asound
+#define snd_seq_queue_timer_sizeof snd_seq_queue_timer_sizeof_dylibloader_wrapper_asound
+#define snd_seq_queue_timer_malloc snd_seq_queue_timer_malloc_dylibloader_wrapper_asound
+#define snd_seq_queue_timer_free snd_seq_queue_timer_free_dylibloader_wrapper_asound
+#define snd_seq_queue_timer_copy snd_seq_queue_timer_copy_dylibloader_wrapper_asound
+#define snd_seq_queue_timer_get_queue snd_seq_queue_timer_get_queue_dylibloader_wrapper_asound
+#define snd_seq_queue_timer_get_type snd_seq_queue_timer_get_type_dylibloader_wrapper_asound
+#define snd_seq_queue_timer_get_id snd_seq_queue_timer_get_id_dylibloader_wrapper_asound
+#define snd_seq_queue_timer_get_resolution snd_seq_queue_timer_get_resolution_dylibloader_wrapper_asound
+#define snd_seq_queue_timer_set_type snd_seq_queue_timer_set_type_dylibloader_wrapper_asound
+#define snd_seq_queue_timer_set_id snd_seq_queue_timer_set_id_dylibloader_wrapper_asound
+#define snd_seq_queue_timer_set_resolution snd_seq_queue_timer_set_resolution_dylibloader_wrapper_asound
+#define snd_seq_get_queue_timer snd_seq_get_queue_timer_dylibloader_wrapper_asound
+#define snd_seq_set_queue_timer snd_seq_set_queue_timer_dylibloader_wrapper_asound
+#define snd_seq_free_event snd_seq_free_event_dylibloader_wrapper_asound
+#define snd_seq_event_length snd_seq_event_length_dylibloader_wrapper_asound
+#define snd_seq_event_output snd_seq_event_output_dylibloader_wrapper_asound
+#define snd_seq_event_output_buffer snd_seq_event_output_buffer_dylibloader_wrapper_asound
+#define snd_seq_event_output_direct snd_seq_event_output_direct_dylibloader_wrapper_asound
+#define snd_seq_event_input snd_seq_event_input_dylibloader_wrapper_asound
+#define snd_seq_event_input_pending snd_seq_event_input_pending_dylibloader_wrapper_asound
+#define snd_seq_drain_output snd_seq_drain_output_dylibloader_wrapper_asound
+#define snd_seq_event_output_pending snd_seq_event_output_pending_dylibloader_wrapper_asound
+#define snd_seq_extract_output snd_seq_extract_output_dylibloader_wrapper_asound
+#define snd_seq_drop_output snd_seq_drop_output_dylibloader_wrapper_asound
+#define snd_seq_drop_output_buffer snd_seq_drop_output_buffer_dylibloader_wrapper_asound
+#define snd_seq_drop_input snd_seq_drop_input_dylibloader_wrapper_asound
+#define snd_seq_drop_input_buffer snd_seq_drop_input_buffer_dylibloader_wrapper_asound
+#define snd_seq_remove_events_sizeof snd_seq_remove_events_sizeof_dylibloader_wrapper_asound
+#define snd_seq_remove_events_malloc snd_seq_remove_events_malloc_dylibloader_wrapper_asound
+#define snd_seq_remove_events_free snd_seq_remove_events_free_dylibloader_wrapper_asound
+#define snd_seq_remove_events_copy snd_seq_remove_events_copy_dylibloader_wrapper_asound
+#define snd_seq_remove_events_get_condition snd_seq_remove_events_get_condition_dylibloader_wrapper_asound
+#define snd_seq_remove_events_get_queue snd_seq_remove_events_get_queue_dylibloader_wrapper_asound
+#define snd_seq_remove_events_get_time snd_seq_remove_events_get_time_dylibloader_wrapper_asound
+#define snd_seq_remove_events_get_dest snd_seq_remove_events_get_dest_dylibloader_wrapper_asound
+#define snd_seq_remove_events_get_channel snd_seq_remove_events_get_channel_dylibloader_wrapper_asound
+#define snd_seq_remove_events_get_event_type snd_seq_remove_events_get_event_type_dylibloader_wrapper_asound
+#define snd_seq_remove_events_get_tag snd_seq_remove_events_get_tag_dylibloader_wrapper_asound
+#define snd_seq_remove_events_set_condition snd_seq_remove_events_set_condition_dylibloader_wrapper_asound
+#define snd_seq_remove_events_set_queue snd_seq_remove_events_set_queue_dylibloader_wrapper_asound
+#define snd_seq_remove_events_set_time snd_seq_remove_events_set_time_dylibloader_wrapper_asound
+#define snd_seq_remove_events_set_dest snd_seq_remove_events_set_dest_dylibloader_wrapper_asound
+#define snd_seq_remove_events_set_channel snd_seq_remove_events_set_channel_dylibloader_wrapper_asound
+#define snd_seq_remove_events_set_event_type snd_seq_remove_events_set_event_type_dylibloader_wrapper_asound
+#define snd_seq_remove_events_set_tag snd_seq_remove_events_set_tag_dylibloader_wrapper_asound
+#define snd_seq_remove_events snd_seq_remove_events_dylibloader_wrapper_asound
+#define snd_seq_set_bit snd_seq_set_bit_dylibloader_wrapper_asound
+#define snd_seq_unset_bit snd_seq_unset_bit_dylibloader_wrapper_asound
+#define snd_seq_change_bit snd_seq_change_bit_dylibloader_wrapper_asound
+#define snd_seq_get_bit snd_seq_get_bit_dylibloader_wrapper_asound
+#define snd_seq_control_queue snd_seq_control_queue_dylibloader_wrapper_asound
+#define snd_seq_create_simple_port snd_seq_create_simple_port_dylibloader_wrapper_asound
+#define snd_seq_delete_simple_port snd_seq_delete_simple_port_dylibloader_wrapper_asound
+#define snd_seq_connect_from snd_seq_connect_from_dylibloader_wrapper_asound
+#define snd_seq_connect_to snd_seq_connect_to_dylibloader_wrapper_asound
+#define snd_seq_disconnect_from snd_seq_disconnect_from_dylibloader_wrapper_asound
+#define snd_seq_disconnect_to snd_seq_disconnect_to_dylibloader_wrapper_asound
+#define snd_seq_set_client_name snd_seq_set_client_name_dylibloader_wrapper_asound
+#define snd_seq_set_client_event_filter snd_seq_set_client_event_filter_dylibloader_wrapper_asound
+#define snd_seq_set_client_pool_output snd_seq_set_client_pool_output_dylibloader_wrapper_asound
+#define snd_seq_set_client_pool_output_room snd_seq_set_client_pool_output_room_dylibloader_wrapper_asound
+#define snd_seq_set_client_pool_input snd_seq_set_client_pool_input_dylibloader_wrapper_asound
+#define snd_seq_sync_output_queue snd_seq_sync_output_queue_dylibloader_wrapper_asound
+#define snd_seq_parse_address snd_seq_parse_address_dylibloader_wrapper_asound
+#define snd_seq_reset_pool_output snd_seq_reset_pool_output_dylibloader_wrapper_asound
+#define snd_seq_reset_pool_input snd_seq_reset_pool_input_dylibloader_wrapper_asound
+#define snd_midi_event_new snd_midi_event_new_dylibloader_wrapper_asound
+#define snd_midi_event_resize_buffer snd_midi_event_resize_buffer_dylibloader_wrapper_asound
+#define snd_midi_event_free snd_midi_event_free_dylibloader_wrapper_asound
+#define snd_midi_event_init snd_midi_event_init_dylibloader_wrapper_asound
+#define snd_midi_event_reset_encode snd_midi_event_reset_encode_dylibloader_wrapper_asound
+#define snd_midi_event_reset_decode snd_midi_event_reset_decode_dylibloader_wrapper_asound
+#define snd_midi_event_no_status snd_midi_event_no_status_dylibloader_wrapper_asound
+#define snd_midi_event_encode snd_midi_event_encode_dylibloader_wrapper_asound
+#define snd_midi_event_encode_byte snd_midi_event_encode_byte_dylibloader_wrapper_asound
+#define snd_midi_event_decode snd_midi_event_decode_dylibloader_wrapper_asound
+extern const char* (*snd_asoundlib_version_dylibloader_wrapper_asound)( void);
+extern int (*snd_dlpath_dylibloader_wrapper_asound)( char*, size_t,const char*);
+extern void* (*snd_dlopen_dylibloader_wrapper_asound)(const char*, int, char*, size_t);
+extern void* (*snd_dlsym_dylibloader_wrapper_asound)( void*,const char*,const char*);
+extern int (*snd_dlclose_dylibloader_wrapper_asound)( void*);
+extern int (*snd_async_add_handler_dylibloader_wrapper_asound)( snd_async_handler_t**, int, snd_async_callback_t, void*);
+extern int (*snd_async_del_handler_dylibloader_wrapper_asound)( snd_async_handler_t*);
+extern int (*snd_async_handler_get_fd_dylibloader_wrapper_asound)( snd_async_handler_t*);
+extern int (*snd_async_handler_get_signo_dylibloader_wrapper_asound)( snd_async_handler_t*);
+extern void* (*snd_async_handler_get_callback_private_dylibloader_wrapper_asound)( snd_async_handler_t*);
+extern struct snd_shm_area* (*snd_shm_area_create_dylibloader_wrapper_asound)( int, void*);
+extern struct snd_shm_area* (*snd_shm_area_share_dylibloader_wrapper_asound)(struct snd_shm_area*);
+extern int (*snd_shm_area_destroy_dylibloader_wrapper_asound)(struct snd_shm_area*);
+extern int (*snd_user_file_dylibloader_wrapper_asound)(const char*, char**);
+extern int (*snd_input_stdio_open_dylibloader_wrapper_asound)( snd_input_t**,const char*,const char*);
+extern int (*snd_input_stdio_attach_dylibloader_wrapper_asound)( snd_input_t**, FILE*, int);
+extern int (*snd_input_buffer_open_dylibloader_wrapper_asound)( snd_input_t**,const char*, ssize_t);
+extern int (*snd_input_close_dylibloader_wrapper_asound)( snd_input_t*);
+extern int (*snd_input_scanf_dylibloader_wrapper_asound)( snd_input_t*,const char*,...);
+extern char* (*snd_input_gets_dylibloader_wrapper_asound)( snd_input_t*, char*, size_t);
+extern int (*snd_input_getc_dylibloader_wrapper_asound)( snd_input_t*);
+extern int (*snd_input_ungetc_dylibloader_wrapper_asound)( snd_input_t*, int);
+extern int (*snd_output_stdio_open_dylibloader_wrapper_asound)( snd_output_t**,const char*,const char*);
+extern int (*snd_output_stdio_attach_dylibloader_wrapper_asound)( snd_output_t**, FILE*, int);
+extern int (*snd_output_buffer_open_dylibloader_wrapper_asound)( snd_output_t**);
+extern size_t (*snd_output_buffer_string_dylibloader_wrapper_asound)( snd_output_t*, char**);
+extern int (*snd_output_close_dylibloader_wrapper_asound)( snd_output_t*);
+extern int (*snd_output_printf_dylibloader_wrapper_asound)( snd_output_t*,const char*,...);
+extern int (*snd_output_vprintf_dylibloader_wrapper_asound)( snd_output_t*,const char*, va_list);
+extern int (*snd_output_puts_dylibloader_wrapper_asound)( snd_output_t*,const char*);
+extern int (*snd_output_putc_dylibloader_wrapper_asound)( snd_output_t*, int);
+extern int (*snd_output_flush_dylibloader_wrapper_asound)( snd_output_t*);
+extern const char* (*snd_strerror_dylibloader_wrapper_asound)( int);
+extern int (*snd_lib_error_set_handler_dylibloader_wrapper_asound)( snd_lib_error_handler_t);
+extern snd_local_error_handler_t (*snd_lib_error_set_local_dylibloader_wrapper_asound)( snd_local_error_handler_t);
+extern const char* (*snd_config_topdir_dylibloader_wrapper_asound)( void);
+extern int (*snd_config_top_dylibloader_wrapper_asound)( snd_config_t**);
+extern int (*snd_config_load_dylibloader_wrapper_asound)( snd_config_t*, snd_input_t*);
+extern int (*snd_config_load_override_dylibloader_wrapper_asound)( snd_config_t*, snd_input_t*);
+extern int (*snd_config_save_dylibloader_wrapper_asound)( snd_config_t*, snd_output_t*);
+extern int (*snd_config_update_dylibloader_wrapper_asound)( void);
+extern int (*snd_config_update_r_dylibloader_wrapper_asound)( snd_config_t**, snd_config_update_t**,const char*);
+extern int (*snd_config_update_free_dylibloader_wrapper_asound)( snd_config_update_t*);
+extern int (*snd_config_update_free_global_dylibloader_wrapper_asound)( void);
+extern int (*snd_config_update_ref_dylibloader_wrapper_asound)( snd_config_t**);
+extern void (*snd_config_ref_dylibloader_wrapper_asound)( snd_config_t*);
+extern void (*snd_config_unref_dylibloader_wrapper_asound)( snd_config_t*);
+extern int (*snd_config_search_dylibloader_wrapper_asound)( snd_config_t*,const char*, snd_config_t**);
+extern int (*snd_config_searchv_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t**,...);
+extern int (*snd_config_search_definition_dylibloader_wrapper_asound)( snd_config_t*,const char*,const char*, snd_config_t**);
+extern int (*snd_config_expand_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t*,const char*, snd_config_t*, snd_config_t**);
+extern int (*snd_config_evaluate_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t*, snd_config_t*, snd_config_t**);
+extern int (*snd_config_add_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t*);
+extern int (*snd_config_add_before_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t*);
+extern int (*snd_config_add_after_dylibloader_wrapper_asound)( snd_config_t*, snd_config_t*);
+extern int (*snd_config_remove_dylibloader_wrapper_asound)( snd_config_t*);
+extern int (*snd_config_delete_dylibloader_wrapper_asound)( snd_config_t*);
+extern int (*snd_config_delete_compound_members_dylibloader_wrapper_asound)(const snd_config_t*);
+extern int (*snd_config_copy_dylibloader_wrapper_asound)( snd_config_t**, snd_config_t*);
+extern int (*snd_config_make_dylibloader_wrapper_asound)( snd_config_t**,const char*, snd_config_type_t);
+extern int (*snd_config_make_integer_dylibloader_wrapper_asound)( snd_config_t**,const char*);
+extern int (*snd_config_make_integer64_dylibloader_wrapper_asound)( snd_config_t**,const char*);
+extern int (*snd_config_make_real_dylibloader_wrapper_asound)( snd_config_t**,const char*);
+extern int (*snd_config_make_string_dylibloader_wrapper_asound)( snd_config_t**,const char*);
+extern int (*snd_config_make_pointer_dylibloader_wrapper_asound)( snd_config_t**,const char*);
+extern int (*snd_config_make_compound_dylibloader_wrapper_asound)( snd_config_t**,const char*, int);
+extern int (*snd_config_imake_integer_dylibloader_wrapper_asound)( snd_config_t**,const char*,const long);
+extern int (*snd_config_imake_integer64_dylibloader_wrapper_asound)( snd_config_t**,const char*,const long long);
+extern int (*snd_config_imake_real_dylibloader_wrapper_asound)( snd_config_t**,const char*,const double);
+extern int (*snd_config_imake_string_dylibloader_wrapper_asound)( snd_config_t**,const char*,const char*);
+extern int (*snd_config_imake_safe_string_dylibloader_wrapper_asound)( snd_config_t**,const char*,const char*);
+extern int (*snd_config_imake_pointer_dylibloader_wrapper_asound)( snd_config_t**,const char*,const void*);
+extern snd_config_type_t (*snd_config_get_type_dylibloader_wrapper_asound)(const snd_config_t*);
+extern int (*snd_config_is_array_dylibloader_wrapper_asound)(const snd_config_t*);
+extern int (*snd_config_set_id_dylibloader_wrapper_asound)( snd_config_t*,const char*);
+extern int (*snd_config_set_integer_dylibloader_wrapper_asound)( snd_config_t*, long);
+extern int (*snd_config_set_integer64_dylibloader_wrapper_asound)( snd_config_t*, long long);
+extern int (*snd_config_set_real_dylibloader_wrapper_asound)( snd_config_t*, double);
+extern int (*snd_config_set_string_dylibloader_wrapper_asound)( snd_config_t*,const char*);
+extern int (*snd_config_set_ascii_dylibloader_wrapper_asound)( snd_config_t*,const char*);
+extern int (*snd_config_set_pointer_dylibloader_wrapper_asound)( snd_config_t*,const void*);
+extern int (*snd_config_get_id_dylibloader_wrapper_asound)(const snd_config_t*,const char**);
+extern int (*snd_config_get_integer_dylibloader_wrapper_asound)(const snd_config_t*, long*);
+extern int (*snd_config_get_integer64_dylibloader_wrapper_asound)(const snd_config_t*, long long*);
+extern int (*snd_config_get_real_dylibloader_wrapper_asound)(const snd_config_t*, double*);
+extern int (*snd_config_get_ireal_dylibloader_wrapper_asound)(const snd_config_t*, double*);
+extern int (*snd_config_get_string_dylibloader_wrapper_asound)(const snd_config_t*,const char**);
+extern int (*snd_config_get_ascii_dylibloader_wrapper_asound)(const snd_config_t*, char**);
+extern int (*snd_config_get_pointer_dylibloader_wrapper_asound)(const snd_config_t*,const void**);
+extern int (*snd_config_test_id_dylibloader_wrapper_asound)(const snd_config_t*,const char*);
+extern snd_config_iterator_t (*snd_config_iterator_first_dylibloader_wrapper_asound)(const snd_config_t*);
+extern snd_config_iterator_t (*snd_config_iterator_next_dylibloader_wrapper_asound)(const snd_config_iterator_t);
+extern snd_config_iterator_t (*snd_config_iterator_end_dylibloader_wrapper_asound)(const snd_config_t*);
+extern snd_config_t* (*snd_config_iterator_entry_dylibloader_wrapper_asound)(const snd_config_iterator_t);
+extern int (*snd_config_get_bool_ascii_dylibloader_wrapper_asound)(const char*);
+extern int (*snd_config_get_bool_dylibloader_wrapper_asound)(const snd_config_t*);
+extern int (*snd_config_get_ctl_iface_ascii_dylibloader_wrapper_asound)(const char*);
+extern int (*snd_config_get_ctl_iface_dylibloader_wrapper_asound)(const snd_config_t*);
+extern int (*snd_names_list_dylibloader_wrapper_asound)(const char*, snd_devname_t**);
+extern void (*snd_names_list_free_dylibloader_wrapper_asound)( snd_devname_t*);
+extern int (*snd_pcm_open_dylibloader_wrapper_asound)( snd_pcm_t**,const char*, snd_pcm_stream_t, int);
+extern int (*snd_pcm_open_lconf_dylibloader_wrapper_asound)( snd_pcm_t**,const char*, snd_pcm_stream_t, int, snd_config_t*);
+extern int (*snd_pcm_open_fallback_dylibloader_wrapper_asound)( snd_pcm_t**, snd_config_t*,const char*,const char*, snd_pcm_stream_t, int);
+extern int (*snd_pcm_close_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern const char* (*snd_pcm_name_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern snd_pcm_type_t (*snd_pcm_type_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern snd_pcm_stream_t (*snd_pcm_stream_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_poll_descriptors_count_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_poll_descriptors_dylibloader_wrapper_asound)( snd_pcm_t*,struct pollfd*, unsigned int);
+extern int (*snd_pcm_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_pcm_t*,struct pollfd*, unsigned int, unsigned short*);
+extern int (*snd_pcm_nonblock_dylibloader_wrapper_asound)( snd_pcm_t*, int);
+extern int (*snd_async_add_pcm_handler_dylibloader_wrapper_asound)( snd_async_handler_t**, snd_pcm_t*, snd_async_callback_t, void*);
+extern snd_pcm_t* (*snd_async_handler_get_pcm_dylibloader_wrapper_asound)( snd_async_handler_t*);
+extern int (*snd_pcm_info_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_info_t*);
+extern int (*snd_pcm_hw_params_current_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_free_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_sw_params_current_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*);
+extern int (*snd_pcm_sw_params_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*);
+extern int (*snd_pcm_prepare_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_reset_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_status_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_status_t*);
+extern int (*snd_pcm_start_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_drop_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_drain_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_pause_dylibloader_wrapper_asound)( snd_pcm_t*, int);
+extern snd_pcm_state_t (*snd_pcm_state_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_hwsync_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_delay_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sframes_t*);
+extern int (*snd_pcm_resume_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_htimestamp_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_uframes_t*, snd_htimestamp_t*);
+extern snd_pcm_sframes_t (*snd_pcm_avail_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern snd_pcm_sframes_t (*snd_pcm_avail_update_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_avail_delay_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sframes_t*, snd_pcm_sframes_t*);
+extern snd_pcm_sframes_t (*snd_pcm_rewindable_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern snd_pcm_sframes_t (*snd_pcm_rewind_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_uframes_t);
+extern snd_pcm_sframes_t (*snd_pcm_forwardable_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern snd_pcm_sframes_t (*snd_pcm_forward_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_uframes_t);
+extern snd_pcm_sframes_t (*snd_pcm_writei_dylibloader_wrapper_asound)( snd_pcm_t*,const void*, snd_pcm_uframes_t);
+extern snd_pcm_sframes_t (*snd_pcm_readi_dylibloader_wrapper_asound)( snd_pcm_t*, void*, snd_pcm_uframes_t);
+extern snd_pcm_sframes_t (*snd_pcm_writen_dylibloader_wrapper_asound)( snd_pcm_t*, void**, snd_pcm_uframes_t);
+extern snd_pcm_sframes_t (*snd_pcm_readn_dylibloader_wrapper_asound)( snd_pcm_t*, void**, snd_pcm_uframes_t);
+extern int (*snd_pcm_wait_dylibloader_wrapper_asound)( snd_pcm_t*, int);
+extern int (*snd_pcm_link_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_t*);
+extern int (*snd_pcm_unlink_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern snd_pcm_chmap_query_t** (*snd_pcm_query_chmaps_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern snd_pcm_chmap_query_t** (*snd_pcm_query_chmaps_from_hw_dylibloader_wrapper_asound)( int, int, int, snd_pcm_stream_t);
+extern void (*snd_pcm_free_chmaps_dylibloader_wrapper_asound)( snd_pcm_chmap_query_t**);
+extern snd_pcm_chmap_t* (*snd_pcm_get_chmap_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_set_chmap_dylibloader_wrapper_asound)( snd_pcm_t*,const snd_pcm_chmap_t*);
+extern const char* (*snd_pcm_chmap_type_name_dylibloader_wrapper_asound)(enum snd_pcm_chmap_type);
+extern const char* (*snd_pcm_chmap_name_dylibloader_wrapper_asound)(enum snd_pcm_chmap_position);
+extern const char* (*snd_pcm_chmap_long_name_dylibloader_wrapper_asound)(enum snd_pcm_chmap_position);
+extern int (*snd_pcm_chmap_print_dylibloader_wrapper_asound)(const snd_pcm_chmap_t*, size_t, char*);
+extern unsigned int (*snd_pcm_chmap_from_string_dylibloader_wrapper_asound)(const char*);
+extern snd_pcm_chmap_t* (*snd_pcm_chmap_parse_string_dylibloader_wrapper_asound)(const char*);
+extern int (*snd_pcm_recover_dylibloader_wrapper_asound)( snd_pcm_t*, int, int);
+extern int (*snd_pcm_set_params_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_format_t, snd_pcm_access_t, unsigned int, unsigned int, int, unsigned int);
+extern int (*snd_pcm_get_params_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_uframes_t*, snd_pcm_uframes_t*);
+extern size_t (*snd_pcm_info_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_pcm_info_malloc_dylibloader_wrapper_asound)( snd_pcm_info_t**);
+extern void (*snd_pcm_info_free_dylibloader_wrapper_asound)( snd_pcm_info_t*);
+extern void (*snd_pcm_info_copy_dylibloader_wrapper_asound)( snd_pcm_info_t*,const snd_pcm_info_t*);
+extern unsigned int (*snd_pcm_info_get_device_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern unsigned int (*snd_pcm_info_get_subdevice_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern snd_pcm_stream_t (*snd_pcm_info_get_stream_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern int (*snd_pcm_info_get_card_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern const char* (*snd_pcm_info_get_id_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern const char* (*snd_pcm_info_get_name_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern const char* (*snd_pcm_info_get_subdevice_name_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern snd_pcm_class_t (*snd_pcm_info_get_class_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern snd_pcm_subclass_t (*snd_pcm_info_get_subclass_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern unsigned int (*snd_pcm_info_get_subdevices_count_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern unsigned int (*snd_pcm_info_get_subdevices_avail_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern snd_pcm_sync_id_t (*snd_pcm_info_get_sync_dylibloader_wrapper_asound)(const snd_pcm_info_t*);
+extern void (*snd_pcm_info_set_device_dylibloader_wrapper_asound)( snd_pcm_info_t*, unsigned int);
+extern void (*snd_pcm_info_set_subdevice_dylibloader_wrapper_asound)( snd_pcm_info_t*, unsigned int);
+extern void (*snd_pcm_info_set_stream_dylibloader_wrapper_asound)( snd_pcm_info_t*, snd_pcm_stream_t);
+extern int (*snd_pcm_hw_params_any_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_can_mmap_sample_resolution_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_is_double_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_is_batch_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_is_block_transfer_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_is_monotonic_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_can_overrange_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_can_pause_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_can_resume_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_is_half_duplex_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_is_joint_duplex_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_can_sync_start_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_can_disable_period_wakeup_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_supports_audio_wallclock_ts_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_supports_audio_ts_type_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, int);
+extern int (*snd_pcm_hw_params_get_rate_numden_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, unsigned int*);
+extern int (*snd_pcm_hw_params_get_sbits_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_get_fifo_size_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*);
+extern size_t (*snd_pcm_hw_params_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_pcm_hw_params_malloc_dylibloader_wrapper_asound)( snd_pcm_hw_params_t**);
+extern void (*snd_pcm_hw_params_free_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*);
+extern void (*snd_pcm_hw_params_copy_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*,const snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_get_access_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_access_t*);
+extern int (*snd_pcm_hw_params_test_access_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_access_t);
+extern int (*snd_pcm_hw_params_set_access_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_access_t);
+extern int (*snd_pcm_hw_params_set_access_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_access_t*);
+extern int (*snd_pcm_hw_params_set_access_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_access_t*);
+extern int (*snd_pcm_hw_params_set_access_mask_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_access_mask_t*);
+extern int (*snd_pcm_hw_params_get_access_mask_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*, snd_pcm_access_mask_t*);
+extern int (*snd_pcm_hw_params_get_format_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_format_t*);
+extern int (*snd_pcm_hw_params_test_format_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_format_t);
+extern int (*snd_pcm_hw_params_set_format_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_format_t);
+extern int (*snd_pcm_hw_params_set_format_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_format_t*);
+extern int (*snd_pcm_hw_params_set_format_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_format_t*);
+extern int (*snd_pcm_hw_params_set_format_mask_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_format_mask_t*);
+extern void (*snd_pcm_hw_params_get_format_mask_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*, snd_pcm_format_mask_t*);
+extern int (*snd_pcm_hw_params_get_subformat_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_subformat_t*);
+extern int (*snd_pcm_hw_params_test_subformat_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_subformat_t);
+extern int (*snd_pcm_hw_params_set_subformat_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_subformat_t);
+extern int (*snd_pcm_hw_params_set_subformat_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_subformat_t*);
+extern int (*snd_pcm_hw_params_set_subformat_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_subformat_t*);
+extern int (*snd_pcm_hw_params_set_subformat_mask_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_subformat_mask_t*);
+extern void (*snd_pcm_hw_params_get_subformat_mask_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*, snd_pcm_subformat_mask_t*);
+extern int (*snd_pcm_hw_params_get_channels_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_get_channels_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_get_channels_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_test_channels_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int);
+extern int (*snd_pcm_hw_params_set_channels_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int);
+extern int (*snd_pcm_hw_params_set_channels_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_set_channels_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_set_channels_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, unsigned int*);
+extern int (*snd_pcm_hw_params_set_channels_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_set_channels_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_set_channels_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_get_rate_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_rate_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_rate_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_test_rate_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+extern int (*snd_pcm_hw_params_set_rate_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+extern int (*snd_pcm_hw_params_set_rate_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_rate_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_rate_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_rate_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_rate_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_rate_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_rate_resample_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int);
+extern int (*snd_pcm_hw_params_get_rate_resample_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_set_export_buffer_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int);
+extern int (*snd_pcm_hw_params_get_export_buffer_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_set_period_wakeup_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int);
+extern int (*snd_pcm_hw_params_get_period_wakeup_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_get_period_time_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_period_time_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_period_time_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_test_period_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+extern int (*snd_pcm_hw_params_set_period_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+extern int (*snd_pcm_hw_params_set_period_time_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_period_time_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_period_time_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_period_time_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_period_time_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_period_time_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_period_size_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+extern int (*snd_pcm_hw_params_get_period_size_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+extern int (*snd_pcm_hw_params_get_period_size_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+extern int (*snd_pcm_hw_params_test_period_size_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t, int);
+extern int (*snd_pcm_hw_params_set_period_size_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t, int);
+extern int (*snd_pcm_hw_params_set_period_size_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+extern int (*snd_pcm_hw_params_set_period_size_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+extern int (*snd_pcm_hw_params_set_period_size_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*, snd_pcm_uframes_t*, int*);
+extern int (*snd_pcm_hw_params_set_period_size_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+extern int (*snd_pcm_hw_params_set_period_size_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+extern int (*snd_pcm_hw_params_set_period_size_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, int*);
+extern int (*snd_pcm_hw_params_set_period_size_integer_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_get_periods_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_periods_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_periods_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_test_periods_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+extern int (*snd_pcm_hw_params_set_periods_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+extern int (*snd_pcm_hw_params_set_periods_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_periods_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_periods_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_periods_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_periods_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_periods_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_periods_integer_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*);
+extern int (*snd_pcm_hw_params_get_buffer_time_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_buffer_time_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_buffer_time_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_test_buffer_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+extern int (*snd_pcm_hw_params_set_buffer_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+extern int (*snd_pcm_hw_params_set_buffer_time_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_buffer_time_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_buffer_time_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_buffer_time_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_buffer_time_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_buffer_time_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_buffer_size_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_hw_params_get_buffer_size_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_hw_params_get_buffer_size_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_hw_params_test_buffer_size_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t);
+extern int (*snd_pcm_hw_params_set_buffer_size_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t);
+extern int (*snd_pcm_hw_params_set_buffer_size_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_hw_params_set_buffer_size_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_hw_params_set_buffer_size_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_hw_params_set_buffer_size_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_hw_params_set_buffer_size_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_hw_params_set_buffer_size_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_hw_params_get_min_align_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
+extern size_t (*snd_pcm_sw_params_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_pcm_sw_params_malloc_dylibloader_wrapper_asound)( snd_pcm_sw_params_t**);
+extern void (*snd_pcm_sw_params_free_dylibloader_wrapper_asound)( snd_pcm_sw_params_t*);
+extern void (*snd_pcm_sw_params_copy_dylibloader_wrapper_asound)( snd_pcm_sw_params_t*,const snd_pcm_sw_params_t*);
+extern int (*snd_pcm_sw_params_get_boundary_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_sw_params_set_tstamp_mode_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_tstamp_t);
+extern int (*snd_pcm_sw_params_get_tstamp_mode_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_tstamp_t*);
+extern int (*snd_pcm_sw_params_set_avail_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+extern int (*snd_pcm_sw_params_get_avail_min_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_sw_params_set_period_event_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, int);
+extern int (*snd_pcm_sw_params_get_period_event_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, int*);
+extern int (*snd_pcm_sw_params_set_start_threshold_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+extern int (*snd_pcm_sw_params_get_start_threshold_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_sw_params_set_stop_threshold_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+extern int (*snd_pcm_sw_params_get_stop_threshold_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_sw_params_set_silence_threshold_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+extern int (*snd_pcm_sw_params_get_silence_threshold_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_sw_params_set_silence_size_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+extern int (*snd_pcm_sw_params_get_silence_size_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+extern size_t (*snd_pcm_access_mask_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_pcm_access_mask_malloc_dylibloader_wrapper_asound)( snd_pcm_access_mask_t**);
+extern void (*snd_pcm_access_mask_free_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*);
+extern void (*snd_pcm_access_mask_copy_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*,const snd_pcm_access_mask_t*);
+extern void (*snd_pcm_access_mask_none_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*);
+extern void (*snd_pcm_access_mask_any_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*);
+extern int (*snd_pcm_access_mask_test_dylibloader_wrapper_asound)(const snd_pcm_access_mask_t*, snd_pcm_access_t);
+extern int (*snd_pcm_access_mask_empty_dylibloader_wrapper_asound)(const snd_pcm_access_mask_t*);
+extern void (*snd_pcm_access_mask_set_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*, snd_pcm_access_t);
+extern void (*snd_pcm_access_mask_reset_dylibloader_wrapper_asound)( snd_pcm_access_mask_t*, snd_pcm_access_t);
+extern size_t (*snd_pcm_format_mask_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_pcm_format_mask_malloc_dylibloader_wrapper_asound)( snd_pcm_format_mask_t**);
+extern void (*snd_pcm_format_mask_free_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*);
+extern void (*snd_pcm_format_mask_copy_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*,const snd_pcm_format_mask_t*);
+extern void (*snd_pcm_format_mask_none_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*);
+extern void (*snd_pcm_format_mask_any_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*);
+extern int (*snd_pcm_format_mask_test_dylibloader_wrapper_asound)(const snd_pcm_format_mask_t*, snd_pcm_format_t);
+extern int (*snd_pcm_format_mask_empty_dylibloader_wrapper_asound)(const snd_pcm_format_mask_t*);
+extern void (*snd_pcm_format_mask_set_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*, snd_pcm_format_t);
+extern void (*snd_pcm_format_mask_reset_dylibloader_wrapper_asound)( snd_pcm_format_mask_t*, snd_pcm_format_t);
+extern size_t (*snd_pcm_subformat_mask_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_pcm_subformat_mask_malloc_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t**);
+extern void (*snd_pcm_subformat_mask_free_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*);
+extern void (*snd_pcm_subformat_mask_copy_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*,const snd_pcm_subformat_mask_t*);
+extern void (*snd_pcm_subformat_mask_none_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*);
+extern void (*snd_pcm_subformat_mask_any_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*);
+extern int (*snd_pcm_subformat_mask_test_dylibloader_wrapper_asound)(const snd_pcm_subformat_mask_t*, snd_pcm_subformat_t);
+extern int (*snd_pcm_subformat_mask_empty_dylibloader_wrapper_asound)(const snd_pcm_subformat_mask_t*);
+extern void (*snd_pcm_subformat_mask_set_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*, snd_pcm_subformat_t);
+extern void (*snd_pcm_subformat_mask_reset_dylibloader_wrapper_asound)( snd_pcm_subformat_mask_t*, snd_pcm_subformat_t);
+extern size_t (*snd_pcm_status_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_pcm_status_malloc_dylibloader_wrapper_asound)( snd_pcm_status_t**);
+extern void (*snd_pcm_status_free_dylibloader_wrapper_asound)( snd_pcm_status_t*);
+extern void (*snd_pcm_status_copy_dylibloader_wrapper_asound)( snd_pcm_status_t*,const snd_pcm_status_t*);
+extern snd_pcm_state_t (*snd_pcm_status_get_state_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
+extern void (*snd_pcm_status_get_trigger_tstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_timestamp_t*);
+extern void (*snd_pcm_status_get_trigger_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
+extern void (*snd_pcm_status_get_tstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_timestamp_t*);
+extern void (*snd_pcm_status_get_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
+extern void (*snd_pcm_status_get_audio_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
+extern void (*snd_pcm_status_get_driver_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
+extern snd_pcm_sframes_t (*snd_pcm_status_get_delay_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
+extern snd_pcm_uframes_t (*snd_pcm_status_get_avail_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
+extern snd_pcm_uframes_t (*snd_pcm_status_get_avail_max_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
+extern snd_pcm_uframes_t (*snd_pcm_status_get_overrange_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
+extern const char* (*snd_pcm_type_name_dylibloader_wrapper_asound)( snd_pcm_type_t);
+extern const char* (*snd_pcm_stream_name_dylibloader_wrapper_asound)(const snd_pcm_stream_t);
+extern const char* (*snd_pcm_access_name_dylibloader_wrapper_asound)(const snd_pcm_access_t);
+extern const char* (*snd_pcm_format_name_dylibloader_wrapper_asound)(const snd_pcm_format_t);
+extern const char* (*snd_pcm_format_description_dylibloader_wrapper_asound)(const snd_pcm_format_t);
+extern const char* (*snd_pcm_subformat_name_dylibloader_wrapper_asound)(const snd_pcm_subformat_t);
+extern const char* (*snd_pcm_subformat_description_dylibloader_wrapper_asound)(const snd_pcm_subformat_t);
+extern snd_pcm_format_t (*snd_pcm_format_value_dylibloader_wrapper_asound)(const char*);
+extern const char* (*snd_pcm_tstamp_mode_name_dylibloader_wrapper_asound)(const snd_pcm_tstamp_t);
+extern const char* (*snd_pcm_state_name_dylibloader_wrapper_asound)(const snd_pcm_state_t);
+extern int (*snd_pcm_dump_dylibloader_wrapper_asound)( snd_pcm_t*, snd_output_t*);
+extern int (*snd_pcm_dump_hw_setup_dylibloader_wrapper_asound)( snd_pcm_t*, snd_output_t*);
+extern int (*snd_pcm_dump_sw_setup_dylibloader_wrapper_asound)( snd_pcm_t*, snd_output_t*);
+extern int (*snd_pcm_dump_setup_dylibloader_wrapper_asound)( snd_pcm_t*, snd_output_t*);
+extern int (*snd_pcm_hw_params_dump_dylibloader_wrapper_asound)( snd_pcm_hw_params_t*, snd_output_t*);
+extern int (*snd_pcm_sw_params_dump_dylibloader_wrapper_asound)( snd_pcm_sw_params_t*, snd_output_t*);
+extern int (*snd_pcm_status_dump_dylibloader_wrapper_asound)( snd_pcm_status_t*, snd_output_t*);
+extern int (*snd_pcm_mmap_begin_dylibloader_wrapper_asound)( snd_pcm_t*,const snd_pcm_channel_area_t**, snd_pcm_uframes_t*, snd_pcm_uframes_t*);
+extern snd_pcm_sframes_t (*snd_pcm_mmap_commit_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_uframes_t, snd_pcm_uframes_t);
+extern snd_pcm_sframes_t (*snd_pcm_mmap_writei_dylibloader_wrapper_asound)( snd_pcm_t*,const void*, snd_pcm_uframes_t);
+extern snd_pcm_sframes_t (*snd_pcm_mmap_readi_dylibloader_wrapper_asound)( snd_pcm_t*, void*, snd_pcm_uframes_t);
+extern snd_pcm_sframes_t (*snd_pcm_mmap_writen_dylibloader_wrapper_asound)( snd_pcm_t*, void**, snd_pcm_uframes_t);
+extern snd_pcm_sframes_t (*snd_pcm_mmap_readn_dylibloader_wrapper_asound)( snd_pcm_t*, void**, snd_pcm_uframes_t);
+extern int (*snd_pcm_format_signed_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern int (*snd_pcm_format_unsigned_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern int (*snd_pcm_format_linear_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern int (*snd_pcm_format_float_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern int (*snd_pcm_format_little_endian_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern int (*snd_pcm_format_big_endian_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern int (*snd_pcm_format_cpu_endian_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern int (*snd_pcm_format_width_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern int (*snd_pcm_format_physical_width_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern snd_pcm_format_t (*snd_pcm_build_linear_format_dylibloader_wrapper_asound)( int, int, int, int);
+extern ssize_t (*snd_pcm_format_size_dylibloader_wrapper_asound)( snd_pcm_format_t, size_t);
+extern uint8_t (*snd_pcm_format_silence_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern uint16_t (*snd_pcm_format_silence_16_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern uint32_t (*snd_pcm_format_silence_32_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern uint64_t (*snd_pcm_format_silence_64_dylibloader_wrapper_asound)( snd_pcm_format_t);
+extern int (*snd_pcm_format_set_silence_dylibloader_wrapper_asound)( snd_pcm_format_t, void*, unsigned int);
+extern snd_pcm_sframes_t (*snd_pcm_bytes_to_frames_dylibloader_wrapper_asound)( snd_pcm_t*, ssize_t);
+extern ssize_t (*snd_pcm_frames_to_bytes_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sframes_t);
+extern long (*snd_pcm_bytes_to_samples_dylibloader_wrapper_asound)( snd_pcm_t*, ssize_t);
+extern ssize_t (*snd_pcm_samples_to_bytes_dylibloader_wrapper_asound)( snd_pcm_t*, long);
+extern int (*snd_pcm_area_silence_dylibloader_wrapper_asound)(const snd_pcm_channel_area_t*, snd_pcm_uframes_t, unsigned int, snd_pcm_format_t);
+extern int (*snd_pcm_areas_silence_dylibloader_wrapper_asound)(const snd_pcm_channel_area_t*, snd_pcm_uframes_t, unsigned int, snd_pcm_uframes_t, snd_pcm_format_t);
+extern int (*snd_pcm_area_copy_dylibloader_wrapper_asound)(const snd_pcm_channel_area_t*, snd_pcm_uframes_t,const snd_pcm_channel_area_t*, snd_pcm_uframes_t, unsigned int, snd_pcm_format_t);
+extern int (*snd_pcm_areas_copy_dylibloader_wrapper_asound)(const snd_pcm_channel_area_t*, snd_pcm_uframes_t,const snd_pcm_channel_area_t*, snd_pcm_uframes_t, unsigned int, snd_pcm_uframes_t, snd_pcm_format_t);
+extern int (*snd_pcm_areas_copy_wrap_dylibloader_wrapper_asound)(const snd_pcm_channel_area_t*, snd_pcm_uframes_t,const snd_pcm_uframes_t,const snd_pcm_channel_area_t*, snd_pcm_uframes_t,const snd_pcm_uframes_t,const unsigned int, snd_pcm_uframes_t,const snd_pcm_format_t);
+extern snd_pcm_t* (*snd_pcm_hook_get_pcm_dylibloader_wrapper_asound)( snd_pcm_hook_t*);
+extern void* (*snd_pcm_hook_get_private_dylibloader_wrapper_asound)( snd_pcm_hook_t*);
+extern void (*snd_pcm_hook_set_private_dylibloader_wrapper_asound)( snd_pcm_hook_t*, void*);
+extern int (*snd_pcm_hook_add_dylibloader_wrapper_asound)( snd_pcm_hook_t**, snd_pcm_t*, snd_pcm_hook_type_t, snd_pcm_hook_func_t, void*);
+extern int (*snd_pcm_hook_remove_dylibloader_wrapper_asound)( snd_pcm_hook_t*);
+extern snd_pcm_uframes_t (*snd_pcm_meter_get_bufsize_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern unsigned int (*snd_pcm_meter_get_channels_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern unsigned int (*snd_pcm_meter_get_rate_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern snd_pcm_uframes_t (*snd_pcm_meter_get_now_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern snd_pcm_uframes_t (*snd_pcm_meter_get_boundary_dylibloader_wrapper_asound)( snd_pcm_t*);
+extern int (*snd_pcm_meter_add_scope_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_scope_t*);
+extern snd_pcm_scope_t* (*snd_pcm_meter_search_scope_dylibloader_wrapper_asound)( snd_pcm_t*,const char*);
+extern int (*snd_pcm_scope_malloc_dylibloader_wrapper_asound)( snd_pcm_scope_t**);
+extern void (*snd_pcm_scope_set_ops_dylibloader_wrapper_asound)( snd_pcm_scope_t*,const snd_pcm_scope_ops_t*);
+extern void (*snd_pcm_scope_set_name_dylibloader_wrapper_asound)( snd_pcm_scope_t*,const char*);
+extern const char* (*snd_pcm_scope_get_name_dylibloader_wrapper_asound)( snd_pcm_scope_t*);
+extern void* (*snd_pcm_scope_get_callback_private_dylibloader_wrapper_asound)( snd_pcm_scope_t*);
+extern void (*snd_pcm_scope_set_callback_private_dylibloader_wrapper_asound)( snd_pcm_scope_t*, void*);
+extern int (*snd_pcm_scope_s16_open_dylibloader_wrapper_asound)( snd_pcm_t*,const char*, snd_pcm_scope_t**);
+extern int16_t* (*snd_pcm_scope_s16_get_channel_buffer_dylibloader_wrapper_asound)( snd_pcm_scope_t*, unsigned int);
+extern int (*snd_spcm_init_dylibloader_wrapper_asound)( snd_pcm_t*, unsigned int, unsigned int, snd_pcm_format_t, snd_pcm_subformat_t, snd_spcm_latency_t, snd_pcm_access_t, snd_spcm_xrun_type_t);
+extern int (*snd_spcm_init_duplex_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_t*, unsigned int, unsigned int, snd_pcm_format_t, snd_pcm_subformat_t, snd_spcm_latency_t, snd_pcm_access_t, snd_spcm_xrun_type_t, snd_spcm_duplex_type_t);
+extern int (*snd_spcm_init_get_params_dylibloader_wrapper_asound)( snd_pcm_t*, unsigned int*, snd_pcm_uframes_t*, snd_pcm_uframes_t*);
+extern const char* (*snd_pcm_start_mode_name_dylibloader_wrapper_asound)( snd_pcm_start_t);
+extern const char* (*snd_pcm_xrun_mode_name_dylibloader_wrapper_asound)( snd_pcm_xrun_t);
+extern int (*snd_pcm_sw_params_set_start_mode_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_start_t);
+extern snd_pcm_start_t (*snd_pcm_sw_params_get_start_mode_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*);
+extern int (*snd_pcm_sw_params_set_xrun_mode_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_xrun_t);
+extern snd_pcm_xrun_t (*snd_pcm_sw_params_get_xrun_mode_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*);
+extern int (*snd_pcm_sw_params_set_xfer_align_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
+extern int (*snd_pcm_sw_params_get_xfer_align_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
+extern int (*snd_pcm_sw_params_set_sleep_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, unsigned int);
+extern int (*snd_pcm_sw_params_get_sleep_min_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, unsigned int*);
+extern int (*snd_pcm_hw_params_get_tick_time_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_tick_time_min_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_get_tick_time_max_dylibloader_wrapper_asound)(const snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_test_tick_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+extern int (*snd_pcm_hw_params_set_tick_time_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int, int);
+extern int (*snd_pcm_hw_params_set_tick_time_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_tick_time_max_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_tick_time_minmax_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_tick_time_near_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_tick_time_first_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_pcm_hw_params_set_tick_time_last_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_hw_params_t*, unsigned int*, int*);
+extern int (*snd_rawmidi_open_dylibloader_wrapper_asound)( snd_rawmidi_t**, snd_rawmidi_t**,const char*, int);
+extern int (*snd_rawmidi_open_lconf_dylibloader_wrapper_asound)( snd_rawmidi_t**, snd_rawmidi_t**,const char*, int, snd_config_t*);
+extern int (*snd_rawmidi_close_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+extern int (*snd_rawmidi_poll_descriptors_count_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+extern int (*snd_rawmidi_poll_descriptors_dylibloader_wrapper_asound)( snd_rawmidi_t*,struct pollfd*, unsigned int);
+extern int (*snd_rawmidi_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_rawmidi_t*,struct pollfd*, unsigned int, unsigned short*);
+extern int (*snd_rawmidi_nonblock_dylibloader_wrapper_asound)( snd_rawmidi_t*, int);
+extern size_t (*snd_rawmidi_info_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_rawmidi_info_malloc_dylibloader_wrapper_asound)( snd_rawmidi_info_t**);
+extern void (*snd_rawmidi_info_free_dylibloader_wrapper_asound)( snd_rawmidi_info_t*);
+extern void (*snd_rawmidi_info_copy_dylibloader_wrapper_asound)( snd_rawmidi_info_t*,const snd_rawmidi_info_t*);
+extern unsigned int (*snd_rawmidi_info_get_device_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+extern unsigned int (*snd_rawmidi_info_get_subdevice_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+extern snd_rawmidi_stream_t (*snd_rawmidi_info_get_stream_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+extern int (*snd_rawmidi_info_get_card_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+extern unsigned int (*snd_rawmidi_info_get_flags_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+extern const char* (*snd_rawmidi_info_get_id_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+extern const char* (*snd_rawmidi_info_get_name_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+extern const char* (*snd_rawmidi_info_get_subdevice_name_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+extern unsigned int (*snd_rawmidi_info_get_subdevices_count_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+extern unsigned int (*snd_rawmidi_info_get_subdevices_avail_dylibloader_wrapper_asound)(const snd_rawmidi_info_t*);
+extern void (*snd_rawmidi_info_set_device_dylibloader_wrapper_asound)( snd_rawmidi_info_t*, unsigned int);
+extern void (*snd_rawmidi_info_set_subdevice_dylibloader_wrapper_asound)( snd_rawmidi_info_t*, unsigned int);
+extern void (*snd_rawmidi_info_set_stream_dylibloader_wrapper_asound)( snd_rawmidi_info_t*, snd_rawmidi_stream_t);
+extern int (*snd_rawmidi_info_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_info_t*);
+extern size_t (*snd_rawmidi_params_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_rawmidi_params_malloc_dylibloader_wrapper_asound)( snd_rawmidi_params_t**);
+extern void (*snd_rawmidi_params_free_dylibloader_wrapper_asound)( snd_rawmidi_params_t*);
+extern void (*snd_rawmidi_params_copy_dylibloader_wrapper_asound)( snd_rawmidi_params_t*,const snd_rawmidi_params_t*);
+extern int (*snd_rawmidi_params_set_buffer_size_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_params_t*, size_t);
+extern size_t (*snd_rawmidi_params_get_buffer_size_dylibloader_wrapper_asound)(const snd_rawmidi_params_t*);
+extern int (*snd_rawmidi_params_set_avail_min_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_params_t*, size_t);
+extern size_t (*snd_rawmidi_params_get_avail_min_dylibloader_wrapper_asound)(const snd_rawmidi_params_t*);
+extern int (*snd_rawmidi_params_set_no_active_sensing_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_params_t*, int);
+extern int (*snd_rawmidi_params_get_no_active_sensing_dylibloader_wrapper_asound)(const snd_rawmidi_params_t*);
+extern int (*snd_rawmidi_params_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_params_t*);
+extern int (*snd_rawmidi_params_current_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_params_t*);
+extern size_t (*snd_rawmidi_status_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_rawmidi_status_malloc_dylibloader_wrapper_asound)( snd_rawmidi_status_t**);
+extern void (*snd_rawmidi_status_free_dylibloader_wrapper_asound)( snd_rawmidi_status_t*);
+extern void (*snd_rawmidi_status_copy_dylibloader_wrapper_asound)( snd_rawmidi_status_t*,const snd_rawmidi_status_t*);
+extern void (*snd_rawmidi_status_get_tstamp_dylibloader_wrapper_asound)(const snd_rawmidi_status_t*, snd_htimestamp_t*);
+extern size_t (*snd_rawmidi_status_get_avail_dylibloader_wrapper_asound)(const snd_rawmidi_status_t*);
+extern size_t (*snd_rawmidi_status_get_xruns_dylibloader_wrapper_asound)(const snd_rawmidi_status_t*);
+extern int (*snd_rawmidi_status_dylibloader_wrapper_asound)( snd_rawmidi_t*, snd_rawmidi_status_t*);
+extern int (*snd_rawmidi_drain_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+extern int (*snd_rawmidi_drop_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+extern ssize_t (*snd_rawmidi_write_dylibloader_wrapper_asound)( snd_rawmidi_t*,const void*, size_t);
+extern ssize_t (*snd_rawmidi_read_dylibloader_wrapper_asound)( snd_rawmidi_t*, void*, size_t);
+extern const char* (*snd_rawmidi_name_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+extern snd_rawmidi_type_t (*snd_rawmidi_type_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+extern snd_rawmidi_stream_t (*snd_rawmidi_stream_dylibloader_wrapper_asound)( snd_rawmidi_t*);
+extern int (*snd_timer_query_open_dylibloader_wrapper_asound)( snd_timer_query_t**,const char*, int);
+extern int (*snd_timer_query_open_lconf_dylibloader_wrapper_asound)( snd_timer_query_t**,const char*, int, snd_config_t*);
+extern int (*snd_timer_query_close_dylibloader_wrapper_asound)( snd_timer_query_t*);
+extern int (*snd_timer_query_next_device_dylibloader_wrapper_asound)( snd_timer_query_t*, snd_timer_id_t*);
+extern int (*snd_timer_query_info_dylibloader_wrapper_asound)( snd_timer_query_t*, snd_timer_ginfo_t*);
+extern int (*snd_timer_query_params_dylibloader_wrapper_asound)( snd_timer_query_t*, snd_timer_gparams_t*);
+extern int (*snd_timer_query_status_dylibloader_wrapper_asound)( snd_timer_query_t*, snd_timer_gstatus_t*);
+extern int (*snd_timer_open_dylibloader_wrapper_asound)( snd_timer_t**,const char*, int);
+extern int (*snd_timer_open_lconf_dylibloader_wrapper_asound)( snd_timer_t**,const char*, int, snd_config_t*);
+extern int (*snd_timer_close_dylibloader_wrapper_asound)( snd_timer_t*);
+extern int (*snd_async_add_timer_handler_dylibloader_wrapper_asound)( snd_async_handler_t**, snd_timer_t*, snd_async_callback_t, void*);
+extern snd_timer_t* (*snd_async_handler_get_timer_dylibloader_wrapper_asound)( snd_async_handler_t*);
+extern int (*snd_timer_poll_descriptors_count_dylibloader_wrapper_asound)( snd_timer_t*);
+extern int (*snd_timer_poll_descriptors_dylibloader_wrapper_asound)( snd_timer_t*,struct pollfd*, unsigned int);
+extern int (*snd_timer_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_timer_t*,struct pollfd*, unsigned int, unsigned short*);
+extern int (*snd_timer_info_dylibloader_wrapper_asound)( snd_timer_t*, snd_timer_info_t*);
+extern int (*snd_timer_params_dylibloader_wrapper_asound)( snd_timer_t*, snd_timer_params_t*);
+extern int (*snd_timer_status_dylibloader_wrapper_asound)( snd_timer_t*, snd_timer_status_t*);
+extern int (*snd_timer_start_dylibloader_wrapper_asound)( snd_timer_t*);
+extern int (*snd_timer_stop_dylibloader_wrapper_asound)( snd_timer_t*);
+extern int (*snd_timer_continue_dylibloader_wrapper_asound)( snd_timer_t*);
+extern ssize_t (*snd_timer_read_dylibloader_wrapper_asound)( snd_timer_t*, void*, size_t);
+extern size_t (*snd_timer_id_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_timer_id_malloc_dylibloader_wrapper_asound)( snd_timer_id_t**);
+extern void (*snd_timer_id_free_dylibloader_wrapper_asound)( snd_timer_id_t*);
+extern void (*snd_timer_id_copy_dylibloader_wrapper_asound)( snd_timer_id_t*,const snd_timer_id_t*);
+extern void (*snd_timer_id_set_class_dylibloader_wrapper_asound)( snd_timer_id_t*, int);
+extern int (*snd_timer_id_get_class_dylibloader_wrapper_asound)( snd_timer_id_t*);
+extern void (*snd_timer_id_set_sclass_dylibloader_wrapper_asound)( snd_timer_id_t*, int);
+extern int (*snd_timer_id_get_sclass_dylibloader_wrapper_asound)( snd_timer_id_t*);
+extern void (*snd_timer_id_set_card_dylibloader_wrapper_asound)( snd_timer_id_t*, int);
+extern int (*snd_timer_id_get_card_dylibloader_wrapper_asound)( snd_timer_id_t*);
+extern void (*snd_timer_id_set_device_dylibloader_wrapper_asound)( snd_timer_id_t*, int);
+extern int (*snd_timer_id_get_device_dylibloader_wrapper_asound)( snd_timer_id_t*);
+extern void (*snd_timer_id_set_subdevice_dylibloader_wrapper_asound)( snd_timer_id_t*, int);
+extern int (*snd_timer_id_get_subdevice_dylibloader_wrapper_asound)( snd_timer_id_t*);
+extern size_t (*snd_timer_ginfo_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_timer_ginfo_malloc_dylibloader_wrapper_asound)( snd_timer_ginfo_t**);
+extern void (*snd_timer_ginfo_free_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+extern void (*snd_timer_ginfo_copy_dylibloader_wrapper_asound)( snd_timer_ginfo_t*,const snd_timer_ginfo_t*);
+extern int (*snd_timer_ginfo_set_tid_dylibloader_wrapper_asound)( snd_timer_ginfo_t*, snd_timer_id_t*);
+extern snd_timer_id_t* (*snd_timer_ginfo_get_tid_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+extern unsigned int (*snd_timer_ginfo_get_flags_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+extern int (*snd_timer_ginfo_get_card_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+extern char* (*snd_timer_ginfo_get_id_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+extern char* (*snd_timer_ginfo_get_name_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+extern unsigned long (*snd_timer_ginfo_get_resolution_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+extern unsigned long (*snd_timer_ginfo_get_resolution_min_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+extern unsigned long (*snd_timer_ginfo_get_resolution_max_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+extern unsigned int (*snd_timer_ginfo_get_clients_dylibloader_wrapper_asound)( snd_timer_ginfo_t*);
+extern size_t (*snd_timer_info_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_timer_info_malloc_dylibloader_wrapper_asound)( snd_timer_info_t**);
+extern void (*snd_timer_info_free_dylibloader_wrapper_asound)( snd_timer_info_t*);
+extern void (*snd_timer_info_copy_dylibloader_wrapper_asound)( snd_timer_info_t*,const snd_timer_info_t*);
+extern int (*snd_timer_info_is_slave_dylibloader_wrapper_asound)( snd_timer_info_t*);
+extern int (*snd_timer_info_get_card_dylibloader_wrapper_asound)( snd_timer_info_t*);
+extern const char* (*snd_timer_info_get_id_dylibloader_wrapper_asound)( snd_timer_info_t*);
+extern const char* (*snd_timer_info_get_name_dylibloader_wrapper_asound)( snd_timer_info_t*);
+extern long (*snd_timer_info_get_resolution_dylibloader_wrapper_asound)( snd_timer_info_t*);
+extern size_t (*snd_timer_params_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_timer_params_malloc_dylibloader_wrapper_asound)( snd_timer_params_t**);
+extern void (*snd_timer_params_free_dylibloader_wrapper_asound)( snd_timer_params_t*);
+extern void (*snd_timer_params_copy_dylibloader_wrapper_asound)( snd_timer_params_t*,const snd_timer_params_t*);
+extern int (*snd_timer_params_set_auto_start_dylibloader_wrapper_asound)( snd_timer_params_t*, int);
+extern int (*snd_timer_params_get_auto_start_dylibloader_wrapper_asound)( snd_timer_params_t*);
+extern int (*snd_timer_params_set_exclusive_dylibloader_wrapper_asound)( snd_timer_params_t*, int);
+extern int (*snd_timer_params_get_exclusive_dylibloader_wrapper_asound)( snd_timer_params_t*);
+extern int (*snd_timer_params_set_early_event_dylibloader_wrapper_asound)( snd_timer_params_t*, int);
+extern int (*snd_timer_params_get_early_event_dylibloader_wrapper_asound)( snd_timer_params_t*);
+extern void (*snd_timer_params_set_ticks_dylibloader_wrapper_asound)( snd_timer_params_t*, long);
+extern long (*snd_timer_params_get_ticks_dylibloader_wrapper_asound)( snd_timer_params_t*);
+extern void (*snd_timer_params_set_queue_size_dylibloader_wrapper_asound)( snd_timer_params_t*, long);
+extern long (*snd_timer_params_get_queue_size_dylibloader_wrapper_asound)( snd_timer_params_t*);
+extern void (*snd_timer_params_set_filter_dylibloader_wrapper_asound)( snd_timer_params_t*, unsigned int);
+extern unsigned int (*snd_timer_params_get_filter_dylibloader_wrapper_asound)( snd_timer_params_t*);
+extern size_t (*snd_timer_status_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_timer_status_malloc_dylibloader_wrapper_asound)( snd_timer_status_t**);
+extern void (*snd_timer_status_free_dylibloader_wrapper_asound)( snd_timer_status_t*);
+extern void (*snd_timer_status_copy_dylibloader_wrapper_asound)( snd_timer_status_t*,const snd_timer_status_t*);
+extern snd_htimestamp_t (*snd_timer_status_get_timestamp_dylibloader_wrapper_asound)( snd_timer_status_t*);
+extern long (*snd_timer_status_get_resolution_dylibloader_wrapper_asound)( snd_timer_status_t*);
+extern long (*snd_timer_status_get_lost_dylibloader_wrapper_asound)( snd_timer_status_t*);
+extern long (*snd_timer_status_get_overrun_dylibloader_wrapper_asound)( snd_timer_status_t*);
+extern long (*snd_timer_status_get_queue_dylibloader_wrapper_asound)( snd_timer_status_t*);
+extern long (*snd_timer_info_get_ticks_dylibloader_wrapper_asound)( snd_timer_info_t*);
+extern int (*snd_hwdep_open_dylibloader_wrapper_asound)( snd_hwdep_t**,const char*, int);
+extern int (*snd_hwdep_close_dylibloader_wrapper_asound)( snd_hwdep_t*);
+extern int (*snd_hwdep_poll_descriptors_dylibloader_wrapper_asound)( snd_hwdep_t*,struct pollfd*, unsigned int);
+extern int (*snd_hwdep_poll_descriptors_count_dylibloader_wrapper_asound)( snd_hwdep_t*);
+extern int (*snd_hwdep_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_hwdep_t*,struct pollfd*, unsigned int, unsigned short*);
+extern int (*snd_hwdep_nonblock_dylibloader_wrapper_asound)( snd_hwdep_t*, int);
+extern int (*snd_hwdep_info_dylibloader_wrapper_asound)( snd_hwdep_t*, snd_hwdep_info_t*);
+extern int (*snd_hwdep_dsp_status_dylibloader_wrapper_asound)( snd_hwdep_t*, snd_hwdep_dsp_status_t*);
+extern int (*snd_hwdep_dsp_load_dylibloader_wrapper_asound)( snd_hwdep_t*, snd_hwdep_dsp_image_t*);
+extern int (*snd_hwdep_ioctl_dylibloader_wrapper_asound)( snd_hwdep_t*, unsigned int, void*);
+extern ssize_t (*snd_hwdep_write_dylibloader_wrapper_asound)( snd_hwdep_t*,const void*, size_t);
+extern ssize_t (*snd_hwdep_read_dylibloader_wrapper_asound)( snd_hwdep_t*, void*, size_t);
+extern size_t (*snd_hwdep_info_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_hwdep_info_malloc_dylibloader_wrapper_asound)( snd_hwdep_info_t**);
+extern void (*snd_hwdep_info_free_dylibloader_wrapper_asound)( snd_hwdep_info_t*);
+extern void (*snd_hwdep_info_copy_dylibloader_wrapper_asound)( snd_hwdep_info_t*,const snd_hwdep_info_t*);
+extern unsigned int (*snd_hwdep_info_get_device_dylibloader_wrapper_asound)(const snd_hwdep_info_t*);
+extern int (*snd_hwdep_info_get_card_dylibloader_wrapper_asound)(const snd_hwdep_info_t*);
+extern const char* (*snd_hwdep_info_get_id_dylibloader_wrapper_asound)(const snd_hwdep_info_t*);
+extern const char* (*snd_hwdep_info_get_name_dylibloader_wrapper_asound)(const snd_hwdep_info_t*);
+extern snd_hwdep_iface_t (*snd_hwdep_info_get_iface_dylibloader_wrapper_asound)(const snd_hwdep_info_t*);
+extern void (*snd_hwdep_info_set_device_dylibloader_wrapper_asound)( snd_hwdep_info_t*, unsigned int);
+extern size_t (*snd_hwdep_dsp_status_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_hwdep_dsp_status_malloc_dylibloader_wrapper_asound)( snd_hwdep_dsp_status_t**);
+extern void (*snd_hwdep_dsp_status_free_dylibloader_wrapper_asound)( snd_hwdep_dsp_status_t*);
+extern void (*snd_hwdep_dsp_status_copy_dylibloader_wrapper_asound)( snd_hwdep_dsp_status_t*,const snd_hwdep_dsp_status_t*);
+extern unsigned int (*snd_hwdep_dsp_status_get_version_dylibloader_wrapper_asound)(const snd_hwdep_dsp_status_t*);
+extern const char* (*snd_hwdep_dsp_status_get_id_dylibloader_wrapper_asound)(const snd_hwdep_dsp_status_t*);
+extern unsigned int (*snd_hwdep_dsp_status_get_num_dsps_dylibloader_wrapper_asound)(const snd_hwdep_dsp_status_t*);
+extern unsigned int (*snd_hwdep_dsp_status_get_dsp_loaded_dylibloader_wrapper_asound)(const snd_hwdep_dsp_status_t*);
+extern unsigned int (*snd_hwdep_dsp_status_get_chip_ready_dylibloader_wrapper_asound)(const snd_hwdep_dsp_status_t*);
+extern size_t (*snd_hwdep_dsp_image_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_hwdep_dsp_image_malloc_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t**);
+extern void (*snd_hwdep_dsp_image_free_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*);
+extern void (*snd_hwdep_dsp_image_copy_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*,const snd_hwdep_dsp_image_t*);
+extern unsigned int (*snd_hwdep_dsp_image_get_index_dylibloader_wrapper_asound)(const snd_hwdep_dsp_image_t*);
+extern const char* (*snd_hwdep_dsp_image_get_name_dylibloader_wrapper_asound)(const snd_hwdep_dsp_image_t*);
+extern const void* (*snd_hwdep_dsp_image_get_image_dylibloader_wrapper_asound)(const snd_hwdep_dsp_image_t*);
+extern size_t (*snd_hwdep_dsp_image_get_length_dylibloader_wrapper_asound)(const snd_hwdep_dsp_image_t*);
+extern void (*snd_hwdep_dsp_image_set_index_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*, unsigned int);
+extern void (*snd_hwdep_dsp_image_set_name_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*,const char*);
+extern void (*snd_hwdep_dsp_image_set_image_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*, void*);
+extern void (*snd_hwdep_dsp_image_set_length_dylibloader_wrapper_asound)( snd_hwdep_dsp_image_t*, size_t);
+extern int (*snd_card_load_dylibloader_wrapper_asound)( int);
+extern int (*snd_card_next_dylibloader_wrapper_asound)( int*);
+extern int (*snd_card_get_index_dylibloader_wrapper_asound)(const char*);
+extern int (*snd_card_get_name_dylibloader_wrapper_asound)( int, char**);
+extern int (*snd_card_get_longname_dylibloader_wrapper_asound)( int, char**);
+extern int (*snd_device_name_hint_dylibloader_wrapper_asound)( int,const char*, void***);
+extern int (*snd_device_name_free_hint_dylibloader_wrapper_asound)( void**);
+extern char* (*snd_device_name_get_hint_dylibloader_wrapper_asound)(const void*,const char*);
+extern int (*snd_ctl_open_dylibloader_wrapper_asound)( snd_ctl_t**,const char*, int);
+extern int (*snd_ctl_open_lconf_dylibloader_wrapper_asound)( snd_ctl_t**,const char*, int, snd_config_t*);
+extern int (*snd_ctl_open_fallback_dylibloader_wrapper_asound)( snd_ctl_t**, snd_config_t*,const char*,const char*, int);
+extern int (*snd_ctl_close_dylibloader_wrapper_asound)( snd_ctl_t*);
+extern int (*snd_ctl_nonblock_dylibloader_wrapper_asound)( snd_ctl_t*, int);
+extern int (*snd_async_add_ctl_handler_dylibloader_wrapper_asound)( snd_async_handler_t**, snd_ctl_t*, snd_async_callback_t, void*);
+extern snd_ctl_t* (*snd_async_handler_get_ctl_dylibloader_wrapper_asound)( snd_async_handler_t*);
+extern int (*snd_ctl_poll_descriptors_count_dylibloader_wrapper_asound)( snd_ctl_t*);
+extern int (*snd_ctl_poll_descriptors_dylibloader_wrapper_asound)( snd_ctl_t*,struct pollfd*, unsigned int);
+extern int (*snd_ctl_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_ctl_t*,struct pollfd*, unsigned int, unsigned short*);
+extern int (*snd_ctl_subscribe_events_dylibloader_wrapper_asound)( snd_ctl_t*, int);
+extern int (*snd_ctl_card_info_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_card_info_t*);
+extern int (*snd_ctl_elem_list_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_list_t*);
+extern int (*snd_ctl_elem_info_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_read_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_value_t*);
+extern int (*snd_ctl_elem_write_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_value_t*);
+extern int (*snd_ctl_elem_lock_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_id_t*);
+extern int (*snd_ctl_elem_unlock_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_id_t*);
+extern int (*snd_ctl_elem_tlv_read_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, unsigned int*, unsigned int);
+extern int (*snd_ctl_elem_tlv_write_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*,const unsigned int*);
+extern int (*snd_ctl_elem_tlv_command_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*,const unsigned int*);
+extern int (*snd_ctl_hwdep_next_device_dylibloader_wrapper_asound)( snd_ctl_t*, int*);
+extern int (*snd_ctl_hwdep_info_dylibloader_wrapper_asound)( snd_ctl_t*, snd_hwdep_info_t*);
+extern int (*snd_ctl_pcm_next_device_dylibloader_wrapper_asound)( snd_ctl_t*, int*);
+extern int (*snd_ctl_pcm_info_dylibloader_wrapper_asound)( snd_ctl_t*, snd_pcm_info_t*);
+extern int (*snd_ctl_pcm_prefer_subdevice_dylibloader_wrapper_asound)( snd_ctl_t*, int);
+extern int (*snd_ctl_rawmidi_next_device_dylibloader_wrapper_asound)( snd_ctl_t*, int*);
+extern int (*snd_ctl_rawmidi_info_dylibloader_wrapper_asound)( snd_ctl_t*, snd_rawmidi_info_t*);
+extern int (*snd_ctl_rawmidi_prefer_subdevice_dylibloader_wrapper_asound)( snd_ctl_t*, int);
+extern int (*snd_ctl_set_power_state_dylibloader_wrapper_asound)( snd_ctl_t*, unsigned int);
+extern int (*snd_ctl_get_power_state_dylibloader_wrapper_asound)( snd_ctl_t*, unsigned int*);
+extern int (*snd_ctl_read_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_event_t*);
+extern int (*snd_ctl_wait_dylibloader_wrapper_asound)( snd_ctl_t*, int);
+extern const char* (*snd_ctl_name_dylibloader_wrapper_asound)( snd_ctl_t*);
+extern snd_ctl_type_t (*snd_ctl_type_dylibloader_wrapper_asound)( snd_ctl_t*);
+extern const char* (*snd_ctl_elem_type_name_dylibloader_wrapper_asound)( snd_ctl_elem_type_t);
+extern const char* (*snd_ctl_elem_iface_name_dylibloader_wrapper_asound)( snd_ctl_elem_iface_t);
+extern const char* (*snd_ctl_event_type_name_dylibloader_wrapper_asound)( snd_ctl_event_type_t);
+extern unsigned int (*snd_ctl_event_elem_get_mask_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+extern unsigned int (*snd_ctl_event_elem_get_numid_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+extern void (*snd_ctl_event_elem_get_id_dylibloader_wrapper_asound)(const snd_ctl_event_t*, snd_ctl_elem_id_t*);
+extern snd_ctl_elem_iface_t (*snd_ctl_event_elem_get_interface_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+extern unsigned int (*snd_ctl_event_elem_get_device_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+extern unsigned int (*snd_ctl_event_elem_get_subdevice_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+extern const char* (*snd_ctl_event_elem_get_name_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+extern unsigned int (*snd_ctl_event_elem_get_index_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+extern int (*snd_ctl_elem_list_alloc_space_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*, unsigned int);
+extern void (*snd_ctl_elem_list_free_space_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*);
+extern char* (*snd_ctl_ascii_elem_id_get_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*);
+extern int (*snd_ctl_ascii_elem_id_parse_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*,const char*);
+extern int (*snd_ctl_ascii_value_parse_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_value_t*, snd_ctl_elem_info_t*,const char*);
+extern size_t (*snd_ctl_elem_id_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_ctl_elem_id_malloc_dylibloader_wrapper_asound)( snd_ctl_elem_id_t**);
+extern void (*snd_ctl_elem_id_free_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*);
+extern void (*snd_ctl_elem_id_clear_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*);
+extern void (*snd_ctl_elem_id_copy_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*,const snd_ctl_elem_id_t*);
+extern unsigned int (*snd_ctl_elem_id_get_numid_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+extern snd_ctl_elem_iface_t (*snd_ctl_elem_id_get_interface_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+extern unsigned int (*snd_ctl_elem_id_get_device_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+extern unsigned int (*snd_ctl_elem_id_get_subdevice_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+extern const char* (*snd_ctl_elem_id_get_name_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+extern unsigned int (*snd_ctl_elem_id_get_index_dylibloader_wrapper_asound)(const snd_ctl_elem_id_t*);
+extern void (*snd_ctl_elem_id_set_numid_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*, unsigned int);
+extern void (*snd_ctl_elem_id_set_interface_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*, snd_ctl_elem_iface_t);
+extern void (*snd_ctl_elem_id_set_device_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*, unsigned int);
+extern void (*snd_ctl_elem_id_set_subdevice_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*, unsigned int);
+extern void (*snd_ctl_elem_id_set_name_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*,const char*);
+extern void (*snd_ctl_elem_id_set_index_dylibloader_wrapper_asound)( snd_ctl_elem_id_t*, unsigned int);
+extern size_t (*snd_ctl_card_info_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_ctl_card_info_malloc_dylibloader_wrapper_asound)( snd_ctl_card_info_t**);
+extern void (*snd_ctl_card_info_free_dylibloader_wrapper_asound)( snd_ctl_card_info_t*);
+extern void (*snd_ctl_card_info_clear_dylibloader_wrapper_asound)( snd_ctl_card_info_t*);
+extern void (*snd_ctl_card_info_copy_dylibloader_wrapper_asound)( snd_ctl_card_info_t*,const snd_ctl_card_info_t*);
+extern int (*snd_ctl_card_info_get_card_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+extern const char* (*snd_ctl_card_info_get_id_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+extern const char* (*snd_ctl_card_info_get_driver_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+extern const char* (*snd_ctl_card_info_get_name_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+extern const char* (*snd_ctl_card_info_get_longname_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+extern const char* (*snd_ctl_card_info_get_mixername_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+extern const char* (*snd_ctl_card_info_get_components_dylibloader_wrapper_asound)(const snd_ctl_card_info_t*);
+extern size_t (*snd_ctl_event_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_ctl_event_malloc_dylibloader_wrapper_asound)( snd_ctl_event_t**);
+extern void (*snd_ctl_event_free_dylibloader_wrapper_asound)( snd_ctl_event_t*);
+extern void (*snd_ctl_event_clear_dylibloader_wrapper_asound)( snd_ctl_event_t*);
+extern void (*snd_ctl_event_copy_dylibloader_wrapper_asound)( snd_ctl_event_t*,const snd_ctl_event_t*);
+extern snd_ctl_event_type_t (*snd_ctl_event_get_type_dylibloader_wrapper_asound)(const snd_ctl_event_t*);
+extern size_t (*snd_ctl_elem_list_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_ctl_elem_list_malloc_dylibloader_wrapper_asound)( snd_ctl_elem_list_t**);
+extern void (*snd_ctl_elem_list_free_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*);
+extern void (*snd_ctl_elem_list_clear_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*);
+extern void (*snd_ctl_elem_list_copy_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*,const snd_ctl_elem_list_t*);
+extern void (*snd_ctl_elem_list_set_offset_dylibloader_wrapper_asound)( snd_ctl_elem_list_t*, unsigned int);
+extern unsigned int (*snd_ctl_elem_list_get_used_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*);
+extern unsigned int (*snd_ctl_elem_list_get_count_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*);
+extern void (*snd_ctl_elem_list_get_id_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int, snd_ctl_elem_id_t*);
+extern unsigned int (*snd_ctl_elem_list_get_numid_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+extern snd_ctl_elem_iface_t (*snd_ctl_elem_list_get_interface_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+extern unsigned int (*snd_ctl_elem_list_get_device_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+extern unsigned int (*snd_ctl_elem_list_get_subdevice_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+extern const char* (*snd_ctl_elem_list_get_name_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+extern unsigned int (*snd_ctl_elem_list_get_index_dylibloader_wrapper_asound)(const snd_ctl_elem_list_t*, unsigned int);
+extern size_t (*snd_ctl_elem_info_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_ctl_elem_info_malloc_dylibloader_wrapper_asound)( snd_ctl_elem_info_t**);
+extern void (*snd_ctl_elem_info_free_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*);
+extern void (*snd_ctl_elem_info_clear_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*);
+extern void (*snd_ctl_elem_info_copy_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*,const snd_ctl_elem_info_t*);
+extern snd_ctl_elem_type_t (*snd_ctl_elem_info_get_type_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_is_readable_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_is_writable_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_is_volatile_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_is_inactive_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_is_locked_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_is_tlv_readable_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_is_tlv_writable_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_is_tlv_commandable_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_is_owner_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_is_user_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern pid_t (*snd_ctl_elem_info_get_owner_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern unsigned int (*snd_ctl_elem_info_get_count_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern long (*snd_ctl_elem_info_get_min_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern long (*snd_ctl_elem_info_get_max_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern long (*snd_ctl_elem_info_get_step_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern long long (*snd_ctl_elem_info_get_min64_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern long long (*snd_ctl_elem_info_get_max64_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern long long (*snd_ctl_elem_info_get_step64_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern unsigned int (*snd_ctl_elem_info_get_items_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern void (*snd_ctl_elem_info_set_item_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, unsigned int);
+extern const char* (*snd_ctl_elem_info_get_item_name_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_get_dimensions_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern int (*snd_ctl_elem_info_get_dimension_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*, unsigned int);
+extern int (*snd_ctl_elem_info_set_dimension_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*,const int [4]);
+extern void (*snd_ctl_elem_info_get_id_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*, snd_ctl_elem_id_t*);
+extern unsigned int (*snd_ctl_elem_info_get_numid_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern snd_ctl_elem_iface_t (*snd_ctl_elem_info_get_interface_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern unsigned int (*snd_ctl_elem_info_get_device_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern unsigned int (*snd_ctl_elem_info_get_subdevice_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern const char* (*snd_ctl_elem_info_get_name_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern unsigned int (*snd_ctl_elem_info_get_index_dylibloader_wrapper_asound)(const snd_ctl_elem_info_t*);
+extern void (*snd_ctl_elem_info_set_id_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*,const snd_ctl_elem_id_t*);
+extern void (*snd_ctl_elem_info_set_numid_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, unsigned int);
+extern void (*snd_ctl_elem_info_set_interface_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, snd_ctl_elem_iface_t);
+extern void (*snd_ctl_elem_info_set_device_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, unsigned int);
+extern void (*snd_ctl_elem_info_set_subdevice_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, unsigned int);
+extern void (*snd_ctl_elem_info_set_name_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*,const char*);
+extern void (*snd_ctl_elem_info_set_index_dylibloader_wrapper_asound)( snd_ctl_elem_info_t*, unsigned int);
+extern int (*snd_ctl_add_integer_elem_set_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*, unsigned int, unsigned int, long, long, long);
+extern int (*snd_ctl_add_integer64_elem_set_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*, unsigned int, unsigned int, long long, long long, long long);
+extern int (*snd_ctl_add_boolean_elem_set_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*, unsigned int, unsigned int);
+extern int (*snd_ctl_add_enumerated_elem_set_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*, unsigned int, unsigned int, unsigned int,const char* []);
+extern int (*snd_ctl_add_bytes_elem_set_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_info_t*, unsigned int, unsigned int);
+extern int (*snd_ctl_elem_add_integer_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, unsigned int, long, long, long);
+extern int (*snd_ctl_elem_add_integer64_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, unsigned int, long long, long long, long long);
+extern int (*snd_ctl_elem_add_boolean_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, unsigned int);
+extern int (*snd_ctl_elem_add_enumerated_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, unsigned int, unsigned int,const char* []);
+extern int (*snd_ctl_elem_add_iec958_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*);
+extern int (*snd_ctl_elem_remove_dylibloader_wrapper_asound)( snd_ctl_t*, snd_ctl_elem_id_t*);
+extern size_t (*snd_ctl_elem_value_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_ctl_elem_value_malloc_dylibloader_wrapper_asound)( snd_ctl_elem_value_t**);
+extern void (*snd_ctl_elem_value_free_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*);
+extern void (*snd_ctl_elem_value_clear_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*);
+extern void (*snd_ctl_elem_value_copy_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*,const snd_ctl_elem_value_t*);
+extern int (*snd_ctl_elem_value_compare_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*,const snd_ctl_elem_value_t*);
+extern void (*snd_ctl_elem_value_get_id_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, snd_ctl_elem_id_t*);
+extern unsigned int (*snd_ctl_elem_value_get_numid_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+extern snd_ctl_elem_iface_t (*snd_ctl_elem_value_get_interface_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+extern unsigned int (*snd_ctl_elem_value_get_device_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+extern unsigned int (*snd_ctl_elem_value_get_subdevice_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+extern const char* (*snd_ctl_elem_value_get_name_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+extern unsigned int (*snd_ctl_elem_value_get_index_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+extern void (*snd_ctl_elem_value_set_id_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*,const snd_ctl_elem_id_t*);
+extern void (*snd_ctl_elem_value_set_numid_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int);
+extern void (*snd_ctl_elem_value_set_interface_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, snd_ctl_elem_iface_t);
+extern void (*snd_ctl_elem_value_set_device_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int);
+extern void (*snd_ctl_elem_value_set_subdevice_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int);
+extern void (*snd_ctl_elem_value_set_name_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*,const char*);
+extern void (*snd_ctl_elem_value_set_index_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int);
+extern int (*snd_ctl_elem_value_get_boolean_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, unsigned int);
+extern long (*snd_ctl_elem_value_get_integer_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, unsigned int);
+extern long long (*snd_ctl_elem_value_get_integer64_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, unsigned int);
+extern unsigned int (*snd_ctl_elem_value_get_enumerated_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, unsigned int);
+extern unsigned char (*snd_ctl_elem_value_get_byte_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, unsigned int);
+extern void (*snd_ctl_elem_value_set_boolean_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int, long);
+extern void (*snd_ctl_elem_value_set_integer_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int, long);
+extern void (*snd_ctl_elem_value_set_integer64_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int, long long);
+extern void (*snd_ctl_elem_value_set_enumerated_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int, unsigned int);
+extern void (*snd_ctl_elem_value_set_byte_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, unsigned int, unsigned char);
+extern void (*snd_ctl_elem_set_bytes_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*, void*, size_t);
+extern const void* (*snd_ctl_elem_value_get_bytes_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*);
+extern void (*snd_ctl_elem_value_get_iec958_dylibloader_wrapper_asound)(const snd_ctl_elem_value_t*, snd_aes_iec958_t*);
+extern void (*snd_ctl_elem_value_set_iec958_dylibloader_wrapper_asound)( snd_ctl_elem_value_t*,const snd_aes_iec958_t*);
+extern int (*snd_tlv_parse_dB_info_dylibloader_wrapper_asound)( unsigned int*, unsigned int, unsigned int**);
+extern int (*snd_tlv_get_dB_range_dylibloader_wrapper_asound)( unsigned int*, long, long, long*, long*);
+extern int (*snd_tlv_convert_to_dB_dylibloader_wrapper_asound)( unsigned int*, long, long, long, long*);
+extern int (*snd_tlv_convert_from_dB_dylibloader_wrapper_asound)( unsigned int*, long, long, long, long*, int);
+extern int (*snd_ctl_get_dB_range_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, long*, long*);
+extern int (*snd_ctl_convert_to_dB_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, long, long*);
+extern int (*snd_ctl_convert_from_dB_dylibloader_wrapper_asound)( snd_ctl_t*,const snd_ctl_elem_id_t*, long, long*, int);
+extern int (*snd_hctl_compare_fast_dylibloader_wrapper_asound)(const snd_hctl_elem_t*,const snd_hctl_elem_t*);
+extern int (*snd_hctl_open_dylibloader_wrapper_asound)( snd_hctl_t**,const char*, int);
+extern int (*snd_hctl_open_ctl_dylibloader_wrapper_asound)( snd_hctl_t**, snd_ctl_t*);
+extern int (*snd_hctl_close_dylibloader_wrapper_asound)( snd_hctl_t*);
+extern int (*snd_hctl_nonblock_dylibloader_wrapper_asound)( snd_hctl_t*, int);
+extern int (*snd_hctl_poll_descriptors_count_dylibloader_wrapper_asound)( snd_hctl_t*);
+extern int (*snd_hctl_poll_descriptors_dylibloader_wrapper_asound)( snd_hctl_t*,struct pollfd*, unsigned int);
+extern int (*snd_hctl_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_hctl_t*,struct pollfd*, unsigned int, unsigned short*);
+extern unsigned int (*snd_hctl_get_count_dylibloader_wrapper_asound)( snd_hctl_t*);
+extern int (*snd_hctl_set_compare_dylibloader_wrapper_asound)( snd_hctl_t*, snd_hctl_compare_t);
+extern snd_hctl_elem_t* (*snd_hctl_first_elem_dylibloader_wrapper_asound)( snd_hctl_t*);
+extern snd_hctl_elem_t* (*snd_hctl_last_elem_dylibloader_wrapper_asound)( snd_hctl_t*);
+extern snd_hctl_elem_t* (*snd_hctl_find_elem_dylibloader_wrapper_asound)( snd_hctl_t*,const snd_ctl_elem_id_t*);
+extern void (*snd_hctl_set_callback_dylibloader_wrapper_asound)( snd_hctl_t*, snd_hctl_callback_t);
+extern void (*snd_hctl_set_callback_private_dylibloader_wrapper_asound)( snd_hctl_t*, void*);
+extern void* (*snd_hctl_get_callback_private_dylibloader_wrapper_asound)( snd_hctl_t*);
+extern int (*snd_hctl_load_dylibloader_wrapper_asound)( snd_hctl_t*);
+extern int (*snd_hctl_free_dylibloader_wrapper_asound)( snd_hctl_t*);
+extern int (*snd_hctl_handle_events_dylibloader_wrapper_asound)( snd_hctl_t*);
+extern const char* (*snd_hctl_name_dylibloader_wrapper_asound)( snd_hctl_t*);
+extern int (*snd_hctl_wait_dylibloader_wrapper_asound)( snd_hctl_t*, int);
+extern snd_ctl_t* (*snd_hctl_ctl_dylibloader_wrapper_asound)( snd_hctl_t*);
+extern snd_hctl_elem_t* (*snd_hctl_elem_next_dylibloader_wrapper_asound)( snd_hctl_elem_t*);
+extern snd_hctl_elem_t* (*snd_hctl_elem_prev_dylibloader_wrapper_asound)( snd_hctl_elem_t*);
+extern int (*snd_hctl_elem_info_dylibloader_wrapper_asound)( snd_hctl_elem_t*, snd_ctl_elem_info_t*);
+extern int (*snd_hctl_elem_read_dylibloader_wrapper_asound)( snd_hctl_elem_t*, snd_ctl_elem_value_t*);
+extern int (*snd_hctl_elem_write_dylibloader_wrapper_asound)( snd_hctl_elem_t*, snd_ctl_elem_value_t*);
+extern int (*snd_hctl_elem_tlv_read_dylibloader_wrapper_asound)( snd_hctl_elem_t*, unsigned int*, unsigned int);
+extern int (*snd_hctl_elem_tlv_write_dylibloader_wrapper_asound)( snd_hctl_elem_t*,const unsigned int*);
+extern int (*snd_hctl_elem_tlv_command_dylibloader_wrapper_asound)( snd_hctl_elem_t*,const unsigned int*);
+extern snd_hctl_t* (*snd_hctl_elem_get_hctl_dylibloader_wrapper_asound)( snd_hctl_elem_t*);
+extern void (*snd_hctl_elem_get_id_dylibloader_wrapper_asound)(const snd_hctl_elem_t*, snd_ctl_elem_id_t*);
+extern unsigned int (*snd_hctl_elem_get_numid_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+extern snd_ctl_elem_iface_t (*snd_hctl_elem_get_interface_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+extern unsigned int (*snd_hctl_elem_get_device_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+extern unsigned int (*snd_hctl_elem_get_subdevice_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+extern const char* (*snd_hctl_elem_get_name_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+extern unsigned int (*snd_hctl_elem_get_index_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+extern void (*snd_hctl_elem_set_callback_dylibloader_wrapper_asound)( snd_hctl_elem_t*, snd_hctl_elem_callback_t);
+extern void* (*snd_hctl_elem_get_callback_private_dylibloader_wrapper_asound)(const snd_hctl_elem_t*);
+extern void (*snd_hctl_elem_set_callback_private_dylibloader_wrapper_asound)( snd_hctl_elem_t*, void*);
+extern int (*snd_sctl_build_dylibloader_wrapper_asound)( snd_sctl_t**, snd_ctl_t*, snd_config_t*, snd_config_t*, int);
+extern int (*snd_sctl_free_dylibloader_wrapper_asound)( snd_sctl_t*);
+extern int (*snd_sctl_install_dylibloader_wrapper_asound)( snd_sctl_t*);
+extern int (*snd_sctl_remove_dylibloader_wrapper_asound)( snd_sctl_t*);
+extern int (*snd_mixer_open_dylibloader_wrapper_asound)( snd_mixer_t**, int);
+extern int (*snd_mixer_close_dylibloader_wrapper_asound)( snd_mixer_t*);
+extern snd_mixer_elem_t* (*snd_mixer_first_elem_dylibloader_wrapper_asound)( snd_mixer_t*);
+extern snd_mixer_elem_t* (*snd_mixer_last_elem_dylibloader_wrapper_asound)( snd_mixer_t*);
+extern int (*snd_mixer_handle_events_dylibloader_wrapper_asound)( snd_mixer_t*);
+extern int (*snd_mixer_attach_dylibloader_wrapper_asound)( snd_mixer_t*,const char*);
+extern int (*snd_mixer_attach_hctl_dylibloader_wrapper_asound)( snd_mixer_t*, snd_hctl_t*);
+extern int (*snd_mixer_detach_dylibloader_wrapper_asound)( snd_mixer_t*,const char*);
+extern int (*snd_mixer_detach_hctl_dylibloader_wrapper_asound)( snd_mixer_t*, snd_hctl_t*);
+extern int (*snd_mixer_get_hctl_dylibloader_wrapper_asound)( snd_mixer_t*,const char*, snd_hctl_t**);
+extern int (*snd_mixer_poll_descriptors_count_dylibloader_wrapper_asound)( snd_mixer_t*);
+extern int (*snd_mixer_poll_descriptors_dylibloader_wrapper_asound)( snd_mixer_t*,struct pollfd*, unsigned int);
+extern int (*snd_mixer_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_mixer_t*,struct pollfd*, unsigned int, unsigned short*);
+extern int (*snd_mixer_load_dylibloader_wrapper_asound)( snd_mixer_t*);
+extern void (*snd_mixer_free_dylibloader_wrapper_asound)( snd_mixer_t*);
+extern int (*snd_mixer_wait_dylibloader_wrapper_asound)( snd_mixer_t*, int);
+extern int (*snd_mixer_set_compare_dylibloader_wrapper_asound)( snd_mixer_t*, snd_mixer_compare_t);
+extern void (*snd_mixer_set_callback_dylibloader_wrapper_asound)( snd_mixer_t*, snd_mixer_callback_t);
+extern void* (*snd_mixer_get_callback_private_dylibloader_wrapper_asound)(const snd_mixer_t*);
+extern void (*snd_mixer_set_callback_private_dylibloader_wrapper_asound)( snd_mixer_t*, void*);
+extern unsigned int (*snd_mixer_get_count_dylibloader_wrapper_asound)(const snd_mixer_t*);
+extern int (*snd_mixer_class_unregister_dylibloader_wrapper_asound)( snd_mixer_class_t*);
+extern snd_mixer_elem_t* (*snd_mixer_elem_next_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern snd_mixer_elem_t* (*snd_mixer_elem_prev_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern void (*snd_mixer_elem_set_callback_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_elem_callback_t);
+extern void* (*snd_mixer_elem_get_callback_private_dylibloader_wrapper_asound)(const snd_mixer_elem_t*);
+extern void (*snd_mixer_elem_set_callback_private_dylibloader_wrapper_asound)( snd_mixer_elem_t*, void*);
+extern snd_mixer_elem_type_t (*snd_mixer_elem_get_type_dylibloader_wrapper_asound)(const snd_mixer_elem_t*);
+extern int (*snd_mixer_class_register_dylibloader_wrapper_asound)( snd_mixer_class_t*, snd_mixer_t*);
+extern int (*snd_mixer_elem_new_dylibloader_wrapper_asound)( snd_mixer_elem_t**, snd_mixer_elem_type_t, int, void*, void*);
+extern int (*snd_mixer_elem_add_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_class_t*);
+extern int (*snd_mixer_elem_remove_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern void (*snd_mixer_elem_free_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_elem_info_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_elem_value_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_elem_attach_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_hctl_elem_t*);
+extern int (*snd_mixer_elem_detach_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_hctl_elem_t*);
+extern int (*snd_mixer_elem_empty_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern void* (*snd_mixer_elem_get_private_dylibloader_wrapper_asound)(const snd_mixer_elem_t*);
+extern size_t (*snd_mixer_class_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_mixer_class_malloc_dylibloader_wrapper_asound)( snd_mixer_class_t**);
+extern void (*snd_mixer_class_free_dylibloader_wrapper_asound)( snd_mixer_class_t*);
+extern void (*snd_mixer_class_copy_dylibloader_wrapper_asound)( snd_mixer_class_t*,const snd_mixer_class_t*);
+extern snd_mixer_t* (*snd_mixer_class_get_mixer_dylibloader_wrapper_asound)(const snd_mixer_class_t*);
+extern snd_mixer_event_t (*snd_mixer_class_get_event_dylibloader_wrapper_asound)(const snd_mixer_class_t*);
+extern void* (*snd_mixer_class_get_private_dylibloader_wrapper_asound)(const snd_mixer_class_t*);
+extern snd_mixer_compare_t (*snd_mixer_class_get_compare_dylibloader_wrapper_asound)(const snd_mixer_class_t*);
+extern int (*snd_mixer_class_set_event_dylibloader_wrapper_asound)( snd_mixer_class_t*, snd_mixer_event_t);
+extern int (*snd_mixer_class_set_private_dylibloader_wrapper_asound)( snd_mixer_class_t*, void*);
+extern int (*snd_mixer_class_set_private_free_dylibloader_wrapper_asound)( snd_mixer_class_t*, void*);
+extern int (*snd_mixer_class_set_compare_dylibloader_wrapper_asound)( snd_mixer_class_t*, snd_mixer_compare_t);
+extern const char* (*snd_mixer_selem_channel_name_dylibloader_wrapper_asound)( snd_mixer_selem_channel_id_t);
+extern int (*snd_mixer_selem_register_dylibloader_wrapper_asound)( snd_mixer_t*,struct snd_mixer_selem_regopt*, snd_mixer_class_t**);
+extern void (*snd_mixer_selem_get_id_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_id_t*);
+extern const char* (*snd_mixer_selem_get_name_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern unsigned int (*snd_mixer_selem_get_index_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern snd_mixer_elem_t* (*snd_mixer_find_selem_dylibloader_wrapper_asound)( snd_mixer_t*,const snd_mixer_selem_id_t*);
+extern int (*snd_mixer_selem_is_active_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_is_playback_mono_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_playback_channel_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t);
+extern int (*snd_mixer_selem_is_capture_mono_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_capture_channel_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t);
+extern int (*snd_mixer_selem_get_capture_group_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_common_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_playback_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_playback_volume_joined_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_capture_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_capture_volume_joined_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_common_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_playback_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_playback_switch_joined_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_capture_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_capture_switch_joined_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_has_capture_switch_exclusive_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_ask_playback_vol_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, long*);
+extern int (*snd_mixer_selem_ask_capture_vol_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, long*);
+extern int (*snd_mixer_selem_ask_playback_dB_vol_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, int, long*);
+extern int (*snd_mixer_selem_ask_capture_dB_vol_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, int, long*);
+extern int (*snd_mixer_selem_get_playback_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long*);
+extern int (*snd_mixer_selem_get_capture_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long*);
+extern int (*snd_mixer_selem_get_playback_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long*);
+extern int (*snd_mixer_selem_get_capture_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long*);
+extern int (*snd_mixer_selem_get_playback_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, int*);
+extern int (*snd_mixer_selem_get_capture_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, int*);
+extern int (*snd_mixer_selem_set_playback_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long);
+extern int (*snd_mixer_selem_set_capture_volume_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long);
+extern int (*snd_mixer_selem_set_playback_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long, int);
+extern int (*snd_mixer_selem_set_capture_dB_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, long, int);
+extern int (*snd_mixer_selem_set_playback_volume_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long);
+extern int (*snd_mixer_selem_set_capture_volume_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long);
+extern int (*snd_mixer_selem_set_playback_dB_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, int);
+extern int (*snd_mixer_selem_set_capture_dB_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, int);
+extern int (*snd_mixer_selem_set_playback_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, int);
+extern int (*snd_mixer_selem_set_capture_switch_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, int);
+extern int (*snd_mixer_selem_set_playback_switch_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, int);
+extern int (*snd_mixer_selem_set_capture_switch_all_dylibloader_wrapper_asound)( snd_mixer_elem_t*, int);
+extern int (*snd_mixer_selem_get_playback_volume_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long*, long*);
+extern int (*snd_mixer_selem_get_playback_dB_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long*, long*);
+extern int (*snd_mixer_selem_set_playback_volume_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, long);
+extern int (*snd_mixer_selem_get_capture_volume_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long*, long*);
+extern int (*snd_mixer_selem_get_capture_dB_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long*, long*);
+extern int (*snd_mixer_selem_set_capture_volume_range_dylibloader_wrapper_asound)( snd_mixer_elem_t*, long, long);
+extern int (*snd_mixer_selem_is_enumerated_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_is_enum_playback_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_is_enum_capture_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_get_enum_items_dylibloader_wrapper_asound)( snd_mixer_elem_t*);
+extern int (*snd_mixer_selem_get_enum_item_name_dylibloader_wrapper_asound)( snd_mixer_elem_t*, unsigned int, size_t, char*);
+extern int (*snd_mixer_selem_get_enum_item_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, unsigned int*);
+extern int (*snd_mixer_selem_set_enum_item_dylibloader_wrapper_asound)( snd_mixer_elem_t*, snd_mixer_selem_channel_id_t, unsigned int);
+extern size_t (*snd_mixer_selem_id_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_mixer_selem_id_malloc_dylibloader_wrapper_asound)( snd_mixer_selem_id_t**);
+extern void (*snd_mixer_selem_id_free_dylibloader_wrapper_asound)( snd_mixer_selem_id_t*);
+extern void (*snd_mixer_selem_id_copy_dylibloader_wrapper_asound)( snd_mixer_selem_id_t*,const snd_mixer_selem_id_t*);
+extern const char* (*snd_mixer_selem_id_get_name_dylibloader_wrapper_asound)(const snd_mixer_selem_id_t*);
+extern unsigned int (*snd_mixer_selem_id_get_index_dylibloader_wrapper_asound)(const snd_mixer_selem_id_t*);
+extern void (*snd_mixer_selem_id_set_name_dylibloader_wrapper_asound)( snd_mixer_selem_id_t*,const char*);
+extern void (*snd_mixer_selem_id_set_index_dylibloader_wrapper_asound)( snd_mixer_selem_id_t*, unsigned int);
+extern int (*snd_mixer_selem_id_parse_dylibloader_wrapper_asound)( snd_mixer_selem_id_t*,const char*);
+extern int (*snd_seq_open_dylibloader_wrapper_asound)( snd_seq_t**,const char*, int, int);
+extern int (*snd_seq_open_lconf_dylibloader_wrapper_asound)( snd_seq_t**,const char*, int, int, snd_config_t*);
+extern const char* (*snd_seq_name_dylibloader_wrapper_asound)( snd_seq_t*);
+extern snd_seq_type_t (*snd_seq_type_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_seq_close_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_seq_poll_descriptors_count_dylibloader_wrapper_asound)( snd_seq_t*, short);
+extern int (*snd_seq_poll_descriptors_dylibloader_wrapper_asound)( snd_seq_t*,struct pollfd*, unsigned int, short);
+extern int (*snd_seq_poll_descriptors_revents_dylibloader_wrapper_asound)( snd_seq_t*,struct pollfd*, unsigned int, unsigned short*);
+extern int (*snd_seq_nonblock_dylibloader_wrapper_asound)( snd_seq_t*, int);
+extern int (*snd_seq_client_id_dylibloader_wrapper_asound)( snd_seq_t*);
+extern size_t (*snd_seq_get_output_buffer_size_dylibloader_wrapper_asound)( snd_seq_t*);
+extern size_t (*snd_seq_get_input_buffer_size_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_seq_set_output_buffer_size_dylibloader_wrapper_asound)( snd_seq_t*, size_t);
+extern int (*snd_seq_set_input_buffer_size_dylibloader_wrapper_asound)( snd_seq_t*, size_t);
+extern size_t (*snd_seq_system_info_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_seq_system_info_malloc_dylibloader_wrapper_asound)( snd_seq_system_info_t**);
+extern void (*snd_seq_system_info_free_dylibloader_wrapper_asound)( snd_seq_system_info_t*);
+extern void (*snd_seq_system_info_copy_dylibloader_wrapper_asound)( snd_seq_system_info_t*,const snd_seq_system_info_t*);
+extern int (*snd_seq_system_info_get_queues_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+extern int (*snd_seq_system_info_get_clients_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+extern int (*snd_seq_system_info_get_ports_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+extern int (*snd_seq_system_info_get_channels_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+extern int (*snd_seq_system_info_get_cur_clients_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+extern int (*snd_seq_system_info_get_cur_queues_dylibloader_wrapper_asound)(const snd_seq_system_info_t*);
+extern int (*snd_seq_system_info_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_system_info_t*);
+extern size_t (*snd_seq_client_info_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_seq_client_info_malloc_dylibloader_wrapper_asound)( snd_seq_client_info_t**);
+extern void (*snd_seq_client_info_free_dylibloader_wrapper_asound)( snd_seq_client_info_t*);
+extern void (*snd_seq_client_info_copy_dylibloader_wrapper_asound)( snd_seq_client_info_t*,const snd_seq_client_info_t*);
+extern int (*snd_seq_client_info_get_client_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+extern snd_seq_client_type_t (*snd_seq_client_info_get_type_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+extern const char* (*snd_seq_client_info_get_name_dylibloader_wrapper_asound)( snd_seq_client_info_t*);
+extern int (*snd_seq_client_info_get_broadcast_filter_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+extern int (*snd_seq_client_info_get_error_bounce_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+extern int (*snd_seq_client_info_get_card_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+extern int (*snd_seq_client_info_get_pid_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+extern const unsigned char* (*snd_seq_client_info_get_event_filter_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+extern int (*snd_seq_client_info_get_num_ports_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+extern int (*snd_seq_client_info_get_event_lost_dylibloader_wrapper_asound)(const snd_seq_client_info_t*);
+extern void (*snd_seq_client_info_set_client_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+extern void (*snd_seq_client_info_set_name_dylibloader_wrapper_asound)( snd_seq_client_info_t*,const char*);
+extern void (*snd_seq_client_info_set_broadcast_filter_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+extern void (*snd_seq_client_info_set_error_bounce_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+extern void (*snd_seq_client_info_set_event_filter_dylibloader_wrapper_asound)( snd_seq_client_info_t*, unsigned char*);
+extern void (*snd_seq_client_info_event_filter_clear_dylibloader_wrapper_asound)( snd_seq_client_info_t*);
+extern void (*snd_seq_client_info_event_filter_add_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+extern void (*snd_seq_client_info_event_filter_del_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+extern int (*snd_seq_client_info_event_filter_check_dylibloader_wrapper_asound)( snd_seq_client_info_t*, int);
+extern int (*snd_seq_get_client_info_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_client_info_t*);
+extern int (*snd_seq_get_any_client_info_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_client_info_t*);
+extern int (*snd_seq_set_client_info_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_client_info_t*);
+extern int (*snd_seq_query_next_client_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_client_info_t*);
+extern size_t (*snd_seq_client_pool_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_seq_client_pool_malloc_dylibloader_wrapper_asound)( snd_seq_client_pool_t**);
+extern void (*snd_seq_client_pool_free_dylibloader_wrapper_asound)( snd_seq_client_pool_t*);
+extern void (*snd_seq_client_pool_copy_dylibloader_wrapper_asound)( snd_seq_client_pool_t*,const snd_seq_client_pool_t*);
+extern int (*snd_seq_client_pool_get_client_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+extern size_t (*snd_seq_client_pool_get_output_pool_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+extern size_t (*snd_seq_client_pool_get_input_pool_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+extern size_t (*snd_seq_client_pool_get_output_room_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+extern size_t (*snd_seq_client_pool_get_output_free_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+extern size_t (*snd_seq_client_pool_get_input_free_dylibloader_wrapper_asound)(const snd_seq_client_pool_t*);
+extern void (*snd_seq_client_pool_set_output_pool_dylibloader_wrapper_asound)( snd_seq_client_pool_t*, size_t);
+extern void (*snd_seq_client_pool_set_input_pool_dylibloader_wrapper_asound)( snd_seq_client_pool_t*, size_t);
+extern void (*snd_seq_client_pool_set_output_room_dylibloader_wrapper_asound)( snd_seq_client_pool_t*, size_t);
+extern int (*snd_seq_get_client_pool_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_client_pool_t*);
+extern int (*snd_seq_set_client_pool_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_client_pool_t*);
+extern size_t (*snd_seq_port_info_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_seq_port_info_malloc_dylibloader_wrapper_asound)( snd_seq_port_info_t**);
+extern void (*snd_seq_port_info_free_dylibloader_wrapper_asound)( snd_seq_port_info_t*);
+extern void (*snd_seq_port_info_copy_dylibloader_wrapper_asound)( snd_seq_port_info_t*,const snd_seq_port_info_t*);
+extern int (*snd_seq_port_info_get_client_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern int (*snd_seq_port_info_get_port_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern const snd_seq_addr_t* (*snd_seq_port_info_get_addr_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern const char* (*snd_seq_port_info_get_name_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern unsigned int (*snd_seq_port_info_get_capability_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern unsigned int (*snd_seq_port_info_get_type_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern int (*snd_seq_port_info_get_midi_channels_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern int (*snd_seq_port_info_get_midi_voices_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern int (*snd_seq_port_info_get_synth_voices_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern int (*snd_seq_port_info_get_read_use_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern int (*snd_seq_port_info_get_write_use_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern int (*snd_seq_port_info_get_port_specified_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern int (*snd_seq_port_info_get_timestamping_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern int (*snd_seq_port_info_get_timestamp_real_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern int (*snd_seq_port_info_get_timestamp_queue_dylibloader_wrapper_asound)(const snd_seq_port_info_t*);
+extern void (*snd_seq_port_info_set_client_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+extern void (*snd_seq_port_info_set_port_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+extern void (*snd_seq_port_info_set_addr_dylibloader_wrapper_asound)( snd_seq_port_info_t*,const snd_seq_addr_t*);
+extern void (*snd_seq_port_info_set_name_dylibloader_wrapper_asound)( snd_seq_port_info_t*,const char*);
+extern void (*snd_seq_port_info_set_capability_dylibloader_wrapper_asound)( snd_seq_port_info_t*, unsigned int);
+extern void (*snd_seq_port_info_set_type_dylibloader_wrapper_asound)( snd_seq_port_info_t*, unsigned int);
+extern void (*snd_seq_port_info_set_midi_channels_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+extern void (*snd_seq_port_info_set_midi_voices_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+extern void (*snd_seq_port_info_set_synth_voices_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+extern void (*snd_seq_port_info_set_port_specified_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+extern void (*snd_seq_port_info_set_timestamping_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+extern void (*snd_seq_port_info_set_timestamp_real_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+extern void (*snd_seq_port_info_set_timestamp_queue_dylibloader_wrapper_asound)( snd_seq_port_info_t*, int);
+extern int (*snd_seq_create_port_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_port_info_t*);
+extern int (*snd_seq_delete_port_dylibloader_wrapper_asound)( snd_seq_t*, int);
+extern int (*snd_seq_get_port_info_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_port_info_t*);
+extern int (*snd_seq_get_any_port_info_dylibloader_wrapper_asound)( snd_seq_t*, int, int, snd_seq_port_info_t*);
+extern int (*snd_seq_set_port_info_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_port_info_t*);
+extern int (*snd_seq_query_next_port_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_port_info_t*);
+extern size_t (*snd_seq_port_subscribe_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_seq_port_subscribe_malloc_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t**);
+extern void (*snd_seq_port_subscribe_free_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*);
+extern void (*snd_seq_port_subscribe_copy_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*,const snd_seq_port_subscribe_t*);
+extern const snd_seq_addr_t* (*snd_seq_port_subscribe_get_sender_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+extern const snd_seq_addr_t* (*snd_seq_port_subscribe_get_dest_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+extern int (*snd_seq_port_subscribe_get_queue_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+extern int (*snd_seq_port_subscribe_get_exclusive_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+extern int (*snd_seq_port_subscribe_get_time_update_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+extern int (*snd_seq_port_subscribe_get_time_real_dylibloader_wrapper_asound)(const snd_seq_port_subscribe_t*);
+extern void (*snd_seq_port_subscribe_set_sender_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*,const snd_seq_addr_t*);
+extern void (*snd_seq_port_subscribe_set_dest_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*,const snd_seq_addr_t*);
+extern void (*snd_seq_port_subscribe_set_queue_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*, int);
+extern void (*snd_seq_port_subscribe_set_exclusive_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*, int);
+extern void (*snd_seq_port_subscribe_set_time_update_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*, int);
+extern void (*snd_seq_port_subscribe_set_time_real_dylibloader_wrapper_asound)( snd_seq_port_subscribe_t*, int);
+extern int (*snd_seq_get_port_subscription_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_port_subscribe_t*);
+extern int (*snd_seq_subscribe_port_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_port_subscribe_t*);
+extern int (*snd_seq_unsubscribe_port_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_port_subscribe_t*);
+extern size_t (*snd_seq_query_subscribe_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_seq_query_subscribe_malloc_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t**);
+extern void (*snd_seq_query_subscribe_free_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*);
+extern void (*snd_seq_query_subscribe_copy_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*,const snd_seq_query_subscribe_t*);
+extern int (*snd_seq_query_subscribe_get_client_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+extern int (*snd_seq_query_subscribe_get_port_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+extern const snd_seq_addr_t* (*snd_seq_query_subscribe_get_root_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+extern snd_seq_query_subs_type_t (*snd_seq_query_subscribe_get_type_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+extern int (*snd_seq_query_subscribe_get_index_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+extern int (*snd_seq_query_subscribe_get_num_subs_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+extern const snd_seq_addr_t* (*snd_seq_query_subscribe_get_addr_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+extern int (*snd_seq_query_subscribe_get_queue_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+extern int (*snd_seq_query_subscribe_get_exclusive_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+extern int (*snd_seq_query_subscribe_get_time_update_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+extern int (*snd_seq_query_subscribe_get_time_real_dylibloader_wrapper_asound)(const snd_seq_query_subscribe_t*);
+extern void (*snd_seq_query_subscribe_set_client_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*, int);
+extern void (*snd_seq_query_subscribe_set_port_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*, int);
+extern void (*snd_seq_query_subscribe_set_root_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*,const snd_seq_addr_t*);
+extern void (*snd_seq_query_subscribe_set_type_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*, snd_seq_query_subs_type_t);
+extern void (*snd_seq_query_subscribe_set_index_dylibloader_wrapper_asound)( snd_seq_query_subscribe_t*, int);
+extern int (*snd_seq_query_port_subscribers_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_query_subscribe_t*);
+extern size_t (*snd_seq_queue_info_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_seq_queue_info_malloc_dylibloader_wrapper_asound)( snd_seq_queue_info_t**);
+extern void (*snd_seq_queue_info_free_dylibloader_wrapper_asound)( snd_seq_queue_info_t*);
+extern void (*snd_seq_queue_info_copy_dylibloader_wrapper_asound)( snd_seq_queue_info_t*,const snd_seq_queue_info_t*);
+extern int (*snd_seq_queue_info_get_queue_dylibloader_wrapper_asound)(const snd_seq_queue_info_t*);
+extern const char* (*snd_seq_queue_info_get_name_dylibloader_wrapper_asound)(const snd_seq_queue_info_t*);
+extern int (*snd_seq_queue_info_get_owner_dylibloader_wrapper_asound)(const snd_seq_queue_info_t*);
+extern int (*snd_seq_queue_info_get_locked_dylibloader_wrapper_asound)(const snd_seq_queue_info_t*);
+extern unsigned int (*snd_seq_queue_info_get_flags_dylibloader_wrapper_asound)(const snd_seq_queue_info_t*);
+extern void (*snd_seq_queue_info_set_name_dylibloader_wrapper_asound)( snd_seq_queue_info_t*,const char*);
+extern void (*snd_seq_queue_info_set_owner_dylibloader_wrapper_asound)( snd_seq_queue_info_t*, int);
+extern void (*snd_seq_queue_info_set_locked_dylibloader_wrapper_asound)( snd_seq_queue_info_t*, int);
+extern void (*snd_seq_queue_info_set_flags_dylibloader_wrapper_asound)( snd_seq_queue_info_t*, unsigned int);
+extern int (*snd_seq_create_queue_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_queue_info_t*);
+extern int (*snd_seq_alloc_named_queue_dylibloader_wrapper_asound)( snd_seq_t*,const char*);
+extern int (*snd_seq_alloc_queue_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_seq_free_queue_dylibloader_wrapper_asound)( snd_seq_t*, int);
+extern int (*snd_seq_get_queue_info_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_info_t*);
+extern int (*snd_seq_set_queue_info_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_info_t*);
+extern int (*snd_seq_query_named_queue_dylibloader_wrapper_asound)( snd_seq_t*,const char*);
+extern int (*snd_seq_get_queue_usage_dylibloader_wrapper_asound)( snd_seq_t*, int);
+extern int (*snd_seq_set_queue_usage_dylibloader_wrapper_asound)( snd_seq_t*, int, int);
+extern size_t (*snd_seq_queue_status_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_seq_queue_status_malloc_dylibloader_wrapper_asound)( snd_seq_queue_status_t**);
+extern void (*snd_seq_queue_status_free_dylibloader_wrapper_asound)( snd_seq_queue_status_t*);
+extern void (*snd_seq_queue_status_copy_dylibloader_wrapper_asound)( snd_seq_queue_status_t*,const snd_seq_queue_status_t*);
+extern int (*snd_seq_queue_status_get_queue_dylibloader_wrapper_asound)(const snd_seq_queue_status_t*);
+extern int (*snd_seq_queue_status_get_events_dylibloader_wrapper_asound)(const snd_seq_queue_status_t*);
+extern snd_seq_tick_time_t (*snd_seq_queue_status_get_tick_time_dylibloader_wrapper_asound)(const snd_seq_queue_status_t*);
+extern const snd_seq_real_time_t* (*snd_seq_queue_status_get_real_time_dylibloader_wrapper_asound)(const snd_seq_queue_status_t*);
+extern unsigned int (*snd_seq_queue_status_get_status_dylibloader_wrapper_asound)(const snd_seq_queue_status_t*);
+extern int (*snd_seq_get_queue_status_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_status_t*);
+extern size_t (*snd_seq_queue_tempo_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_seq_queue_tempo_malloc_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t**);
+extern void (*snd_seq_queue_tempo_free_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*);
+extern void (*snd_seq_queue_tempo_copy_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*,const snd_seq_queue_tempo_t*);
+extern int (*snd_seq_queue_tempo_get_queue_dylibloader_wrapper_asound)(const snd_seq_queue_tempo_t*);
+extern unsigned int (*snd_seq_queue_tempo_get_tempo_dylibloader_wrapper_asound)(const snd_seq_queue_tempo_t*);
+extern int (*snd_seq_queue_tempo_get_ppq_dylibloader_wrapper_asound)(const snd_seq_queue_tempo_t*);
+extern unsigned int (*snd_seq_queue_tempo_get_skew_dylibloader_wrapper_asound)(const snd_seq_queue_tempo_t*);
+extern unsigned int (*snd_seq_queue_tempo_get_skew_base_dylibloader_wrapper_asound)(const snd_seq_queue_tempo_t*);
+extern void (*snd_seq_queue_tempo_set_tempo_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*, unsigned int);
+extern void (*snd_seq_queue_tempo_set_ppq_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*, int);
+extern void (*snd_seq_queue_tempo_set_skew_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*, unsigned int);
+extern void (*snd_seq_queue_tempo_set_skew_base_dylibloader_wrapper_asound)( snd_seq_queue_tempo_t*, unsigned int);
+extern int (*snd_seq_get_queue_tempo_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_tempo_t*);
+extern int (*snd_seq_set_queue_tempo_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_tempo_t*);
+extern size_t (*snd_seq_queue_timer_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_seq_queue_timer_malloc_dylibloader_wrapper_asound)( snd_seq_queue_timer_t**);
+extern void (*snd_seq_queue_timer_free_dylibloader_wrapper_asound)( snd_seq_queue_timer_t*);
+extern void (*snd_seq_queue_timer_copy_dylibloader_wrapper_asound)( snd_seq_queue_timer_t*,const snd_seq_queue_timer_t*);
+extern int (*snd_seq_queue_timer_get_queue_dylibloader_wrapper_asound)(const snd_seq_queue_timer_t*);
+extern snd_seq_queue_timer_type_t (*snd_seq_queue_timer_get_type_dylibloader_wrapper_asound)(const snd_seq_queue_timer_t*);
+extern const snd_timer_id_t* (*snd_seq_queue_timer_get_id_dylibloader_wrapper_asound)(const snd_seq_queue_timer_t*);
+extern unsigned int (*snd_seq_queue_timer_get_resolution_dylibloader_wrapper_asound)(const snd_seq_queue_timer_t*);
+extern void (*snd_seq_queue_timer_set_type_dylibloader_wrapper_asound)( snd_seq_queue_timer_t*, snd_seq_queue_timer_type_t);
+extern void (*snd_seq_queue_timer_set_id_dylibloader_wrapper_asound)( snd_seq_queue_timer_t*,const snd_timer_id_t*);
+extern void (*snd_seq_queue_timer_set_resolution_dylibloader_wrapper_asound)( snd_seq_queue_timer_t*, unsigned int);
+extern int (*snd_seq_get_queue_timer_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_timer_t*);
+extern int (*snd_seq_set_queue_timer_dylibloader_wrapper_asound)( snd_seq_t*, int, snd_seq_queue_timer_t*);
+extern int (*snd_seq_free_event_dylibloader_wrapper_asound)( snd_seq_event_t*);
+extern ssize_t (*snd_seq_event_length_dylibloader_wrapper_asound)( snd_seq_event_t*);
+extern int (*snd_seq_event_output_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_event_t*);
+extern int (*snd_seq_event_output_buffer_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_event_t*);
+extern int (*snd_seq_event_output_direct_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_event_t*);
+extern int (*snd_seq_event_input_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_event_t**);
+extern int (*snd_seq_event_input_pending_dylibloader_wrapper_asound)( snd_seq_t*, int);
+extern int (*snd_seq_drain_output_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_seq_event_output_pending_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_seq_extract_output_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_event_t**);
+extern int (*snd_seq_drop_output_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_seq_drop_output_buffer_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_seq_drop_input_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_seq_drop_input_buffer_dylibloader_wrapper_asound)( snd_seq_t*);
+extern size_t (*snd_seq_remove_events_sizeof_dylibloader_wrapper_asound)( void);
+extern int (*snd_seq_remove_events_malloc_dylibloader_wrapper_asound)( snd_seq_remove_events_t**);
+extern void (*snd_seq_remove_events_free_dylibloader_wrapper_asound)( snd_seq_remove_events_t*);
+extern void (*snd_seq_remove_events_copy_dylibloader_wrapper_asound)( snd_seq_remove_events_t*,const snd_seq_remove_events_t*);
+extern unsigned int (*snd_seq_remove_events_get_condition_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+extern int (*snd_seq_remove_events_get_queue_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+extern const snd_seq_timestamp_t* (*snd_seq_remove_events_get_time_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+extern const snd_seq_addr_t* (*snd_seq_remove_events_get_dest_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+extern int (*snd_seq_remove_events_get_channel_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+extern int (*snd_seq_remove_events_get_event_type_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+extern int (*snd_seq_remove_events_get_tag_dylibloader_wrapper_asound)(const snd_seq_remove_events_t*);
+extern void (*snd_seq_remove_events_set_condition_dylibloader_wrapper_asound)( snd_seq_remove_events_t*, unsigned int);
+extern void (*snd_seq_remove_events_set_queue_dylibloader_wrapper_asound)( snd_seq_remove_events_t*, int);
+extern void (*snd_seq_remove_events_set_time_dylibloader_wrapper_asound)( snd_seq_remove_events_t*,const snd_seq_timestamp_t*);
+extern void (*snd_seq_remove_events_set_dest_dylibloader_wrapper_asound)( snd_seq_remove_events_t*,const snd_seq_addr_t*);
+extern void (*snd_seq_remove_events_set_channel_dylibloader_wrapper_asound)( snd_seq_remove_events_t*, int);
+extern void (*snd_seq_remove_events_set_event_type_dylibloader_wrapper_asound)( snd_seq_remove_events_t*, int);
+extern void (*snd_seq_remove_events_set_tag_dylibloader_wrapper_asound)( snd_seq_remove_events_t*, int);
+extern int (*snd_seq_remove_events_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_remove_events_t*);
+extern void (*snd_seq_set_bit_dylibloader_wrapper_asound)( int, void*);
+extern void (*snd_seq_unset_bit_dylibloader_wrapper_asound)( int, void*);
+extern int (*snd_seq_change_bit_dylibloader_wrapper_asound)( int, void*);
+extern int (*snd_seq_get_bit_dylibloader_wrapper_asound)( int, void*);
+extern int (*snd_seq_control_queue_dylibloader_wrapper_asound)( snd_seq_t*, int, int, int, snd_seq_event_t*);
+extern int (*snd_seq_create_simple_port_dylibloader_wrapper_asound)( snd_seq_t*,const char*, unsigned int, unsigned int);
+extern int (*snd_seq_delete_simple_port_dylibloader_wrapper_asound)( snd_seq_t*, int);
+extern int (*snd_seq_connect_from_dylibloader_wrapper_asound)( snd_seq_t*, int, int, int);
+extern int (*snd_seq_connect_to_dylibloader_wrapper_asound)( snd_seq_t*, int, int, int);
+extern int (*snd_seq_disconnect_from_dylibloader_wrapper_asound)( snd_seq_t*, int, int, int);
+extern int (*snd_seq_disconnect_to_dylibloader_wrapper_asound)( snd_seq_t*, int, int, int);
+extern int (*snd_seq_set_client_name_dylibloader_wrapper_asound)( snd_seq_t*,const char*);
+extern int (*snd_seq_set_client_event_filter_dylibloader_wrapper_asound)( snd_seq_t*, int);
+extern int (*snd_seq_set_client_pool_output_dylibloader_wrapper_asound)( snd_seq_t*, size_t);
+extern int (*snd_seq_set_client_pool_output_room_dylibloader_wrapper_asound)( snd_seq_t*, size_t);
+extern int (*snd_seq_set_client_pool_input_dylibloader_wrapper_asound)( snd_seq_t*, size_t);
+extern int (*snd_seq_sync_output_queue_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_seq_parse_address_dylibloader_wrapper_asound)( snd_seq_t*, snd_seq_addr_t*,const char*);
+extern int (*snd_seq_reset_pool_output_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_seq_reset_pool_input_dylibloader_wrapper_asound)( snd_seq_t*);
+extern int (*snd_midi_event_new_dylibloader_wrapper_asound)( size_t, snd_midi_event_t**);
+extern int (*snd_midi_event_resize_buffer_dylibloader_wrapper_asound)( snd_midi_event_t*, size_t);
+extern void (*snd_midi_event_free_dylibloader_wrapper_asound)( snd_midi_event_t*);
+extern void (*snd_midi_event_init_dylibloader_wrapper_asound)( snd_midi_event_t*);
+extern void (*snd_midi_event_reset_encode_dylibloader_wrapper_asound)( snd_midi_event_t*);
+extern void (*snd_midi_event_reset_decode_dylibloader_wrapper_asound)( snd_midi_event_t*);
+extern void (*snd_midi_event_no_status_dylibloader_wrapper_asound)( snd_midi_event_t*, int);
+extern long (*snd_midi_event_encode_dylibloader_wrapper_asound)( snd_midi_event_t*,const unsigned char*, long, snd_seq_event_t*);
+extern int (*snd_midi_event_encode_byte_dylibloader_wrapper_asound)( snd_midi_event_t*, int, snd_seq_event_t*);
+extern long (*snd_midi_event_decode_dylibloader_wrapper_asound)( snd_midi_event_t*, unsigned char*, long,const snd_seq_event_t*);
+int initialize_asound(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index ea0cba6c52..61475c74e7 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -37,8 +37,14 @@
#include <errno.h>
+#ifdef PULSEAUDIO_ENABLED
+extern "C" {
+extern int initialize_pulse(int verbose);
+}
+#endif
+
Error AudioDriverALSA::init_device() {
- mix_rate = GLOBAL_GET("audio/mix_rate");
+ mix_rate = GLOBAL_GET("audio/driver/mix_rate");
speaker_mode = SPEAKER_MODE_STEREO;
channels = 2;
@@ -104,7 +110,7 @@ Error AudioDriverALSA::init_device() {
// In ALSA the period size seems to be the one that will determine the actual latency
// Ref: https://www.alsa-project.org/main/index.php/FramesPeriods
unsigned int periods = 2;
- int latency = GLOBAL_GET("audio/output_latency");
+ int latency = GLOBAL_GET("audio/driver/output_latency");
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
buffer_size = buffer_frames * periods;
period_size = buffer_frames;
@@ -147,6 +153,21 @@ Error AudioDriverALSA::init_device() {
}
Error AudioDriverALSA::init() {
+#ifdef DEBUG_ENABLED
+ int dylibloader_verbose = 1;
+#else
+ int dylibloader_verbose = 0;
+#endif
+#ifdef PULSEAUDIO_ENABLED
+ // On pulse enabled systems Alsa will silently use pulse.
+ // It doesn't matter if this fails as that likely means there is no pulse
+ initialize_pulse(dylibloader_verbose);
+#endif
+
+ if (initialize_asound(dylibloader_verbose)) {
+ return ERR_CANT_OPEN;
+ }
+
active = false;
thread_exited = false;
exit_thread = false;
diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h
index c0233f41e1..ca97e76bc2 100644
--- a/drivers/alsa/audio_driver_alsa.h
+++ b/drivers/alsa/audio_driver_alsa.h
@@ -37,7 +37,7 @@
#include "core/os/thread.h"
#include "servers/audio_server.h"
-#include <alsa/asoundlib.h>
+#include "asound-so_wrap.h"
class AudioDriverALSA : public AudioDriver {
Thread thread;
diff --git a/drivers/alsamidi/midi_driver_alsamidi.h b/drivers/alsamidi/midi_driver_alsamidi.h
index 474f139bd6..c327712ee7 100644
--- a/drivers/alsamidi/midi_driver_alsamidi.h
+++ b/drivers/alsamidi/midi_driver_alsamidi.h
@@ -38,7 +38,7 @@
#include "core/os/thread.h"
#include "core/templates/vector.h"
-#include <alsa/asoundlib.h>
+#include "../alsa/asound-so_wrap.h"
#include <stdio.h>
class MIDIDriverALSAMidi : public MIDIDriver {
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp
index 6f88107086..f40036d628 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.cpp
+++ b/drivers/coreaudio/audio_driver_coreaudio.cpp
@@ -116,7 +116,7 @@ Error AudioDriverCoreAudio::init() {
break;
}
- mix_rate = GLOBAL_GET("audio/mix_rate");
+ mix_rate = GLOBAL_GET("audio/driver/mix_rate");
zeromem(&strdesc, sizeof(strdesc));
strdesc.mFormatID = kAudioFormatLinearPCM;
@@ -131,7 +131,7 @@ Error AudioDriverCoreAudio::init() {
result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc));
ERR_FAIL_COND_V(result != noErr, FAILED);
- int latency = GLOBAL_GET("audio/output_latency");
+ int latency = GLOBAL_GET("audio/driver/output_latency");
// Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
@@ -157,7 +157,7 @@ Error AudioDriverCoreAudio::init() {
result = AudioUnitInitialize(audio_unit);
ERR_FAIL_COND_V(result != noErr, FAILED);
- if (GLOBAL_GET("audio/enable_audio_input")) {
+ if (GLOBAL_GET("audio/driver/enable_input")) {
return capture_init();
}
return OK;
@@ -403,7 +403,7 @@ Error AudioDriverCoreAudio::capture_init() {
break;
}
- mix_rate = GLOBAL_GET("audio/mix_rate");
+ mix_rate = GLOBAL_GET("audio/driver/mix_rate");
zeromem(&strdesc, sizeof(strdesc));
strdesc.mFormatID = kAudioFormatLinearPCM;
@@ -506,7 +506,8 @@ Array AudioDriverCoreAudio::_get_device_list(bool capture) {
UInt32 size = 0;
AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, nullptr, &size);
- AudioDeviceID *audioDevices = (AudioDeviceID *)malloc(size);
+ AudioDeviceID *audioDevices = (AudioDeviceID *)memalloc(size);
+ ERR_FAIL_NULL_V_MSG(audioDevices, list, "Out of memory.");
AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, nullptr, &size, audioDevices);
UInt32 deviceCount = size / sizeof(AudioDeviceID);
@@ -515,14 +516,15 @@ Array AudioDriverCoreAudio::_get_device_list(bool capture) {
prop.mSelector = kAudioDevicePropertyStreamConfiguration;
AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, nullptr, &size);
- AudioBufferList *bufferList = (AudioBufferList *)malloc(size);
+ AudioBufferList *bufferList = (AudioBufferList *)memalloc(size);
+ ERR_FAIL_NULL_V_MSG(bufferList, list, "Out of memory.");
AudioObjectGetPropertyData(audioDevices[i], &prop, 0, nullptr, &size, bufferList);
UInt32 channelCount = 0;
for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++)
channelCount += bufferList->mBuffers[j].mNumberChannels;
- free(bufferList);
+ memfree(bufferList);
if (channelCount >= 1) {
CFStringRef cfname;
@@ -534,17 +536,18 @@ Array AudioDriverCoreAudio::_get_device_list(bool capture) {
CFIndex length = CFStringGetLength(cfname);
CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
- char *buffer = (char *)malloc(maxSize);
+ char *buffer = (char *)memalloc(maxSize);
+ ERR_FAIL_NULL_V_MSG(buffer, list, "Out of memory.");
if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) {
// Append the ID to the name in case we have devices with duplicate name
list.push_back(String(buffer) + " (" + itos(audioDevices[i]) + ")");
}
- free(buffer);
+ memfree(buffer);
}
}
- free(audioDevices);
+ memfree(audioDevices);
return list;
}
@@ -561,7 +564,8 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) {
UInt32 size = 0;
AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, nullptr, &size);
- AudioDeviceID *audioDevices = (AudioDeviceID *)malloc(size);
+ AudioDeviceID *audioDevices = (AudioDeviceID *)memalloc(size);
+ ERR_FAIL_NULL_MSG(audioDevices, "Out of memory.");
AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, nullptr, &size, audioDevices);
UInt32 deviceCount = size / sizeof(AudioDeviceID);
@@ -570,14 +574,15 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) {
prop.mSelector = kAudioDevicePropertyStreamConfiguration;
AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, nullptr, &size);
- AudioBufferList *bufferList = (AudioBufferList *)malloc(size);
+ AudioBufferList *bufferList = (AudioBufferList *)memalloc(size);
+ ERR_FAIL_NULL_MSG(bufferList, "Out of memory.");
AudioObjectGetPropertyData(audioDevices[i], &prop, 0, nullptr, &size, bufferList);
UInt32 channelCount = 0;
for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++)
channelCount += bufferList->mBuffers[j].mNumberChannels;
- free(bufferList);
+ memfree(bufferList);
if (channelCount >= 1) {
CFStringRef cfname;
@@ -589,7 +594,8 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) {
CFIndex length = CFStringGetLength(cfname);
CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
- char *buffer = (char *)malloc(maxSize);
+ char *buffer = (char *)memalloc(maxSize);
+ ERR_FAIL_NULL_MSG(buffer, "Out of memory.");
if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) {
String name = String(buffer) + " (" + itos(audioDevices[i]) + ")";
if (name == device) {
@@ -598,11 +604,11 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) {
}
}
- free(buffer);
+ memfree(buffer);
}
}
- free(audioDevices);
+ memfree(audioDevices);
}
if (!found) {
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h
index 72ab18d115..9d6be1a802 100644
--- a/drivers/dummy/rasterizer_dummy.h
+++ b/drivers/dummy/rasterizer_dummy.h
@@ -80,11 +80,11 @@ public:
int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; }
AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); }
uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; }
- void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const Vector<RID> &p_directional_lights, const RID *p_positional_light_instances, uint32_t p_positional_light_count) override {}
/* SKY API */
- RID sky_create() override { return RID(); }
+ RID sky_allocate() override { return RID(); }
+ void sky_initialize(RID p_rid) override {}
void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {}
void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {}
void sky_set_material(RID p_sky, RID p_material) override {}
@@ -92,8 +92,8 @@ public:
/* ENVIRONMENT API */
- RID environment_create() override { return RID(); }
-
+ RID environment_allocate() override { return RID(); }
+ void environment_initialize(RID p_rid) override {}
void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {}
void environment_set_sky(RID p_env, RID p_sky) override {}
void environment_set_sky_custom_fov(RID p_env, float p_scale) override {}
@@ -112,7 +112,7 @@ public:
void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {}
void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
- void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
+ void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {}
void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {}
@@ -123,11 +123,9 @@ public:
void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {}
void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {}
- void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) override {}
+ void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) override {}
void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
- void environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) override {}
- void environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size) override {}
Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
@@ -135,8 +133,8 @@ public:
RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; }
int environment_get_canvas_max_layer(RID p_env) const override { return 0; }
- RID camera_effects_create() override { return RID(); }
-
+ RID camera_effects_allocate() override { return RID(); }
+ void camera_effects_initialize(RID p_rid) override {}
void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {}
void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {}
@@ -177,11 +175,8 @@ public:
void gi_probe_set_quality(RS::GIProbeQuality) override {}
- void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) override {}
- void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) override {}
+ void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) override {}
void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
- void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances) override {}
- void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_lights) override {}
void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
void set_scene_pass(uint64_t p_pass) override {}
@@ -212,61 +207,48 @@ public:
class RasterizerStorageDummy : public RendererStorage {
public:
+ bool can_create_resources_async() const override { return false; }
+
/* TEXTURE API */
struct DummyTexture {
- int width = 0;
- int height = 0;
- uint32_t flags = 0;
- Image::Format format = Image::Format::FORMAT_MAX;
Ref<Image> image;
- String path;
- };
-
- struct DummySurface {
- uint32_t format = 0;
- RS::PrimitiveType primitive = RS::PrimitiveType::PRIMITIVE_MAX;
- Vector<uint8_t> array;
- int vertex_count = 0;
- Vector<uint8_t> index_array;
- int index_count = 0;
- AABB aabb;
- Vector<Vector<uint8_t>> blend_shapes;
- Vector<AABB> bone_aabbs;
- };
-
- struct DummyMesh {
- Vector<DummySurface> surfaces;
- int blend_shape_count = 0;
- RS::BlendShapeMode blend_shape_mode = RS::BlendShapeMode::BLEND_SHAPE_MODE_NORMALIZED;
};
-
mutable RID_PtrOwner<DummyTexture> texture_owner;
- mutable RID_PtrOwner<DummyMesh> mesh_owner;
- RID texture_2d_create(const Ref<Image> &p_image) override { return RID(); }
- RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override { return RID(); }
- RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override { return RID(); }
- RID texture_proxy_create(RID p_base) override { return RID(); }
+ RID texture_allocate() override {
+ DummyTexture *texture = memnew(DummyTexture);
+ ERR_FAIL_COND_V(!texture, RID());
+ return texture_owner.make_rid(texture);
+ }
+ void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override {
+ DummyTexture *t = texture_owner.getornull(p_texture);
+ ERR_FAIL_COND(!t);
+ t->image = p_image->duplicate();
+ }
+ void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {}
void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
+ void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {}
void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {}
+ void texture_proxy_initialize(RID p_texture, RID p_base) override {}
void texture_proxy_update(RID p_proxy, RID p_base) override {}
- RID texture_2d_placeholder_create() override { return RID(); }
- RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type) override { return RID(); }
- RID texture_3d_placeholder_create() override { return RID(); }
+ void texture_2d_placeholder_initialize(RID p_texture) override {}
+ void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override {}
+ void texture_3d_placeholder_initialize(RID p_texture) override {}
+
+ Ref<Image> texture_2d_get(RID p_texture) const override {
+ DummyTexture *t = texture_owner.getornull(p_texture);
+ ERR_FAIL_COND_V(!t, Ref<Image>());
+ return t->image;
+ }
- Ref<Image> texture_2d_get(RID p_texture) const override { return Ref<Image>(); }
Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
void texture_replace(RID p_texture, RID p_by_texture) override {}
void texture_set_size_override(RID p_texture, int p_width, int p_height) override {}
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
- void texture_bind(RID p_texture, uint32_t p_texture_no) = 0;
-#endif
void texture_set_path(RID p_texture, const String &p_path) override {}
String texture_get_path(RID p_texture) const override { return String(); }
@@ -284,113 +266,18 @@ public:
/* CANVAS TEXTURE API */
- RID canvas_texture_create() override { return RID(); }
+ RID canvas_texture_allocate() override { return RID(); }
+ void canvas_texture_initialize(RID p_rid) override {}
void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override {}
void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override {}
void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override {}
void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override {}
-#if 0
- RID texture_create() override {
- DummyTexture *texture = memnew(DummyTexture);
- ERR_FAIL_COND_V(!texture, RID());
- return texture_owner.make_rid(texture);
- }
-
- void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingServer::TextureType p_type = RS::TEXTURE_TYPE_2D, uint32_t p_flags = RS::TEXTURE_FLAGS_DEFAULT) override {
- DummyTexture *t = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!t);
- t->width = p_width;
- t->height = p_height;
- t->flags = p_flags;
- t->format = p_format;
- t->image = Ref<Image>(memnew(Image));
- t->image->create(p_width, p_height, false, p_format);
- }
- void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_level) override {
- DummyTexture *t = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!t);
- t->width = p_image->get_width();
- t->height = p_image->get_height();
- t->format = p_image->get_format();
- t->image->create(t->width, t->height, false, t->format, p_image->get_data());
- }
-
- void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_level) override {
- DummyTexture *t = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND(!t);
- ERR_FAIL_COND_MSG(p_image.is_null(), "It's not a reference to a valid Image object.");
- ERR_FAIL_COND(t->format != p_image->get_format());
- ERR_FAIL_COND(src_w <= 0 || src_h <= 0);
- ERR_FAIL_COND(src_x < 0 || src_y < 0 || src_x + src_w > p_image->get_width() || src_y + src_h > p_image->get_height());
- ERR_FAIL_COND(dst_x < 0 || dst_y < 0 || dst_x + src_w > t->width || dst_y + src_h > t->height);
-
- t->image->blit_rect(p_image, Rect2(src_x, src_y, src_w, src_h), Vector2(dst_x, dst_y));
- }
-
- Ref<Image> texture_get_data(RID p_texture, int p_level) const override {
- DummyTexture *t = texture_owner.getornull(p_texture);
- ERR_FAIL_COND_V(!t, Ref<Image>());
- return t->image;
- }
- void texture_set_flags(RID p_texture, uint32_t p_flags) override {
- DummyTexture *t = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!t);
- t->flags = p_flags;
- }
- uint32_t texture_get_flags(RID p_texture) const override {
- DummyTexture *t = texture_owner.getornull(p_texture);
- ERR_FAIL_COND_V(!t, 0);
- return t->flags;
- }
- Image::Format texture_get_format(RID p_texture) const override {
- DummyTexture *t = texture_owner.getornull(p_texture);
- ERR_FAIL_COND_V(!t, Image::FORMAT_RGB8);
- return t->format;
- }
-
- RenderingServer::TextureType texture_get_type(RID p_texture) const override { return RS::TEXTURE_TYPE_2D; }
- uint32_t texture_get_texid(RID p_texture) const override { return 0; }
- uint32_t texture_get_width(RID p_texture) const override { return 0; }
- uint32_t texture_get_height(RID p_texture) const override { return 0; }
- uint32_t texture_get_depth(RID p_texture) const override { return 0; }
- void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth_3d) override {}
- void texture_bind(RID p_texture, uint32_t p_texture_no) override {}
-
- void texture_set_path(RID p_texture, const String &p_path) override {
- DummyTexture *t = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!t);
- t->path = p_path;
- }
- String texture_get_path(RID p_texture) const override {
- DummyTexture *t = texture_owner.getornull(p_texture);
- ERR_FAIL_COND_V(!t, String());
- return t->path;
- }
-
- void texture_set_shrink_all_x2_on_set_data(bool p_enable) override {}
-
- void texture_debug_usage(List<RS::TextureInfo> *r_info) override {}
-
- RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const override { return RID(); }
-
- void texture_set_detect_3d_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata) override {}
- void texture_set_detect_srgb_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata) override {}
- void texture_set_detect_normal_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata) override {}
-
- void textures_keep_original(bool p_enable) override {}
-
- void texture_set_proxy(RID p_proxy, RID p_base) override {}
- Size2 texture_size_with_proxy(RID p_texture) const override { return Size2(); }
- void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override {}
-#endif
-
/* SHADER API */
- RID shader_create() override { return RID(); }
-
+ RID shader_allocate() override { return RID(); }
+ void shader_initialize(RID p_rid) override {}
void shader_set_code(RID p_shader, const String &p_code) override {}
String shader_get_code(RID p_shader) const override { return ""; }
void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
@@ -403,8 +290,8 @@ public:
/* COMMON MATERIAL API */
- RID material_create() override { return RID(); }
-
+ RID material_allocate() override { return RID(); }
+ void material_initialize(RID p_rid) override {}
void material_set_render_priority(RID p_material, int priority) override {}
void material_set_shader(RID p_shader_material, RID p_shader) override {}
@@ -420,14 +307,8 @@ public:
/* MESH API */
- RID mesh_create() override {
- DummyMesh *mesh = memnew(DummyMesh);
- ERR_FAIL_COND_V(!mesh, RID());
- mesh->blend_shape_count = 0;
- mesh->blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
- return mesh_owner.make_rid(mesh);
- }
-
+ RID mesh_allocate() override { return RID(); }
+ void mesh_initialize(RID p_rid) override {}
void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {}
bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; }
RID mesh_instance_create(RID p_base) override { return RID(); }
@@ -440,139 +321,31 @@ public:
void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
-#if 0
- void mesh_add_surface(RID p_mesh, uint32_t p_format, RS::PrimitiveType p_primitive, const Vector<uint8_t> &p_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<Vector<uint8_t> > &p_blend_shapes = Vector<Vector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()) override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!m);
-
- m->surfaces.push_back(DummySurface());
- DummySurface *s = &m->surfaces.write[m->surfaces.size() - 1];
- s->format = p_format;
- s->primitive = p_primitive;
- s->array = p_array;
- s->vertex_count = p_vertex_count;
- s->index_array = p_index_array;
- s->index_count = p_index_count;
- s->aabb = p_aabb;
- s->blend_shapes = p_blend_shapes;
- s->bone_aabbs = p_bone_aabbs;
- }
-
- void mesh_set_blend_shape_count(RID p_mesh, int p_amount) override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!m);
- m->blend_shape_count = p_amount;
- }
-#endif
-
- int mesh_get_blend_shape_count(RID p_mesh) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, 0);
- return m->blend_shape_count;
- }
+ int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
- void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!m);
- m->blend_shape_mode = p_mode;
- }
- RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, RS::BLEND_SHAPE_MODE_NORMALIZED);
- return m->blend_shape_mode;
- }
+ void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {}
+ RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; }
void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
-#if 0
- int mesh_surface_get_array_len(RID p_mesh, int p_surface) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, 0);
-
- return m->surfaces[p_surface].vertex_count;
- }
- int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, 0);
-
- return m->surfaces[p_surface].index_count;
- }
-
- Vector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, Vector<uint8_t>());
-
- return m->surfaces[p_surface].array;
- }
- Vector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, Vector<uint8_t>());
-
- return m->surfaces[p_surface].index_array;
- }
-
- uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, 0);
-
- return m->surfaces[p_surface].format;
- }
- RS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, RS::PRIMITIVE_POINTS);
-
- return m->surfaces[p_surface].primitive;
- }
-
- AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, AABB());
-
- return m->surfaces[p_surface].aabb;
- }
- Vector<Vector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, Vector<Vector<uint8_t> >());
-
- return m->surfaces[p_surface].blend_shapes;
- }
- Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, Vector<AABB>());
-
- return m->surfaces[p_surface].bone_aabbs;
- }
-
- void mesh_remove_surface(RID p_mesh, int p_index) override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!m);
- ERR_FAIL_COND(p_index >= m->surfaces.size());
-
- m->surfaces.remove(p_index);
- }
-#endif
-
RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); }
- int mesh_get_surface_count(RID p_mesh) const override {
- DummyMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, 0);
- return m->surfaces.size();
- }
+ int mesh_get_surface_count(RID p_mesh) const override { return 0; }
void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {}
AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); }
AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); }
+ void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {}
void mesh_clear(RID p_mesh) override {}
/* MULTIMESH API */
- RID multimesh_create() override { return RID(); }
-
- void multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {}
+ RID multimesh_allocate() override { return RID(); }
+ void multimesh_initialize(RID p_rid) override {}
+ void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {}
int multimesh_get_instance_count(RID p_multimesh) const override { return 0; }
void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {}
@@ -596,7 +369,8 @@ public:
/* IMMEDIATE API */
- RID immediate_create() override { return RID(); }
+ RID immediate_allocate() override { return RID(); }
+ void immediate_initialize(RID p_rid) override {}
void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) override {}
void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) override {}
void immediate_normal(RID p_immediate, const Vector3 &p_normal) override {}
@@ -612,8 +386,9 @@ public:
/* SKELETON API */
- RID skeleton_create() override { return RID(); }
- void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {}
+ RID skeleton_allocate() override { return RID(); }
+ void skeleton_initialize(RID p_rid) override {}
+ void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {}
void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {}
int skeleton_get_bone_count(RID p_skeleton) const override { return 0; }
void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) override {}
@@ -623,7 +398,14 @@ public:
/* Light API */
- RID light_create(RS::LightType p_type) override { return RID(); }
+ RID directional_light_allocate() override { return RID(); }
+ void directional_light_initialize(RID p_rid) override {}
+ RID omni_light_allocate() override { return RID(); }
+ void omni_light_initialize(RID p_rid) override {}
+ RID spot_light_allocate() override { return RID(); }
+ void spot_light_initialize(RID p_rid) override {}
+ RID reflection_probe_allocate() override { return RID(); }
+ void reflection_probe_initialize(RID p_rid) override {}
void light_set_color(RID p_light, const Color &p_color) override {}
void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {}
@@ -661,8 +443,6 @@ public:
/* PROBE API */
- RID reflection_probe_create() override { return RID(); }
-
void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override {}
void reflection_probe_set_intensity(RID p_probe, float p_intensity) override {}
void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override {}
@@ -690,7 +470,8 @@ public:
/* DECAL API */
- RID decal_create() override { return RID(); }
+ RID decal_allocate() override { return RID(); }
+ void decal_initialize(RID p_rid) override {}
void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {}
void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {}
void decal_set_emission_energy(RID p_decal, float p_energy) override {}
@@ -705,9 +486,9 @@ public:
/* GI PROBE API */
- RID gi_probe_create() override { return RID(); }
-
- void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override {}
+ RID gi_probe_allocate() override { return RID(); }
+ void gi_probe_initialize(RID p_rid) override {}
+ void gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override {}
AABB gi_probe_get_bounds(RID p_gi_probe) const override { return AABB(); }
Vector3i gi_probe_get_octree_size(RID p_gi_probe) const override { return Vector3i(); }
@@ -751,72 +532,8 @@ public:
uint32_t gi_probe_get_version(RID p_gi_probe) override { return 0; }
/* LIGHTMAP CAPTURE */
-#if 0
- struct Instantiable {
- SelfList<RendererSceneRender::GeometryInstance>::List instance_list;
-
- _FORCE_INLINE_ void instance_change_notify(bool p_aabb = true, bool p_materials = true) override {
- SelfList<RendererSceneRender::GeometryInstance> *instances = instance_list.first();
- while (instances) override {
- //instances->self()->base_changed(p_aabb, p_materials);
- instances = instances->next();
- }
- }
-
- _FORCE_INLINE_ void instance_remove_deps() override {
- SelfList<RendererSceneRender::GeometryInstance> *instances = instance_list.first();
- while (instances) override {
- SelfList<RendererSceneRender::GeometryInstance> *next = instances->next();
- //instances->self()->base_removed();
- instances = next;
- }
- }
-
- Instantiable() override {}
- ~Instantiable() override {
- }
- };
-
- struct LightmapCapture : public Instantiable {
- Vector<LightmapCaptureOctree> octree;
- AABB bounds;
- Transform cell_xform;
- int cell_subdiv;
- float energy;
- LightmapCapture() override {
- energy = 1.0;
- cell_subdiv = 1;
- }
- };
-
- mutable RID_PtrOwner<LightmapCapture> lightmap_capture_data_owner;
- void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) override {}
- AABB lightmap_capture_get_bounds(RID p_capture) const override { return AABB(); }
- void lightmap_capture_set_octree(RID p_capture, const Vector<uint8_t> &p_octree) override {}
- RID lightmap_capture_create() override {
- LightmapCapture *capture = memnew(LightmapCapture);
- return lightmap_capture_data_owner.make_rid(capture);
- }
- Vector<uint8_t> lightmap_capture_get_octree(RID p_capture) const override {
- const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND_V(!capture, Vector<uint8_t>());
- return Vector<uint8_t>();
- }
- void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) override {}
- Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const override { return Transform(); }
- void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) override {}
- int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const override { return 0; }
- void lightmap_capture_set_energy(RID p_capture, float p_energy) override {}
- float lightmap_capture_get_energy(RID p_capture) const override { return 0.0; }
- const Vector<LightmapCaptureOctree> *lightmap_capture_get_octree_ptr(RID p_capture) const override {
- const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND_V(!capture, nullptr);
- return &capture->octree;
- }
-#endif
-
- RID lightmap_create() override { return RID(); }
-
+ RID lightmap_allocate() override { return RID(); }
+ void lightmap_initialize(RID p_rid) override {}
void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override {}
void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {}
void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {}
@@ -833,8 +550,8 @@ public:
/* PARTICLES */
- RID particles_create() override { return RID(); }
-
+ RID particles_allocate() override { return RID(); }
+ void particles_initialize(RID p_rid) override {}
void particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
void particles_set_emitting(RID p_particles, bool p_emitting) override {}
void particles_set_amount(RID p_particles, int p_amount) override {}
@@ -876,7 +593,8 @@ public:
/* PARTICLES COLLISION */
- RID particles_collision_create() override { return RID(); }
+ RID particles_collision_allocate() override { return RID(); }
+ void particles_collision_initialize(RID p_rid) override {}
void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {}
void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {}
void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) override {}
@@ -935,14 +653,7 @@ public:
void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
- RS::InstanceType get_base_type(RID p_rid) const override {
- if (mesh_owner.owns(p_rid)) {
- return RS::INSTANCE_MESH;
- }
-
- return RS::INSTANCE_NONE;
- }
-
+ RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
bool free(RID p_rid) override {
if (texture_owner.owns(p_rid)) {
// delete the texture
@@ -950,13 +661,6 @@ public:
texture_owner.free(p_rid);
memdelete(texture);
}
-
- if (mesh_owner.owns(p_rid)) {
- // delete the mesh
- DummyMesh *mesh = mesh_owner.getornull(p_rid);
- mesh_owner.free(p_rid);
- memdelete(mesh);
- }
return true;
}
@@ -970,7 +674,7 @@ public:
void render_info_end_capture() override {}
int get_captured_render_info(RS::RenderInfo p_info) override { return 0; }
- int get_render_info(RS::RenderInfo p_info) override { return 0; }
+ uint64_t get_render_info(RS::RenderInfo p_info) override { return 0; }
String get_video_adapter_name() const override { return String(); }
String get_video_adapter_vendor() const override { return String(); }
diff --git a/drivers/dummy/texture_loader_dummy.cpp b/drivers/dummy/texture_loader_dummy.cpp
index 2484e6d140..f148e42845 100644
--- a/drivers/dummy/texture_loader_dummy.cpp
+++ b/drivers/dummy/texture_loader_dummy.cpp
@@ -35,7 +35,7 @@
#include <string.h>
-RES ResourceFormatDummyTexture::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatDummyTexture::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) {
unsigned int width = 8;
unsigned int height = 8;
diff --git a/drivers/dummy/texture_loader_dummy.h b/drivers/dummy/texture_loader_dummy.h
index 3b71b5824f..00e6b9cc53 100644
--- a/drivers/dummy/texture_loader_dummy.h
+++ b/drivers/dummy/texture_loader_dummy.h
@@ -36,7 +36,7 @@
class ResourceFormatDummyTexture : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/drivers/pulseaudio/SCsub b/drivers/pulseaudio/SCsub
index 91e1140b75..467d1448dc 100644
--- a/drivers/pulseaudio/SCsub
+++ b/drivers/pulseaudio/SCsub
@@ -2,4 +2,7 @@
Import("env")
+if "pulseaudio" in env and env["pulseaudio"]:
+ env.add_source_files(env.drivers_sources, "pulse-so_wrap.c")
+
env.add_source_files(env.drivers_sources, "*.cpp")
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index a5092c8c5c..5e87bc019b 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -179,7 +179,7 @@ Error AudioDriverPulseAudio::init_device() {
break;
}
- int latency = GLOBAL_GET("audio/output_latency");
+ int latency = GLOBAL_GET("audio/driver/output_latency");
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
pa_buffer_size = buffer_frames * pa_map.channels;
@@ -233,11 +233,20 @@ Error AudioDriverPulseAudio::init_device() {
}
Error AudioDriverPulseAudio::init() {
+#ifdef DEBUG_ENABLED
+ int dylibloader_verbose = 1;
+#else
+ int dylibloader_verbose = 0;
+#endif
+ if (initialize_pulse(dylibloader_verbose)) {
+ return ERR_CANT_OPEN;
+ }
+
active = false;
thread_exited = false;
exit_thread = false;
- mix_rate = GLOBAL_GET("audio/mix_rate");
+ mix_rate = GLOBAL_GET("audio/driver/mix_rate");
pa_ml = pa_mainloop_new();
ERR_FAIL_COND_V(pa_ml == nullptr, ERR_CANT_OPEN);
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h
index 2ddf8d2592..fa9b573d94 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.h
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.h
@@ -37,7 +37,7 @@
#include "core/os/thread.h"
#include "servers/audio_server.h"
-#include <pulse/pulseaudio.h>
+#include "pulse-so_wrap.h"
class AudioDriverPulseAudio : public AudioDriver {
Thread thread;
diff --git a/drivers/pulseaudio/pulse-so_wrap.c b/drivers/pulseaudio/pulse-so_wrap.c
new file mode 100644
index 0000000000..12bdcc704e
--- /dev/null
+++ b/drivers/pulseaudio/pulse-so_wrap.c
@@ -0,0 +1,3950 @@
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-20 00:08:31
+// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/pulse/pulseaudio.h --sys-include <pulse/pulseaudio.h> --soname libpulse.so.0 --omit-prefix _pa_ --init-name pulse --output-header pulse-so_wrap.h --output-implementation pulse-so_wrap.c
+//
+#include <stdint.h>
+
+#define pa_get_library_version pa_get_library_version_dylibloader_orig_pulse
+#define pa_bytes_per_second pa_bytes_per_second_dylibloader_orig_pulse
+#define pa_frame_size pa_frame_size_dylibloader_orig_pulse
+#define pa_sample_size pa_sample_size_dylibloader_orig_pulse
+#define pa_sample_size_of_format pa_sample_size_of_format_dylibloader_orig_pulse
+#define pa_bytes_to_usec pa_bytes_to_usec_dylibloader_orig_pulse
+#define pa_usec_to_bytes pa_usec_to_bytes_dylibloader_orig_pulse
+#define pa_sample_spec_init pa_sample_spec_init_dylibloader_orig_pulse
+#define pa_sample_format_valid pa_sample_format_valid_dylibloader_orig_pulse
+#define pa_sample_rate_valid pa_sample_rate_valid_dylibloader_orig_pulse
+#define pa_channels_valid pa_channels_valid_dylibloader_orig_pulse
+#define pa_sample_spec_valid pa_sample_spec_valid_dylibloader_orig_pulse
+#define pa_sample_spec_equal pa_sample_spec_equal_dylibloader_orig_pulse
+#define pa_sample_format_to_string pa_sample_format_to_string_dylibloader_orig_pulse
+#define pa_parse_sample_format pa_parse_sample_format_dylibloader_orig_pulse
+#define pa_sample_spec_snprint pa_sample_spec_snprint_dylibloader_orig_pulse
+#define pa_bytes_snprint pa_bytes_snprint_dylibloader_orig_pulse
+#define pa_sample_format_is_le pa_sample_format_is_le_dylibloader_orig_pulse
+#define pa_sample_format_is_be pa_sample_format_is_be_dylibloader_orig_pulse
+#define pa_direction_valid pa_direction_valid_dylibloader_orig_pulse
+#define pa_direction_to_string pa_direction_to_string_dylibloader_orig_pulse
+#define pa_mainloop_api_once pa_mainloop_api_once_dylibloader_orig_pulse
+#define pa_proplist_new pa_proplist_new_dylibloader_orig_pulse
+#define pa_proplist_free pa_proplist_free_dylibloader_orig_pulse
+#define pa_proplist_key_valid pa_proplist_key_valid_dylibloader_orig_pulse
+#define pa_proplist_sets pa_proplist_sets_dylibloader_orig_pulse
+#define pa_proplist_setp pa_proplist_setp_dylibloader_orig_pulse
+#define pa_proplist_setf pa_proplist_setf_dylibloader_orig_pulse
+#define pa_proplist_set pa_proplist_set_dylibloader_orig_pulse
+#define pa_proplist_gets pa_proplist_gets_dylibloader_orig_pulse
+#define pa_proplist_get pa_proplist_get_dylibloader_orig_pulse
+#define pa_proplist_update pa_proplist_update_dylibloader_orig_pulse
+#define pa_proplist_unset pa_proplist_unset_dylibloader_orig_pulse
+#define pa_proplist_unset_many pa_proplist_unset_many_dylibloader_orig_pulse
+#define pa_proplist_iterate pa_proplist_iterate_dylibloader_orig_pulse
+#define pa_proplist_to_string pa_proplist_to_string_dylibloader_orig_pulse
+#define pa_proplist_to_string_sep pa_proplist_to_string_sep_dylibloader_orig_pulse
+#define pa_proplist_from_string pa_proplist_from_string_dylibloader_orig_pulse
+#define pa_proplist_contains pa_proplist_contains_dylibloader_orig_pulse
+#define pa_proplist_clear pa_proplist_clear_dylibloader_orig_pulse
+#define pa_proplist_copy pa_proplist_copy_dylibloader_orig_pulse
+#define pa_proplist_size pa_proplist_size_dylibloader_orig_pulse
+#define pa_proplist_isempty pa_proplist_isempty_dylibloader_orig_pulse
+#define pa_proplist_equal pa_proplist_equal_dylibloader_orig_pulse
+#define pa_channel_map_init pa_channel_map_init_dylibloader_orig_pulse
+#define pa_channel_map_init_mono pa_channel_map_init_mono_dylibloader_orig_pulse
+#define pa_channel_map_init_stereo pa_channel_map_init_stereo_dylibloader_orig_pulse
+#define pa_channel_map_init_auto pa_channel_map_init_auto_dylibloader_orig_pulse
+#define pa_channel_map_init_extend pa_channel_map_init_extend_dylibloader_orig_pulse
+#define pa_channel_position_to_string pa_channel_position_to_string_dylibloader_orig_pulse
+#define pa_channel_position_from_string pa_channel_position_from_string_dylibloader_orig_pulse
+#define pa_channel_position_to_pretty_string pa_channel_position_to_pretty_string_dylibloader_orig_pulse
+#define pa_channel_map_snprint pa_channel_map_snprint_dylibloader_orig_pulse
+#define pa_channel_map_parse pa_channel_map_parse_dylibloader_orig_pulse
+#define pa_channel_map_equal pa_channel_map_equal_dylibloader_orig_pulse
+#define pa_channel_map_valid pa_channel_map_valid_dylibloader_orig_pulse
+#define pa_channel_map_compatible pa_channel_map_compatible_dylibloader_orig_pulse
+#define pa_channel_map_superset pa_channel_map_superset_dylibloader_orig_pulse
+#define pa_channel_map_can_balance pa_channel_map_can_balance_dylibloader_orig_pulse
+#define pa_channel_map_can_fade pa_channel_map_can_fade_dylibloader_orig_pulse
+#define pa_channel_map_can_lfe_balance pa_channel_map_can_lfe_balance_dylibloader_orig_pulse
+#define pa_channel_map_to_name pa_channel_map_to_name_dylibloader_orig_pulse
+#define pa_channel_map_to_pretty_name pa_channel_map_to_pretty_name_dylibloader_orig_pulse
+#define pa_channel_map_has_position pa_channel_map_has_position_dylibloader_orig_pulse
+#define pa_channel_map_mask pa_channel_map_mask_dylibloader_orig_pulse
+#define pa_encoding_to_string pa_encoding_to_string_dylibloader_orig_pulse
+#define pa_encoding_from_string pa_encoding_from_string_dylibloader_orig_pulse
+#define pa_format_info_new pa_format_info_new_dylibloader_orig_pulse
+#define pa_format_info_copy pa_format_info_copy_dylibloader_orig_pulse
+#define pa_format_info_free pa_format_info_free_dylibloader_orig_pulse
+#define pa_format_info_valid pa_format_info_valid_dylibloader_orig_pulse
+#define pa_format_info_is_pcm pa_format_info_is_pcm_dylibloader_orig_pulse
+#define pa_format_info_is_compatible pa_format_info_is_compatible_dylibloader_orig_pulse
+#define pa_format_info_snprint pa_format_info_snprint_dylibloader_orig_pulse
+#define pa_format_info_from_string pa_format_info_from_string_dylibloader_orig_pulse
+#define pa_format_info_from_sample_spec pa_format_info_from_sample_spec_dylibloader_orig_pulse
+#define pa_format_info_to_sample_spec pa_format_info_to_sample_spec_dylibloader_orig_pulse
+#define pa_format_info_get_prop_type pa_format_info_get_prop_type_dylibloader_orig_pulse
+#define pa_format_info_get_prop_int pa_format_info_get_prop_int_dylibloader_orig_pulse
+#define pa_format_info_get_prop_int_range pa_format_info_get_prop_int_range_dylibloader_orig_pulse
+#define pa_format_info_get_prop_int_array pa_format_info_get_prop_int_array_dylibloader_orig_pulse
+#define pa_format_info_get_prop_string pa_format_info_get_prop_string_dylibloader_orig_pulse
+#define pa_format_info_get_prop_string_array pa_format_info_get_prop_string_array_dylibloader_orig_pulse
+#define pa_format_info_free_string_array pa_format_info_free_string_array_dylibloader_orig_pulse
+#define pa_format_info_get_sample_format pa_format_info_get_sample_format_dylibloader_orig_pulse
+#define pa_format_info_get_rate pa_format_info_get_rate_dylibloader_orig_pulse
+#define pa_format_info_get_channels pa_format_info_get_channels_dylibloader_orig_pulse
+#define pa_format_info_get_channel_map pa_format_info_get_channel_map_dylibloader_orig_pulse
+#define pa_format_info_set_prop_int pa_format_info_set_prop_int_dylibloader_orig_pulse
+#define pa_format_info_set_prop_int_array pa_format_info_set_prop_int_array_dylibloader_orig_pulse
+#define pa_format_info_set_prop_int_range pa_format_info_set_prop_int_range_dylibloader_orig_pulse
+#define pa_format_info_set_prop_string pa_format_info_set_prop_string_dylibloader_orig_pulse
+#define pa_format_info_set_prop_string_array pa_format_info_set_prop_string_array_dylibloader_orig_pulse
+#define pa_format_info_set_sample_format pa_format_info_set_sample_format_dylibloader_orig_pulse
+#define pa_format_info_set_rate pa_format_info_set_rate_dylibloader_orig_pulse
+#define pa_format_info_set_channels pa_format_info_set_channels_dylibloader_orig_pulse
+#define pa_format_info_set_channel_map pa_format_info_set_channel_map_dylibloader_orig_pulse
+#define pa_operation_ref pa_operation_ref_dylibloader_orig_pulse
+#define pa_operation_unref pa_operation_unref_dylibloader_orig_pulse
+#define pa_operation_cancel pa_operation_cancel_dylibloader_orig_pulse
+#define pa_operation_get_state pa_operation_get_state_dylibloader_orig_pulse
+#define pa_operation_set_state_callback pa_operation_set_state_callback_dylibloader_orig_pulse
+#define pa_context_new pa_context_new_dylibloader_orig_pulse
+#define pa_context_new_with_proplist pa_context_new_with_proplist_dylibloader_orig_pulse
+#define pa_context_unref pa_context_unref_dylibloader_orig_pulse
+#define pa_context_ref pa_context_ref_dylibloader_orig_pulse
+#define pa_context_set_state_callback pa_context_set_state_callback_dylibloader_orig_pulse
+#define pa_context_set_event_callback pa_context_set_event_callback_dylibloader_orig_pulse
+#define pa_context_errno pa_context_errno_dylibloader_orig_pulse
+#define pa_context_is_pending pa_context_is_pending_dylibloader_orig_pulse
+#define pa_context_get_state pa_context_get_state_dylibloader_orig_pulse
+#define pa_context_connect pa_context_connect_dylibloader_orig_pulse
+#define pa_context_disconnect pa_context_disconnect_dylibloader_orig_pulse
+#define pa_context_drain pa_context_drain_dylibloader_orig_pulse
+#define pa_context_exit_daemon pa_context_exit_daemon_dylibloader_orig_pulse
+#define pa_context_set_default_sink pa_context_set_default_sink_dylibloader_orig_pulse
+#define pa_context_set_default_source pa_context_set_default_source_dylibloader_orig_pulse
+#define pa_context_is_local pa_context_is_local_dylibloader_orig_pulse
+#define pa_context_set_name pa_context_set_name_dylibloader_orig_pulse
+#define pa_context_get_server pa_context_get_server_dylibloader_orig_pulse
+#define pa_context_get_protocol_version pa_context_get_protocol_version_dylibloader_orig_pulse
+#define pa_context_get_server_protocol_version pa_context_get_server_protocol_version_dylibloader_orig_pulse
+#define pa_context_proplist_update pa_context_proplist_update_dylibloader_orig_pulse
+#define pa_context_proplist_remove pa_context_proplist_remove_dylibloader_orig_pulse
+#define pa_context_get_index pa_context_get_index_dylibloader_orig_pulse
+#define pa_context_rttime_new pa_context_rttime_new_dylibloader_orig_pulse
+#define pa_context_rttime_restart pa_context_rttime_restart_dylibloader_orig_pulse
+#define pa_context_get_tile_size pa_context_get_tile_size_dylibloader_orig_pulse
+#define pa_context_load_cookie_from_file pa_context_load_cookie_from_file_dylibloader_orig_pulse
+#define pa_cvolume_equal pa_cvolume_equal_dylibloader_orig_pulse
+#define pa_cvolume_init pa_cvolume_init_dylibloader_orig_pulse
+#define pa_cvolume_set pa_cvolume_set_dylibloader_orig_pulse
+#define pa_cvolume_snprint pa_cvolume_snprint_dylibloader_orig_pulse
+#define pa_sw_cvolume_snprint_dB pa_sw_cvolume_snprint_dB_dylibloader_orig_pulse
+#define pa_cvolume_snprint_verbose pa_cvolume_snprint_verbose_dylibloader_orig_pulse
+#define pa_volume_snprint pa_volume_snprint_dylibloader_orig_pulse
+#define pa_sw_volume_snprint_dB pa_sw_volume_snprint_dB_dylibloader_orig_pulse
+#define pa_volume_snprint_verbose pa_volume_snprint_verbose_dylibloader_orig_pulse
+#define pa_cvolume_avg pa_cvolume_avg_dylibloader_orig_pulse
+#define pa_cvolume_avg_mask pa_cvolume_avg_mask_dylibloader_orig_pulse
+#define pa_cvolume_max pa_cvolume_max_dylibloader_orig_pulse
+#define pa_cvolume_max_mask pa_cvolume_max_mask_dylibloader_orig_pulse
+#define pa_cvolume_min pa_cvolume_min_dylibloader_orig_pulse
+#define pa_cvolume_min_mask pa_cvolume_min_mask_dylibloader_orig_pulse
+#define pa_cvolume_valid pa_cvolume_valid_dylibloader_orig_pulse
+#define pa_cvolume_channels_equal_to pa_cvolume_channels_equal_to_dylibloader_orig_pulse
+#define pa_sw_volume_multiply pa_sw_volume_multiply_dylibloader_orig_pulse
+#define pa_sw_cvolume_multiply pa_sw_cvolume_multiply_dylibloader_orig_pulse
+#define pa_sw_cvolume_multiply_scalar pa_sw_cvolume_multiply_scalar_dylibloader_orig_pulse
+#define pa_sw_volume_divide pa_sw_volume_divide_dylibloader_orig_pulse
+#define pa_sw_cvolume_divide pa_sw_cvolume_divide_dylibloader_orig_pulse
+#define pa_sw_cvolume_divide_scalar pa_sw_cvolume_divide_scalar_dylibloader_orig_pulse
+#define pa_sw_volume_from_dB pa_sw_volume_from_dB_dylibloader_orig_pulse
+#define pa_sw_volume_to_dB pa_sw_volume_to_dB_dylibloader_orig_pulse
+#define pa_sw_volume_from_linear pa_sw_volume_from_linear_dylibloader_orig_pulse
+#define pa_sw_volume_to_linear pa_sw_volume_to_linear_dylibloader_orig_pulse
+#define pa_cvolume_remap pa_cvolume_remap_dylibloader_orig_pulse
+#define pa_cvolume_compatible pa_cvolume_compatible_dylibloader_orig_pulse
+#define pa_cvolume_compatible_with_channel_map pa_cvolume_compatible_with_channel_map_dylibloader_orig_pulse
+#define pa_cvolume_get_balance pa_cvolume_get_balance_dylibloader_orig_pulse
+#define pa_cvolume_set_balance pa_cvolume_set_balance_dylibloader_orig_pulse
+#define pa_cvolume_get_fade pa_cvolume_get_fade_dylibloader_orig_pulse
+#define pa_cvolume_set_fade pa_cvolume_set_fade_dylibloader_orig_pulse
+#define pa_cvolume_get_lfe_balance pa_cvolume_get_lfe_balance_dylibloader_orig_pulse
+#define pa_cvolume_set_lfe_balance pa_cvolume_set_lfe_balance_dylibloader_orig_pulse
+#define pa_cvolume_scale pa_cvolume_scale_dylibloader_orig_pulse
+#define pa_cvolume_scale_mask pa_cvolume_scale_mask_dylibloader_orig_pulse
+#define pa_cvolume_set_position pa_cvolume_set_position_dylibloader_orig_pulse
+#define pa_cvolume_get_position pa_cvolume_get_position_dylibloader_orig_pulse
+#define pa_cvolume_merge pa_cvolume_merge_dylibloader_orig_pulse
+#define pa_cvolume_inc_clamp pa_cvolume_inc_clamp_dylibloader_orig_pulse
+#define pa_cvolume_inc pa_cvolume_inc_dylibloader_orig_pulse
+#define pa_cvolume_dec pa_cvolume_dec_dylibloader_orig_pulse
+#define pa_stream_new pa_stream_new_dylibloader_orig_pulse
+#define pa_stream_new_with_proplist pa_stream_new_with_proplist_dylibloader_orig_pulse
+#define pa_stream_new_extended pa_stream_new_extended_dylibloader_orig_pulse
+#define pa_stream_unref pa_stream_unref_dylibloader_orig_pulse
+#define pa_stream_ref pa_stream_ref_dylibloader_orig_pulse
+#define pa_stream_get_state pa_stream_get_state_dylibloader_orig_pulse
+#define pa_stream_get_context pa_stream_get_context_dylibloader_orig_pulse
+#define pa_stream_get_index pa_stream_get_index_dylibloader_orig_pulse
+#define pa_stream_get_device_index pa_stream_get_device_index_dylibloader_orig_pulse
+#define pa_stream_get_device_name pa_stream_get_device_name_dylibloader_orig_pulse
+#define pa_stream_is_suspended pa_stream_is_suspended_dylibloader_orig_pulse
+#define pa_stream_is_corked pa_stream_is_corked_dylibloader_orig_pulse
+#define pa_stream_connect_playback pa_stream_connect_playback_dylibloader_orig_pulse
+#define pa_stream_connect_record pa_stream_connect_record_dylibloader_orig_pulse
+#define pa_stream_disconnect pa_stream_disconnect_dylibloader_orig_pulse
+#define pa_stream_begin_write pa_stream_begin_write_dylibloader_orig_pulse
+#define pa_stream_cancel_write pa_stream_cancel_write_dylibloader_orig_pulse
+#define pa_stream_write pa_stream_write_dylibloader_orig_pulse
+#define pa_stream_write_ext_free pa_stream_write_ext_free_dylibloader_orig_pulse
+#define pa_stream_peek pa_stream_peek_dylibloader_orig_pulse
+#define pa_stream_drop pa_stream_drop_dylibloader_orig_pulse
+#define pa_stream_writable_size pa_stream_writable_size_dylibloader_orig_pulse
+#define pa_stream_readable_size pa_stream_readable_size_dylibloader_orig_pulse
+#define pa_stream_drain pa_stream_drain_dylibloader_orig_pulse
+#define pa_stream_update_timing_info pa_stream_update_timing_info_dylibloader_orig_pulse
+#define pa_stream_set_state_callback pa_stream_set_state_callback_dylibloader_orig_pulse
+#define pa_stream_set_write_callback pa_stream_set_write_callback_dylibloader_orig_pulse
+#define pa_stream_set_read_callback pa_stream_set_read_callback_dylibloader_orig_pulse
+#define pa_stream_set_overflow_callback pa_stream_set_overflow_callback_dylibloader_orig_pulse
+#define pa_stream_get_underflow_index pa_stream_get_underflow_index_dylibloader_orig_pulse
+#define pa_stream_set_underflow_callback pa_stream_set_underflow_callback_dylibloader_orig_pulse
+#define pa_stream_set_started_callback pa_stream_set_started_callback_dylibloader_orig_pulse
+#define pa_stream_set_latency_update_callback pa_stream_set_latency_update_callback_dylibloader_orig_pulse
+#define pa_stream_set_moved_callback pa_stream_set_moved_callback_dylibloader_orig_pulse
+#define pa_stream_set_suspended_callback pa_stream_set_suspended_callback_dylibloader_orig_pulse
+#define pa_stream_set_event_callback pa_stream_set_event_callback_dylibloader_orig_pulse
+#define pa_stream_set_buffer_attr_callback pa_stream_set_buffer_attr_callback_dylibloader_orig_pulse
+#define pa_stream_cork pa_stream_cork_dylibloader_orig_pulse
+#define pa_stream_flush pa_stream_flush_dylibloader_orig_pulse
+#define pa_stream_prebuf pa_stream_prebuf_dylibloader_orig_pulse
+#define pa_stream_trigger pa_stream_trigger_dylibloader_orig_pulse
+#define pa_stream_set_name pa_stream_set_name_dylibloader_orig_pulse
+#define pa_stream_get_time pa_stream_get_time_dylibloader_orig_pulse
+#define pa_stream_get_latency pa_stream_get_latency_dylibloader_orig_pulse
+#define pa_stream_get_timing_info pa_stream_get_timing_info_dylibloader_orig_pulse
+#define pa_stream_get_sample_spec pa_stream_get_sample_spec_dylibloader_orig_pulse
+#define pa_stream_get_channel_map pa_stream_get_channel_map_dylibloader_orig_pulse
+#define pa_stream_get_format_info pa_stream_get_format_info_dylibloader_orig_pulse
+#define pa_stream_get_buffer_attr pa_stream_get_buffer_attr_dylibloader_orig_pulse
+#define pa_stream_set_buffer_attr pa_stream_set_buffer_attr_dylibloader_orig_pulse
+#define pa_stream_update_sample_rate pa_stream_update_sample_rate_dylibloader_orig_pulse
+#define pa_stream_proplist_update pa_stream_proplist_update_dylibloader_orig_pulse
+#define pa_stream_proplist_remove pa_stream_proplist_remove_dylibloader_orig_pulse
+#define pa_stream_set_monitor_stream pa_stream_set_monitor_stream_dylibloader_orig_pulse
+#define pa_stream_get_monitor_stream pa_stream_get_monitor_stream_dylibloader_orig_pulse
+#define pa_context_get_sink_info_by_name pa_context_get_sink_info_by_name_dylibloader_orig_pulse
+#define pa_context_get_sink_info_by_index pa_context_get_sink_info_by_index_dylibloader_orig_pulse
+#define pa_context_get_sink_info_list pa_context_get_sink_info_list_dylibloader_orig_pulse
+#define pa_context_set_sink_volume_by_index pa_context_set_sink_volume_by_index_dylibloader_orig_pulse
+#define pa_context_set_sink_volume_by_name pa_context_set_sink_volume_by_name_dylibloader_orig_pulse
+#define pa_context_set_sink_mute_by_index pa_context_set_sink_mute_by_index_dylibloader_orig_pulse
+#define pa_context_set_sink_mute_by_name pa_context_set_sink_mute_by_name_dylibloader_orig_pulse
+#define pa_context_suspend_sink_by_name pa_context_suspend_sink_by_name_dylibloader_orig_pulse
+#define pa_context_suspend_sink_by_index pa_context_suspend_sink_by_index_dylibloader_orig_pulse
+#define pa_context_set_sink_port_by_index pa_context_set_sink_port_by_index_dylibloader_orig_pulse
+#define pa_context_set_sink_port_by_name pa_context_set_sink_port_by_name_dylibloader_orig_pulse
+#define pa_context_get_source_info_by_name pa_context_get_source_info_by_name_dylibloader_orig_pulse
+#define pa_context_get_source_info_by_index pa_context_get_source_info_by_index_dylibloader_orig_pulse
+#define pa_context_get_source_info_list pa_context_get_source_info_list_dylibloader_orig_pulse
+#define pa_context_set_source_volume_by_index pa_context_set_source_volume_by_index_dylibloader_orig_pulse
+#define pa_context_set_source_volume_by_name pa_context_set_source_volume_by_name_dylibloader_orig_pulse
+#define pa_context_set_source_mute_by_index pa_context_set_source_mute_by_index_dylibloader_orig_pulse
+#define pa_context_set_source_mute_by_name pa_context_set_source_mute_by_name_dylibloader_orig_pulse
+#define pa_context_suspend_source_by_name pa_context_suspend_source_by_name_dylibloader_orig_pulse
+#define pa_context_suspend_source_by_index pa_context_suspend_source_by_index_dylibloader_orig_pulse
+#define pa_context_set_source_port_by_index pa_context_set_source_port_by_index_dylibloader_orig_pulse
+#define pa_context_set_source_port_by_name pa_context_set_source_port_by_name_dylibloader_orig_pulse
+#define pa_context_get_server_info pa_context_get_server_info_dylibloader_orig_pulse
+#define pa_context_get_module_info pa_context_get_module_info_dylibloader_orig_pulse
+#define pa_context_get_module_info_list pa_context_get_module_info_list_dylibloader_orig_pulse
+#define pa_context_load_module pa_context_load_module_dylibloader_orig_pulse
+#define pa_context_unload_module pa_context_unload_module_dylibloader_orig_pulse
+#define pa_context_get_client_info pa_context_get_client_info_dylibloader_orig_pulse
+#define pa_context_get_client_info_list pa_context_get_client_info_list_dylibloader_orig_pulse
+#define pa_context_kill_client pa_context_kill_client_dylibloader_orig_pulse
+#define pa_context_get_card_info_by_index pa_context_get_card_info_by_index_dylibloader_orig_pulse
+#define pa_context_get_card_info_by_name pa_context_get_card_info_by_name_dylibloader_orig_pulse
+#define pa_context_get_card_info_list pa_context_get_card_info_list_dylibloader_orig_pulse
+#define pa_context_set_card_profile_by_index pa_context_set_card_profile_by_index_dylibloader_orig_pulse
+#define pa_context_set_card_profile_by_name pa_context_set_card_profile_by_name_dylibloader_orig_pulse
+#define pa_context_set_port_latency_offset pa_context_set_port_latency_offset_dylibloader_orig_pulse
+#define pa_context_get_sink_input_info pa_context_get_sink_input_info_dylibloader_orig_pulse
+#define pa_context_get_sink_input_info_list pa_context_get_sink_input_info_list_dylibloader_orig_pulse
+#define pa_context_move_sink_input_by_name pa_context_move_sink_input_by_name_dylibloader_orig_pulse
+#define pa_context_move_sink_input_by_index pa_context_move_sink_input_by_index_dylibloader_orig_pulse
+#define pa_context_set_sink_input_volume pa_context_set_sink_input_volume_dylibloader_orig_pulse
+#define pa_context_set_sink_input_mute pa_context_set_sink_input_mute_dylibloader_orig_pulse
+#define pa_context_kill_sink_input pa_context_kill_sink_input_dylibloader_orig_pulse
+#define pa_context_get_source_output_info pa_context_get_source_output_info_dylibloader_orig_pulse
+#define pa_context_get_source_output_info_list pa_context_get_source_output_info_list_dylibloader_orig_pulse
+#define pa_context_move_source_output_by_name pa_context_move_source_output_by_name_dylibloader_orig_pulse
+#define pa_context_move_source_output_by_index pa_context_move_source_output_by_index_dylibloader_orig_pulse
+#define pa_context_set_source_output_volume pa_context_set_source_output_volume_dylibloader_orig_pulse
+#define pa_context_set_source_output_mute pa_context_set_source_output_mute_dylibloader_orig_pulse
+#define pa_context_kill_source_output pa_context_kill_source_output_dylibloader_orig_pulse
+#define pa_context_stat pa_context_stat_dylibloader_orig_pulse
+#define pa_context_get_sample_info_by_name pa_context_get_sample_info_by_name_dylibloader_orig_pulse
+#define pa_context_get_sample_info_by_index pa_context_get_sample_info_by_index_dylibloader_orig_pulse
+#define pa_context_get_sample_info_list pa_context_get_sample_info_list_dylibloader_orig_pulse
+#define pa_context_get_autoload_info_by_name pa_context_get_autoload_info_by_name_dylibloader_orig_pulse
+#define pa_context_get_autoload_info_by_index pa_context_get_autoload_info_by_index_dylibloader_orig_pulse
+#define pa_context_get_autoload_info_list pa_context_get_autoload_info_list_dylibloader_orig_pulse
+#define pa_context_add_autoload pa_context_add_autoload_dylibloader_orig_pulse
+#define pa_context_remove_autoload_by_name pa_context_remove_autoload_by_name_dylibloader_orig_pulse
+#define pa_context_remove_autoload_by_index pa_context_remove_autoload_by_index_dylibloader_orig_pulse
+#define pa_context_subscribe pa_context_subscribe_dylibloader_orig_pulse
+#define pa_context_set_subscribe_callback pa_context_set_subscribe_callback_dylibloader_orig_pulse
+#define pa_stream_connect_upload pa_stream_connect_upload_dylibloader_orig_pulse
+#define pa_stream_finish_upload pa_stream_finish_upload_dylibloader_orig_pulse
+#define pa_context_remove_sample pa_context_remove_sample_dylibloader_orig_pulse
+#define pa_context_play_sample pa_context_play_sample_dylibloader_orig_pulse
+#define pa_context_play_sample_with_proplist pa_context_play_sample_with_proplist_dylibloader_orig_pulse
+#define pa_strerror pa_strerror_dylibloader_orig_pulse
+#define pa_xmalloc pa_xmalloc_dylibloader_orig_pulse
+#define pa_xmalloc0 pa_xmalloc0_dylibloader_orig_pulse
+#define pa_xrealloc pa_xrealloc_dylibloader_orig_pulse
+#define pa_xfree pa_xfree_dylibloader_orig_pulse
+#define pa_xstrdup pa_xstrdup_dylibloader_orig_pulse
+#define pa_xstrndup pa_xstrndup_dylibloader_orig_pulse
+#define pa_xmemdup pa_xmemdup_dylibloader_orig_pulse
+#define pa_utf8_valid pa_utf8_valid_dylibloader_orig_pulse
+#define pa_ascii_valid pa_ascii_valid_dylibloader_orig_pulse
+#define pa_utf8_filter pa_utf8_filter_dylibloader_orig_pulse
+#define pa_ascii_filter pa_ascii_filter_dylibloader_orig_pulse
+#define pa_utf8_to_locale pa_utf8_to_locale_dylibloader_orig_pulse
+#define pa_locale_to_utf8 pa_locale_to_utf8_dylibloader_orig_pulse
+#define pa_threaded_mainloop_new pa_threaded_mainloop_new_dylibloader_orig_pulse
+#define pa_threaded_mainloop_free pa_threaded_mainloop_free_dylibloader_orig_pulse
+#define pa_threaded_mainloop_start pa_threaded_mainloop_start_dylibloader_orig_pulse
+#define pa_threaded_mainloop_stop pa_threaded_mainloop_stop_dylibloader_orig_pulse
+#define pa_threaded_mainloop_lock pa_threaded_mainloop_lock_dylibloader_orig_pulse
+#define pa_threaded_mainloop_unlock pa_threaded_mainloop_unlock_dylibloader_orig_pulse
+#define pa_threaded_mainloop_wait pa_threaded_mainloop_wait_dylibloader_orig_pulse
+#define pa_threaded_mainloop_signal pa_threaded_mainloop_signal_dylibloader_orig_pulse
+#define pa_threaded_mainloop_accept pa_threaded_mainloop_accept_dylibloader_orig_pulse
+#define pa_threaded_mainloop_get_retval pa_threaded_mainloop_get_retval_dylibloader_orig_pulse
+#define pa_threaded_mainloop_get_api pa_threaded_mainloop_get_api_dylibloader_orig_pulse
+#define pa_threaded_mainloop_in_thread pa_threaded_mainloop_in_thread_dylibloader_orig_pulse
+#define pa_threaded_mainloop_set_name pa_threaded_mainloop_set_name_dylibloader_orig_pulse
+#define pa_threaded_mainloop_once_unlocked pa_threaded_mainloop_once_unlocked_dylibloader_orig_pulse
+#define pa_mainloop_new pa_mainloop_new_dylibloader_orig_pulse
+#define pa_mainloop_free pa_mainloop_free_dylibloader_orig_pulse
+#define pa_mainloop_prepare pa_mainloop_prepare_dylibloader_orig_pulse
+#define pa_mainloop_poll pa_mainloop_poll_dylibloader_orig_pulse
+#define pa_mainloop_dispatch pa_mainloop_dispatch_dylibloader_orig_pulse
+#define pa_mainloop_get_retval pa_mainloop_get_retval_dylibloader_orig_pulse
+#define pa_mainloop_iterate pa_mainloop_iterate_dylibloader_orig_pulse
+#define pa_mainloop_run pa_mainloop_run_dylibloader_orig_pulse
+#define pa_mainloop_get_api pa_mainloop_get_api_dylibloader_orig_pulse
+#define pa_mainloop_quit pa_mainloop_quit_dylibloader_orig_pulse
+#define pa_mainloop_wakeup pa_mainloop_wakeup_dylibloader_orig_pulse
+#define pa_mainloop_set_poll_func pa_mainloop_set_poll_func_dylibloader_orig_pulse
+#define pa_signal_init pa_signal_init_dylibloader_orig_pulse
+#define pa_signal_done pa_signal_done_dylibloader_orig_pulse
+#define pa_signal_new pa_signal_new_dylibloader_orig_pulse
+#define pa_signal_free pa_signal_free_dylibloader_orig_pulse
+#define pa_signal_set_destroy pa_signal_set_destroy_dylibloader_orig_pulse
+#define pa_get_user_name pa_get_user_name_dylibloader_orig_pulse
+#define pa_get_host_name pa_get_host_name_dylibloader_orig_pulse
+#define pa_get_fqdn pa_get_fqdn_dylibloader_orig_pulse
+#define pa_get_home_dir pa_get_home_dir_dylibloader_orig_pulse
+#define pa_get_binary_name pa_get_binary_name_dylibloader_orig_pulse
+#define pa_path_get_filename pa_path_get_filename_dylibloader_orig_pulse
+#define pa_msleep pa_msleep_dylibloader_orig_pulse
+#define pa_thread_make_realtime pa_thread_make_realtime_dylibloader_orig_pulse
+#define pa_gettimeofday pa_gettimeofday_dylibloader_orig_pulse
+#define pa_timeval_diff pa_timeval_diff_dylibloader_orig_pulse
+#define pa_timeval_cmp pa_timeval_cmp_dylibloader_orig_pulse
+#define pa_timeval_age pa_timeval_age_dylibloader_orig_pulse
+#define pa_timeval_add pa_timeval_add_dylibloader_orig_pulse
+#define pa_timeval_sub pa_timeval_sub_dylibloader_orig_pulse
+#define pa_timeval_store pa_timeval_store_dylibloader_orig_pulse
+#define pa_timeval_load pa_timeval_load_dylibloader_orig_pulse
+#define pa_rtclock_now pa_rtclock_now_dylibloader_orig_pulse
+#include <pulse/pulseaudio.h>
+#undef pa_get_library_version
+#undef pa_bytes_per_second
+#undef pa_frame_size
+#undef pa_sample_size
+#undef pa_sample_size_of_format
+#undef pa_bytes_to_usec
+#undef pa_usec_to_bytes
+#undef pa_sample_spec_init
+#undef pa_sample_format_valid
+#undef pa_sample_rate_valid
+#undef pa_channels_valid
+#undef pa_sample_spec_valid
+#undef pa_sample_spec_equal
+#undef pa_sample_format_to_string
+#undef pa_parse_sample_format
+#undef pa_sample_spec_snprint
+#undef pa_bytes_snprint
+#undef pa_sample_format_is_le
+#undef pa_sample_format_is_be
+#undef pa_direction_valid
+#undef pa_direction_to_string
+#undef pa_mainloop_api_once
+#undef pa_proplist_new
+#undef pa_proplist_free
+#undef pa_proplist_key_valid
+#undef pa_proplist_sets
+#undef pa_proplist_setp
+#undef pa_proplist_setf
+#undef pa_proplist_set
+#undef pa_proplist_gets
+#undef pa_proplist_get
+#undef pa_proplist_update
+#undef pa_proplist_unset
+#undef pa_proplist_unset_many
+#undef pa_proplist_iterate
+#undef pa_proplist_to_string
+#undef pa_proplist_to_string_sep
+#undef pa_proplist_from_string
+#undef pa_proplist_contains
+#undef pa_proplist_clear
+#undef pa_proplist_copy
+#undef pa_proplist_size
+#undef pa_proplist_isempty
+#undef pa_proplist_equal
+#undef pa_channel_map_init
+#undef pa_channel_map_init_mono
+#undef pa_channel_map_init_stereo
+#undef pa_channel_map_init_auto
+#undef pa_channel_map_init_extend
+#undef pa_channel_position_to_string
+#undef pa_channel_position_from_string
+#undef pa_channel_position_to_pretty_string
+#undef pa_channel_map_snprint
+#undef pa_channel_map_parse
+#undef pa_channel_map_equal
+#undef pa_channel_map_valid
+#undef pa_channel_map_compatible
+#undef pa_channel_map_superset
+#undef pa_channel_map_can_balance
+#undef pa_channel_map_can_fade
+#undef pa_channel_map_can_lfe_balance
+#undef pa_channel_map_to_name
+#undef pa_channel_map_to_pretty_name
+#undef pa_channel_map_has_position
+#undef pa_channel_map_mask
+#undef pa_encoding_to_string
+#undef pa_encoding_from_string
+#undef pa_format_info_new
+#undef pa_format_info_copy
+#undef pa_format_info_free
+#undef pa_format_info_valid
+#undef pa_format_info_is_pcm
+#undef pa_format_info_is_compatible
+#undef pa_format_info_snprint
+#undef pa_format_info_from_string
+#undef pa_format_info_from_sample_spec
+#undef pa_format_info_to_sample_spec
+#undef pa_format_info_get_prop_type
+#undef pa_format_info_get_prop_int
+#undef pa_format_info_get_prop_int_range
+#undef pa_format_info_get_prop_int_array
+#undef pa_format_info_get_prop_string
+#undef pa_format_info_get_prop_string_array
+#undef pa_format_info_free_string_array
+#undef pa_format_info_get_sample_format
+#undef pa_format_info_get_rate
+#undef pa_format_info_get_channels
+#undef pa_format_info_get_channel_map
+#undef pa_format_info_set_prop_int
+#undef pa_format_info_set_prop_int_array
+#undef pa_format_info_set_prop_int_range
+#undef pa_format_info_set_prop_string
+#undef pa_format_info_set_prop_string_array
+#undef pa_format_info_set_sample_format
+#undef pa_format_info_set_rate
+#undef pa_format_info_set_channels
+#undef pa_format_info_set_channel_map
+#undef pa_operation_ref
+#undef pa_operation_unref
+#undef pa_operation_cancel
+#undef pa_operation_get_state
+#undef pa_operation_set_state_callback
+#undef pa_context_new
+#undef pa_context_new_with_proplist
+#undef pa_context_unref
+#undef pa_context_ref
+#undef pa_context_set_state_callback
+#undef pa_context_set_event_callback
+#undef pa_context_errno
+#undef pa_context_is_pending
+#undef pa_context_get_state
+#undef pa_context_connect
+#undef pa_context_disconnect
+#undef pa_context_drain
+#undef pa_context_exit_daemon
+#undef pa_context_set_default_sink
+#undef pa_context_set_default_source
+#undef pa_context_is_local
+#undef pa_context_set_name
+#undef pa_context_get_server
+#undef pa_context_get_protocol_version
+#undef pa_context_get_server_protocol_version
+#undef pa_context_proplist_update
+#undef pa_context_proplist_remove
+#undef pa_context_get_index
+#undef pa_context_rttime_new
+#undef pa_context_rttime_restart
+#undef pa_context_get_tile_size
+#undef pa_context_load_cookie_from_file
+#undef pa_cvolume_equal
+#undef pa_cvolume_init
+#undef pa_cvolume_set
+#undef pa_cvolume_snprint
+#undef pa_sw_cvolume_snprint_dB
+#undef pa_cvolume_snprint_verbose
+#undef pa_volume_snprint
+#undef pa_sw_volume_snprint_dB
+#undef pa_volume_snprint_verbose
+#undef pa_cvolume_avg
+#undef pa_cvolume_avg_mask
+#undef pa_cvolume_max
+#undef pa_cvolume_max_mask
+#undef pa_cvolume_min
+#undef pa_cvolume_min_mask
+#undef pa_cvolume_valid
+#undef pa_cvolume_channels_equal_to
+#undef pa_sw_volume_multiply
+#undef pa_sw_cvolume_multiply
+#undef pa_sw_cvolume_multiply_scalar
+#undef pa_sw_volume_divide
+#undef pa_sw_cvolume_divide
+#undef pa_sw_cvolume_divide_scalar
+#undef pa_sw_volume_from_dB
+#undef pa_sw_volume_to_dB
+#undef pa_sw_volume_from_linear
+#undef pa_sw_volume_to_linear
+#undef pa_cvolume_remap
+#undef pa_cvolume_compatible
+#undef pa_cvolume_compatible_with_channel_map
+#undef pa_cvolume_get_balance
+#undef pa_cvolume_set_balance
+#undef pa_cvolume_get_fade
+#undef pa_cvolume_set_fade
+#undef pa_cvolume_get_lfe_balance
+#undef pa_cvolume_set_lfe_balance
+#undef pa_cvolume_scale
+#undef pa_cvolume_scale_mask
+#undef pa_cvolume_set_position
+#undef pa_cvolume_get_position
+#undef pa_cvolume_merge
+#undef pa_cvolume_inc_clamp
+#undef pa_cvolume_inc
+#undef pa_cvolume_dec
+#undef pa_stream_new
+#undef pa_stream_new_with_proplist
+#undef pa_stream_new_extended
+#undef pa_stream_unref
+#undef pa_stream_ref
+#undef pa_stream_get_state
+#undef pa_stream_get_context
+#undef pa_stream_get_index
+#undef pa_stream_get_device_index
+#undef pa_stream_get_device_name
+#undef pa_stream_is_suspended
+#undef pa_stream_is_corked
+#undef pa_stream_connect_playback
+#undef pa_stream_connect_record
+#undef pa_stream_disconnect
+#undef pa_stream_begin_write
+#undef pa_stream_cancel_write
+#undef pa_stream_write
+#undef pa_stream_write_ext_free
+#undef pa_stream_peek
+#undef pa_stream_drop
+#undef pa_stream_writable_size
+#undef pa_stream_readable_size
+#undef pa_stream_drain
+#undef pa_stream_update_timing_info
+#undef pa_stream_set_state_callback
+#undef pa_stream_set_write_callback
+#undef pa_stream_set_read_callback
+#undef pa_stream_set_overflow_callback
+#undef pa_stream_get_underflow_index
+#undef pa_stream_set_underflow_callback
+#undef pa_stream_set_started_callback
+#undef pa_stream_set_latency_update_callback
+#undef pa_stream_set_moved_callback
+#undef pa_stream_set_suspended_callback
+#undef pa_stream_set_event_callback
+#undef pa_stream_set_buffer_attr_callback
+#undef pa_stream_cork
+#undef pa_stream_flush
+#undef pa_stream_prebuf
+#undef pa_stream_trigger
+#undef pa_stream_set_name
+#undef pa_stream_get_time
+#undef pa_stream_get_latency
+#undef pa_stream_get_timing_info
+#undef pa_stream_get_sample_spec
+#undef pa_stream_get_channel_map
+#undef pa_stream_get_format_info
+#undef pa_stream_get_buffer_attr
+#undef pa_stream_set_buffer_attr
+#undef pa_stream_update_sample_rate
+#undef pa_stream_proplist_update
+#undef pa_stream_proplist_remove
+#undef pa_stream_set_monitor_stream
+#undef pa_stream_get_monitor_stream
+#undef pa_context_get_sink_info_by_name
+#undef pa_context_get_sink_info_by_index
+#undef pa_context_get_sink_info_list
+#undef pa_context_set_sink_volume_by_index
+#undef pa_context_set_sink_volume_by_name
+#undef pa_context_set_sink_mute_by_index
+#undef pa_context_set_sink_mute_by_name
+#undef pa_context_suspend_sink_by_name
+#undef pa_context_suspend_sink_by_index
+#undef pa_context_set_sink_port_by_index
+#undef pa_context_set_sink_port_by_name
+#undef pa_context_get_source_info_by_name
+#undef pa_context_get_source_info_by_index
+#undef pa_context_get_source_info_list
+#undef pa_context_set_source_volume_by_index
+#undef pa_context_set_source_volume_by_name
+#undef pa_context_set_source_mute_by_index
+#undef pa_context_set_source_mute_by_name
+#undef pa_context_suspend_source_by_name
+#undef pa_context_suspend_source_by_index
+#undef pa_context_set_source_port_by_index
+#undef pa_context_set_source_port_by_name
+#undef pa_context_get_server_info
+#undef pa_context_get_module_info
+#undef pa_context_get_module_info_list
+#undef pa_context_load_module
+#undef pa_context_unload_module
+#undef pa_context_get_client_info
+#undef pa_context_get_client_info_list
+#undef pa_context_kill_client
+#undef pa_context_get_card_info_by_index
+#undef pa_context_get_card_info_by_name
+#undef pa_context_get_card_info_list
+#undef pa_context_set_card_profile_by_index
+#undef pa_context_set_card_profile_by_name
+#undef pa_context_set_port_latency_offset
+#undef pa_context_get_sink_input_info
+#undef pa_context_get_sink_input_info_list
+#undef pa_context_move_sink_input_by_name
+#undef pa_context_move_sink_input_by_index
+#undef pa_context_set_sink_input_volume
+#undef pa_context_set_sink_input_mute
+#undef pa_context_kill_sink_input
+#undef pa_context_get_source_output_info
+#undef pa_context_get_source_output_info_list
+#undef pa_context_move_source_output_by_name
+#undef pa_context_move_source_output_by_index
+#undef pa_context_set_source_output_volume
+#undef pa_context_set_source_output_mute
+#undef pa_context_kill_source_output
+#undef pa_context_stat
+#undef pa_context_get_sample_info_by_name
+#undef pa_context_get_sample_info_by_index
+#undef pa_context_get_sample_info_list
+#undef pa_context_get_autoload_info_by_name
+#undef pa_context_get_autoload_info_by_index
+#undef pa_context_get_autoload_info_list
+#undef pa_context_add_autoload
+#undef pa_context_remove_autoload_by_name
+#undef pa_context_remove_autoload_by_index
+#undef pa_context_subscribe
+#undef pa_context_set_subscribe_callback
+#undef pa_stream_connect_upload
+#undef pa_stream_finish_upload
+#undef pa_context_remove_sample
+#undef pa_context_play_sample
+#undef pa_context_play_sample_with_proplist
+#undef pa_strerror
+#undef pa_xmalloc
+#undef pa_xmalloc0
+#undef pa_xrealloc
+#undef pa_xfree
+#undef pa_xstrdup
+#undef pa_xstrndup
+#undef pa_xmemdup
+#undef pa_utf8_valid
+#undef pa_ascii_valid
+#undef pa_utf8_filter
+#undef pa_ascii_filter
+#undef pa_utf8_to_locale
+#undef pa_locale_to_utf8
+#undef pa_threaded_mainloop_new
+#undef pa_threaded_mainloop_free
+#undef pa_threaded_mainloop_start
+#undef pa_threaded_mainloop_stop
+#undef pa_threaded_mainloop_lock
+#undef pa_threaded_mainloop_unlock
+#undef pa_threaded_mainloop_wait
+#undef pa_threaded_mainloop_signal
+#undef pa_threaded_mainloop_accept
+#undef pa_threaded_mainloop_get_retval
+#undef pa_threaded_mainloop_get_api
+#undef pa_threaded_mainloop_in_thread
+#undef pa_threaded_mainloop_set_name
+#undef pa_threaded_mainloop_once_unlocked
+#undef pa_mainloop_new
+#undef pa_mainloop_free
+#undef pa_mainloop_prepare
+#undef pa_mainloop_poll
+#undef pa_mainloop_dispatch
+#undef pa_mainloop_get_retval
+#undef pa_mainloop_iterate
+#undef pa_mainloop_run
+#undef pa_mainloop_get_api
+#undef pa_mainloop_quit
+#undef pa_mainloop_wakeup
+#undef pa_mainloop_set_poll_func
+#undef pa_signal_init
+#undef pa_signal_done
+#undef pa_signal_new
+#undef pa_signal_free
+#undef pa_signal_set_destroy
+#undef pa_get_user_name
+#undef pa_get_host_name
+#undef pa_get_fqdn
+#undef pa_get_home_dir
+#undef pa_get_binary_name
+#undef pa_path_get_filename
+#undef pa_msleep
+#undef pa_thread_make_realtime
+#undef pa_gettimeofday
+#undef pa_timeval_diff
+#undef pa_timeval_cmp
+#undef pa_timeval_age
+#undef pa_timeval_add
+#undef pa_timeval_sub
+#undef pa_timeval_store
+#undef pa_timeval_load
+#undef pa_rtclock_now
+#include <dlfcn.h>
+#include <stdio.h>
+const char* (*pa_get_library_version_dylibloader_wrapper_pulse)( void);
+size_t (*pa_bytes_per_second_dylibloader_wrapper_pulse)(const pa_sample_spec*);
+size_t (*pa_frame_size_dylibloader_wrapper_pulse)(const pa_sample_spec*);
+size_t (*pa_sample_size_dylibloader_wrapper_pulse)(const pa_sample_spec*);
+size_t (*pa_sample_size_of_format_dylibloader_wrapper_pulse)( pa_sample_format_t);
+pa_usec_t (*pa_bytes_to_usec_dylibloader_wrapper_pulse)( uint64_t,const pa_sample_spec*);
+size_t (*pa_usec_to_bytes_dylibloader_wrapper_pulse)( pa_usec_t,const pa_sample_spec*);
+pa_sample_spec* (*pa_sample_spec_init_dylibloader_wrapper_pulse)( pa_sample_spec*);
+int (*pa_sample_format_valid_dylibloader_wrapper_pulse)( unsigned);
+int (*pa_sample_rate_valid_dylibloader_wrapper_pulse)( uint32_t);
+int (*pa_channels_valid_dylibloader_wrapper_pulse)( uint8_t);
+int (*pa_sample_spec_valid_dylibloader_wrapper_pulse)(const pa_sample_spec*);
+int (*pa_sample_spec_equal_dylibloader_wrapper_pulse)(const pa_sample_spec*,const pa_sample_spec*);
+const char* (*pa_sample_format_to_string_dylibloader_wrapper_pulse)( pa_sample_format_t);
+pa_sample_format_t (*pa_parse_sample_format_dylibloader_wrapper_pulse)(const char*);
+char* (*pa_sample_spec_snprint_dylibloader_wrapper_pulse)( char*, size_t,const pa_sample_spec*);
+char* (*pa_bytes_snprint_dylibloader_wrapper_pulse)( char*, size_t, unsigned);
+int (*pa_sample_format_is_le_dylibloader_wrapper_pulse)( pa_sample_format_t);
+int (*pa_sample_format_is_be_dylibloader_wrapper_pulse)( pa_sample_format_t);
+int (*pa_direction_valid_dylibloader_wrapper_pulse)( pa_direction_t);
+const char* (*pa_direction_to_string_dylibloader_wrapper_pulse)( pa_direction_t);
+void (*pa_mainloop_api_once_dylibloader_wrapper_pulse)( pa_mainloop_api*, void*, void*);
+pa_proplist* (*pa_proplist_new_dylibloader_wrapper_pulse)( void);
+void (*pa_proplist_free_dylibloader_wrapper_pulse)( pa_proplist*);
+int (*pa_proplist_key_valid_dylibloader_wrapper_pulse)(const char*);
+int (*pa_proplist_sets_dylibloader_wrapper_pulse)( pa_proplist*,const char*,const char*);
+int (*pa_proplist_setp_dylibloader_wrapper_pulse)( pa_proplist*,const char*);
+int (*pa_proplist_setf_dylibloader_wrapper_pulse)( pa_proplist*,const char*,const char*,...);
+int (*pa_proplist_set_dylibloader_wrapper_pulse)( pa_proplist*,const char*,const void*, size_t);
+const char* (*pa_proplist_gets_dylibloader_wrapper_pulse)(const pa_proplist*,const char*);
+int (*pa_proplist_get_dylibloader_wrapper_pulse)(const pa_proplist*,const char*,const void**, size_t*);
+void (*pa_proplist_update_dylibloader_wrapper_pulse)( pa_proplist*, pa_update_mode_t,const pa_proplist*);
+int (*pa_proplist_unset_dylibloader_wrapper_pulse)( pa_proplist*,const char*);
+int (*pa_proplist_unset_many_dylibloader_wrapper_pulse)( pa_proplist*,const char* []);
+const char* (*pa_proplist_iterate_dylibloader_wrapper_pulse)(const pa_proplist*, void**);
+char* (*pa_proplist_to_string_dylibloader_wrapper_pulse)(const pa_proplist*);
+char* (*pa_proplist_to_string_sep_dylibloader_wrapper_pulse)(const pa_proplist*,const char*);
+pa_proplist* (*pa_proplist_from_string_dylibloader_wrapper_pulse)(const char*);
+int (*pa_proplist_contains_dylibloader_wrapper_pulse)(const pa_proplist*,const char*);
+void (*pa_proplist_clear_dylibloader_wrapper_pulse)( pa_proplist*);
+pa_proplist* (*pa_proplist_copy_dylibloader_wrapper_pulse)(const pa_proplist*);
+unsigned (*pa_proplist_size_dylibloader_wrapper_pulse)(const pa_proplist*);
+int (*pa_proplist_isempty_dylibloader_wrapper_pulse)(const pa_proplist*);
+int (*pa_proplist_equal_dylibloader_wrapper_pulse)(const pa_proplist*,const pa_proplist*);
+pa_channel_map* (*pa_channel_map_init_dylibloader_wrapper_pulse)( pa_channel_map*);
+pa_channel_map* (*pa_channel_map_init_mono_dylibloader_wrapper_pulse)( pa_channel_map*);
+pa_channel_map* (*pa_channel_map_init_stereo_dylibloader_wrapper_pulse)( pa_channel_map*);
+pa_channel_map* (*pa_channel_map_init_auto_dylibloader_wrapper_pulse)( pa_channel_map*, unsigned, pa_channel_map_def_t);
+pa_channel_map* (*pa_channel_map_init_extend_dylibloader_wrapper_pulse)( pa_channel_map*, unsigned, pa_channel_map_def_t);
+const char* (*pa_channel_position_to_string_dylibloader_wrapper_pulse)( pa_channel_position_t);
+pa_channel_position_t (*pa_channel_position_from_string_dylibloader_wrapper_pulse)(const char*);
+const char* (*pa_channel_position_to_pretty_string_dylibloader_wrapper_pulse)( pa_channel_position_t);
+char* (*pa_channel_map_snprint_dylibloader_wrapper_pulse)( char*, size_t,const pa_channel_map*);
+pa_channel_map* (*pa_channel_map_parse_dylibloader_wrapper_pulse)( pa_channel_map*,const char*);
+int (*pa_channel_map_equal_dylibloader_wrapper_pulse)(const pa_channel_map*,const pa_channel_map*);
+int (*pa_channel_map_valid_dylibloader_wrapper_pulse)(const pa_channel_map*);
+int (*pa_channel_map_compatible_dylibloader_wrapper_pulse)(const pa_channel_map*,const pa_sample_spec*);
+int (*pa_channel_map_superset_dylibloader_wrapper_pulse)(const pa_channel_map*,const pa_channel_map*);
+int (*pa_channel_map_can_balance_dylibloader_wrapper_pulse)(const pa_channel_map*);
+int (*pa_channel_map_can_fade_dylibloader_wrapper_pulse)(const pa_channel_map*);
+int (*pa_channel_map_can_lfe_balance_dylibloader_wrapper_pulse)(const pa_channel_map*);
+const char* (*pa_channel_map_to_name_dylibloader_wrapper_pulse)(const pa_channel_map*);
+const char* (*pa_channel_map_to_pretty_name_dylibloader_wrapper_pulse)(const pa_channel_map*);
+int (*pa_channel_map_has_position_dylibloader_wrapper_pulse)(const pa_channel_map*, pa_channel_position_t);
+pa_channel_position_mask_t (*pa_channel_map_mask_dylibloader_wrapper_pulse)(const pa_channel_map*);
+const char* (*pa_encoding_to_string_dylibloader_wrapper_pulse)( pa_encoding_t);
+pa_encoding_t (*pa_encoding_from_string_dylibloader_wrapper_pulse)(const char*);
+pa_format_info* (*pa_format_info_new_dylibloader_wrapper_pulse)( void);
+pa_format_info* (*pa_format_info_copy_dylibloader_wrapper_pulse)(const pa_format_info*);
+void (*pa_format_info_free_dylibloader_wrapper_pulse)( pa_format_info*);
+int (*pa_format_info_valid_dylibloader_wrapper_pulse)(const pa_format_info*);
+int (*pa_format_info_is_pcm_dylibloader_wrapper_pulse)(const pa_format_info*);
+int (*pa_format_info_is_compatible_dylibloader_wrapper_pulse)(const pa_format_info*,const pa_format_info*);
+char* (*pa_format_info_snprint_dylibloader_wrapper_pulse)( char*, size_t,const pa_format_info*);
+pa_format_info* (*pa_format_info_from_string_dylibloader_wrapper_pulse)(const char*);
+pa_format_info* (*pa_format_info_from_sample_spec_dylibloader_wrapper_pulse)(const pa_sample_spec*,const pa_channel_map*);
+int (*pa_format_info_to_sample_spec_dylibloader_wrapper_pulse)(const pa_format_info*, pa_sample_spec*, pa_channel_map*);
+pa_prop_type_t (*pa_format_info_get_prop_type_dylibloader_wrapper_pulse)(const pa_format_info*,const char*);
+int (*pa_format_info_get_prop_int_dylibloader_wrapper_pulse)(const pa_format_info*,const char*, int*);
+int (*pa_format_info_get_prop_int_range_dylibloader_wrapper_pulse)(const pa_format_info*,const char*, int*, int*);
+int (*pa_format_info_get_prop_int_array_dylibloader_wrapper_pulse)(const pa_format_info*,const char*, int**, int*);
+int (*pa_format_info_get_prop_string_dylibloader_wrapper_pulse)(const pa_format_info*,const char*, char**);
+int (*pa_format_info_get_prop_string_array_dylibloader_wrapper_pulse)(const pa_format_info*,const char*, char***, int*);
+void (*pa_format_info_free_string_array_dylibloader_wrapper_pulse)( char**, int);
+int (*pa_format_info_get_sample_format_dylibloader_wrapper_pulse)(const pa_format_info*, pa_sample_format_t*);
+int (*pa_format_info_get_rate_dylibloader_wrapper_pulse)(const pa_format_info*, uint32_t*);
+int (*pa_format_info_get_channels_dylibloader_wrapper_pulse)(const pa_format_info*, uint8_t*);
+int (*pa_format_info_get_channel_map_dylibloader_wrapper_pulse)(const pa_format_info*, pa_channel_map*);
+void (*pa_format_info_set_prop_int_dylibloader_wrapper_pulse)( pa_format_info*,const char*, int);
+void (*pa_format_info_set_prop_int_array_dylibloader_wrapper_pulse)( pa_format_info*,const char*,const int*, int);
+void (*pa_format_info_set_prop_int_range_dylibloader_wrapper_pulse)( pa_format_info*,const char*, int, int);
+void (*pa_format_info_set_prop_string_dylibloader_wrapper_pulse)( pa_format_info*,const char*,const char*);
+void (*pa_format_info_set_prop_string_array_dylibloader_wrapper_pulse)( pa_format_info*,const char*,const char**, int);
+void (*pa_format_info_set_sample_format_dylibloader_wrapper_pulse)( pa_format_info*, pa_sample_format_t);
+void (*pa_format_info_set_rate_dylibloader_wrapper_pulse)( pa_format_info*, int);
+void (*pa_format_info_set_channels_dylibloader_wrapper_pulse)( pa_format_info*, int);
+void (*pa_format_info_set_channel_map_dylibloader_wrapper_pulse)( pa_format_info*,const pa_channel_map*);
+pa_operation* (*pa_operation_ref_dylibloader_wrapper_pulse)( pa_operation*);
+void (*pa_operation_unref_dylibloader_wrapper_pulse)( pa_operation*);
+void (*pa_operation_cancel_dylibloader_wrapper_pulse)( pa_operation*);
+pa_operation_state_t (*pa_operation_get_state_dylibloader_wrapper_pulse)(const pa_operation*);
+void (*pa_operation_set_state_callback_dylibloader_wrapper_pulse)( pa_operation*, pa_operation_notify_cb_t, void*);
+pa_context* (*pa_context_new_dylibloader_wrapper_pulse)( pa_mainloop_api*,const char*);
+pa_context* (*pa_context_new_with_proplist_dylibloader_wrapper_pulse)( pa_mainloop_api*,const char*,const pa_proplist*);
+void (*pa_context_unref_dylibloader_wrapper_pulse)( pa_context*);
+pa_context* (*pa_context_ref_dylibloader_wrapper_pulse)( pa_context*);
+void (*pa_context_set_state_callback_dylibloader_wrapper_pulse)( pa_context*, pa_context_notify_cb_t, void*);
+void (*pa_context_set_event_callback_dylibloader_wrapper_pulse)( pa_context*, pa_context_event_cb_t, void*);
+int (*pa_context_errno_dylibloader_wrapper_pulse)(const pa_context*);
+int (*pa_context_is_pending_dylibloader_wrapper_pulse)(const pa_context*);
+pa_context_state_t (*pa_context_get_state_dylibloader_wrapper_pulse)(const pa_context*);
+int (*pa_context_connect_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_context_flags_t,const pa_spawn_api*);
+void (*pa_context_disconnect_dylibloader_wrapper_pulse)( pa_context*);
+pa_operation* (*pa_context_drain_dylibloader_wrapper_pulse)( pa_context*, pa_context_notify_cb_t, void*);
+pa_operation* (*pa_context_exit_daemon_dylibloader_wrapper_pulse)( pa_context*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_default_sink_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_default_source_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_context_success_cb_t, void*);
+int (*pa_context_is_local_dylibloader_wrapper_pulse)(const pa_context*);
+pa_operation* (*pa_context_set_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_context_success_cb_t, void*);
+const char* (*pa_context_get_server_dylibloader_wrapper_pulse)(const pa_context*);
+uint32_t (*pa_context_get_protocol_version_dylibloader_wrapper_pulse)(const pa_context*);
+uint32_t (*pa_context_get_server_protocol_version_dylibloader_wrapper_pulse)(const pa_context*);
+pa_operation* (*pa_context_proplist_update_dylibloader_wrapper_pulse)( pa_context*, pa_update_mode_t,const pa_proplist*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_proplist_remove_dylibloader_wrapper_pulse)( pa_context*,const char* [], pa_context_success_cb_t, void*);
+uint32_t (*pa_context_get_index_dylibloader_wrapper_pulse)(const pa_context*);
+pa_time_event* (*pa_context_rttime_new_dylibloader_wrapper_pulse)(const pa_context*, pa_usec_t, pa_time_event_cb_t, void*);
+void (*pa_context_rttime_restart_dylibloader_wrapper_pulse)(const pa_context*, pa_time_event*, pa_usec_t);
+size_t (*pa_context_get_tile_size_dylibloader_wrapper_pulse)(const pa_context*,const pa_sample_spec*);
+int (*pa_context_load_cookie_from_file_dylibloader_wrapper_pulse)( pa_context*,const char*);
+int (*pa_cvolume_equal_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_cvolume*);
+pa_cvolume* (*pa_cvolume_init_dylibloader_wrapper_pulse)( pa_cvolume*);
+pa_cvolume* (*pa_cvolume_set_dylibloader_wrapper_pulse)( pa_cvolume*, unsigned, pa_volume_t);
+char* (*pa_cvolume_snprint_dylibloader_wrapper_pulse)( char*, size_t,const pa_cvolume*);
+char* (*pa_sw_cvolume_snprint_dB_dylibloader_wrapper_pulse)( char*, size_t,const pa_cvolume*);
+char* (*pa_cvolume_snprint_verbose_dylibloader_wrapper_pulse)( char*, size_t,const pa_cvolume*,const pa_channel_map*, int);
+char* (*pa_volume_snprint_dylibloader_wrapper_pulse)( char*, size_t, pa_volume_t);
+char* (*pa_sw_volume_snprint_dB_dylibloader_wrapper_pulse)( char*, size_t, pa_volume_t);
+char* (*pa_volume_snprint_verbose_dylibloader_wrapper_pulse)( char*, size_t, pa_volume_t, int);
+pa_volume_t (*pa_cvolume_avg_dylibloader_wrapper_pulse)(const pa_cvolume*);
+pa_volume_t (*pa_cvolume_avg_mask_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*, pa_channel_position_mask_t);
+pa_volume_t (*pa_cvolume_max_dylibloader_wrapper_pulse)(const pa_cvolume*);
+pa_volume_t (*pa_cvolume_max_mask_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*, pa_channel_position_mask_t);
+pa_volume_t (*pa_cvolume_min_dylibloader_wrapper_pulse)(const pa_cvolume*);
+pa_volume_t (*pa_cvolume_min_mask_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*, pa_channel_position_mask_t);
+int (*pa_cvolume_valid_dylibloader_wrapper_pulse)(const pa_cvolume*);
+int (*pa_cvolume_channels_equal_to_dylibloader_wrapper_pulse)(const pa_cvolume*, pa_volume_t);
+pa_volume_t (*pa_sw_volume_multiply_dylibloader_wrapper_pulse)( pa_volume_t, pa_volume_t);
+pa_cvolume* (*pa_sw_cvolume_multiply_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_cvolume*,const pa_cvolume*);
+pa_cvolume* (*pa_sw_cvolume_multiply_scalar_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_cvolume*, pa_volume_t);
+pa_volume_t (*pa_sw_volume_divide_dylibloader_wrapper_pulse)( pa_volume_t, pa_volume_t);
+pa_cvolume* (*pa_sw_cvolume_divide_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_cvolume*,const pa_cvolume*);
+pa_cvolume* (*pa_sw_cvolume_divide_scalar_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_cvolume*, pa_volume_t);
+pa_volume_t (*pa_sw_volume_from_dB_dylibloader_wrapper_pulse)( double);
+double (*pa_sw_volume_to_dB_dylibloader_wrapper_pulse)( pa_volume_t);
+pa_volume_t (*pa_sw_volume_from_linear_dylibloader_wrapper_pulse)( double);
+double (*pa_sw_volume_to_linear_dylibloader_wrapper_pulse)( pa_volume_t);
+pa_cvolume* (*pa_cvolume_remap_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_channel_map*,const pa_channel_map*);
+int (*pa_cvolume_compatible_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_sample_spec*);
+int (*pa_cvolume_compatible_with_channel_map_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*);
+float (*pa_cvolume_get_balance_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*);
+pa_cvolume* (*pa_cvolume_set_balance_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_channel_map*, float);
+float (*pa_cvolume_get_fade_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*);
+pa_cvolume* (*pa_cvolume_set_fade_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_channel_map*, float);
+float (*pa_cvolume_get_lfe_balance_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*);
+pa_cvolume* (*pa_cvolume_set_lfe_balance_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_channel_map*, float);
+pa_cvolume* (*pa_cvolume_scale_dylibloader_wrapper_pulse)( pa_cvolume*, pa_volume_t);
+pa_cvolume* (*pa_cvolume_scale_mask_dylibloader_wrapper_pulse)( pa_cvolume*, pa_volume_t,const pa_channel_map*, pa_channel_position_mask_t);
+pa_cvolume* (*pa_cvolume_set_position_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_channel_map*, pa_channel_position_t, pa_volume_t);
+pa_volume_t (*pa_cvolume_get_position_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*, pa_channel_position_t);
+pa_cvolume* (*pa_cvolume_merge_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_cvolume*,const pa_cvolume*);
+pa_cvolume* (*pa_cvolume_inc_clamp_dylibloader_wrapper_pulse)( pa_cvolume*, pa_volume_t, pa_volume_t);
+pa_cvolume* (*pa_cvolume_inc_dylibloader_wrapper_pulse)( pa_cvolume*, pa_volume_t);
+pa_cvolume* (*pa_cvolume_dec_dylibloader_wrapper_pulse)( pa_cvolume*, pa_volume_t);
+pa_stream* (*pa_stream_new_dylibloader_wrapper_pulse)( pa_context*,const char*,const pa_sample_spec*,const pa_channel_map*);
+pa_stream* (*pa_stream_new_with_proplist_dylibloader_wrapper_pulse)( pa_context*,const char*,const pa_sample_spec*,const pa_channel_map*, pa_proplist*);
+pa_stream* (*pa_stream_new_extended_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_format_info**, unsigned int, pa_proplist*);
+void (*pa_stream_unref_dylibloader_wrapper_pulse)( pa_stream*);
+pa_stream* (*pa_stream_ref_dylibloader_wrapper_pulse)( pa_stream*);
+pa_stream_state_t (*pa_stream_get_state_dylibloader_wrapper_pulse)(const pa_stream*);
+pa_context* (*pa_stream_get_context_dylibloader_wrapper_pulse)(const pa_stream*);
+uint32_t (*pa_stream_get_index_dylibloader_wrapper_pulse)(const pa_stream*);
+uint32_t (*pa_stream_get_device_index_dylibloader_wrapper_pulse)(const pa_stream*);
+const char* (*pa_stream_get_device_name_dylibloader_wrapper_pulse)(const pa_stream*);
+int (*pa_stream_is_suspended_dylibloader_wrapper_pulse)(const pa_stream*);
+int (*pa_stream_is_corked_dylibloader_wrapper_pulse)(const pa_stream*);
+int (*pa_stream_connect_playback_dylibloader_wrapper_pulse)( pa_stream*,const char*,const pa_buffer_attr*, pa_stream_flags_t,const pa_cvolume*, pa_stream*);
+int (*pa_stream_connect_record_dylibloader_wrapper_pulse)( pa_stream*,const char*,const pa_buffer_attr*, pa_stream_flags_t);
+int (*pa_stream_disconnect_dylibloader_wrapper_pulse)( pa_stream*);
+int (*pa_stream_begin_write_dylibloader_wrapper_pulse)( pa_stream*, void**, size_t*);
+int (*pa_stream_cancel_write_dylibloader_wrapper_pulse)( pa_stream*);
+int (*pa_stream_write_dylibloader_wrapper_pulse)( pa_stream*,const void*, size_t, pa_free_cb_t, int64_t, pa_seek_mode_t);
+int (*pa_stream_write_ext_free_dylibloader_wrapper_pulse)( pa_stream*,const void*, size_t, pa_free_cb_t, void*, int64_t, pa_seek_mode_t);
+int (*pa_stream_peek_dylibloader_wrapper_pulse)( pa_stream*,const void**, size_t*);
+int (*pa_stream_drop_dylibloader_wrapper_pulse)( pa_stream*);
+size_t (*pa_stream_writable_size_dylibloader_wrapper_pulse)(const pa_stream*);
+size_t (*pa_stream_readable_size_dylibloader_wrapper_pulse)(const pa_stream*);
+pa_operation* (*pa_stream_drain_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_success_cb_t, void*);
+pa_operation* (*pa_stream_update_timing_info_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_success_cb_t, void*);
+void (*pa_stream_set_state_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+void (*pa_stream_set_write_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_request_cb_t, void*);
+void (*pa_stream_set_read_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_request_cb_t, void*);
+void (*pa_stream_set_overflow_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+int64_t (*pa_stream_get_underflow_index_dylibloader_wrapper_pulse)(const pa_stream*);
+void (*pa_stream_set_underflow_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+void (*pa_stream_set_started_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+void (*pa_stream_set_latency_update_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+void (*pa_stream_set_moved_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+void (*pa_stream_set_suspended_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+void (*pa_stream_set_event_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_event_cb_t, void*);
+void (*pa_stream_set_buffer_attr_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+pa_operation* (*pa_stream_cork_dylibloader_wrapper_pulse)( pa_stream*, int, pa_stream_success_cb_t, void*);
+pa_operation* (*pa_stream_flush_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_success_cb_t, void*);
+pa_operation* (*pa_stream_prebuf_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_success_cb_t, void*);
+pa_operation* (*pa_stream_trigger_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_success_cb_t, void*);
+pa_operation* (*pa_stream_set_name_dylibloader_wrapper_pulse)( pa_stream*,const char*, pa_stream_success_cb_t, void*);
+int (*pa_stream_get_time_dylibloader_wrapper_pulse)( pa_stream*, pa_usec_t*);
+int (*pa_stream_get_latency_dylibloader_wrapper_pulse)( pa_stream*, pa_usec_t*, int*);
+const pa_timing_info* (*pa_stream_get_timing_info_dylibloader_wrapper_pulse)( pa_stream*);
+const pa_sample_spec* (*pa_stream_get_sample_spec_dylibloader_wrapper_pulse)( pa_stream*);
+const pa_channel_map* (*pa_stream_get_channel_map_dylibloader_wrapper_pulse)( pa_stream*);
+const pa_format_info* (*pa_stream_get_format_info_dylibloader_wrapper_pulse)(const pa_stream*);
+const pa_buffer_attr* (*pa_stream_get_buffer_attr_dylibloader_wrapper_pulse)( pa_stream*);
+pa_operation* (*pa_stream_set_buffer_attr_dylibloader_wrapper_pulse)( pa_stream*,const pa_buffer_attr*, pa_stream_success_cb_t, void*);
+pa_operation* (*pa_stream_update_sample_rate_dylibloader_wrapper_pulse)( pa_stream*, uint32_t, pa_stream_success_cb_t, void*);
+pa_operation* (*pa_stream_proplist_update_dylibloader_wrapper_pulse)( pa_stream*, pa_update_mode_t, pa_proplist*, pa_stream_success_cb_t, void*);
+pa_operation* (*pa_stream_proplist_remove_dylibloader_wrapper_pulse)( pa_stream*,const char* [], pa_stream_success_cb_t, void*);
+int (*pa_stream_set_monitor_stream_dylibloader_wrapper_pulse)( pa_stream*, uint32_t);
+uint32_t (*pa_stream_get_monitor_stream_dylibloader_wrapper_pulse)(const pa_stream*);
+pa_operation* (*pa_context_get_sink_info_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_sink_info_cb_t, void*);
+pa_operation* (*pa_context_get_sink_info_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_sink_info_cb_t, void*);
+pa_operation* (*pa_context_get_sink_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_sink_info_cb_t, void*);
+pa_operation* (*pa_context_set_sink_volume_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const pa_cvolume*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_sink_volume_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*,const pa_cvolume*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_sink_mute_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_sink_mute_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, int, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_suspend_sink_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, int, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_suspend_sink_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_sink_port_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const char*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_sink_port_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_get_source_info_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_source_info_cb_t, void*);
+pa_operation* (*pa_context_get_source_info_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_source_info_cb_t, void*);
+pa_operation* (*pa_context_get_source_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_source_info_cb_t, void*);
+pa_operation* (*pa_context_set_source_volume_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const pa_cvolume*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_source_volume_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*,const pa_cvolume*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_source_mute_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_source_mute_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, int, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_suspend_source_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, int, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_suspend_source_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_source_port_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const char*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_source_port_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_get_server_info_dylibloader_wrapper_pulse)( pa_context*, pa_server_info_cb_t, void*);
+pa_operation* (*pa_context_get_module_info_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_module_info_cb_t, void*);
+pa_operation* (*pa_context_get_module_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_module_info_cb_t, void*);
+pa_operation* (*pa_context_load_module_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_context_index_cb_t, void*);
+pa_operation* (*pa_context_unload_module_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_get_client_info_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_client_info_cb_t, void*);
+pa_operation* (*pa_context_get_client_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_client_info_cb_t, void*);
+pa_operation* (*pa_context_kill_client_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_get_card_info_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_card_info_cb_t, void*);
+pa_operation* (*pa_context_get_card_info_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_card_info_cb_t, void*);
+pa_operation* (*pa_context_get_card_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_card_info_cb_t, void*);
+pa_operation* (*pa_context_set_card_profile_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const char*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_card_profile_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_port_latency_offset_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, int64_t, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_get_sink_input_info_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_sink_input_info_cb_t, void*);
+pa_operation* (*pa_context_get_sink_input_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_sink_input_info_cb_t, void*);
+pa_operation* (*pa_context_move_sink_input_by_name_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const char*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_move_sink_input_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, uint32_t, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_sink_input_volume_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const pa_cvolume*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_sink_input_mute_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_kill_sink_input_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_get_source_output_info_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_source_output_info_cb_t, void*);
+pa_operation* (*pa_context_get_source_output_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_source_output_info_cb_t, void*);
+pa_operation* (*pa_context_move_source_output_by_name_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const char*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_move_source_output_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, uint32_t, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_source_output_volume_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const pa_cvolume*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_set_source_output_mute_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_kill_source_output_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_stat_dylibloader_wrapper_pulse)( pa_context*, pa_stat_info_cb_t, void*);
+pa_operation* (*pa_context_get_sample_info_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_sample_info_cb_t, void*);
+pa_operation* (*pa_context_get_sample_info_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_sample_info_cb_t, void*);
+pa_operation* (*pa_context_get_sample_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_sample_info_cb_t, void*);
+pa_operation* (*pa_context_get_autoload_info_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_autoload_type_t, pa_autoload_info_cb_t, void*);
+pa_operation* (*pa_context_get_autoload_info_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_autoload_info_cb_t, void*);
+pa_operation* (*pa_context_get_autoload_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_autoload_info_cb_t, void*);
+pa_operation* (*pa_context_add_autoload_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_autoload_type_t,const char*,const char*, pa_context_index_cb_t, void*);
+pa_operation* (*pa_context_remove_autoload_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_autoload_type_t, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_remove_autoload_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_subscribe_dylibloader_wrapper_pulse)( pa_context*, pa_subscription_mask_t, pa_context_success_cb_t, void*);
+void (*pa_context_set_subscribe_callback_dylibloader_wrapper_pulse)( pa_context*, pa_context_subscribe_cb_t, void*);
+int (*pa_stream_connect_upload_dylibloader_wrapper_pulse)( pa_stream*, size_t);
+int (*pa_stream_finish_upload_dylibloader_wrapper_pulse)( pa_stream*);
+pa_operation* (*pa_context_remove_sample_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_play_sample_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_volume_t, pa_context_success_cb_t, void*);
+pa_operation* (*pa_context_play_sample_with_proplist_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_volume_t,const pa_proplist*, pa_context_play_sample_cb_t, void*);
+const char* (*pa_strerror_dylibloader_wrapper_pulse)( int);
+void* (*pa_xmalloc_dylibloader_wrapper_pulse)( size_t);
+void* (*pa_xmalloc0_dylibloader_wrapper_pulse)( size_t);
+void* (*pa_xrealloc_dylibloader_wrapper_pulse)( void*, size_t);
+void (*pa_xfree_dylibloader_wrapper_pulse)( void*);
+char* (*pa_xstrdup_dylibloader_wrapper_pulse)(const char*);
+char* (*pa_xstrndup_dylibloader_wrapper_pulse)(const char*, size_t);
+void* (*pa_xmemdup_dylibloader_wrapper_pulse)(const void*, size_t);
+char* (*pa_utf8_valid_dylibloader_wrapper_pulse)(const char*);
+char* (*pa_ascii_valid_dylibloader_wrapper_pulse)(const char*);
+char* (*pa_utf8_filter_dylibloader_wrapper_pulse)(const char*);
+char* (*pa_ascii_filter_dylibloader_wrapper_pulse)(const char*);
+char* (*pa_utf8_to_locale_dylibloader_wrapper_pulse)(const char*);
+char* (*pa_locale_to_utf8_dylibloader_wrapper_pulse)(const char*);
+pa_threaded_mainloop* (*pa_threaded_mainloop_new_dylibloader_wrapper_pulse)( void);
+void (*pa_threaded_mainloop_free_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+int (*pa_threaded_mainloop_start_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+void (*pa_threaded_mainloop_stop_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+void (*pa_threaded_mainloop_lock_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+void (*pa_threaded_mainloop_unlock_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+void (*pa_threaded_mainloop_wait_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+void (*pa_threaded_mainloop_signal_dylibloader_wrapper_pulse)( pa_threaded_mainloop*, int);
+void (*pa_threaded_mainloop_accept_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+int (*pa_threaded_mainloop_get_retval_dylibloader_wrapper_pulse)(const pa_threaded_mainloop*);
+pa_mainloop_api* (*pa_threaded_mainloop_get_api_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+int (*pa_threaded_mainloop_in_thread_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+void (*pa_threaded_mainloop_set_name_dylibloader_wrapper_pulse)( pa_threaded_mainloop*,const char*);
+void (*pa_threaded_mainloop_once_unlocked_dylibloader_wrapper_pulse)( pa_threaded_mainloop*, void*, void*);
+pa_mainloop* (*pa_mainloop_new_dylibloader_wrapper_pulse)( void);
+void (*pa_mainloop_free_dylibloader_wrapper_pulse)( pa_mainloop*);
+int (*pa_mainloop_prepare_dylibloader_wrapper_pulse)( pa_mainloop*, int);
+int (*pa_mainloop_poll_dylibloader_wrapper_pulse)( pa_mainloop*);
+int (*pa_mainloop_dispatch_dylibloader_wrapper_pulse)( pa_mainloop*);
+int (*pa_mainloop_get_retval_dylibloader_wrapper_pulse)(const pa_mainloop*);
+int (*pa_mainloop_iterate_dylibloader_wrapper_pulse)( pa_mainloop*, int, int*);
+int (*pa_mainloop_run_dylibloader_wrapper_pulse)( pa_mainloop*, int*);
+pa_mainloop_api* (*pa_mainloop_get_api_dylibloader_wrapper_pulse)( pa_mainloop*);
+void (*pa_mainloop_quit_dylibloader_wrapper_pulse)( pa_mainloop*, int);
+void (*pa_mainloop_wakeup_dylibloader_wrapper_pulse)( pa_mainloop*);
+void (*pa_mainloop_set_poll_func_dylibloader_wrapper_pulse)( pa_mainloop*, pa_poll_func, void*);
+int (*pa_signal_init_dylibloader_wrapper_pulse)( pa_mainloop_api*);
+void (*pa_signal_done_dylibloader_wrapper_pulse)( void);
+pa_signal_event* (*pa_signal_new_dylibloader_wrapper_pulse)( int, pa_signal_cb_t, void*);
+void (*pa_signal_free_dylibloader_wrapper_pulse)( pa_signal_event*);
+void (*pa_signal_set_destroy_dylibloader_wrapper_pulse)( pa_signal_event*, pa_signal_destroy_cb_t);
+char* (*pa_get_user_name_dylibloader_wrapper_pulse)( char*, size_t);
+char* (*pa_get_host_name_dylibloader_wrapper_pulse)( char*, size_t);
+char* (*pa_get_fqdn_dylibloader_wrapper_pulse)( char*, size_t);
+char* (*pa_get_home_dir_dylibloader_wrapper_pulse)( char*, size_t);
+char* (*pa_get_binary_name_dylibloader_wrapper_pulse)( char*, size_t);
+char* (*pa_path_get_filename_dylibloader_wrapper_pulse)(const char*);
+int (*pa_msleep_dylibloader_wrapper_pulse)( unsigned long);
+int (*pa_thread_make_realtime_dylibloader_wrapper_pulse)( int);
+struct timeval* (*pa_gettimeofday_dylibloader_wrapper_pulse)(struct timeval*);
+pa_usec_t (*pa_timeval_diff_dylibloader_wrapper_pulse)(struct timeval*,struct timeval*);
+int (*pa_timeval_cmp_dylibloader_wrapper_pulse)(struct timeval*,struct timeval*);
+pa_usec_t (*pa_timeval_age_dylibloader_wrapper_pulse)(struct timeval*);
+struct timeval* (*pa_timeval_add_dylibloader_wrapper_pulse)(struct timeval*, pa_usec_t);
+struct timeval* (*pa_timeval_sub_dylibloader_wrapper_pulse)(struct timeval*, pa_usec_t);
+struct timeval* (*pa_timeval_store_dylibloader_wrapper_pulse)(struct timeval*, pa_usec_t);
+pa_usec_t (*pa_timeval_load_dylibloader_wrapper_pulse)(struct timeval*);
+pa_usec_t (*pa_rtclock_now_dylibloader_wrapper_pulse)( void);
+int initialize_pulse(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libpulse.so.0", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// pa_get_library_version
+ *(void **) (&pa_get_library_version_dylibloader_wrapper_pulse) = dlsym(handle, "pa_get_library_version");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_bytes_per_second
+ *(void **) (&pa_bytes_per_second_dylibloader_wrapper_pulse) = dlsym(handle, "pa_bytes_per_second");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_frame_size
+ *(void **) (&pa_frame_size_dylibloader_wrapper_pulse) = dlsym(handle, "pa_frame_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sample_size
+ *(void **) (&pa_sample_size_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sample_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sample_size_of_format
+ *(void **) (&pa_sample_size_of_format_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sample_size_of_format");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_bytes_to_usec
+ *(void **) (&pa_bytes_to_usec_dylibloader_wrapper_pulse) = dlsym(handle, "pa_bytes_to_usec");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_usec_to_bytes
+ *(void **) (&pa_usec_to_bytes_dylibloader_wrapper_pulse) = dlsym(handle, "pa_usec_to_bytes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sample_spec_init
+ *(void **) (&pa_sample_spec_init_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sample_spec_init");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sample_format_valid
+ *(void **) (&pa_sample_format_valid_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sample_format_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sample_rate_valid
+ *(void **) (&pa_sample_rate_valid_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sample_rate_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channels_valid
+ *(void **) (&pa_channels_valid_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channels_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sample_spec_valid
+ *(void **) (&pa_sample_spec_valid_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sample_spec_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sample_spec_equal
+ *(void **) (&pa_sample_spec_equal_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sample_spec_equal");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sample_format_to_string
+ *(void **) (&pa_sample_format_to_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sample_format_to_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_parse_sample_format
+ *(void **) (&pa_parse_sample_format_dylibloader_wrapper_pulse) = dlsym(handle, "pa_parse_sample_format");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sample_spec_snprint
+ *(void **) (&pa_sample_spec_snprint_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sample_spec_snprint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_bytes_snprint
+ *(void **) (&pa_bytes_snprint_dylibloader_wrapper_pulse) = dlsym(handle, "pa_bytes_snprint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sample_format_is_le
+ *(void **) (&pa_sample_format_is_le_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sample_format_is_le");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sample_format_is_be
+ *(void **) (&pa_sample_format_is_be_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sample_format_is_be");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_direction_valid
+ *(void **) (&pa_direction_valid_dylibloader_wrapper_pulse) = dlsym(handle, "pa_direction_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_direction_to_string
+ *(void **) (&pa_direction_to_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_direction_to_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_api_once
+ *(void **) (&pa_mainloop_api_once_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_api_once");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_new
+ *(void **) (&pa_proplist_new_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_free
+ *(void **) (&pa_proplist_free_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_key_valid
+ *(void **) (&pa_proplist_key_valid_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_key_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_sets
+ *(void **) (&pa_proplist_sets_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_sets");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_setp
+ *(void **) (&pa_proplist_setp_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_setp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_setf
+ *(void **) (&pa_proplist_setf_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_setf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_set
+ *(void **) (&pa_proplist_set_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_set");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_gets
+ *(void **) (&pa_proplist_gets_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_gets");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_get
+ *(void **) (&pa_proplist_get_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_get");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_update
+ *(void **) (&pa_proplist_update_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_update");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_unset
+ *(void **) (&pa_proplist_unset_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_unset");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_unset_many
+ *(void **) (&pa_proplist_unset_many_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_unset_many");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_iterate
+ *(void **) (&pa_proplist_iterate_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_iterate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_to_string
+ *(void **) (&pa_proplist_to_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_to_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_to_string_sep
+ *(void **) (&pa_proplist_to_string_sep_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_to_string_sep");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_from_string
+ *(void **) (&pa_proplist_from_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_from_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_contains
+ *(void **) (&pa_proplist_contains_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_contains");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_clear
+ *(void **) (&pa_proplist_clear_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_clear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_copy
+ *(void **) (&pa_proplist_copy_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_size
+ *(void **) (&pa_proplist_size_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_isempty
+ *(void **) (&pa_proplist_isempty_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_isempty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_proplist_equal
+ *(void **) (&pa_proplist_equal_dylibloader_wrapper_pulse) = dlsym(handle, "pa_proplist_equal");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_init
+ *(void **) (&pa_channel_map_init_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_init");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_init_mono
+ *(void **) (&pa_channel_map_init_mono_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_init_mono");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_init_stereo
+ *(void **) (&pa_channel_map_init_stereo_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_init_stereo");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_init_auto
+ *(void **) (&pa_channel_map_init_auto_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_init_auto");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_init_extend
+ *(void **) (&pa_channel_map_init_extend_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_init_extend");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_position_to_string
+ *(void **) (&pa_channel_position_to_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_position_to_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_position_from_string
+ *(void **) (&pa_channel_position_from_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_position_from_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_position_to_pretty_string
+ *(void **) (&pa_channel_position_to_pretty_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_position_to_pretty_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_snprint
+ *(void **) (&pa_channel_map_snprint_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_snprint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_parse
+ *(void **) (&pa_channel_map_parse_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_parse");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_equal
+ *(void **) (&pa_channel_map_equal_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_equal");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_valid
+ *(void **) (&pa_channel_map_valid_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_compatible
+ *(void **) (&pa_channel_map_compatible_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_compatible");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_superset
+ *(void **) (&pa_channel_map_superset_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_superset");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_can_balance
+ *(void **) (&pa_channel_map_can_balance_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_can_balance");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_can_fade
+ *(void **) (&pa_channel_map_can_fade_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_can_fade");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_can_lfe_balance
+ *(void **) (&pa_channel_map_can_lfe_balance_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_can_lfe_balance");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_to_name
+ *(void **) (&pa_channel_map_to_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_to_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_to_pretty_name
+ *(void **) (&pa_channel_map_to_pretty_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_to_pretty_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_has_position
+ *(void **) (&pa_channel_map_has_position_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_has_position");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_channel_map_mask
+ *(void **) (&pa_channel_map_mask_dylibloader_wrapper_pulse) = dlsym(handle, "pa_channel_map_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_encoding_to_string
+ *(void **) (&pa_encoding_to_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_encoding_to_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_encoding_from_string
+ *(void **) (&pa_encoding_from_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_encoding_from_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_new
+ *(void **) (&pa_format_info_new_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_copy
+ *(void **) (&pa_format_info_copy_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_free
+ *(void **) (&pa_format_info_free_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_valid
+ *(void **) (&pa_format_info_valid_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_is_pcm
+ *(void **) (&pa_format_info_is_pcm_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_is_pcm");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_is_compatible
+ *(void **) (&pa_format_info_is_compatible_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_is_compatible");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_snprint
+ *(void **) (&pa_format_info_snprint_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_snprint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_from_string
+ *(void **) (&pa_format_info_from_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_from_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_from_sample_spec
+ *(void **) (&pa_format_info_from_sample_spec_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_from_sample_spec");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_to_sample_spec
+ *(void **) (&pa_format_info_to_sample_spec_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_to_sample_spec");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_get_prop_type
+ *(void **) (&pa_format_info_get_prop_type_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_get_prop_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_get_prop_int
+ *(void **) (&pa_format_info_get_prop_int_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_get_prop_int");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_get_prop_int_range
+ *(void **) (&pa_format_info_get_prop_int_range_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_get_prop_int_range");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_get_prop_int_array
+ *(void **) (&pa_format_info_get_prop_int_array_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_get_prop_int_array");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_get_prop_string
+ *(void **) (&pa_format_info_get_prop_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_get_prop_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_get_prop_string_array
+ *(void **) (&pa_format_info_get_prop_string_array_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_get_prop_string_array");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_free_string_array
+ *(void **) (&pa_format_info_free_string_array_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_free_string_array");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_get_sample_format
+ *(void **) (&pa_format_info_get_sample_format_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_get_sample_format");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_get_rate
+ *(void **) (&pa_format_info_get_rate_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_get_rate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_get_channels
+ *(void **) (&pa_format_info_get_channels_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_get_channels");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_get_channel_map
+ *(void **) (&pa_format_info_get_channel_map_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_get_channel_map");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_set_prop_int
+ *(void **) (&pa_format_info_set_prop_int_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_set_prop_int");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_set_prop_int_array
+ *(void **) (&pa_format_info_set_prop_int_array_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_set_prop_int_array");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_set_prop_int_range
+ *(void **) (&pa_format_info_set_prop_int_range_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_set_prop_int_range");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_set_prop_string
+ *(void **) (&pa_format_info_set_prop_string_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_set_prop_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_set_prop_string_array
+ *(void **) (&pa_format_info_set_prop_string_array_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_set_prop_string_array");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_set_sample_format
+ *(void **) (&pa_format_info_set_sample_format_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_set_sample_format");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_set_rate
+ *(void **) (&pa_format_info_set_rate_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_set_rate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_set_channels
+ *(void **) (&pa_format_info_set_channels_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_set_channels");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_format_info_set_channel_map
+ *(void **) (&pa_format_info_set_channel_map_dylibloader_wrapper_pulse) = dlsym(handle, "pa_format_info_set_channel_map");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_operation_ref
+ *(void **) (&pa_operation_ref_dylibloader_wrapper_pulse) = dlsym(handle, "pa_operation_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_operation_unref
+ *(void **) (&pa_operation_unref_dylibloader_wrapper_pulse) = dlsym(handle, "pa_operation_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_operation_cancel
+ *(void **) (&pa_operation_cancel_dylibloader_wrapper_pulse) = dlsym(handle, "pa_operation_cancel");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_operation_get_state
+ *(void **) (&pa_operation_get_state_dylibloader_wrapper_pulse) = dlsym(handle, "pa_operation_get_state");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_operation_set_state_callback
+ *(void **) (&pa_operation_set_state_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_operation_set_state_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_new
+ *(void **) (&pa_context_new_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_new_with_proplist
+ *(void **) (&pa_context_new_with_proplist_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_new_with_proplist");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_unref
+ *(void **) (&pa_context_unref_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_ref
+ *(void **) (&pa_context_ref_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_state_callback
+ *(void **) (&pa_context_set_state_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_state_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_event_callback
+ *(void **) (&pa_context_set_event_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_event_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_errno
+ *(void **) (&pa_context_errno_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_errno");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_is_pending
+ *(void **) (&pa_context_is_pending_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_is_pending");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_state
+ *(void **) (&pa_context_get_state_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_state");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_connect
+ *(void **) (&pa_context_connect_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_connect");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_disconnect
+ *(void **) (&pa_context_disconnect_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_disconnect");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_drain
+ *(void **) (&pa_context_drain_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_drain");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_exit_daemon
+ *(void **) (&pa_context_exit_daemon_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_exit_daemon");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_default_sink
+ *(void **) (&pa_context_set_default_sink_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_default_sink");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_default_source
+ *(void **) (&pa_context_set_default_source_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_default_source");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_is_local
+ *(void **) (&pa_context_is_local_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_is_local");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_name
+ *(void **) (&pa_context_set_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_server
+ *(void **) (&pa_context_get_server_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_server");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_protocol_version
+ *(void **) (&pa_context_get_protocol_version_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_protocol_version");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_server_protocol_version
+ *(void **) (&pa_context_get_server_protocol_version_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_server_protocol_version");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_proplist_update
+ *(void **) (&pa_context_proplist_update_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_proplist_update");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_proplist_remove
+ *(void **) (&pa_context_proplist_remove_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_proplist_remove");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_index
+ *(void **) (&pa_context_get_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_rttime_new
+ *(void **) (&pa_context_rttime_new_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_rttime_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_rttime_restart
+ *(void **) (&pa_context_rttime_restart_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_rttime_restart");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_tile_size
+ *(void **) (&pa_context_get_tile_size_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_tile_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_load_cookie_from_file
+ *(void **) (&pa_context_load_cookie_from_file_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_load_cookie_from_file");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_equal
+ *(void **) (&pa_cvolume_equal_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_equal");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_init
+ *(void **) (&pa_cvolume_init_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_init");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_set
+ *(void **) (&pa_cvolume_set_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_set");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_snprint
+ *(void **) (&pa_cvolume_snprint_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_snprint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_cvolume_snprint_dB
+ *(void **) (&pa_sw_cvolume_snprint_dB_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_cvolume_snprint_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_snprint_verbose
+ *(void **) (&pa_cvolume_snprint_verbose_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_snprint_verbose");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_volume_snprint
+ *(void **) (&pa_volume_snprint_dylibloader_wrapper_pulse) = dlsym(handle, "pa_volume_snprint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_volume_snprint_dB
+ *(void **) (&pa_sw_volume_snprint_dB_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_volume_snprint_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_volume_snprint_verbose
+ *(void **) (&pa_volume_snprint_verbose_dylibloader_wrapper_pulse) = dlsym(handle, "pa_volume_snprint_verbose");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_avg
+ *(void **) (&pa_cvolume_avg_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_avg");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_avg_mask
+ *(void **) (&pa_cvolume_avg_mask_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_avg_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_max
+ *(void **) (&pa_cvolume_max_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_max");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_max_mask
+ *(void **) (&pa_cvolume_max_mask_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_max_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_min
+ *(void **) (&pa_cvolume_min_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_min");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_min_mask
+ *(void **) (&pa_cvolume_min_mask_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_min_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_valid
+ *(void **) (&pa_cvolume_valid_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_channels_equal_to
+ *(void **) (&pa_cvolume_channels_equal_to_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_channels_equal_to");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_volume_multiply
+ *(void **) (&pa_sw_volume_multiply_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_volume_multiply");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_cvolume_multiply
+ *(void **) (&pa_sw_cvolume_multiply_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_cvolume_multiply");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_cvolume_multiply_scalar
+ *(void **) (&pa_sw_cvolume_multiply_scalar_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_cvolume_multiply_scalar");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_volume_divide
+ *(void **) (&pa_sw_volume_divide_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_volume_divide");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_cvolume_divide
+ *(void **) (&pa_sw_cvolume_divide_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_cvolume_divide");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_cvolume_divide_scalar
+ *(void **) (&pa_sw_cvolume_divide_scalar_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_cvolume_divide_scalar");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_volume_from_dB
+ *(void **) (&pa_sw_volume_from_dB_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_volume_from_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_volume_to_dB
+ *(void **) (&pa_sw_volume_to_dB_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_volume_to_dB");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_volume_from_linear
+ *(void **) (&pa_sw_volume_from_linear_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_volume_from_linear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_sw_volume_to_linear
+ *(void **) (&pa_sw_volume_to_linear_dylibloader_wrapper_pulse) = dlsym(handle, "pa_sw_volume_to_linear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_remap
+ *(void **) (&pa_cvolume_remap_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_remap");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_compatible
+ *(void **) (&pa_cvolume_compatible_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_compatible");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_compatible_with_channel_map
+ *(void **) (&pa_cvolume_compatible_with_channel_map_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_compatible_with_channel_map");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_get_balance
+ *(void **) (&pa_cvolume_get_balance_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_get_balance");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_set_balance
+ *(void **) (&pa_cvolume_set_balance_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_set_balance");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_get_fade
+ *(void **) (&pa_cvolume_get_fade_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_get_fade");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_set_fade
+ *(void **) (&pa_cvolume_set_fade_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_set_fade");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_get_lfe_balance
+ *(void **) (&pa_cvolume_get_lfe_balance_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_get_lfe_balance");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_set_lfe_balance
+ *(void **) (&pa_cvolume_set_lfe_balance_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_set_lfe_balance");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_scale
+ *(void **) (&pa_cvolume_scale_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_scale");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_scale_mask
+ *(void **) (&pa_cvolume_scale_mask_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_scale_mask");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_set_position
+ *(void **) (&pa_cvolume_set_position_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_set_position");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_get_position
+ *(void **) (&pa_cvolume_get_position_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_get_position");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_merge
+ *(void **) (&pa_cvolume_merge_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_merge");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_inc_clamp
+ *(void **) (&pa_cvolume_inc_clamp_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_inc_clamp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_inc
+ *(void **) (&pa_cvolume_inc_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_inc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_cvolume_dec
+ *(void **) (&pa_cvolume_dec_dylibloader_wrapper_pulse) = dlsym(handle, "pa_cvolume_dec");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_new
+ *(void **) (&pa_stream_new_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_new_with_proplist
+ *(void **) (&pa_stream_new_with_proplist_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_new_with_proplist");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_new_extended
+ *(void **) (&pa_stream_new_extended_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_new_extended");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_unref
+ *(void **) (&pa_stream_unref_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_ref
+ *(void **) (&pa_stream_ref_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_state
+ *(void **) (&pa_stream_get_state_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_state");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_context
+ *(void **) (&pa_stream_get_context_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_context");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_index
+ *(void **) (&pa_stream_get_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_device_index
+ *(void **) (&pa_stream_get_device_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_device_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_device_name
+ *(void **) (&pa_stream_get_device_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_device_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_is_suspended
+ *(void **) (&pa_stream_is_suspended_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_is_suspended");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_is_corked
+ *(void **) (&pa_stream_is_corked_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_is_corked");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_connect_playback
+ *(void **) (&pa_stream_connect_playback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_connect_playback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_connect_record
+ *(void **) (&pa_stream_connect_record_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_connect_record");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_disconnect
+ *(void **) (&pa_stream_disconnect_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_disconnect");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_begin_write
+ *(void **) (&pa_stream_begin_write_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_begin_write");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_cancel_write
+ *(void **) (&pa_stream_cancel_write_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_cancel_write");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_write
+ *(void **) (&pa_stream_write_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_write");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_write_ext_free
+ *(void **) (&pa_stream_write_ext_free_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_write_ext_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_peek
+ *(void **) (&pa_stream_peek_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_peek");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_drop
+ *(void **) (&pa_stream_drop_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_drop");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_writable_size
+ *(void **) (&pa_stream_writable_size_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_writable_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_readable_size
+ *(void **) (&pa_stream_readable_size_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_readable_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_drain
+ *(void **) (&pa_stream_drain_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_drain");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_update_timing_info
+ *(void **) (&pa_stream_update_timing_info_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_update_timing_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_state_callback
+ *(void **) (&pa_stream_set_state_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_state_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_write_callback
+ *(void **) (&pa_stream_set_write_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_write_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_read_callback
+ *(void **) (&pa_stream_set_read_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_read_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_overflow_callback
+ *(void **) (&pa_stream_set_overflow_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_overflow_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_underflow_index
+ *(void **) (&pa_stream_get_underflow_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_underflow_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_underflow_callback
+ *(void **) (&pa_stream_set_underflow_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_underflow_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_started_callback
+ *(void **) (&pa_stream_set_started_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_started_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_latency_update_callback
+ *(void **) (&pa_stream_set_latency_update_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_latency_update_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_moved_callback
+ *(void **) (&pa_stream_set_moved_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_moved_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_suspended_callback
+ *(void **) (&pa_stream_set_suspended_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_suspended_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_event_callback
+ *(void **) (&pa_stream_set_event_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_event_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_buffer_attr_callback
+ *(void **) (&pa_stream_set_buffer_attr_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_buffer_attr_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_cork
+ *(void **) (&pa_stream_cork_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_cork");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_flush
+ *(void **) (&pa_stream_flush_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_flush");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_prebuf
+ *(void **) (&pa_stream_prebuf_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_prebuf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_trigger
+ *(void **) (&pa_stream_trigger_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_trigger");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_name
+ *(void **) (&pa_stream_set_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_time
+ *(void **) (&pa_stream_get_time_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_time");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_latency
+ *(void **) (&pa_stream_get_latency_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_latency");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_timing_info
+ *(void **) (&pa_stream_get_timing_info_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_timing_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_sample_spec
+ *(void **) (&pa_stream_get_sample_spec_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_sample_spec");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_channel_map
+ *(void **) (&pa_stream_get_channel_map_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_channel_map");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_format_info
+ *(void **) (&pa_stream_get_format_info_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_format_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_buffer_attr
+ *(void **) (&pa_stream_get_buffer_attr_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_buffer_attr");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_buffer_attr
+ *(void **) (&pa_stream_set_buffer_attr_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_buffer_attr");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_update_sample_rate
+ *(void **) (&pa_stream_update_sample_rate_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_update_sample_rate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_proplist_update
+ *(void **) (&pa_stream_proplist_update_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_proplist_update");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_proplist_remove
+ *(void **) (&pa_stream_proplist_remove_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_proplist_remove");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_set_monitor_stream
+ *(void **) (&pa_stream_set_monitor_stream_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_set_monitor_stream");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_get_monitor_stream
+ *(void **) (&pa_stream_get_monitor_stream_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_get_monitor_stream");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_sink_info_by_name
+ *(void **) (&pa_context_get_sink_info_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_sink_info_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_sink_info_by_index
+ *(void **) (&pa_context_get_sink_info_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_sink_info_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_sink_info_list
+ *(void **) (&pa_context_get_sink_info_list_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_sink_info_list");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_sink_volume_by_index
+ *(void **) (&pa_context_set_sink_volume_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_sink_volume_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_sink_volume_by_name
+ *(void **) (&pa_context_set_sink_volume_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_sink_volume_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_sink_mute_by_index
+ *(void **) (&pa_context_set_sink_mute_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_sink_mute_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_sink_mute_by_name
+ *(void **) (&pa_context_set_sink_mute_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_sink_mute_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_suspend_sink_by_name
+ *(void **) (&pa_context_suspend_sink_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_suspend_sink_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_suspend_sink_by_index
+ *(void **) (&pa_context_suspend_sink_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_suspend_sink_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_sink_port_by_index
+ *(void **) (&pa_context_set_sink_port_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_sink_port_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_sink_port_by_name
+ *(void **) (&pa_context_set_sink_port_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_sink_port_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_source_info_by_name
+ *(void **) (&pa_context_get_source_info_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_source_info_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_source_info_by_index
+ *(void **) (&pa_context_get_source_info_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_source_info_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_source_info_list
+ *(void **) (&pa_context_get_source_info_list_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_source_info_list");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_source_volume_by_index
+ *(void **) (&pa_context_set_source_volume_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_source_volume_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_source_volume_by_name
+ *(void **) (&pa_context_set_source_volume_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_source_volume_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_source_mute_by_index
+ *(void **) (&pa_context_set_source_mute_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_source_mute_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_source_mute_by_name
+ *(void **) (&pa_context_set_source_mute_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_source_mute_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_suspend_source_by_name
+ *(void **) (&pa_context_suspend_source_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_suspend_source_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_suspend_source_by_index
+ *(void **) (&pa_context_suspend_source_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_suspend_source_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_source_port_by_index
+ *(void **) (&pa_context_set_source_port_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_source_port_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_source_port_by_name
+ *(void **) (&pa_context_set_source_port_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_source_port_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_server_info
+ *(void **) (&pa_context_get_server_info_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_server_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_module_info
+ *(void **) (&pa_context_get_module_info_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_module_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_module_info_list
+ *(void **) (&pa_context_get_module_info_list_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_module_info_list");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_load_module
+ *(void **) (&pa_context_load_module_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_load_module");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_unload_module
+ *(void **) (&pa_context_unload_module_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_unload_module");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_client_info
+ *(void **) (&pa_context_get_client_info_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_client_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_client_info_list
+ *(void **) (&pa_context_get_client_info_list_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_client_info_list");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_kill_client
+ *(void **) (&pa_context_kill_client_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_kill_client");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_card_info_by_index
+ *(void **) (&pa_context_get_card_info_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_card_info_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_card_info_by_name
+ *(void **) (&pa_context_get_card_info_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_card_info_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_card_info_list
+ *(void **) (&pa_context_get_card_info_list_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_card_info_list");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_card_profile_by_index
+ *(void **) (&pa_context_set_card_profile_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_card_profile_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_card_profile_by_name
+ *(void **) (&pa_context_set_card_profile_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_card_profile_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_port_latency_offset
+ *(void **) (&pa_context_set_port_latency_offset_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_port_latency_offset");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_sink_input_info
+ *(void **) (&pa_context_get_sink_input_info_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_sink_input_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_sink_input_info_list
+ *(void **) (&pa_context_get_sink_input_info_list_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_sink_input_info_list");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_move_sink_input_by_name
+ *(void **) (&pa_context_move_sink_input_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_move_sink_input_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_move_sink_input_by_index
+ *(void **) (&pa_context_move_sink_input_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_move_sink_input_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_sink_input_volume
+ *(void **) (&pa_context_set_sink_input_volume_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_sink_input_volume");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_sink_input_mute
+ *(void **) (&pa_context_set_sink_input_mute_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_sink_input_mute");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_kill_sink_input
+ *(void **) (&pa_context_kill_sink_input_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_kill_sink_input");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_source_output_info
+ *(void **) (&pa_context_get_source_output_info_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_source_output_info");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_source_output_info_list
+ *(void **) (&pa_context_get_source_output_info_list_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_source_output_info_list");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_move_source_output_by_name
+ *(void **) (&pa_context_move_source_output_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_move_source_output_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_move_source_output_by_index
+ *(void **) (&pa_context_move_source_output_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_move_source_output_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_source_output_volume
+ *(void **) (&pa_context_set_source_output_volume_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_source_output_volume");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_source_output_mute
+ *(void **) (&pa_context_set_source_output_mute_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_source_output_mute");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_kill_source_output
+ *(void **) (&pa_context_kill_source_output_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_kill_source_output");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_stat
+ *(void **) (&pa_context_stat_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_stat");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_sample_info_by_name
+ *(void **) (&pa_context_get_sample_info_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_sample_info_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_sample_info_by_index
+ *(void **) (&pa_context_get_sample_info_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_sample_info_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_sample_info_list
+ *(void **) (&pa_context_get_sample_info_list_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_sample_info_list");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_autoload_info_by_name
+ *(void **) (&pa_context_get_autoload_info_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_autoload_info_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_autoload_info_by_index
+ *(void **) (&pa_context_get_autoload_info_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_autoload_info_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_get_autoload_info_list
+ *(void **) (&pa_context_get_autoload_info_list_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_get_autoload_info_list");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_add_autoload
+ *(void **) (&pa_context_add_autoload_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_add_autoload");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_remove_autoload_by_name
+ *(void **) (&pa_context_remove_autoload_by_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_remove_autoload_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_remove_autoload_by_index
+ *(void **) (&pa_context_remove_autoload_by_index_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_remove_autoload_by_index");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_subscribe
+ *(void **) (&pa_context_subscribe_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_subscribe");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_set_subscribe_callback
+ *(void **) (&pa_context_set_subscribe_callback_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_set_subscribe_callback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_connect_upload
+ *(void **) (&pa_stream_connect_upload_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_connect_upload");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_stream_finish_upload
+ *(void **) (&pa_stream_finish_upload_dylibloader_wrapper_pulse) = dlsym(handle, "pa_stream_finish_upload");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_remove_sample
+ *(void **) (&pa_context_remove_sample_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_remove_sample");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_play_sample
+ *(void **) (&pa_context_play_sample_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_play_sample");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_context_play_sample_with_proplist
+ *(void **) (&pa_context_play_sample_with_proplist_dylibloader_wrapper_pulse) = dlsym(handle, "pa_context_play_sample_with_proplist");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_strerror
+ *(void **) (&pa_strerror_dylibloader_wrapper_pulse) = dlsym(handle, "pa_strerror");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_xmalloc
+ *(void **) (&pa_xmalloc_dylibloader_wrapper_pulse) = dlsym(handle, "pa_xmalloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_xmalloc0
+ *(void **) (&pa_xmalloc0_dylibloader_wrapper_pulse) = dlsym(handle, "pa_xmalloc0");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_xrealloc
+ *(void **) (&pa_xrealloc_dylibloader_wrapper_pulse) = dlsym(handle, "pa_xrealloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_xfree
+ *(void **) (&pa_xfree_dylibloader_wrapper_pulse) = dlsym(handle, "pa_xfree");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_xstrdup
+ *(void **) (&pa_xstrdup_dylibloader_wrapper_pulse) = dlsym(handle, "pa_xstrdup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_xstrndup
+ *(void **) (&pa_xstrndup_dylibloader_wrapper_pulse) = dlsym(handle, "pa_xstrndup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_xmemdup
+ *(void **) (&pa_xmemdup_dylibloader_wrapper_pulse) = dlsym(handle, "pa_xmemdup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_utf8_valid
+ *(void **) (&pa_utf8_valid_dylibloader_wrapper_pulse) = dlsym(handle, "pa_utf8_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_ascii_valid
+ *(void **) (&pa_ascii_valid_dylibloader_wrapper_pulse) = dlsym(handle, "pa_ascii_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_utf8_filter
+ *(void **) (&pa_utf8_filter_dylibloader_wrapper_pulse) = dlsym(handle, "pa_utf8_filter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_ascii_filter
+ *(void **) (&pa_ascii_filter_dylibloader_wrapper_pulse) = dlsym(handle, "pa_ascii_filter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_utf8_to_locale
+ *(void **) (&pa_utf8_to_locale_dylibloader_wrapper_pulse) = dlsym(handle, "pa_utf8_to_locale");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_locale_to_utf8
+ *(void **) (&pa_locale_to_utf8_dylibloader_wrapper_pulse) = dlsym(handle, "pa_locale_to_utf8");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_new
+ *(void **) (&pa_threaded_mainloop_new_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_free
+ *(void **) (&pa_threaded_mainloop_free_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_start
+ *(void **) (&pa_threaded_mainloop_start_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_start");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_stop
+ *(void **) (&pa_threaded_mainloop_stop_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_stop");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_lock
+ *(void **) (&pa_threaded_mainloop_lock_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_lock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_unlock
+ *(void **) (&pa_threaded_mainloop_unlock_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_unlock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_wait
+ *(void **) (&pa_threaded_mainloop_wait_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_wait");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_signal
+ *(void **) (&pa_threaded_mainloop_signal_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_signal");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_accept
+ *(void **) (&pa_threaded_mainloop_accept_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_accept");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_get_retval
+ *(void **) (&pa_threaded_mainloop_get_retval_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_get_retval");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_get_api
+ *(void **) (&pa_threaded_mainloop_get_api_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_get_api");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_in_thread
+ *(void **) (&pa_threaded_mainloop_in_thread_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_in_thread");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_set_name
+ *(void **) (&pa_threaded_mainloop_set_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_set_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_threaded_mainloop_once_unlocked
+ *(void **) (&pa_threaded_mainloop_once_unlocked_dylibloader_wrapper_pulse) = dlsym(handle, "pa_threaded_mainloop_once_unlocked");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_new
+ *(void **) (&pa_mainloop_new_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_free
+ *(void **) (&pa_mainloop_free_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_prepare
+ *(void **) (&pa_mainloop_prepare_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_prepare");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_poll
+ *(void **) (&pa_mainloop_poll_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_poll");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_dispatch
+ *(void **) (&pa_mainloop_dispatch_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_dispatch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_get_retval
+ *(void **) (&pa_mainloop_get_retval_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_get_retval");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_iterate
+ *(void **) (&pa_mainloop_iterate_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_iterate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_run
+ *(void **) (&pa_mainloop_run_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_run");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_get_api
+ *(void **) (&pa_mainloop_get_api_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_get_api");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_quit
+ *(void **) (&pa_mainloop_quit_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_quit");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_wakeup
+ *(void **) (&pa_mainloop_wakeup_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_wakeup");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_mainloop_set_poll_func
+ *(void **) (&pa_mainloop_set_poll_func_dylibloader_wrapper_pulse) = dlsym(handle, "pa_mainloop_set_poll_func");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_signal_init
+ *(void **) (&pa_signal_init_dylibloader_wrapper_pulse) = dlsym(handle, "pa_signal_init");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_signal_done
+ *(void **) (&pa_signal_done_dylibloader_wrapper_pulse) = dlsym(handle, "pa_signal_done");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_signal_new
+ *(void **) (&pa_signal_new_dylibloader_wrapper_pulse) = dlsym(handle, "pa_signal_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_signal_free
+ *(void **) (&pa_signal_free_dylibloader_wrapper_pulse) = dlsym(handle, "pa_signal_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_signal_set_destroy
+ *(void **) (&pa_signal_set_destroy_dylibloader_wrapper_pulse) = dlsym(handle, "pa_signal_set_destroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_get_user_name
+ *(void **) (&pa_get_user_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_get_user_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_get_host_name
+ *(void **) (&pa_get_host_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_get_host_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_get_fqdn
+ *(void **) (&pa_get_fqdn_dylibloader_wrapper_pulse) = dlsym(handle, "pa_get_fqdn");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_get_home_dir
+ *(void **) (&pa_get_home_dir_dylibloader_wrapper_pulse) = dlsym(handle, "pa_get_home_dir");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_get_binary_name
+ *(void **) (&pa_get_binary_name_dylibloader_wrapper_pulse) = dlsym(handle, "pa_get_binary_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_path_get_filename
+ *(void **) (&pa_path_get_filename_dylibloader_wrapper_pulse) = dlsym(handle, "pa_path_get_filename");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_msleep
+ *(void **) (&pa_msleep_dylibloader_wrapper_pulse) = dlsym(handle, "pa_msleep");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_thread_make_realtime
+ *(void **) (&pa_thread_make_realtime_dylibloader_wrapper_pulse) = dlsym(handle, "pa_thread_make_realtime");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_gettimeofday
+ *(void **) (&pa_gettimeofday_dylibloader_wrapper_pulse) = dlsym(handle, "pa_gettimeofday");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_timeval_diff
+ *(void **) (&pa_timeval_diff_dylibloader_wrapper_pulse) = dlsym(handle, "pa_timeval_diff");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_timeval_cmp
+ *(void **) (&pa_timeval_cmp_dylibloader_wrapper_pulse) = dlsym(handle, "pa_timeval_cmp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_timeval_age
+ *(void **) (&pa_timeval_age_dylibloader_wrapper_pulse) = dlsym(handle, "pa_timeval_age");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_timeval_add
+ *(void **) (&pa_timeval_add_dylibloader_wrapper_pulse) = dlsym(handle, "pa_timeval_add");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_timeval_sub
+ *(void **) (&pa_timeval_sub_dylibloader_wrapper_pulse) = dlsym(handle, "pa_timeval_sub");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_timeval_store
+ *(void **) (&pa_timeval_store_dylibloader_wrapper_pulse) = dlsym(handle, "pa_timeval_store");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_timeval_load
+ *(void **) (&pa_timeval_load_dylibloader_wrapper_pulse) = dlsym(handle, "pa_timeval_load");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// pa_rtclock_now
+ *(void **) (&pa_rtclock_now_dylibloader_wrapper_pulse) = dlsym(handle, "pa_rtclock_now");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/drivers/pulseaudio/pulse-so_wrap.h b/drivers/pulseaudio/pulse-so_wrap.h
new file mode 100644
index 0000000000..7f9a70fae1
--- /dev/null
+++ b/drivers/pulseaudio/pulse-so_wrap.h
@@ -0,0 +1,1446 @@
+#ifndef DYLIBLOAD_WRAPPER_PULSE
+#define DYLIBLOAD_WRAPPER_PULSE
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-20 00:08:31
+// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/pulse/pulseaudio.h --sys-include <pulse/pulseaudio.h> --soname libpulse.so.0 --omit-prefix _pa_ --init-name pulse --output-header pulse-so_wrap.h --output-implementation pulse-so_wrap.c
+//
+#include <stdint.h>
+
+#define pa_get_library_version pa_get_library_version_dylibloader_orig_pulse
+#define pa_bytes_per_second pa_bytes_per_second_dylibloader_orig_pulse
+#define pa_frame_size pa_frame_size_dylibloader_orig_pulse
+#define pa_sample_size pa_sample_size_dylibloader_orig_pulse
+#define pa_sample_size_of_format pa_sample_size_of_format_dylibloader_orig_pulse
+#define pa_bytes_to_usec pa_bytes_to_usec_dylibloader_orig_pulse
+#define pa_usec_to_bytes pa_usec_to_bytes_dylibloader_orig_pulse
+#define pa_sample_spec_init pa_sample_spec_init_dylibloader_orig_pulse
+#define pa_sample_format_valid pa_sample_format_valid_dylibloader_orig_pulse
+#define pa_sample_rate_valid pa_sample_rate_valid_dylibloader_orig_pulse
+#define pa_channels_valid pa_channels_valid_dylibloader_orig_pulse
+#define pa_sample_spec_valid pa_sample_spec_valid_dylibloader_orig_pulse
+#define pa_sample_spec_equal pa_sample_spec_equal_dylibloader_orig_pulse
+#define pa_sample_format_to_string pa_sample_format_to_string_dylibloader_orig_pulse
+#define pa_parse_sample_format pa_parse_sample_format_dylibloader_orig_pulse
+#define pa_sample_spec_snprint pa_sample_spec_snprint_dylibloader_orig_pulse
+#define pa_bytes_snprint pa_bytes_snprint_dylibloader_orig_pulse
+#define pa_sample_format_is_le pa_sample_format_is_le_dylibloader_orig_pulse
+#define pa_sample_format_is_be pa_sample_format_is_be_dylibloader_orig_pulse
+#define pa_direction_valid pa_direction_valid_dylibloader_orig_pulse
+#define pa_direction_to_string pa_direction_to_string_dylibloader_orig_pulse
+#define pa_mainloop_api_once pa_mainloop_api_once_dylibloader_orig_pulse
+#define pa_proplist_new pa_proplist_new_dylibloader_orig_pulse
+#define pa_proplist_free pa_proplist_free_dylibloader_orig_pulse
+#define pa_proplist_key_valid pa_proplist_key_valid_dylibloader_orig_pulse
+#define pa_proplist_sets pa_proplist_sets_dylibloader_orig_pulse
+#define pa_proplist_setp pa_proplist_setp_dylibloader_orig_pulse
+#define pa_proplist_setf pa_proplist_setf_dylibloader_orig_pulse
+#define pa_proplist_set pa_proplist_set_dylibloader_orig_pulse
+#define pa_proplist_gets pa_proplist_gets_dylibloader_orig_pulse
+#define pa_proplist_get pa_proplist_get_dylibloader_orig_pulse
+#define pa_proplist_update pa_proplist_update_dylibloader_orig_pulse
+#define pa_proplist_unset pa_proplist_unset_dylibloader_orig_pulse
+#define pa_proplist_unset_many pa_proplist_unset_many_dylibloader_orig_pulse
+#define pa_proplist_iterate pa_proplist_iterate_dylibloader_orig_pulse
+#define pa_proplist_to_string pa_proplist_to_string_dylibloader_orig_pulse
+#define pa_proplist_to_string_sep pa_proplist_to_string_sep_dylibloader_orig_pulse
+#define pa_proplist_from_string pa_proplist_from_string_dylibloader_orig_pulse
+#define pa_proplist_contains pa_proplist_contains_dylibloader_orig_pulse
+#define pa_proplist_clear pa_proplist_clear_dylibloader_orig_pulse
+#define pa_proplist_copy pa_proplist_copy_dylibloader_orig_pulse
+#define pa_proplist_size pa_proplist_size_dylibloader_orig_pulse
+#define pa_proplist_isempty pa_proplist_isempty_dylibloader_orig_pulse
+#define pa_proplist_equal pa_proplist_equal_dylibloader_orig_pulse
+#define pa_channel_map_init pa_channel_map_init_dylibloader_orig_pulse
+#define pa_channel_map_init_mono pa_channel_map_init_mono_dylibloader_orig_pulse
+#define pa_channel_map_init_stereo pa_channel_map_init_stereo_dylibloader_orig_pulse
+#define pa_channel_map_init_auto pa_channel_map_init_auto_dylibloader_orig_pulse
+#define pa_channel_map_init_extend pa_channel_map_init_extend_dylibloader_orig_pulse
+#define pa_channel_position_to_string pa_channel_position_to_string_dylibloader_orig_pulse
+#define pa_channel_position_from_string pa_channel_position_from_string_dylibloader_orig_pulse
+#define pa_channel_position_to_pretty_string pa_channel_position_to_pretty_string_dylibloader_orig_pulse
+#define pa_channel_map_snprint pa_channel_map_snprint_dylibloader_orig_pulse
+#define pa_channel_map_parse pa_channel_map_parse_dylibloader_orig_pulse
+#define pa_channel_map_equal pa_channel_map_equal_dylibloader_orig_pulse
+#define pa_channel_map_valid pa_channel_map_valid_dylibloader_orig_pulse
+#define pa_channel_map_compatible pa_channel_map_compatible_dylibloader_orig_pulse
+#define pa_channel_map_superset pa_channel_map_superset_dylibloader_orig_pulse
+#define pa_channel_map_can_balance pa_channel_map_can_balance_dylibloader_orig_pulse
+#define pa_channel_map_can_fade pa_channel_map_can_fade_dylibloader_orig_pulse
+#define pa_channel_map_can_lfe_balance pa_channel_map_can_lfe_balance_dylibloader_orig_pulse
+#define pa_channel_map_to_name pa_channel_map_to_name_dylibloader_orig_pulse
+#define pa_channel_map_to_pretty_name pa_channel_map_to_pretty_name_dylibloader_orig_pulse
+#define pa_channel_map_has_position pa_channel_map_has_position_dylibloader_orig_pulse
+#define pa_channel_map_mask pa_channel_map_mask_dylibloader_orig_pulse
+#define pa_encoding_to_string pa_encoding_to_string_dylibloader_orig_pulse
+#define pa_encoding_from_string pa_encoding_from_string_dylibloader_orig_pulse
+#define pa_format_info_new pa_format_info_new_dylibloader_orig_pulse
+#define pa_format_info_copy pa_format_info_copy_dylibloader_orig_pulse
+#define pa_format_info_free pa_format_info_free_dylibloader_orig_pulse
+#define pa_format_info_valid pa_format_info_valid_dylibloader_orig_pulse
+#define pa_format_info_is_pcm pa_format_info_is_pcm_dylibloader_orig_pulse
+#define pa_format_info_is_compatible pa_format_info_is_compatible_dylibloader_orig_pulse
+#define pa_format_info_snprint pa_format_info_snprint_dylibloader_orig_pulse
+#define pa_format_info_from_string pa_format_info_from_string_dylibloader_orig_pulse
+#define pa_format_info_from_sample_spec pa_format_info_from_sample_spec_dylibloader_orig_pulse
+#define pa_format_info_to_sample_spec pa_format_info_to_sample_spec_dylibloader_orig_pulse
+#define pa_format_info_get_prop_type pa_format_info_get_prop_type_dylibloader_orig_pulse
+#define pa_format_info_get_prop_int pa_format_info_get_prop_int_dylibloader_orig_pulse
+#define pa_format_info_get_prop_int_range pa_format_info_get_prop_int_range_dylibloader_orig_pulse
+#define pa_format_info_get_prop_int_array pa_format_info_get_prop_int_array_dylibloader_orig_pulse
+#define pa_format_info_get_prop_string pa_format_info_get_prop_string_dylibloader_orig_pulse
+#define pa_format_info_get_prop_string_array pa_format_info_get_prop_string_array_dylibloader_orig_pulse
+#define pa_format_info_free_string_array pa_format_info_free_string_array_dylibloader_orig_pulse
+#define pa_format_info_get_sample_format pa_format_info_get_sample_format_dylibloader_orig_pulse
+#define pa_format_info_get_rate pa_format_info_get_rate_dylibloader_orig_pulse
+#define pa_format_info_get_channels pa_format_info_get_channels_dylibloader_orig_pulse
+#define pa_format_info_get_channel_map pa_format_info_get_channel_map_dylibloader_orig_pulse
+#define pa_format_info_set_prop_int pa_format_info_set_prop_int_dylibloader_orig_pulse
+#define pa_format_info_set_prop_int_array pa_format_info_set_prop_int_array_dylibloader_orig_pulse
+#define pa_format_info_set_prop_int_range pa_format_info_set_prop_int_range_dylibloader_orig_pulse
+#define pa_format_info_set_prop_string pa_format_info_set_prop_string_dylibloader_orig_pulse
+#define pa_format_info_set_prop_string_array pa_format_info_set_prop_string_array_dylibloader_orig_pulse
+#define pa_format_info_set_sample_format pa_format_info_set_sample_format_dylibloader_orig_pulse
+#define pa_format_info_set_rate pa_format_info_set_rate_dylibloader_orig_pulse
+#define pa_format_info_set_channels pa_format_info_set_channels_dylibloader_orig_pulse
+#define pa_format_info_set_channel_map pa_format_info_set_channel_map_dylibloader_orig_pulse
+#define pa_operation_ref pa_operation_ref_dylibloader_orig_pulse
+#define pa_operation_unref pa_operation_unref_dylibloader_orig_pulse
+#define pa_operation_cancel pa_operation_cancel_dylibloader_orig_pulse
+#define pa_operation_get_state pa_operation_get_state_dylibloader_orig_pulse
+#define pa_operation_set_state_callback pa_operation_set_state_callback_dylibloader_orig_pulse
+#define pa_context_new pa_context_new_dylibloader_orig_pulse
+#define pa_context_new_with_proplist pa_context_new_with_proplist_dylibloader_orig_pulse
+#define pa_context_unref pa_context_unref_dylibloader_orig_pulse
+#define pa_context_ref pa_context_ref_dylibloader_orig_pulse
+#define pa_context_set_state_callback pa_context_set_state_callback_dylibloader_orig_pulse
+#define pa_context_set_event_callback pa_context_set_event_callback_dylibloader_orig_pulse
+#define pa_context_errno pa_context_errno_dylibloader_orig_pulse
+#define pa_context_is_pending pa_context_is_pending_dylibloader_orig_pulse
+#define pa_context_get_state pa_context_get_state_dylibloader_orig_pulse
+#define pa_context_connect pa_context_connect_dylibloader_orig_pulse
+#define pa_context_disconnect pa_context_disconnect_dylibloader_orig_pulse
+#define pa_context_drain pa_context_drain_dylibloader_orig_pulse
+#define pa_context_exit_daemon pa_context_exit_daemon_dylibloader_orig_pulse
+#define pa_context_set_default_sink pa_context_set_default_sink_dylibloader_orig_pulse
+#define pa_context_set_default_source pa_context_set_default_source_dylibloader_orig_pulse
+#define pa_context_is_local pa_context_is_local_dylibloader_orig_pulse
+#define pa_context_set_name pa_context_set_name_dylibloader_orig_pulse
+#define pa_context_get_server pa_context_get_server_dylibloader_orig_pulse
+#define pa_context_get_protocol_version pa_context_get_protocol_version_dylibloader_orig_pulse
+#define pa_context_get_server_protocol_version pa_context_get_server_protocol_version_dylibloader_orig_pulse
+#define pa_context_proplist_update pa_context_proplist_update_dylibloader_orig_pulse
+#define pa_context_proplist_remove pa_context_proplist_remove_dylibloader_orig_pulse
+#define pa_context_get_index pa_context_get_index_dylibloader_orig_pulse
+#define pa_context_rttime_new pa_context_rttime_new_dylibloader_orig_pulse
+#define pa_context_rttime_restart pa_context_rttime_restart_dylibloader_orig_pulse
+#define pa_context_get_tile_size pa_context_get_tile_size_dylibloader_orig_pulse
+#define pa_context_load_cookie_from_file pa_context_load_cookie_from_file_dylibloader_orig_pulse
+#define pa_cvolume_equal pa_cvolume_equal_dylibloader_orig_pulse
+#define pa_cvolume_init pa_cvolume_init_dylibloader_orig_pulse
+#define pa_cvolume_set pa_cvolume_set_dylibloader_orig_pulse
+#define pa_cvolume_snprint pa_cvolume_snprint_dylibloader_orig_pulse
+#define pa_sw_cvolume_snprint_dB pa_sw_cvolume_snprint_dB_dylibloader_orig_pulse
+#define pa_cvolume_snprint_verbose pa_cvolume_snprint_verbose_dylibloader_orig_pulse
+#define pa_volume_snprint pa_volume_snprint_dylibloader_orig_pulse
+#define pa_sw_volume_snprint_dB pa_sw_volume_snprint_dB_dylibloader_orig_pulse
+#define pa_volume_snprint_verbose pa_volume_snprint_verbose_dylibloader_orig_pulse
+#define pa_cvolume_avg pa_cvolume_avg_dylibloader_orig_pulse
+#define pa_cvolume_avg_mask pa_cvolume_avg_mask_dylibloader_orig_pulse
+#define pa_cvolume_max pa_cvolume_max_dylibloader_orig_pulse
+#define pa_cvolume_max_mask pa_cvolume_max_mask_dylibloader_orig_pulse
+#define pa_cvolume_min pa_cvolume_min_dylibloader_orig_pulse
+#define pa_cvolume_min_mask pa_cvolume_min_mask_dylibloader_orig_pulse
+#define pa_cvolume_valid pa_cvolume_valid_dylibloader_orig_pulse
+#define pa_cvolume_channels_equal_to pa_cvolume_channels_equal_to_dylibloader_orig_pulse
+#define pa_sw_volume_multiply pa_sw_volume_multiply_dylibloader_orig_pulse
+#define pa_sw_cvolume_multiply pa_sw_cvolume_multiply_dylibloader_orig_pulse
+#define pa_sw_cvolume_multiply_scalar pa_sw_cvolume_multiply_scalar_dylibloader_orig_pulse
+#define pa_sw_volume_divide pa_sw_volume_divide_dylibloader_orig_pulse
+#define pa_sw_cvolume_divide pa_sw_cvolume_divide_dylibloader_orig_pulse
+#define pa_sw_cvolume_divide_scalar pa_sw_cvolume_divide_scalar_dylibloader_orig_pulse
+#define pa_sw_volume_from_dB pa_sw_volume_from_dB_dylibloader_orig_pulse
+#define pa_sw_volume_to_dB pa_sw_volume_to_dB_dylibloader_orig_pulse
+#define pa_sw_volume_from_linear pa_sw_volume_from_linear_dylibloader_orig_pulse
+#define pa_sw_volume_to_linear pa_sw_volume_to_linear_dylibloader_orig_pulse
+#define pa_cvolume_remap pa_cvolume_remap_dylibloader_orig_pulse
+#define pa_cvolume_compatible pa_cvolume_compatible_dylibloader_orig_pulse
+#define pa_cvolume_compatible_with_channel_map pa_cvolume_compatible_with_channel_map_dylibloader_orig_pulse
+#define pa_cvolume_get_balance pa_cvolume_get_balance_dylibloader_orig_pulse
+#define pa_cvolume_set_balance pa_cvolume_set_balance_dylibloader_orig_pulse
+#define pa_cvolume_get_fade pa_cvolume_get_fade_dylibloader_orig_pulse
+#define pa_cvolume_set_fade pa_cvolume_set_fade_dylibloader_orig_pulse
+#define pa_cvolume_get_lfe_balance pa_cvolume_get_lfe_balance_dylibloader_orig_pulse
+#define pa_cvolume_set_lfe_balance pa_cvolume_set_lfe_balance_dylibloader_orig_pulse
+#define pa_cvolume_scale pa_cvolume_scale_dylibloader_orig_pulse
+#define pa_cvolume_scale_mask pa_cvolume_scale_mask_dylibloader_orig_pulse
+#define pa_cvolume_set_position pa_cvolume_set_position_dylibloader_orig_pulse
+#define pa_cvolume_get_position pa_cvolume_get_position_dylibloader_orig_pulse
+#define pa_cvolume_merge pa_cvolume_merge_dylibloader_orig_pulse
+#define pa_cvolume_inc_clamp pa_cvolume_inc_clamp_dylibloader_orig_pulse
+#define pa_cvolume_inc pa_cvolume_inc_dylibloader_orig_pulse
+#define pa_cvolume_dec pa_cvolume_dec_dylibloader_orig_pulse
+#define pa_stream_new pa_stream_new_dylibloader_orig_pulse
+#define pa_stream_new_with_proplist pa_stream_new_with_proplist_dylibloader_orig_pulse
+#define pa_stream_new_extended pa_stream_new_extended_dylibloader_orig_pulse
+#define pa_stream_unref pa_stream_unref_dylibloader_orig_pulse
+#define pa_stream_ref pa_stream_ref_dylibloader_orig_pulse
+#define pa_stream_get_state pa_stream_get_state_dylibloader_orig_pulse
+#define pa_stream_get_context pa_stream_get_context_dylibloader_orig_pulse
+#define pa_stream_get_index pa_stream_get_index_dylibloader_orig_pulse
+#define pa_stream_get_device_index pa_stream_get_device_index_dylibloader_orig_pulse
+#define pa_stream_get_device_name pa_stream_get_device_name_dylibloader_orig_pulse
+#define pa_stream_is_suspended pa_stream_is_suspended_dylibloader_orig_pulse
+#define pa_stream_is_corked pa_stream_is_corked_dylibloader_orig_pulse
+#define pa_stream_connect_playback pa_stream_connect_playback_dylibloader_orig_pulse
+#define pa_stream_connect_record pa_stream_connect_record_dylibloader_orig_pulse
+#define pa_stream_disconnect pa_stream_disconnect_dylibloader_orig_pulse
+#define pa_stream_begin_write pa_stream_begin_write_dylibloader_orig_pulse
+#define pa_stream_cancel_write pa_stream_cancel_write_dylibloader_orig_pulse
+#define pa_stream_write pa_stream_write_dylibloader_orig_pulse
+#define pa_stream_write_ext_free pa_stream_write_ext_free_dylibloader_orig_pulse
+#define pa_stream_peek pa_stream_peek_dylibloader_orig_pulse
+#define pa_stream_drop pa_stream_drop_dylibloader_orig_pulse
+#define pa_stream_writable_size pa_stream_writable_size_dylibloader_orig_pulse
+#define pa_stream_readable_size pa_stream_readable_size_dylibloader_orig_pulse
+#define pa_stream_drain pa_stream_drain_dylibloader_orig_pulse
+#define pa_stream_update_timing_info pa_stream_update_timing_info_dylibloader_orig_pulse
+#define pa_stream_set_state_callback pa_stream_set_state_callback_dylibloader_orig_pulse
+#define pa_stream_set_write_callback pa_stream_set_write_callback_dylibloader_orig_pulse
+#define pa_stream_set_read_callback pa_stream_set_read_callback_dylibloader_orig_pulse
+#define pa_stream_set_overflow_callback pa_stream_set_overflow_callback_dylibloader_orig_pulse
+#define pa_stream_get_underflow_index pa_stream_get_underflow_index_dylibloader_orig_pulse
+#define pa_stream_set_underflow_callback pa_stream_set_underflow_callback_dylibloader_orig_pulse
+#define pa_stream_set_started_callback pa_stream_set_started_callback_dylibloader_orig_pulse
+#define pa_stream_set_latency_update_callback pa_stream_set_latency_update_callback_dylibloader_orig_pulse
+#define pa_stream_set_moved_callback pa_stream_set_moved_callback_dylibloader_orig_pulse
+#define pa_stream_set_suspended_callback pa_stream_set_suspended_callback_dylibloader_orig_pulse
+#define pa_stream_set_event_callback pa_stream_set_event_callback_dylibloader_orig_pulse
+#define pa_stream_set_buffer_attr_callback pa_stream_set_buffer_attr_callback_dylibloader_orig_pulse
+#define pa_stream_cork pa_stream_cork_dylibloader_orig_pulse
+#define pa_stream_flush pa_stream_flush_dylibloader_orig_pulse
+#define pa_stream_prebuf pa_stream_prebuf_dylibloader_orig_pulse
+#define pa_stream_trigger pa_stream_trigger_dylibloader_orig_pulse
+#define pa_stream_set_name pa_stream_set_name_dylibloader_orig_pulse
+#define pa_stream_get_time pa_stream_get_time_dylibloader_orig_pulse
+#define pa_stream_get_latency pa_stream_get_latency_dylibloader_orig_pulse
+#define pa_stream_get_timing_info pa_stream_get_timing_info_dylibloader_orig_pulse
+#define pa_stream_get_sample_spec pa_stream_get_sample_spec_dylibloader_orig_pulse
+#define pa_stream_get_channel_map pa_stream_get_channel_map_dylibloader_orig_pulse
+#define pa_stream_get_format_info pa_stream_get_format_info_dylibloader_orig_pulse
+#define pa_stream_get_buffer_attr pa_stream_get_buffer_attr_dylibloader_orig_pulse
+#define pa_stream_set_buffer_attr pa_stream_set_buffer_attr_dylibloader_orig_pulse
+#define pa_stream_update_sample_rate pa_stream_update_sample_rate_dylibloader_orig_pulse
+#define pa_stream_proplist_update pa_stream_proplist_update_dylibloader_orig_pulse
+#define pa_stream_proplist_remove pa_stream_proplist_remove_dylibloader_orig_pulse
+#define pa_stream_set_monitor_stream pa_stream_set_monitor_stream_dylibloader_orig_pulse
+#define pa_stream_get_monitor_stream pa_stream_get_monitor_stream_dylibloader_orig_pulse
+#define pa_context_get_sink_info_by_name pa_context_get_sink_info_by_name_dylibloader_orig_pulse
+#define pa_context_get_sink_info_by_index pa_context_get_sink_info_by_index_dylibloader_orig_pulse
+#define pa_context_get_sink_info_list pa_context_get_sink_info_list_dylibloader_orig_pulse
+#define pa_context_set_sink_volume_by_index pa_context_set_sink_volume_by_index_dylibloader_orig_pulse
+#define pa_context_set_sink_volume_by_name pa_context_set_sink_volume_by_name_dylibloader_orig_pulse
+#define pa_context_set_sink_mute_by_index pa_context_set_sink_mute_by_index_dylibloader_orig_pulse
+#define pa_context_set_sink_mute_by_name pa_context_set_sink_mute_by_name_dylibloader_orig_pulse
+#define pa_context_suspend_sink_by_name pa_context_suspend_sink_by_name_dylibloader_orig_pulse
+#define pa_context_suspend_sink_by_index pa_context_suspend_sink_by_index_dylibloader_orig_pulse
+#define pa_context_set_sink_port_by_index pa_context_set_sink_port_by_index_dylibloader_orig_pulse
+#define pa_context_set_sink_port_by_name pa_context_set_sink_port_by_name_dylibloader_orig_pulse
+#define pa_context_get_source_info_by_name pa_context_get_source_info_by_name_dylibloader_orig_pulse
+#define pa_context_get_source_info_by_index pa_context_get_source_info_by_index_dylibloader_orig_pulse
+#define pa_context_get_source_info_list pa_context_get_source_info_list_dylibloader_orig_pulse
+#define pa_context_set_source_volume_by_index pa_context_set_source_volume_by_index_dylibloader_orig_pulse
+#define pa_context_set_source_volume_by_name pa_context_set_source_volume_by_name_dylibloader_orig_pulse
+#define pa_context_set_source_mute_by_index pa_context_set_source_mute_by_index_dylibloader_orig_pulse
+#define pa_context_set_source_mute_by_name pa_context_set_source_mute_by_name_dylibloader_orig_pulse
+#define pa_context_suspend_source_by_name pa_context_suspend_source_by_name_dylibloader_orig_pulse
+#define pa_context_suspend_source_by_index pa_context_suspend_source_by_index_dylibloader_orig_pulse
+#define pa_context_set_source_port_by_index pa_context_set_source_port_by_index_dylibloader_orig_pulse
+#define pa_context_set_source_port_by_name pa_context_set_source_port_by_name_dylibloader_orig_pulse
+#define pa_context_get_server_info pa_context_get_server_info_dylibloader_orig_pulse
+#define pa_context_get_module_info pa_context_get_module_info_dylibloader_orig_pulse
+#define pa_context_get_module_info_list pa_context_get_module_info_list_dylibloader_orig_pulse
+#define pa_context_load_module pa_context_load_module_dylibloader_orig_pulse
+#define pa_context_unload_module pa_context_unload_module_dylibloader_orig_pulse
+#define pa_context_get_client_info pa_context_get_client_info_dylibloader_orig_pulse
+#define pa_context_get_client_info_list pa_context_get_client_info_list_dylibloader_orig_pulse
+#define pa_context_kill_client pa_context_kill_client_dylibloader_orig_pulse
+#define pa_context_get_card_info_by_index pa_context_get_card_info_by_index_dylibloader_orig_pulse
+#define pa_context_get_card_info_by_name pa_context_get_card_info_by_name_dylibloader_orig_pulse
+#define pa_context_get_card_info_list pa_context_get_card_info_list_dylibloader_orig_pulse
+#define pa_context_set_card_profile_by_index pa_context_set_card_profile_by_index_dylibloader_orig_pulse
+#define pa_context_set_card_profile_by_name pa_context_set_card_profile_by_name_dylibloader_orig_pulse
+#define pa_context_set_port_latency_offset pa_context_set_port_latency_offset_dylibloader_orig_pulse
+#define pa_context_get_sink_input_info pa_context_get_sink_input_info_dylibloader_orig_pulse
+#define pa_context_get_sink_input_info_list pa_context_get_sink_input_info_list_dylibloader_orig_pulse
+#define pa_context_move_sink_input_by_name pa_context_move_sink_input_by_name_dylibloader_orig_pulse
+#define pa_context_move_sink_input_by_index pa_context_move_sink_input_by_index_dylibloader_orig_pulse
+#define pa_context_set_sink_input_volume pa_context_set_sink_input_volume_dylibloader_orig_pulse
+#define pa_context_set_sink_input_mute pa_context_set_sink_input_mute_dylibloader_orig_pulse
+#define pa_context_kill_sink_input pa_context_kill_sink_input_dylibloader_orig_pulse
+#define pa_context_get_source_output_info pa_context_get_source_output_info_dylibloader_orig_pulse
+#define pa_context_get_source_output_info_list pa_context_get_source_output_info_list_dylibloader_orig_pulse
+#define pa_context_move_source_output_by_name pa_context_move_source_output_by_name_dylibloader_orig_pulse
+#define pa_context_move_source_output_by_index pa_context_move_source_output_by_index_dylibloader_orig_pulse
+#define pa_context_set_source_output_volume pa_context_set_source_output_volume_dylibloader_orig_pulse
+#define pa_context_set_source_output_mute pa_context_set_source_output_mute_dylibloader_orig_pulse
+#define pa_context_kill_source_output pa_context_kill_source_output_dylibloader_orig_pulse
+#define pa_context_stat pa_context_stat_dylibloader_orig_pulse
+#define pa_context_get_sample_info_by_name pa_context_get_sample_info_by_name_dylibloader_orig_pulse
+#define pa_context_get_sample_info_by_index pa_context_get_sample_info_by_index_dylibloader_orig_pulse
+#define pa_context_get_sample_info_list pa_context_get_sample_info_list_dylibloader_orig_pulse
+#define pa_context_get_autoload_info_by_name pa_context_get_autoload_info_by_name_dylibloader_orig_pulse
+#define pa_context_get_autoload_info_by_index pa_context_get_autoload_info_by_index_dylibloader_orig_pulse
+#define pa_context_get_autoload_info_list pa_context_get_autoload_info_list_dylibloader_orig_pulse
+#define pa_context_add_autoload pa_context_add_autoload_dylibloader_orig_pulse
+#define pa_context_remove_autoload_by_name pa_context_remove_autoload_by_name_dylibloader_orig_pulse
+#define pa_context_remove_autoload_by_index pa_context_remove_autoload_by_index_dylibloader_orig_pulse
+#define pa_context_subscribe pa_context_subscribe_dylibloader_orig_pulse
+#define pa_context_set_subscribe_callback pa_context_set_subscribe_callback_dylibloader_orig_pulse
+#define pa_stream_connect_upload pa_stream_connect_upload_dylibloader_orig_pulse
+#define pa_stream_finish_upload pa_stream_finish_upload_dylibloader_orig_pulse
+#define pa_context_remove_sample pa_context_remove_sample_dylibloader_orig_pulse
+#define pa_context_play_sample pa_context_play_sample_dylibloader_orig_pulse
+#define pa_context_play_sample_with_proplist pa_context_play_sample_with_proplist_dylibloader_orig_pulse
+#define pa_strerror pa_strerror_dylibloader_orig_pulse
+#define pa_xmalloc pa_xmalloc_dylibloader_orig_pulse
+#define pa_xmalloc0 pa_xmalloc0_dylibloader_orig_pulse
+#define pa_xrealloc pa_xrealloc_dylibloader_orig_pulse
+#define pa_xfree pa_xfree_dylibloader_orig_pulse
+#define pa_xstrdup pa_xstrdup_dylibloader_orig_pulse
+#define pa_xstrndup pa_xstrndup_dylibloader_orig_pulse
+#define pa_xmemdup pa_xmemdup_dylibloader_orig_pulse
+#define pa_utf8_valid pa_utf8_valid_dylibloader_orig_pulse
+#define pa_ascii_valid pa_ascii_valid_dylibloader_orig_pulse
+#define pa_utf8_filter pa_utf8_filter_dylibloader_orig_pulse
+#define pa_ascii_filter pa_ascii_filter_dylibloader_orig_pulse
+#define pa_utf8_to_locale pa_utf8_to_locale_dylibloader_orig_pulse
+#define pa_locale_to_utf8 pa_locale_to_utf8_dylibloader_orig_pulse
+#define pa_threaded_mainloop_new pa_threaded_mainloop_new_dylibloader_orig_pulse
+#define pa_threaded_mainloop_free pa_threaded_mainloop_free_dylibloader_orig_pulse
+#define pa_threaded_mainloop_start pa_threaded_mainloop_start_dylibloader_orig_pulse
+#define pa_threaded_mainloop_stop pa_threaded_mainloop_stop_dylibloader_orig_pulse
+#define pa_threaded_mainloop_lock pa_threaded_mainloop_lock_dylibloader_orig_pulse
+#define pa_threaded_mainloop_unlock pa_threaded_mainloop_unlock_dylibloader_orig_pulse
+#define pa_threaded_mainloop_wait pa_threaded_mainloop_wait_dylibloader_orig_pulse
+#define pa_threaded_mainloop_signal pa_threaded_mainloop_signal_dylibloader_orig_pulse
+#define pa_threaded_mainloop_accept pa_threaded_mainloop_accept_dylibloader_orig_pulse
+#define pa_threaded_mainloop_get_retval pa_threaded_mainloop_get_retval_dylibloader_orig_pulse
+#define pa_threaded_mainloop_get_api pa_threaded_mainloop_get_api_dylibloader_orig_pulse
+#define pa_threaded_mainloop_in_thread pa_threaded_mainloop_in_thread_dylibloader_orig_pulse
+#define pa_threaded_mainloop_set_name pa_threaded_mainloop_set_name_dylibloader_orig_pulse
+#define pa_threaded_mainloop_once_unlocked pa_threaded_mainloop_once_unlocked_dylibloader_orig_pulse
+#define pa_mainloop_new pa_mainloop_new_dylibloader_orig_pulse
+#define pa_mainloop_free pa_mainloop_free_dylibloader_orig_pulse
+#define pa_mainloop_prepare pa_mainloop_prepare_dylibloader_orig_pulse
+#define pa_mainloop_poll pa_mainloop_poll_dylibloader_orig_pulse
+#define pa_mainloop_dispatch pa_mainloop_dispatch_dylibloader_orig_pulse
+#define pa_mainloop_get_retval pa_mainloop_get_retval_dylibloader_orig_pulse
+#define pa_mainloop_iterate pa_mainloop_iterate_dylibloader_orig_pulse
+#define pa_mainloop_run pa_mainloop_run_dylibloader_orig_pulse
+#define pa_mainloop_get_api pa_mainloop_get_api_dylibloader_orig_pulse
+#define pa_mainloop_quit pa_mainloop_quit_dylibloader_orig_pulse
+#define pa_mainloop_wakeup pa_mainloop_wakeup_dylibloader_orig_pulse
+#define pa_mainloop_set_poll_func pa_mainloop_set_poll_func_dylibloader_orig_pulse
+#define pa_signal_init pa_signal_init_dylibloader_orig_pulse
+#define pa_signal_done pa_signal_done_dylibloader_orig_pulse
+#define pa_signal_new pa_signal_new_dylibloader_orig_pulse
+#define pa_signal_free pa_signal_free_dylibloader_orig_pulse
+#define pa_signal_set_destroy pa_signal_set_destroy_dylibloader_orig_pulse
+#define pa_get_user_name pa_get_user_name_dylibloader_orig_pulse
+#define pa_get_host_name pa_get_host_name_dylibloader_orig_pulse
+#define pa_get_fqdn pa_get_fqdn_dylibloader_orig_pulse
+#define pa_get_home_dir pa_get_home_dir_dylibloader_orig_pulse
+#define pa_get_binary_name pa_get_binary_name_dylibloader_orig_pulse
+#define pa_path_get_filename pa_path_get_filename_dylibloader_orig_pulse
+#define pa_msleep pa_msleep_dylibloader_orig_pulse
+#define pa_thread_make_realtime pa_thread_make_realtime_dylibloader_orig_pulse
+#define pa_gettimeofday pa_gettimeofday_dylibloader_orig_pulse
+#define pa_timeval_diff pa_timeval_diff_dylibloader_orig_pulse
+#define pa_timeval_cmp pa_timeval_cmp_dylibloader_orig_pulse
+#define pa_timeval_age pa_timeval_age_dylibloader_orig_pulse
+#define pa_timeval_add pa_timeval_add_dylibloader_orig_pulse
+#define pa_timeval_sub pa_timeval_sub_dylibloader_orig_pulse
+#define pa_timeval_store pa_timeval_store_dylibloader_orig_pulse
+#define pa_timeval_load pa_timeval_load_dylibloader_orig_pulse
+#define pa_rtclock_now pa_rtclock_now_dylibloader_orig_pulse
+#include <pulse/pulseaudio.h>
+#undef pa_get_library_version
+#undef pa_bytes_per_second
+#undef pa_frame_size
+#undef pa_sample_size
+#undef pa_sample_size_of_format
+#undef pa_bytes_to_usec
+#undef pa_usec_to_bytes
+#undef pa_sample_spec_init
+#undef pa_sample_format_valid
+#undef pa_sample_rate_valid
+#undef pa_channels_valid
+#undef pa_sample_spec_valid
+#undef pa_sample_spec_equal
+#undef pa_sample_format_to_string
+#undef pa_parse_sample_format
+#undef pa_sample_spec_snprint
+#undef pa_bytes_snprint
+#undef pa_sample_format_is_le
+#undef pa_sample_format_is_be
+#undef pa_direction_valid
+#undef pa_direction_to_string
+#undef pa_mainloop_api_once
+#undef pa_proplist_new
+#undef pa_proplist_free
+#undef pa_proplist_key_valid
+#undef pa_proplist_sets
+#undef pa_proplist_setp
+#undef pa_proplist_setf
+#undef pa_proplist_set
+#undef pa_proplist_gets
+#undef pa_proplist_get
+#undef pa_proplist_update
+#undef pa_proplist_unset
+#undef pa_proplist_unset_many
+#undef pa_proplist_iterate
+#undef pa_proplist_to_string
+#undef pa_proplist_to_string_sep
+#undef pa_proplist_from_string
+#undef pa_proplist_contains
+#undef pa_proplist_clear
+#undef pa_proplist_copy
+#undef pa_proplist_size
+#undef pa_proplist_isempty
+#undef pa_proplist_equal
+#undef pa_channel_map_init
+#undef pa_channel_map_init_mono
+#undef pa_channel_map_init_stereo
+#undef pa_channel_map_init_auto
+#undef pa_channel_map_init_extend
+#undef pa_channel_position_to_string
+#undef pa_channel_position_from_string
+#undef pa_channel_position_to_pretty_string
+#undef pa_channel_map_snprint
+#undef pa_channel_map_parse
+#undef pa_channel_map_equal
+#undef pa_channel_map_valid
+#undef pa_channel_map_compatible
+#undef pa_channel_map_superset
+#undef pa_channel_map_can_balance
+#undef pa_channel_map_can_fade
+#undef pa_channel_map_can_lfe_balance
+#undef pa_channel_map_to_name
+#undef pa_channel_map_to_pretty_name
+#undef pa_channel_map_has_position
+#undef pa_channel_map_mask
+#undef pa_encoding_to_string
+#undef pa_encoding_from_string
+#undef pa_format_info_new
+#undef pa_format_info_copy
+#undef pa_format_info_free
+#undef pa_format_info_valid
+#undef pa_format_info_is_pcm
+#undef pa_format_info_is_compatible
+#undef pa_format_info_snprint
+#undef pa_format_info_from_string
+#undef pa_format_info_from_sample_spec
+#undef pa_format_info_to_sample_spec
+#undef pa_format_info_get_prop_type
+#undef pa_format_info_get_prop_int
+#undef pa_format_info_get_prop_int_range
+#undef pa_format_info_get_prop_int_array
+#undef pa_format_info_get_prop_string
+#undef pa_format_info_get_prop_string_array
+#undef pa_format_info_free_string_array
+#undef pa_format_info_get_sample_format
+#undef pa_format_info_get_rate
+#undef pa_format_info_get_channels
+#undef pa_format_info_get_channel_map
+#undef pa_format_info_set_prop_int
+#undef pa_format_info_set_prop_int_array
+#undef pa_format_info_set_prop_int_range
+#undef pa_format_info_set_prop_string
+#undef pa_format_info_set_prop_string_array
+#undef pa_format_info_set_sample_format
+#undef pa_format_info_set_rate
+#undef pa_format_info_set_channels
+#undef pa_format_info_set_channel_map
+#undef pa_operation_ref
+#undef pa_operation_unref
+#undef pa_operation_cancel
+#undef pa_operation_get_state
+#undef pa_operation_set_state_callback
+#undef pa_context_new
+#undef pa_context_new_with_proplist
+#undef pa_context_unref
+#undef pa_context_ref
+#undef pa_context_set_state_callback
+#undef pa_context_set_event_callback
+#undef pa_context_errno
+#undef pa_context_is_pending
+#undef pa_context_get_state
+#undef pa_context_connect
+#undef pa_context_disconnect
+#undef pa_context_drain
+#undef pa_context_exit_daemon
+#undef pa_context_set_default_sink
+#undef pa_context_set_default_source
+#undef pa_context_is_local
+#undef pa_context_set_name
+#undef pa_context_get_server
+#undef pa_context_get_protocol_version
+#undef pa_context_get_server_protocol_version
+#undef pa_context_proplist_update
+#undef pa_context_proplist_remove
+#undef pa_context_get_index
+#undef pa_context_rttime_new
+#undef pa_context_rttime_restart
+#undef pa_context_get_tile_size
+#undef pa_context_load_cookie_from_file
+#undef pa_cvolume_equal
+#undef pa_cvolume_init
+#undef pa_cvolume_set
+#undef pa_cvolume_snprint
+#undef pa_sw_cvolume_snprint_dB
+#undef pa_cvolume_snprint_verbose
+#undef pa_volume_snprint
+#undef pa_sw_volume_snprint_dB
+#undef pa_volume_snprint_verbose
+#undef pa_cvolume_avg
+#undef pa_cvolume_avg_mask
+#undef pa_cvolume_max
+#undef pa_cvolume_max_mask
+#undef pa_cvolume_min
+#undef pa_cvolume_min_mask
+#undef pa_cvolume_valid
+#undef pa_cvolume_channels_equal_to
+#undef pa_sw_volume_multiply
+#undef pa_sw_cvolume_multiply
+#undef pa_sw_cvolume_multiply_scalar
+#undef pa_sw_volume_divide
+#undef pa_sw_cvolume_divide
+#undef pa_sw_cvolume_divide_scalar
+#undef pa_sw_volume_from_dB
+#undef pa_sw_volume_to_dB
+#undef pa_sw_volume_from_linear
+#undef pa_sw_volume_to_linear
+#undef pa_cvolume_remap
+#undef pa_cvolume_compatible
+#undef pa_cvolume_compatible_with_channel_map
+#undef pa_cvolume_get_balance
+#undef pa_cvolume_set_balance
+#undef pa_cvolume_get_fade
+#undef pa_cvolume_set_fade
+#undef pa_cvolume_get_lfe_balance
+#undef pa_cvolume_set_lfe_balance
+#undef pa_cvolume_scale
+#undef pa_cvolume_scale_mask
+#undef pa_cvolume_set_position
+#undef pa_cvolume_get_position
+#undef pa_cvolume_merge
+#undef pa_cvolume_inc_clamp
+#undef pa_cvolume_inc
+#undef pa_cvolume_dec
+#undef pa_stream_new
+#undef pa_stream_new_with_proplist
+#undef pa_stream_new_extended
+#undef pa_stream_unref
+#undef pa_stream_ref
+#undef pa_stream_get_state
+#undef pa_stream_get_context
+#undef pa_stream_get_index
+#undef pa_stream_get_device_index
+#undef pa_stream_get_device_name
+#undef pa_stream_is_suspended
+#undef pa_stream_is_corked
+#undef pa_stream_connect_playback
+#undef pa_stream_connect_record
+#undef pa_stream_disconnect
+#undef pa_stream_begin_write
+#undef pa_stream_cancel_write
+#undef pa_stream_write
+#undef pa_stream_write_ext_free
+#undef pa_stream_peek
+#undef pa_stream_drop
+#undef pa_stream_writable_size
+#undef pa_stream_readable_size
+#undef pa_stream_drain
+#undef pa_stream_update_timing_info
+#undef pa_stream_set_state_callback
+#undef pa_stream_set_write_callback
+#undef pa_stream_set_read_callback
+#undef pa_stream_set_overflow_callback
+#undef pa_stream_get_underflow_index
+#undef pa_stream_set_underflow_callback
+#undef pa_stream_set_started_callback
+#undef pa_stream_set_latency_update_callback
+#undef pa_stream_set_moved_callback
+#undef pa_stream_set_suspended_callback
+#undef pa_stream_set_event_callback
+#undef pa_stream_set_buffer_attr_callback
+#undef pa_stream_cork
+#undef pa_stream_flush
+#undef pa_stream_prebuf
+#undef pa_stream_trigger
+#undef pa_stream_set_name
+#undef pa_stream_get_time
+#undef pa_stream_get_latency
+#undef pa_stream_get_timing_info
+#undef pa_stream_get_sample_spec
+#undef pa_stream_get_channel_map
+#undef pa_stream_get_format_info
+#undef pa_stream_get_buffer_attr
+#undef pa_stream_set_buffer_attr
+#undef pa_stream_update_sample_rate
+#undef pa_stream_proplist_update
+#undef pa_stream_proplist_remove
+#undef pa_stream_set_monitor_stream
+#undef pa_stream_get_monitor_stream
+#undef pa_context_get_sink_info_by_name
+#undef pa_context_get_sink_info_by_index
+#undef pa_context_get_sink_info_list
+#undef pa_context_set_sink_volume_by_index
+#undef pa_context_set_sink_volume_by_name
+#undef pa_context_set_sink_mute_by_index
+#undef pa_context_set_sink_mute_by_name
+#undef pa_context_suspend_sink_by_name
+#undef pa_context_suspend_sink_by_index
+#undef pa_context_set_sink_port_by_index
+#undef pa_context_set_sink_port_by_name
+#undef pa_context_get_source_info_by_name
+#undef pa_context_get_source_info_by_index
+#undef pa_context_get_source_info_list
+#undef pa_context_set_source_volume_by_index
+#undef pa_context_set_source_volume_by_name
+#undef pa_context_set_source_mute_by_index
+#undef pa_context_set_source_mute_by_name
+#undef pa_context_suspend_source_by_name
+#undef pa_context_suspend_source_by_index
+#undef pa_context_set_source_port_by_index
+#undef pa_context_set_source_port_by_name
+#undef pa_context_get_server_info
+#undef pa_context_get_module_info
+#undef pa_context_get_module_info_list
+#undef pa_context_load_module
+#undef pa_context_unload_module
+#undef pa_context_get_client_info
+#undef pa_context_get_client_info_list
+#undef pa_context_kill_client
+#undef pa_context_get_card_info_by_index
+#undef pa_context_get_card_info_by_name
+#undef pa_context_get_card_info_list
+#undef pa_context_set_card_profile_by_index
+#undef pa_context_set_card_profile_by_name
+#undef pa_context_set_port_latency_offset
+#undef pa_context_get_sink_input_info
+#undef pa_context_get_sink_input_info_list
+#undef pa_context_move_sink_input_by_name
+#undef pa_context_move_sink_input_by_index
+#undef pa_context_set_sink_input_volume
+#undef pa_context_set_sink_input_mute
+#undef pa_context_kill_sink_input
+#undef pa_context_get_source_output_info
+#undef pa_context_get_source_output_info_list
+#undef pa_context_move_source_output_by_name
+#undef pa_context_move_source_output_by_index
+#undef pa_context_set_source_output_volume
+#undef pa_context_set_source_output_mute
+#undef pa_context_kill_source_output
+#undef pa_context_stat
+#undef pa_context_get_sample_info_by_name
+#undef pa_context_get_sample_info_by_index
+#undef pa_context_get_sample_info_list
+#undef pa_context_get_autoload_info_by_name
+#undef pa_context_get_autoload_info_by_index
+#undef pa_context_get_autoload_info_list
+#undef pa_context_add_autoload
+#undef pa_context_remove_autoload_by_name
+#undef pa_context_remove_autoload_by_index
+#undef pa_context_subscribe
+#undef pa_context_set_subscribe_callback
+#undef pa_stream_connect_upload
+#undef pa_stream_finish_upload
+#undef pa_context_remove_sample
+#undef pa_context_play_sample
+#undef pa_context_play_sample_with_proplist
+#undef pa_strerror
+#undef pa_xmalloc
+#undef pa_xmalloc0
+#undef pa_xrealloc
+#undef pa_xfree
+#undef pa_xstrdup
+#undef pa_xstrndup
+#undef pa_xmemdup
+#undef pa_utf8_valid
+#undef pa_ascii_valid
+#undef pa_utf8_filter
+#undef pa_ascii_filter
+#undef pa_utf8_to_locale
+#undef pa_locale_to_utf8
+#undef pa_threaded_mainloop_new
+#undef pa_threaded_mainloop_free
+#undef pa_threaded_mainloop_start
+#undef pa_threaded_mainloop_stop
+#undef pa_threaded_mainloop_lock
+#undef pa_threaded_mainloop_unlock
+#undef pa_threaded_mainloop_wait
+#undef pa_threaded_mainloop_signal
+#undef pa_threaded_mainloop_accept
+#undef pa_threaded_mainloop_get_retval
+#undef pa_threaded_mainloop_get_api
+#undef pa_threaded_mainloop_in_thread
+#undef pa_threaded_mainloop_set_name
+#undef pa_threaded_mainloop_once_unlocked
+#undef pa_mainloop_new
+#undef pa_mainloop_free
+#undef pa_mainloop_prepare
+#undef pa_mainloop_poll
+#undef pa_mainloop_dispatch
+#undef pa_mainloop_get_retval
+#undef pa_mainloop_iterate
+#undef pa_mainloop_run
+#undef pa_mainloop_get_api
+#undef pa_mainloop_quit
+#undef pa_mainloop_wakeup
+#undef pa_mainloop_set_poll_func
+#undef pa_signal_init
+#undef pa_signal_done
+#undef pa_signal_new
+#undef pa_signal_free
+#undef pa_signal_set_destroy
+#undef pa_get_user_name
+#undef pa_get_host_name
+#undef pa_get_fqdn
+#undef pa_get_home_dir
+#undef pa_get_binary_name
+#undef pa_path_get_filename
+#undef pa_msleep
+#undef pa_thread_make_realtime
+#undef pa_gettimeofday
+#undef pa_timeval_diff
+#undef pa_timeval_cmp
+#undef pa_timeval_age
+#undef pa_timeval_add
+#undef pa_timeval_sub
+#undef pa_timeval_store
+#undef pa_timeval_load
+#undef pa_rtclock_now
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define pa_get_library_version pa_get_library_version_dylibloader_wrapper_pulse
+#define pa_bytes_per_second pa_bytes_per_second_dylibloader_wrapper_pulse
+#define pa_frame_size pa_frame_size_dylibloader_wrapper_pulse
+#define pa_sample_size pa_sample_size_dylibloader_wrapper_pulse
+#define pa_sample_size_of_format pa_sample_size_of_format_dylibloader_wrapper_pulse
+#define pa_bytes_to_usec pa_bytes_to_usec_dylibloader_wrapper_pulse
+#define pa_usec_to_bytes pa_usec_to_bytes_dylibloader_wrapper_pulse
+#define pa_sample_spec_init pa_sample_spec_init_dylibloader_wrapper_pulse
+#define pa_sample_format_valid pa_sample_format_valid_dylibloader_wrapper_pulse
+#define pa_sample_rate_valid pa_sample_rate_valid_dylibloader_wrapper_pulse
+#define pa_channels_valid pa_channels_valid_dylibloader_wrapper_pulse
+#define pa_sample_spec_valid pa_sample_spec_valid_dylibloader_wrapper_pulse
+#define pa_sample_spec_equal pa_sample_spec_equal_dylibloader_wrapper_pulse
+#define pa_sample_format_to_string pa_sample_format_to_string_dylibloader_wrapper_pulse
+#define pa_parse_sample_format pa_parse_sample_format_dylibloader_wrapper_pulse
+#define pa_sample_spec_snprint pa_sample_spec_snprint_dylibloader_wrapper_pulse
+#define pa_bytes_snprint pa_bytes_snprint_dylibloader_wrapper_pulse
+#define pa_sample_format_is_le pa_sample_format_is_le_dylibloader_wrapper_pulse
+#define pa_sample_format_is_be pa_sample_format_is_be_dylibloader_wrapper_pulse
+#define pa_direction_valid pa_direction_valid_dylibloader_wrapper_pulse
+#define pa_direction_to_string pa_direction_to_string_dylibloader_wrapper_pulse
+#define pa_mainloop_api_once pa_mainloop_api_once_dylibloader_wrapper_pulse
+#define pa_proplist_new pa_proplist_new_dylibloader_wrapper_pulse
+#define pa_proplist_free pa_proplist_free_dylibloader_wrapper_pulse
+#define pa_proplist_key_valid pa_proplist_key_valid_dylibloader_wrapper_pulse
+#define pa_proplist_sets pa_proplist_sets_dylibloader_wrapper_pulse
+#define pa_proplist_setp pa_proplist_setp_dylibloader_wrapper_pulse
+#define pa_proplist_setf pa_proplist_setf_dylibloader_wrapper_pulse
+#define pa_proplist_set pa_proplist_set_dylibloader_wrapper_pulse
+#define pa_proplist_gets pa_proplist_gets_dylibloader_wrapper_pulse
+#define pa_proplist_get pa_proplist_get_dylibloader_wrapper_pulse
+#define pa_proplist_update pa_proplist_update_dylibloader_wrapper_pulse
+#define pa_proplist_unset pa_proplist_unset_dylibloader_wrapper_pulse
+#define pa_proplist_unset_many pa_proplist_unset_many_dylibloader_wrapper_pulse
+#define pa_proplist_iterate pa_proplist_iterate_dylibloader_wrapper_pulse
+#define pa_proplist_to_string pa_proplist_to_string_dylibloader_wrapper_pulse
+#define pa_proplist_to_string_sep pa_proplist_to_string_sep_dylibloader_wrapper_pulse
+#define pa_proplist_from_string pa_proplist_from_string_dylibloader_wrapper_pulse
+#define pa_proplist_contains pa_proplist_contains_dylibloader_wrapper_pulse
+#define pa_proplist_clear pa_proplist_clear_dylibloader_wrapper_pulse
+#define pa_proplist_copy pa_proplist_copy_dylibloader_wrapper_pulse
+#define pa_proplist_size pa_proplist_size_dylibloader_wrapper_pulse
+#define pa_proplist_isempty pa_proplist_isempty_dylibloader_wrapper_pulse
+#define pa_proplist_equal pa_proplist_equal_dylibloader_wrapper_pulse
+#define pa_channel_map_init pa_channel_map_init_dylibloader_wrapper_pulse
+#define pa_channel_map_init_mono pa_channel_map_init_mono_dylibloader_wrapper_pulse
+#define pa_channel_map_init_stereo pa_channel_map_init_stereo_dylibloader_wrapper_pulse
+#define pa_channel_map_init_auto pa_channel_map_init_auto_dylibloader_wrapper_pulse
+#define pa_channel_map_init_extend pa_channel_map_init_extend_dylibloader_wrapper_pulse
+#define pa_channel_position_to_string pa_channel_position_to_string_dylibloader_wrapper_pulse
+#define pa_channel_position_from_string pa_channel_position_from_string_dylibloader_wrapper_pulse
+#define pa_channel_position_to_pretty_string pa_channel_position_to_pretty_string_dylibloader_wrapper_pulse
+#define pa_channel_map_snprint pa_channel_map_snprint_dylibloader_wrapper_pulse
+#define pa_channel_map_parse pa_channel_map_parse_dylibloader_wrapper_pulse
+#define pa_channel_map_equal pa_channel_map_equal_dylibloader_wrapper_pulse
+#define pa_channel_map_valid pa_channel_map_valid_dylibloader_wrapper_pulse
+#define pa_channel_map_compatible pa_channel_map_compatible_dylibloader_wrapper_pulse
+#define pa_channel_map_superset pa_channel_map_superset_dylibloader_wrapper_pulse
+#define pa_channel_map_can_balance pa_channel_map_can_balance_dylibloader_wrapper_pulse
+#define pa_channel_map_can_fade pa_channel_map_can_fade_dylibloader_wrapper_pulse
+#define pa_channel_map_can_lfe_balance pa_channel_map_can_lfe_balance_dylibloader_wrapper_pulse
+#define pa_channel_map_to_name pa_channel_map_to_name_dylibloader_wrapper_pulse
+#define pa_channel_map_to_pretty_name pa_channel_map_to_pretty_name_dylibloader_wrapper_pulse
+#define pa_channel_map_has_position pa_channel_map_has_position_dylibloader_wrapper_pulse
+#define pa_channel_map_mask pa_channel_map_mask_dylibloader_wrapper_pulse
+#define pa_encoding_to_string pa_encoding_to_string_dylibloader_wrapper_pulse
+#define pa_encoding_from_string pa_encoding_from_string_dylibloader_wrapper_pulse
+#define pa_format_info_new pa_format_info_new_dylibloader_wrapper_pulse
+#define pa_format_info_copy pa_format_info_copy_dylibloader_wrapper_pulse
+#define pa_format_info_free pa_format_info_free_dylibloader_wrapper_pulse
+#define pa_format_info_valid pa_format_info_valid_dylibloader_wrapper_pulse
+#define pa_format_info_is_pcm pa_format_info_is_pcm_dylibloader_wrapper_pulse
+#define pa_format_info_is_compatible pa_format_info_is_compatible_dylibloader_wrapper_pulse
+#define pa_format_info_snprint pa_format_info_snprint_dylibloader_wrapper_pulse
+#define pa_format_info_from_string pa_format_info_from_string_dylibloader_wrapper_pulse
+#define pa_format_info_from_sample_spec pa_format_info_from_sample_spec_dylibloader_wrapper_pulse
+#define pa_format_info_to_sample_spec pa_format_info_to_sample_spec_dylibloader_wrapper_pulse
+#define pa_format_info_get_prop_type pa_format_info_get_prop_type_dylibloader_wrapper_pulse
+#define pa_format_info_get_prop_int pa_format_info_get_prop_int_dylibloader_wrapper_pulse
+#define pa_format_info_get_prop_int_range pa_format_info_get_prop_int_range_dylibloader_wrapper_pulse
+#define pa_format_info_get_prop_int_array pa_format_info_get_prop_int_array_dylibloader_wrapper_pulse
+#define pa_format_info_get_prop_string pa_format_info_get_prop_string_dylibloader_wrapper_pulse
+#define pa_format_info_get_prop_string_array pa_format_info_get_prop_string_array_dylibloader_wrapper_pulse
+#define pa_format_info_free_string_array pa_format_info_free_string_array_dylibloader_wrapper_pulse
+#define pa_format_info_get_sample_format pa_format_info_get_sample_format_dylibloader_wrapper_pulse
+#define pa_format_info_get_rate pa_format_info_get_rate_dylibloader_wrapper_pulse
+#define pa_format_info_get_channels pa_format_info_get_channels_dylibloader_wrapper_pulse
+#define pa_format_info_get_channel_map pa_format_info_get_channel_map_dylibloader_wrapper_pulse
+#define pa_format_info_set_prop_int pa_format_info_set_prop_int_dylibloader_wrapper_pulse
+#define pa_format_info_set_prop_int_array pa_format_info_set_prop_int_array_dylibloader_wrapper_pulse
+#define pa_format_info_set_prop_int_range pa_format_info_set_prop_int_range_dylibloader_wrapper_pulse
+#define pa_format_info_set_prop_string pa_format_info_set_prop_string_dylibloader_wrapper_pulse
+#define pa_format_info_set_prop_string_array pa_format_info_set_prop_string_array_dylibloader_wrapper_pulse
+#define pa_format_info_set_sample_format pa_format_info_set_sample_format_dylibloader_wrapper_pulse
+#define pa_format_info_set_rate pa_format_info_set_rate_dylibloader_wrapper_pulse
+#define pa_format_info_set_channels pa_format_info_set_channels_dylibloader_wrapper_pulse
+#define pa_format_info_set_channel_map pa_format_info_set_channel_map_dylibloader_wrapper_pulse
+#define pa_operation_ref pa_operation_ref_dylibloader_wrapper_pulse
+#define pa_operation_unref pa_operation_unref_dylibloader_wrapper_pulse
+#define pa_operation_cancel pa_operation_cancel_dylibloader_wrapper_pulse
+#define pa_operation_get_state pa_operation_get_state_dylibloader_wrapper_pulse
+#define pa_operation_set_state_callback pa_operation_set_state_callback_dylibloader_wrapper_pulse
+#define pa_context_new pa_context_new_dylibloader_wrapper_pulse
+#define pa_context_new_with_proplist pa_context_new_with_proplist_dylibloader_wrapper_pulse
+#define pa_context_unref pa_context_unref_dylibloader_wrapper_pulse
+#define pa_context_ref pa_context_ref_dylibloader_wrapper_pulse
+#define pa_context_set_state_callback pa_context_set_state_callback_dylibloader_wrapper_pulse
+#define pa_context_set_event_callback pa_context_set_event_callback_dylibloader_wrapper_pulse
+#define pa_context_errno pa_context_errno_dylibloader_wrapper_pulse
+#define pa_context_is_pending pa_context_is_pending_dylibloader_wrapper_pulse
+#define pa_context_get_state pa_context_get_state_dylibloader_wrapper_pulse
+#define pa_context_connect pa_context_connect_dylibloader_wrapper_pulse
+#define pa_context_disconnect pa_context_disconnect_dylibloader_wrapper_pulse
+#define pa_context_drain pa_context_drain_dylibloader_wrapper_pulse
+#define pa_context_exit_daemon pa_context_exit_daemon_dylibloader_wrapper_pulse
+#define pa_context_set_default_sink pa_context_set_default_sink_dylibloader_wrapper_pulse
+#define pa_context_set_default_source pa_context_set_default_source_dylibloader_wrapper_pulse
+#define pa_context_is_local pa_context_is_local_dylibloader_wrapper_pulse
+#define pa_context_set_name pa_context_set_name_dylibloader_wrapper_pulse
+#define pa_context_get_server pa_context_get_server_dylibloader_wrapper_pulse
+#define pa_context_get_protocol_version pa_context_get_protocol_version_dylibloader_wrapper_pulse
+#define pa_context_get_server_protocol_version pa_context_get_server_protocol_version_dylibloader_wrapper_pulse
+#define pa_context_proplist_update pa_context_proplist_update_dylibloader_wrapper_pulse
+#define pa_context_proplist_remove pa_context_proplist_remove_dylibloader_wrapper_pulse
+#define pa_context_get_index pa_context_get_index_dylibloader_wrapper_pulse
+#define pa_context_rttime_new pa_context_rttime_new_dylibloader_wrapper_pulse
+#define pa_context_rttime_restart pa_context_rttime_restart_dylibloader_wrapper_pulse
+#define pa_context_get_tile_size pa_context_get_tile_size_dylibloader_wrapper_pulse
+#define pa_context_load_cookie_from_file pa_context_load_cookie_from_file_dylibloader_wrapper_pulse
+#define pa_cvolume_equal pa_cvolume_equal_dylibloader_wrapper_pulse
+#define pa_cvolume_init pa_cvolume_init_dylibloader_wrapper_pulse
+#define pa_cvolume_set pa_cvolume_set_dylibloader_wrapper_pulse
+#define pa_cvolume_snprint pa_cvolume_snprint_dylibloader_wrapper_pulse
+#define pa_sw_cvolume_snprint_dB pa_sw_cvolume_snprint_dB_dylibloader_wrapper_pulse
+#define pa_cvolume_snprint_verbose pa_cvolume_snprint_verbose_dylibloader_wrapper_pulse
+#define pa_volume_snprint pa_volume_snprint_dylibloader_wrapper_pulse
+#define pa_sw_volume_snprint_dB pa_sw_volume_snprint_dB_dylibloader_wrapper_pulse
+#define pa_volume_snprint_verbose pa_volume_snprint_verbose_dylibloader_wrapper_pulse
+#define pa_cvolume_avg pa_cvolume_avg_dylibloader_wrapper_pulse
+#define pa_cvolume_avg_mask pa_cvolume_avg_mask_dylibloader_wrapper_pulse
+#define pa_cvolume_max pa_cvolume_max_dylibloader_wrapper_pulse
+#define pa_cvolume_max_mask pa_cvolume_max_mask_dylibloader_wrapper_pulse
+#define pa_cvolume_min pa_cvolume_min_dylibloader_wrapper_pulse
+#define pa_cvolume_min_mask pa_cvolume_min_mask_dylibloader_wrapper_pulse
+#define pa_cvolume_valid pa_cvolume_valid_dylibloader_wrapper_pulse
+#define pa_cvolume_channels_equal_to pa_cvolume_channels_equal_to_dylibloader_wrapper_pulse
+#define pa_sw_volume_multiply pa_sw_volume_multiply_dylibloader_wrapper_pulse
+#define pa_sw_cvolume_multiply pa_sw_cvolume_multiply_dylibloader_wrapper_pulse
+#define pa_sw_cvolume_multiply_scalar pa_sw_cvolume_multiply_scalar_dylibloader_wrapper_pulse
+#define pa_sw_volume_divide pa_sw_volume_divide_dylibloader_wrapper_pulse
+#define pa_sw_cvolume_divide pa_sw_cvolume_divide_dylibloader_wrapper_pulse
+#define pa_sw_cvolume_divide_scalar pa_sw_cvolume_divide_scalar_dylibloader_wrapper_pulse
+#define pa_sw_volume_from_dB pa_sw_volume_from_dB_dylibloader_wrapper_pulse
+#define pa_sw_volume_to_dB pa_sw_volume_to_dB_dylibloader_wrapper_pulse
+#define pa_sw_volume_from_linear pa_sw_volume_from_linear_dylibloader_wrapper_pulse
+#define pa_sw_volume_to_linear pa_sw_volume_to_linear_dylibloader_wrapper_pulse
+#define pa_cvolume_remap pa_cvolume_remap_dylibloader_wrapper_pulse
+#define pa_cvolume_compatible pa_cvolume_compatible_dylibloader_wrapper_pulse
+#define pa_cvolume_compatible_with_channel_map pa_cvolume_compatible_with_channel_map_dylibloader_wrapper_pulse
+#define pa_cvolume_get_balance pa_cvolume_get_balance_dylibloader_wrapper_pulse
+#define pa_cvolume_set_balance pa_cvolume_set_balance_dylibloader_wrapper_pulse
+#define pa_cvolume_get_fade pa_cvolume_get_fade_dylibloader_wrapper_pulse
+#define pa_cvolume_set_fade pa_cvolume_set_fade_dylibloader_wrapper_pulse
+#define pa_cvolume_get_lfe_balance pa_cvolume_get_lfe_balance_dylibloader_wrapper_pulse
+#define pa_cvolume_set_lfe_balance pa_cvolume_set_lfe_balance_dylibloader_wrapper_pulse
+#define pa_cvolume_scale pa_cvolume_scale_dylibloader_wrapper_pulse
+#define pa_cvolume_scale_mask pa_cvolume_scale_mask_dylibloader_wrapper_pulse
+#define pa_cvolume_set_position pa_cvolume_set_position_dylibloader_wrapper_pulse
+#define pa_cvolume_get_position pa_cvolume_get_position_dylibloader_wrapper_pulse
+#define pa_cvolume_merge pa_cvolume_merge_dylibloader_wrapper_pulse
+#define pa_cvolume_inc_clamp pa_cvolume_inc_clamp_dylibloader_wrapper_pulse
+#define pa_cvolume_inc pa_cvolume_inc_dylibloader_wrapper_pulse
+#define pa_cvolume_dec pa_cvolume_dec_dylibloader_wrapper_pulse
+#define pa_stream_new pa_stream_new_dylibloader_wrapper_pulse
+#define pa_stream_new_with_proplist pa_stream_new_with_proplist_dylibloader_wrapper_pulse
+#define pa_stream_new_extended pa_stream_new_extended_dylibloader_wrapper_pulse
+#define pa_stream_unref pa_stream_unref_dylibloader_wrapper_pulse
+#define pa_stream_ref pa_stream_ref_dylibloader_wrapper_pulse
+#define pa_stream_get_state pa_stream_get_state_dylibloader_wrapper_pulse
+#define pa_stream_get_context pa_stream_get_context_dylibloader_wrapper_pulse
+#define pa_stream_get_index pa_stream_get_index_dylibloader_wrapper_pulse
+#define pa_stream_get_device_index pa_stream_get_device_index_dylibloader_wrapper_pulse
+#define pa_stream_get_device_name pa_stream_get_device_name_dylibloader_wrapper_pulse
+#define pa_stream_is_suspended pa_stream_is_suspended_dylibloader_wrapper_pulse
+#define pa_stream_is_corked pa_stream_is_corked_dylibloader_wrapper_pulse
+#define pa_stream_connect_playback pa_stream_connect_playback_dylibloader_wrapper_pulse
+#define pa_stream_connect_record pa_stream_connect_record_dylibloader_wrapper_pulse
+#define pa_stream_disconnect pa_stream_disconnect_dylibloader_wrapper_pulse
+#define pa_stream_begin_write pa_stream_begin_write_dylibloader_wrapper_pulse
+#define pa_stream_cancel_write pa_stream_cancel_write_dylibloader_wrapper_pulse
+#define pa_stream_write pa_stream_write_dylibloader_wrapper_pulse
+#define pa_stream_write_ext_free pa_stream_write_ext_free_dylibloader_wrapper_pulse
+#define pa_stream_peek pa_stream_peek_dylibloader_wrapper_pulse
+#define pa_stream_drop pa_stream_drop_dylibloader_wrapper_pulse
+#define pa_stream_writable_size pa_stream_writable_size_dylibloader_wrapper_pulse
+#define pa_stream_readable_size pa_stream_readable_size_dylibloader_wrapper_pulse
+#define pa_stream_drain pa_stream_drain_dylibloader_wrapper_pulse
+#define pa_stream_update_timing_info pa_stream_update_timing_info_dylibloader_wrapper_pulse
+#define pa_stream_set_state_callback pa_stream_set_state_callback_dylibloader_wrapper_pulse
+#define pa_stream_set_write_callback pa_stream_set_write_callback_dylibloader_wrapper_pulse
+#define pa_stream_set_read_callback pa_stream_set_read_callback_dylibloader_wrapper_pulse
+#define pa_stream_set_overflow_callback pa_stream_set_overflow_callback_dylibloader_wrapper_pulse
+#define pa_stream_get_underflow_index pa_stream_get_underflow_index_dylibloader_wrapper_pulse
+#define pa_stream_set_underflow_callback pa_stream_set_underflow_callback_dylibloader_wrapper_pulse
+#define pa_stream_set_started_callback pa_stream_set_started_callback_dylibloader_wrapper_pulse
+#define pa_stream_set_latency_update_callback pa_stream_set_latency_update_callback_dylibloader_wrapper_pulse
+#define pa_stream_set_moved_callback pa_stream_set_moved_callback_dylibloader_wrapper_pulse
+#define pa_stream_set_suspended_callback pa_stream_set_suspended_callback_dylibloader_wrapper_pulse
+#define pa_stream_set_event_callback pa_stream_set_event_callback_dylibloader_wrapper_pulse
+#define pa_stream_set_buffer_attr_callback pa_stream_set_buffer_attr_callback_dylibloader_wrapper_pulse
+#define pa_stream_cork pa_stream_cork_dylibloader_wrapper_pulse
+#define pa_stream_flush pa_stream_flush_dylibloader_wrapper_pulse
+#define pa_stream_prebuf pa_stream_prebuf_dylibloader_wrapper_pulse
+#define pa_stream_trigger pa_stream_trigger_dylibloader_wrapper_pulse
+#define pa_stream_set_name pa_stream_set_name_dylibloader_wrapper_pulse
+#define pa_stream_get_time pa_stream_get_time_dylibloader_wrapper_pulse
+#define pa_stream_get_latency pa_stream_get_latency_dylibloader_wrapper_pulse
+#define pa_stream_get_timing_info pa_stream_get_timing_info_dylibloader_wrapper_pulse
+#define pa_stream_get_sample_spec pa_stream_get_sample_spec_dylibloader_wrapper_pulse
+#define pa_stream_get_channel_map pa_stream_get_channel_map_dylibloader_wrapper_pulse
+#define pa_stream_get_format_info pa_stream_get_format_info_dylibloader_wrapper_pulse
+#define pa_stream_get_buffer_attr pa_stream_get_buffer_attr_dylibloader_wrapper_pulse
+#define pa_stream_set_buffer_attr pa_stream_set_buffer_attr_dylibloader_wrapper_pulse
+#define pa_stream_update_sample_rate pa_stream_update_sample_rate_dylibloader_wrapper_pulse
+#define pa_stream_proplist_update pa_stream_proplist_update_dylibloader_wrapper_pulse
+#define pa_stream_proplist_remove pa_stream_proplist_remove_dylibloader_wrapper_pulse
+#define pa_stream_set_monitor_stream pa_stream_set_monitor_stream_dylibloader_wrapper_pulse
+#define pa_stream_get_monitor_stream pa_stream_get_monitor_stream_dylibloader_wrapper_pulse
+#define pa_context_get_sink_info_by_name pa_context_get_sink_info_by_name_dylibloader_wrapper_pulse
+#define pa_context_get_sink_info_by_index pa_context_get_sink_info_by_index_dylibloader_wrapper_pulse
+#define pa_context_get_sink_info_list pa_context_get_sink_info_list_dylibloader_wrapper_pulse
+#define pa_context_set_sink_volume_by_index pa_context_set_sink_volume_by_index_dylibloader_wrapper_pulse
+#define pa_context_set_sink_volume_by_name pa_context_set_sink_volume_by_name_dylibloader_wrapper_pulse
+#define pa_context_set_sink_mute_by_index pa_context_set_sink_mute_by_index_dylibloader_wrapper_pulse
+#define pa_context_set_sink_mute_by_name pa_context_set_sink_mute_by_name_dylibloader_wrapper_pulse
+#define pa_context_suspend_sink_by_name pa_context_suspend_sink_by_name_dylibloader_wrapper_pulse
+#define pa_context_suspend_sink_by_index pa_context_suspend_sink_by_index_dylibloader_wrapper_pulse
+#define pa_context_set_sink_port_by_index pa_context_set_sink_port_by_index_dylibloader_wrapper_pulse
+#define pa_context_set_sink_port_by_name pa_context_set_sink_port_by_name_dylibloader_wrapper_pulse
+#define pa_context_get_source_info_by_name pa_context_get_source_info_by_name_dylibloader_wrapper_pulse
+#define pa_context_get_source_info_by_index pa_context_get_source_info_by_index_dylibloader_wrapper_pulse
+#define pa_context_get_source_info_list pa_context_get_source_info_list_dylibloader_wrapper_pulse
+#define pa_context_set_source_volume_by_index pa_context_set_source_volume_by_index_dylibloader_wrapper_pulse
+#define pa_context_set_source_volume_by_name pa_context_set_source_volume_by_name_dylibloader_wrapper_pulse
+#define pa_context_set_source_mute_by_index pa_context_set_source_mute_by_index_dylibloader_wrapper_pulse
+#define pa_context_set_source_mute_by_name pa_context_set_source_mute_by_name_dylibloader_wrapper_pulse
+#define pa_context_suspend_source_by_name pa_context_suspend_source_by_name_dylibloader_wrapper_pulse
+#define pa_context_suspend_source_by_index pa_context_suspend_source_by_index_dylibloader_wrapper_pulse
+#define pa_context_set_source_port_by_index pa_context_set_source_port_by_index_dylibloader_wrapper_pulse
+#define pa_context_set_source_port_by_name pa_context_set_source_port_by_name_dylibloader_wrapper_pulse
+#define pa_context_get_server_info pa_context_get_server_info_dylibloader_wrapper_pulse
+#define pa_context_get_module_info pa_context_get_module_info_dylibloader_wrapper_pulse
+#define pa_context_get_module_info_list pa_context_get_module_info_list_dylibloader_wrapper_pulse
+#define pa_context_load_module pa_context_load_module_dylibloader_wrapper_pulse
+#define pa_context_unload_module pa_context_unload_module_dylibloader_wrapper_pulse
+#define pa_context_get_client_info pa_context_get_client_info_dylibloader_wrapper_pulse
+#define pa_context_get_client_info_list pa_context_get_client_info_list_dylibloader_wrapper_pulse
+#define pa_context_kill_client pa_context_kill_client_dylibloader_wrapper_pulse
+#define pa_context_get_card_info_by_index pa_context_get_card_info_by_index_dylibloader_wrapper_pulse
+#define pa_context_get_card_info_by_name pa_context_get_card_info_by_name_dylibloader_wrapper_pulse
+#define pa_context_get_card_info_list pa_context_get_card_info_list_dylibloader_wrapper_pulse
+#define pa_context_set_card_profile_by_index pa_context_set_card_profile_by_index_dylibloader_wrapper_pulse
+#define pa_context_set_card_profile_by_name pa_context_set_card_profile_by_name_dylibloader_wrapper_pulse
+#define pa_context_set_port_latency_offset pa_context_set_port_latency_offset_dylibloader_wrapper_pulse
+#define pa_context_get_sink_input_info pa_context_get_sink_input_info_dylibloader_wrapper_pulse
+#define pa_context_get_sink_input_info_list pa_context_get_sink_input_info_list_dylibloader_wrapper_pulse
+#define pa_context_move_sink_input_by_name pa_context_move_sink_input_by_name_dylibloader_wrapper_pulse
+#define pa_context_move_sink_input_by_index pa_context_move_sink_input_by_index_dylibloader_wrapper_pulse
+#define pa_context_set_sink_input_volume pa_context_set_sink_input_volume_dylibloader_wrapper_pulse
+#define pa_context_set_sink_input_mute pa_context_set_sink_input_mute_dylibloader_wrapper_pulse
+#define pa_context_kill_sink_input pa_context_kill_sink_input_dylibloader_wrapper_pulse
+#define pa_context_get_source_output_info pa_context_get_source_output_info_dylibloader_wrapper_pulse
+#define pa_context_get_source_output_info_list pa_context_get_source_output_info_list_dylibloader_wrapper_pulse
+#define pa_context_move_source_output_by_name pa_context_move_source_output_by_name_dylibloader_wrapper_pulse
+#define pa_context_move_source_output_by_index pa_context_move_source_output_by_index_dylibloader_wrapper_pulse
+#define pa_context_set_source_output_volume pa_context_set_source_output_volume_dylibloader_wrapper_pulse
+#define pa_context_set_source_output_mute pa_context_set_source_output_mute_dylibloader_wrapper_pulse
+#define pa_context_kill_source_output pa_context_kill_source_output_dylibloader_wrapper_pulse
+#define pa_context_stat pa_context_stat_dylibloader_wrapper_pulse
+#define pa_context_get_sample_info_by_name pa_context_get_sample_info_by_name_dylibloader_wrapper_pulse
+#define pa_context_get_sample_info_by_index pa_context_get_sample_info_by_index_dylibloader_wrapper_pulse
+#define pa_context_get_sample_info_list pa_context_get_sample_info_list_dylibloader_wrapper_pulse
+#define pa_context_get_autoload_info_by_name pa_context_get_autoload_info_by_name_dylibloader_wrapper_pulse
+#define pa_context_get_autoload_info_by_index pa_context_get_autoload_info_by_index_dylibloader_wrapper_pulse
+#define pa_context_get_autoload_info_list pa_context_get_autoload_info_list_dylibloader_wrapper_pulse
+#define pa_context_add_autoload pa_context_add_autoload_dylibloader_wrapper_pulse
+#define pa_context_remove_autoload_by_name pa_context_remove_autoload_by_name_dylibloader_wrapper_pulse
+#define pa_context_remove_autoload_by_index pa_context_remove_autoload_by_index_dylibloader_wrapper_pulse
+#define pa_context_subscribe pa_context_subscribe_dylibloader_wrapper_pulse
+#define pa_context_set_subscribe_callback pa_context_set_subscribe_callback_dylibloader_wrapper_pulse
+#define pa_stream_connect_upload pa_stream_connect_upload_dylibloader_wrapper_pulse
+#define pa_stream_finish_upload pa_stream_finish_upload_dylibloader_wrapper_pulse
+#define pa_context_remove_sample pa_context_remove_sample_dylibloader_wrapper_pulse
+#define pa_context_play_sample pa_context_play_sample_dylibloader_wrapper_pulse
+#define pa_context_play_sample_with_proplist pa_context_play_sample_with_proplist_dylibloader_wrapper_pulse
+#define pa_strerror pa_strerror_dylibloader_wrapper_pulse
+#define pa_xmalloc pa_xmalloc_dylibloader_wrapper_pulse
+#define pa_xmalloc0 pa_xmalloc0_dylibloader_wrapper_pulse
+#define pa_xrealloc pa_xrealloc_dylibloader_wrapper_pulse
+#define pa_xfree pa_xfree_dylibloader_wrapper_pulse
+#define pa_xstrdup pa_xstrdup_dylibloader_wrapper_pulse
+#define pa_xstrndup pa_xstrndup_dylibloader_wrapper_pulse
+#define pa_xmemdup pa_xmemdup_dylibloader_wrapper_pulse
+#define pa_utf8_valid pa_utf8_valid_dylibloader_wrapper_pulse
+#define pa_ascii_valid pa_ascii_valid_dylibloader_wrapper_pulse
+#define pa_utf8_filter pa_utf8_filter_dylibloader_wrapper_pulse
+#define pa_ascii_filter pa_ascii_filter_dylibloader_wrapper_pulse
+#define pa_utf8_to_locale pa_utf8_to_locale_dylibloader_wrapper_pulse
+#define pa_locale_to_utf8 pa_locale_to_utf8_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_new pa_threaded_mainloop_new_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_free pa_threaded_mainloop_free_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_start pa_threaded_mainloop_start_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_stop pa_threaded_mainloop_stop_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_lock pa_threaded_mainloop_lock_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_unlock pa_threaded_mainloop_unlock_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_wait pa_threaded_mainloop_wait_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_signal pa_threaded_mainloop_signal_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_accept pa_threaded_mainloop_accept_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_get_retval pa_threaded_mainloop_get_retval_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_get_api pa_threaded_mainloop_get_api_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_in_thread pa_threaded_mainloop_in_thread_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_set_name pa_threaded_mainloop_set_name_dylibloader_wrapper_pulse
+#define pa_threaded_mainloop_once_unlocked pa_threaded_mainloop_once_unlocked_dylibloader_wrapper_pulse
+#define pa_mainloop_new pa_mainloop_new_dylibloader_wrapper_pulse
+#define pa_mainloop_free pa_mainloop_free_dylibloader_wrapper_pulse
+#define pa_mainloop_prepare pa_mainloop_prepare_dylibloader_wrapper_pulse
+#define pa_mainloop_poll pa_mainloop_poll_dylibloader_wrapper_pulse
+#define pa_mainloop_dispatch pa_mainloop_dispatch_dylibloader_wrapper_pulse
+#define pa_mainloop_get_retval pa_mainloop_get_retval_dylibloader_wrapper_pulse
+#define pa_mainloop_iterate pa_mainloop_iterate_dylibloader_wrapper_pulse
+#define pa_mainloop_run pa_mainloop_run_dylibloader_wrapper_pulse
+#define pa_mainloop_get_api pa_mainloop_get_api_dylibloader_wrapper_pulse
+#define pa_mainloop_quit pa_mainloop_quit_dylibloader_wrapper_pulse
+#define pa_mainloop_wakeup pa_mainloop_wakeup_dylibloader_wrapper_pulse
+#define pa_mainloop_set_poll_func pa_mainloop_set_poll_func_dylibloader_wrapper_pulse
+#define pa_signal_init pa_signal_init_dylibloader_wrapper_pulse
+#define pa_signal_done pa_signal_done_dylibloader_wrapper_pulse
+#define pa_signal_new pa_signal_new_dylibloader_wrapper_pulse
+#define pa_signal_free pa_signal_free_dylibloader_wrapper_pulse
+#define pa_signal_set_destroy pa_signal_set_destroy_dylibloader_wrapper_pulse
+#define pa_get_user_name pa_get_user_name_dylibloader_wrapper_pulse
+#define pa_get_host_name pa_get_host_name_dylibloader_wrapper_pulse
+#define pa_get_fqdn pa_get_fqdn_dylibloader_wrapper_pulse
+#define pa_get_home_dir pa_get_home_dir_dylibloader_wrapper_pulse
+#define pa_get_binary_name pa_get_binary_name_dylibloader_wrapper_pulse
+#define pa_path_get_filename pa_path_get_filename_dylibloader_wrapper_pulse
+#define pa_msleep pa_msleep_dylibloader_wrapper_pulse
+#define pa_thread_make_realtime pa_thread_make_realtime_dylibloader_wrapper_pulse
+#define pa_gettimeofday pa_gettimeofday_dylibloader_wrapper_pulse
+#define pa_timeval_diff pa_timeval_diff_dylibloader_wrapper_pulse
+#define pa_timeval_cmp pa_timeval_cmp_dylibloader_wrapper_pulse
+#define pa_timeval_age pa_timeval_age_dylibloader_wrapper_pulse
+#define pa_timeval_add pa_timeval_add_dylibloader_wrapper_pulse
+#define pa_timeval_sub pa_timeval_sub_dylibloader_wrapper_pulse
+#define pa_timeval_store pa_timeval_store_dylibloader_wrapper_pulse
+#define pa_timeval_load pa_timeval_load_dylibloader_wrapper_pulse
+#define pa_rtclock_now pa_rtclock_now_dylibloader_wrapper_pulse
+extern const char* (*pa_get_library_version_dylibloader_wrapper_pulse)( void);
+extern size_t (*pa_bytes_per_second_dylibloader_wrapper_pulse)(const pa_sample_spec*);
+extern size_t (*pa_frame_size_dylibloader_wrapper_pulse)(const pa_sample_spec*);
+extern size_t (*pa_sample_size_dylibloader_wrapper_pulse)(const pa_sample_spec*);
+extern size_t (*pa_sample_size_of_format_dylibloader_wrapper_pulse)( pa_sample_format_t);
+extern pa_usec_t (*pa_bytes_to_usec_dylibloader_wrapper_pulse)( uint64_t,const pa_sample_spec*);
+extern size_t (*pa_usec_to_bytes_dylibloader_wrapper_pulse)( pa_usec_t,const pa_sample_spec*);
+extern pa_sample_spec* (*pa_sample_spec_init_dylibloader_wrapper_pulse)( pa_sample_spec*);
+extern int (*pa_sample_format_valid_dylibloader_wrapper_pulse)( unsigned);
+extern int (*pa_sample_rate_valid_dylibloader_wrapper_pulse)( uint32_t);
+extern int (*pa_channels_valid_dylibloader_wrapper_pulse)( uint8_t);
+extern int (*pa_sample_spec_valid_dylibloader_wrapper_pulse)(const pa_sample_spec*);
+extern int (*pa_sample_spec_equal_dylibloader_wrapper_pulse)(const pa_sample_spec*,const pa_sample_spec*);
+extern const char* (*pa_sample_format_to_string_dylibloader_wrapper_pulse)( pa_sample_format_t);
+extern pa_sample_format_t (*pa_parse_sample_format_dylibloader_wrapper_pulse)(const char*);
+extern char* (*pa_sample_spec_snprint_dylibloader_wrapper_pulse)( char*, size_t,const pa_sample_spec*);
+extern char* (*pa_bytes_snprint_dylibloader_wrapper_pulse)( char*, size_t, unsigned);
+extern int (*pa_sample_format_is_le_dylibloader_wrapper_pulse)( pa_sample_format_t);
+extern int (*pa_sample_format_is_be_dylibloader_wrapper_pulse)( pa_sample_format_t);
+extern int (*pa_direction_valid_dylibloader_wrapper_pulse)( pa_direction_t);
+extern const char* (*pa_direction_to_string_dylibloader_wrapper_pulse)( pa_direction_t);
+extern void (*pa_mainloop_api_once_dylibloader_wrapper_pulse)( pa_mainloop_api*, void*, void*);
+extern pa_proplist* (*pa_proplist_new_dylibloader_wrapper_pulse)( void);
+extern void (*pa_proplist_free_dylibloader_wrapper_pulse)( pa_proplist*);
+extern int (*pa_proplist_key_valid_dylibloader_wrapper_pulse)(const char*);
+extern int (*pa_proplist_sets_dylibloader_wrapper_pulse)( pa_proplist*,const char*,const char*);
+extern int (*pa_proplist_setp_dylibloader_wrapper_pulse)( pa_proplist*,const char*);
+extern int (*pa_proplist_setf_dylibloader_wrapper_pulse)( pa_proplist*,const char*,const char*,...);
+extern int (*pa_proplist_set_dylibloader_wrapper_pulse)( pa_proplist*,const char*,const void*, size_t);
+extern const char* (*pa_proplist_gets_dylibloader_wrapper_pulse)(const pa_proplist*,const char*);
+extern int (*pa_proplist_get_dylibloader_wrapper_pulse)(const pa_proplist*,const char*,const void**, size_t*);
+extern void (*pa_proplist_update_dylibloader_wrapper_pulse)( pa_proplist*, pa_update_mode_t,const pa_proplist*);
+extern int (*pa_proplist_unset_dylibloader_wrapper_pulse)( pa_proplist*,const char*);
+extern int (*pa_proplist_unset_many_dylibloader_wrapper_pulse)( pa_proplist*,const char* []);
+extern const char* (*pa_proplist_iterate_dylibloader_wrapper_pulse)(const pa_proplist*, void**);
+extern char* (*pa_proplist_to_string_dylibloader_wrapper_pulse)(const pa_proplist*);
+extern char* (*pa_proplist_to_string_sep_dylibloader_wrapper_pulse)(const pa_proplist*,const char*);
+extern pa_proplist* (*pa_proplist_from_string_dylibloader_wrapper_pulse)(const char*);
+extern int (*pa_proplist_contains_dylibloader_wrapper_pulse)(const pa_proplist*,const char*);
+extern void (*pa_proplist_clear_dylibloader_wrapper_pulse)( pa_proplist*);
+extern pa_proplist* (*pa_proplist_copy_dylibloader_wrapper_pulse)(const pa_proplist*);
+extern unsigned (*pa_proplist_size_dylibloader_wrapper_pulse)(const pa_proplist*);
+extern int (*pa_proplist_isempty_dylibloader_wrapper_pulse)(const pa_proplist*);
+extern int (*pa_proplist_equal_dylibloader_wrapper_pulse)(const pa_proplist*,const pa_proplist*);
+extern pa_channel_map* (*pa_channel_map_init_dylibloader_wrapper_pulse)( pa_channel_map*);
+extern pa_channel_map* (*pa_channel_map_init_mono_dylibloader_wrapper_pulse)( pa_channel_map*);
+extern pa_channel_map* (*pa_channel_map_init_stereo_dylibloader_wrapper_pulse)( pa_channel_map*);
+extern pa_channel_map* (*pa_channel_map_init_auto_dylibloader_wrapper_pulse)( pa_channel_map*, unsigned, pa_channel_map_def_t);
+extern pa_channel_map* (*pa_channel_map_init_extend_dylibloader_wrapper_pulse)( pa_channel_map*, unsigned, pa_channel_map_def_t);
+extern const char* (*pa_channel_position_to_string_dylibloader_wrapper_pulse)( pa_channel_position_t);
+extern pa_channel_position_t (*pa_channel_position_from_string_dylibloader_wrapper_pulse)(const char*);
+extern const char* (*pa_channel_position_to_pretty_string_dylibloader_wrapper_pulse)( pa_channel_position_t);
+extern char* (*pa_channel_map_snprint_dylibloader_wrapper_pulse)( char*, size_t,const pa_channel_map*);
+extern pa_channel_map* (*pa_channel_map_parse_dylibloader_wrapper_pulse)( pa_channel_map*,const char*);
+extern int (*pa_channel_map_equal_dylibloader_wrapper_pulse)(const pa_channel_map*,const pa_channel_map*);
+extern int (*pa_channel_map_valid_dylibloader_wrapper_pulse)(const pa_channel_map*);
+extern int (*pa_channel_map_compatible_dylibloader_wrapper_pulse)(const pa_channel_map*,const pa_sample_spec*);
+extern int (*pa_channel_map_superset_dylibloader_wrapper_pulse)(const pa_channel_map*,const pa_channel_map*);
+extern int (*pa_channel_map_can_balance_dylibloader_wrapper_pulse)(const pa_channel_map*);
+extern int (*pa_channel_map_can_fade_dylibloader_wrapper_pulse)(const pa_channel_map*);
+extern int (*pa_channel_map_can_lfe_balance_dylibloader_wrapper_pulse)(const pa_channel_map*);
+extern const char* (*pa_channel_map_to_name_dylibloader_wrapper_pulse)(const pa_channel_map*);
+extern const char* (*pa_channel_map_to_pretty_name_dylibloader_wrapper_pulse)(const pa_channel_map*);
+extern int (*pa_channel_map_has_position_dylibloader_wrapper_pulse)(const pa_channel_map*, pa_channel_position_t);
+extern pa_channel_position_mask_t (*pa_channel_map_mask_dylibloader_wrapper_pulse)(const pa_channel_map*);
+extern const char* (*pa_encoding_to_string_dylibloader_wrapper_pulse)( pa_encoding_t);
+extern pa_encoding_t (*pa_encoding_from_string_dylibloader_wrapper_pulse)(const char*);
+extern pa_format_info* (*pa_format_info_new_dylibloader_wrapper_pulse)( void);
+extern pa_format_info* (*pa_format_info_copy_dylibloader_wrapper_pulse)(const pa_format_info*);
+extern void (*pa_format_info_free_dylibloader_wrapper_pulse)( pa_format_info*);
+extern int (*pa_format_info_valid_dylibloader_wrapper_pulse)(const pa_format_info*);
+extern int (*pa_format_info_is_pcm_dylibloader_wrapper_pulse)(const pa_format_info*);
+extern int (*pa_format_info_is_compatible_dylibloader_wrapper_pulse)(const pa_format_info*,const pa_format_info*);
+extern char* (*pa_format_info_snprint_dylibloader_wrapper_pulse)( char*, size_t,const pa_format_info*);
+extern pa_format_info* (*pa_format_info_from_string_dylibloader_wrapper_pulse)(const char*);
+extern pa_format_info* (*pa_format_info_from_sample_spec_dylibloader_wrapper_pulse)(const pa_sample_spec*,const pa_channel_map*);
+extern int (*pa_format_info_to_sample_spec_dylibloader_wrapper_pulse)(const pa_format_info*, pa_sample_spec*, pa_channel_map*);
+extern pa_prop_type_t (*pa_format_info_get_prop_type_dylibloader_wrapper_pulse)(const pa_format_info*,const char*);
+extern int (*pa_format_info_get_prop_int_dylibloader_wrapper_pulse)(const pa_format_info*,const char*, int*);
+extern int (*pa_format_info_get_prop_int_range_dylibloader_wrapper_pulse)(const pa_format_info*,const char*, int*, int*);
+extern int (*pa_format_info_get_prop_int_array_dylibloader_wrapper_pulse)(const pa_format_info*,const char*, int**, int*);
+extern int (*pa_format_info_get_prop_string_dylibloader_wrapper_pulse)(const pa_format_info*,const char*, char**);
+extern int (*pa_format_info_get_prop_string_array_dylibloader_wrapper_pulse)(const pa_format_info*,const char*, char***, int*);
+extern void (*pa_format_info_free_string_array_dylibloader_wrapper_pulse)( char**, int);
+extern int (*pa_format_info_get_sample_format_dylibloader_wrapper_pulse)(const pa_format_info*, pa_sample_format_t*);
+extern int (*pa_format_info_get_rate_dylibloader_wrapper_pulse)(const pa_format_info*, uint32_t*);
+extern int (*pa_format_info_get_channels_dylibloader_wrapper_pulse)(const pa_format_info*, uint8_t*);
+extern int (*pa_format_info_get_channel_map_dylibloader_wrapper_pulse)(const pa_format_info*, pa_channel_map*);
+extern void (*pa_format_info_set_prop_int_dylibloader_wrapper_pulse)( pa_format_info*,const char*, int);
+extern void (*pa_format_info_set_prop_int_array_dylibloader_wrapper_pulse)( pa_format_info*,const char*,const int*, int);
+extern void (*pa_format_info_set_prop_int_range_dylibloader_wrapper_pulse)( pa_format_info*,const char*, int, int);
+extern void (*pa_format_info_set_prop_string_dylibloader_wrapper_pulse)( pa_format_info*,const char*,const char*);
+extern void (*pa_format_info_set_prop_string_array_dylibloader_wrapper_pulse)( pa_format_info*,const char*,const char**, int);
+extern void (*pa_format_info_set_sample_format_dylibloader_wrapper_pulse)( pa_format_info*, pa_sample_format_t);
+extern void (*pa_format_info_set_rate_dylibloader_wrapper_pulse)( pa_format_info*, int);
+extern void (*pa_format_info_set_channels_dylibloader_wrapper_pulse)( pa_format_info*, int);
+extern void (*pa_format_info_set_channel_map_dylibloader_wrapper_pulse)( pa_format_info*,const pa_channel_map*);
+extern pa_operation* (*pa_operation_ref_dylibloader_wrapper_pulse)( pa_operation*);
+extern void (*pa_operation_unref_dylibloader_wrapper_pulse)( pa_operation*);
+extern void (*pa_operation_cancel_dylibloader_wrapper_pulse)( pa_operation*);
+extern pa_operation_state_t (*pa_operation_get_state_dylibloader_wrapper_pulse)(const pa_operation*);
+extern void (*pa_operation_set_state_callback_dylibloader_wrapper_pulse)( pa_operation*, pa_operation_notify_cb_t, void*);
+extern pa_context* (*pa_context_new_dylibloader_wrapper_pulse)( pa_mainloop_api*,const char*);
+extern pa_context* (*pa_context_new_with_proplist_dylibloader_wrapper_pulse)( pa_mainloop_api*,const char*,const pa_proplist*);
+extern void (*pa_context_unref_dylibloader_wrapper_pulse)( pa_context*);
+extern pa_context* (*pa_context_ref_dylibloader_wrapper_pulse)( pa_context*);
+extern void (*pa_context_set_state_callback_dylibloader_wrapper_pulse)( pa_context*, pa_context_notify_cb_t, void*);
+extern void (*pa_context_set_event_callback_dylibloader_wrapper_pulse)( pa_context*, pa_context_event_cb_t, void*);
+extern int (*pa_context_errno_dylibloader_wrapper_pulse)(const pa_context*);
+extern int (*pa_context_is_pending_dylibloader_wrapper_pulse)(const pa_context*);
+extern pa_context_state_t (*pa_context_get_state_dylibloader_wrapper_pulse)(const pa_context*);
+extern int (*pa_context_connect_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_context_flags_t,const pa_spawn_api*);
+extern void (*pa_context_disconnect_dylibloader_wrapper_pulse)( pa_context*);
+extern pa_operation* (*pa_context_drain_dylibloader_wrapper_pulse)( pa_context*, pa_context_notify_cb_t, void*);
+extern pa_operation* (*pa_context_exit_daemon_dylibloader_wrapper_pulse)( pa_context*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_default_sink_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_default_source_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_context_success_cb_t, void*);
+extern int (*pa_context_is_local_dylibloader_wrapper_pulse)(const pa_context*);
+extern pa_operation* (*pa_context_set_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_context_success_cb_t, void*);
+extern const char* (*pa_context_get_server_dylibloader_wrapper_pulse)(const pa_context*);
+extern uint32_t (*pa_context_get_protocol_version_dylibloader_wrapper_pulse)(const pa_context*);
+extern uint32_t (*pa_context_get_server_protocol_version_dylibloader_wrapper_pulse)(const pa_context*);
+extern pa_operation* (*pa_context_proplist_update_dylibloader_wrapper_pulse)( pa_context*, pa_update_mode_t,const pa_proplist*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_proplist_remove_dylibloader_wrapper_pulse)( pa_context*,const char* [], pa_context_success_cb_t, void*);
+extern uint32_t (*pa_context_get_index_dylibloader_wrapper_pulse)(const pa_context*);
+extern pa_time_event* (*pa_context_rttime_new_dylibloader_wrapper_pulse)(const pa_context*, pa_usec_t, pa_time_event_cb_t, void*);
+extern void (*pa_context_rttime_restart_dylibloader_wrapper_pulse)(const pa_context*, pa_time_event*, pa_usec_t);
+extern size_t (*pa_context_get_tile_size_dylibloader_wrapper_pulse)(const pa_context*,const pa_sample_spec*);
+extern int (*pa_context_load_cookie_from_file_dylibloader_wrapper_pulse)( pa_context*,const char*);
+extern int (*pa_cvolume_equal_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_cvolume*);
+extern pa_cvolume* (*pa_cvolume_init_dylibloader_wrapper_pulse)( pa_cvolume*);
+extern pa_cvolume* (*pa_cvolume_set_dylibloader_wrapper_pulse)( pa_cvolume*, unsigned, pa_volume_t);
+extern char* (*pa_cvolume_snprint_dylibloader_wrapper_pulse)( char*, size_t,const pa_cvolume*);
+extern char* (*pa_sw_cvolume_snprint_dB_dylibloader_wrapper_pulse)( char*, size_t,const pa_cvolume*);
+extern char* (*pa_cvolume_snprint_verbose_dylibloader_wrapper_pulse)( char*, size_t,const pa_cvolume*,const pa_channel_map*, int);
+extern char* (*pa_volume_snprint_dylibloader_wrapper_pulse)( char*, size_t, pa_volume_t);
+extern char* (*pa_sw_volume_snprint_dB_dylibloader_wrapper_pulse)( char*, size_t, pa_volume_t);
+extern char* (*pa_volume_snprint_verbose_dylibloader_wrapper_pulse)( char*, size_t, pa_volume_t, int);
+extern pa_volume_t (*pa_cvolume_avg_dylibloader_wrapper_pulse)(const pa_cvolume*);
+extern pa_volume_t (*pa_cvolume_avg_mask_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*, pa_channel_position_mask_t);
+extern pa_volume_t (*pa_cvolume_max_dylibloader_wrapper_pulse)(const pa_cvolume*);
+extern pa_volume_t (*pa_cvolume_max_mask_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*, pa_channel_position_mask_t);
+extern pa_volume_t (*pa_cvolume_min_dylibloader_wrapper_pulse)(const pa_cvolume*);
+extern pa_volume_t (*pa_cvolume_min_mask_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*, pa_channel_position_mask_t);
+extern int (*pa_cvolume_valid_dylibloader_wrapper_pulse)(const pa_cvolume*);
+extern int (*pa_cvolume_channels_equal_to_dylibloader_wrapper_pulse)(const pa_cvolume*, pa_volume_t);
+extern pa_volume_t (*pa_sw_volume_multiply_dylibloader_wrapper_pulse)( pa_volume_t, pa_volume_t);
+extern pa_cvolume* (*pa_sw_cvolume_multiply_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_cvolume*,const pa_cvolume*);
+extern pa_cvolume* (*pa_sw_cvolume_multiply_scalar_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_cvolume*, pa_volume_t);
+extern pa_volume_t (*pa_sw_volume_divide_dylibloader_wrapper_pulse)( pa_volume_t, pa_volume_t);
+extern pa_cvolume* (*pa_sw_cvolume_divide_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_cvolume*,const pa_cvolume*);
+extern pa_cvolume* (*pa_sw_cvolume_divide_scalar_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_cvolume*, pa_volume_t);
+extern pa_volume_t (*pa_sw_volume_from_dB_dylibloader_wrapper_pulse)( double);
+extern double (*pa_sw_volume_to_dB_dylibloader_wrapper_pulse)( pa_volume_t);
+extern pa_volume_t (*pa_sw_volume_from_linear_dylibloader_wrapper_pulse)( double);
+extern double (*pa_sw_volume_to_linear_dylibloader_wrapper_pulse)( pa_volume_t);
+extern pa_cvolume* (*pa_cvolume_remap_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_channel_map*,const pa_channel_map*);
+extern int (*pa_cvolume_compatible_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_sample_spec*);
+extern int (*pa_cvolume_compatible_with_channel_map_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*);
+extern float (*pa_cvolume_get_balance_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*);
+extern pa_cvolume* (*pa_cvolume_set_balance_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_channel_map*, float);
+extern float (*pa_cvolume_get_fade_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*);
+extern pa_cvolume* (*pa_cvolume_set_fade_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_channel_map*, float);
+extern float (*pa_cvolume_get_lfe_balance_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*);
+extern pa_cvolume* (*pa_cvolume_set_lfe_balance_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_channel_map*, float);
+extern pa_cvolume* (*pa_cvolume_scale_dylibloader_wrapper_pulse)( pa_cvolume*, pa_volume_t);
+extern pa_cvolume* (*pa_cvolume_scale_mask_dylibloader_wrapper_pulse)( pa_cvolume*, pa_volume_t,const pa_channel_map*, pa_channel_position_mask_t);
+extern pa_cvolume* (*pa_cvolume_set_position_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_channel_map*, pa_channel_position_t, pa_volume_t);
+extern pa_volume_t (*pa_cvolume_get_position_dylibloader_wrapper_pulse)(const pa_cvolume*,const pa_channel_map*, pa_channel_position_t);
+extern pa_cvolume* (*pa_cvolume_merge_dylibloader_wrapper_pulse)( pa_cvolume*,const pa_cvolume*,const pa_cvolume*);
+extern pa_cvolume* (*pa_cvolume_inc_clamp_dylibloader_wrapper_pulse)( pa_cvolume*, pa_volume_t, pa_volume_t);
+extern pa_cvolume* (*pa_cvolume_inc_dylibloader_wrapper_pulse)( pa_cvolume*, pa_volume_t);
+extern pa_cvolume* (*pa_cvolume_dec_dylibloader_wrapper_pulse)( pa_cvolume*, pa_volume_t);
+extern pa_stream* (*pa_stream_new_dylibloader_wrapper_pulse)( pa_context*,const char*,const pa_sample_spec*,const pa_channel_map*);
+extern pa_stream* (*pa_stream_new_with_proplist_dylibloader_wrapper_pulse)( pa_context*,const char*,const pa_sample_spec*,const pa_channel_map*, pa_proplist*);
+extern pa_stream* (*pa_stream_new_extended_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_format_info**, unsigned int, pa_proplist*);
+extern void (*pa_stream_unref_dylibloader_wrapper_pulse)( pa_stream*);
+extern pa_stream* (*pa_stream_ref_dylibloader_wrapper_pulse)( pa_stream*);
+extern pa_stream_state_t (*pa_stream_get_state_dylibloader_wrapper_pulse)(const pa_stream*);
+extern pa_context* (*pa_stream_get_context_dylibloader_wrapper_pulse)(const pa_stream*);
+extern uint32_t (*pa_stream_get_index_dylibloader_wrapper_pulse)(const pa_stream*);
+extern uint32_t (*pa_stream_get_device_index_dylibloader_wrapper_pulse)(const pa_stream*);
+extern const char* (*pa_stream_get_device_name_dylibloader_wrapper_pulse)(const pa_stream*);
+extern int (*pa_stream_is_suspended_dylibloader_wrapper_pulse)(const pa_stream*);
+extern int (*pa_stream_is_corked_dylibloader_wrapper_pulse)(const pa_stream*);
+extern int (*pa_stream_connect_playback_dylibloader_wrapper_pulse)( pa_stream*,const char*,const pa_buffer_attr*, pa_stream_flags_t,const pa_cvolume*, pa_stream*);
+extern int (*pa_stream_connect_record_dylibloader_wrapper_pulse)( pa_stream*,const char*,const pa_buffer_attr*, pa_stream_flags_t);
+extern int (*pa_stream_disconnect_dylibloader_wrapper_pulse)( pa_stream*);
+extern int (*pa_stream_begin_write_dylibloader_wrapper_pulse)( pa_stream*, void**, size_t*);
+extern int (*pa_stream_cancel_write_dylibloader_wrapper_pulse)( pa_stream*);
+extern int (*pa_stream_write_dylibloader_wrapper_pulse)( pa_stream*,const void*, size_t, pa_free_cb_t, int64_t, pa_seek_mode_t);
+extern int (*pa_stream_write_ext_free_dylibloader_wrapper_pulse)( pa_stream*,const void*, size_t, pa_free_cb_t, void*, int64_t, pa_seek_mode_t);
+extern int (*pa_stream_peek_dylibloader_wrapper_pulse)( pa_stream*,const void**, size_t*);
+extern int (*pa_stream_drop_dylibloader_wrapper_pulse)( pa_stream*);
+extern size_t (*pa_stream_writable_size_dylibloader_wrapper_pulse)(const pa_stream*);
+extern size_t (*pa_stream_readable_size_dylibloader_wrapper_pulse)(const pa_stream*);
+extern pa_operation* (*pa_stream_drain_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_success_cb_t, void*);
+extern pa_operation* (*pa_stream_update_timing_info_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_success_cb_t, void*);
+extern void (*pa_stream_set_state_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+extern void (*pa_stream_set_write_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_request_cb_t, void*);
+extern void (*pa_stream_set_read_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_request_cb_t, void*);
+extern void (*pa_stream_set_overflow_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+extern int64_t (*pa_stream_get_underflow_index_dylibloader_wrapper_pulse)(const pa_stream*);
+extern void (*pa_stream_set_underflow_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+extern void (*pa_stream_set_started_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+extern void (*pa_stream_set_latency_update_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+extern void (*pa_stream_set_moved_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+extern void (*pa_stream_set_suspended_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+extern void (*pa_stream_set_event_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_event_cb_t, void*);
+extern void (*pa_stream_set_buffer_attr_callback_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_notify_cb_t, void*);
+extern pa_operation* (*pa_stream_cork_dylibloader_wrapper_pulse)( pa_stream*, int, pa_stream_success_cb_t, void*);
+extern pa_operation* (*pa_stream_flush_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_success_cb_t, void*);
+extern pa_operation* (*pa_stream_prebuf_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_success_cb_t, void*);
+extern pa_operation* (*pa_stream_trigger_dylibloader_wrapper_pulse)( pa_stream*, pa_stream_success_cb_t, void*);
+extern pa_operation* (*pa_stream_set_name_dylibloader_wrapper_pulse)( pa_stream*,const char*, pa_stream_success_cb_t, void*);
+extern int (*pa_stream_get_time_dylibloader_wrapper_pulse)( pa_stream*, pa_usec_t*);
+extern int (*pa_stream_get_latency_dylibloader_wrapper_pulse)( pa_stream*, pa_usec_t*, int*);
+extern const pa_timing_info* (*pa_stream_get_timing_info_dylibloader_wrapper_pulse)( pa_stream*);
+extern const pa_sample_spec* (*pa_stream_get_sample_spec_dylibloader_wrapper_pulse)( pa_stream*);
+extern const pa_channel_map* (*pa_stream_get_channel_map_dylibloader_wrapper_pulse)( pa_stream*);
+extern const pa_format_info* (*pa_stream_get_format_info_dylibloader_wrapper_pulse)(const pa_stream*);
+extern const pa_buffer_attr* (*pa_stream_get_buffer_attr_dylibloader_wrapper_pulse)( pa_stream*);
+extern pa_operation* (*pa_stream_set_buffer_attr_dylibloader_wrapper_pulse)( pa_stream*,const pa_buffer_attr*, pa_stream_success_cb_t, void*);
+extern pa_operation* (*pa_stream_update_sample_rate_dylibloader_wrapper_pulse)( pa_stream*, uint32_t, pa_stream_success_cb_t, void*);
+extern pa_operation* (*pa_stream_proplist_update_dylibloader_wrapper_pulse)( pa_stream*, pa_update_mode_t, pa_proplist*, pa_stream_success_cb_t, void*);
+extern pa_operation* (*pa_stream_proplist_remove_dylibloader_wrapper_pulse)( pa_stream*,const char* [], pa_stream_success_cb_t, void*);
+extern int (*pa_stream_set_monitor_stream_dylibloader_wrapper_pulse)( pa_stream*, uint32_t);
+extern uint32_t (*pa_stream_get_monitor_stream_dylibloader_wrapper_pulse)(const pa_stream*);
+extern pa_operation* (*pa_context_get_sink_info_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_sink_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_sink_info_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_sink_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_sink_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_sink_info_cb_t, void*);
+extern pa_operation* (*pa_context_set_sink_volume_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const pa_cvolume*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_sink_volume_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*,const pa_cvolume*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_sink_mute_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_sink_mute_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, int, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_suspend_sink_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, int, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_suspend_sink_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_sink_port_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const char*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_sink_port_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_get_source_info_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_source_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_source_info_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_source_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_source_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_source_info_cb_t, void*);
+extern pa_operation* (*pa_context_set_source_volume_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const pa_cvolume*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_source_volume_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*,const pa_cvolume*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_source_mute_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_source_mute_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, int, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_suspend_source_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, int, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_suspend_source_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_source_port_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const char*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_source_port_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_get_server_info_dylibloader_wrapper_pulse)( pa_context*, pa_server_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_module_info_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_module_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_module_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_module_info_cb_t, void*);
+extern pa_operation* (*pa_context_load_module_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_context_index_cb_t, void*);
+extern pa_operation* (*pa_context_unload_module_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_get_client_info_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_client_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_client_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_client_info_cb_t, void*);
+extern pa_operation* (*pa_context_kill_client_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_get_card_info_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_card_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_card_info_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_card_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_card_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_card_info_cb_t, void*);
+extern pa_operation* (*pa_context_set_card_profile_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const char*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_card_profile_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_port_latency_offset_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, int64_t, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_get_sink_input_info_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_sink_input_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_sink_input_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_sink_input_info_cb_t, void*);
+extern pa_operation* (*pa_context_move_sink_input_by_name_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const char*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_move_sink_input_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, uint32_t, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_sink_input_volume_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const pa_cvolume*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_sink_input_mute_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_kill_sink_input_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_get_source_output_info_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_source_output_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_source_output_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_source_output_info_cb_t, void*);
+extern pa_operation* (*pa_context_move_source_output_by_name_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const char*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_move_source_output_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, uint32_t, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_source_output_volume_dylibloader_wrapper_pulse)( pa_context*, uint32_t,const pa_cvolume*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_set_source_output_mute_dylibloader_wrapper_pulse)( pa_context*, uint32_t, int, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_kill_source_output_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_stat_dylibloader_wrapper_pulse)( pa_context*, pa_stat_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_sample_info_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_sample_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_sample_info_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_sample_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_sample_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_sample_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_autoload_info_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_autoload_type_t, pa_autoload_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_autoload_info_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_autoload_info_cb_t, void*);
+extern pa_operation* (*pa_context_get_autoload_info_list_dylibloader_wrapper_pulse)( pa_context*, pa_autoload_info_cb_t, void*);
+extern pa_operation* (*pa_context_add_autoload_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_autoload_type_t,const char*,const char*, pa_context_index_cb_t, void*);
+extern pa_operation* (*pa_context_remove_autoload_by_name_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_autoload_type_t, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_remove_autoload_by_index_dylibloader_wrapper_pulse)( pa_context*, uint32_t, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_subscribe_dylibloader_wrapper_pulse)( pa_context*, pa_subscription_mask_t, pa_context_success_cb_t, void*);
+extern void (*pa_context_set_subscribe_callback_dylibloader_wrapper_pulse)( pa_context*, pa_context_subscribe_cb_t, void*);
+extern int (*pa_stream_connect_upload_dylibloader_wrapper_pulse)( pa_stream*, size_t);
+extern int (*pa_stream_finish_upload_dylibloader_wrapper_pulse)( pa_stream*);
+extern pa_operation* (*pa_context_remove_sample_dylibloader_wrapper_pulse)( pa_context*,const char*, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_play_sample_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_volume_t, pa_context_success_cb_t, void*);
+extern pa_operation* (*pa_context_play_sample_with_proplist_dylibloader_wrapper_pulse)( pa_context*,const char*,const char*, pa_volume_t,const pa_proplist*, pa_context_play_sample_cb_t, void*);
+extern const char* (*pa_strerror_dylibloader_wrapper_pulse)( int);
+extern void* (*pa_xmalloc_dylibloader_wrapper_pulse)( size_t);
+extern void* (*pa_xmalloc0_dylibloader_wrapper_pulse)( size_t);
+extern void* (*pa_xrealloc_dylibloader_wrapper_pulse)( void*, size_t);
+extern void (*pa_xfree_dylibloader_wrapper_pulse)( void*);
+extern char* (*pa_xstrdup_dylibloader_wrapper_pulse)(const char*);
+extern char* (*pa_xstrndup_dylibloader_wrapper_pulse)(const char*, size_t);
+extern void* (*pa_xmemdup_dylibloader_wrapper_pulse)(const void*, size_t);
+extern char* (*pa_utf8_valid_dylibloader_wrapper_pulse)(const char*);
+extern char* (*pa_ascii_valid_dylibloader_wrapper_pulse)(const char*);
+extern char* (*pa_utf8_filter_dylibloader_wrapper_pulse)(const char*);
+extern char* (*pa_ascii_filter_dylibloader_wrapper_pulse)(const char*);
+extern char* (*pa_utf8_to_locale_dylibloader_wrapper_pulse)(const char*);
+extern char* (*pa_locale_to_utf8_dylibloader_wrapper_pulse)(const char*);
+extern pa_threaded_mainloop* (*pa_threaded_mainloop_new_dylibloader_wrapper_pulse)( void);
+extern void (*pa_threaded_mainloop_free_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+extern int (*pa_threaded_mainloop_start_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+extern void (*pa_threaded_mainloop_stop_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+extern void (*pa_threaded_mainloop_lock_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+extern void (*pa_threaded_mainloop_unlock_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+extern void (*pa_threaded_mainloop_wait_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+extern void (*pa_threaded_mainloop_signal_dylibloader_wrapper_pulse)( pa_threaded_mainloop*, int);
+extern void (*pa_threaded_mainloop_accept_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+extern int (*pa_threaded_mainloop_get_retval_dylibloader_wrapper_pulse)(const pa_threaded_mainloop*);
+extern pa_mainloop_api* (*pa_threaded_mainloop_get_api_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+extern int (*pa_threaded_mainloop_in_thread_dylibloader_wrapper_pulse)( pa_threaded_mainloop*);
+extern void (*pa_threaded_mainloop_set_name_dylibloader_wrapper_pulse)( pa_threaded_mainloop*,const char*);
+extern void (*pa_threaded_mainloop_once_unlocked_dylibloader_wrapper_pulse)( pa_threaded_mainloop*, void*, void*);
+extern pa_mainloop* (*pa_mainloop_new_dylibloader_wrapper_pulse)( void);
+extern void (*pa_mainloop_free_dylibloader_wrapper_pulse)( pa_mainloop*);
+extern int (*pa_mainloop_prepare_dylibloader_wrapper_pulse)( pa_mainloop*, int);
+extern int (*pa_mainloop_poll_dylibloader_wrapper_pulse)( pa_mainloop*);
+extern int (*pa_mainloop_dispatch_dylibloader_wrapper_pulse)( pa_mainloop*);
+extern int (*pa_mainloop_get_retval_dylibloader_wrapper_pulse)(const pa_mainloop*);
+extern int (*pa_mainloop_iterate_dylibloader_wrapper_pulse)( pa_mainloop*, int, int*);
+extern int (*pa_mainloop_run_dylibloader_wrapper_pulse)( pa_mainloop*, int*);
+extern pa_mainloop_api* (*pa_mainloop_get_api_dylibloader_wrapper_pulse)( pa_mainloop*);
+extern void (*pa_mainloop_quit_dylibloader_wrapper_pulse)( pa_mainloop*, int);
+extern void (*pa_mainloop_wakeup_dylibloader_wrapper_pulse)( pa_mainloop*);
+extern void (*pa_mainloop_set_poll_func_dylibloader_wrapper_pulse)( pa_mainloop*, pa_poll_func, void*);
+extern int (*pa_signal_init_dylibloader_wrapper_pulse)( pa_mainloop_api*);
+extern void (*pa_signal_done_dylibloader_wrapper_pulse)( void);
+extern pa_signal_event* (*pa_signal_new_dylibloader_wrapper_pulse)( int, pa_signal_cb_t, void*);
+extern void (*pa_signal_free_dylibloader_wrapper_pulse)( pa_signal_event*);
+extern void (*pa_signal_set_destroy_dylibloader_wrapper_pulse)( pa_signal_event*, pa_signal_destroy_cb_t);
+extern char* (*pa_get_user_name_dylibloader_wrapper_pulse)( char*, size_t);
+extern char* (*pa_get_host_name_dylibloader_wrapper_pulse)( char*, size_t);
+extern char* (*pa_get_fqdn_dylibloader_wrapper_pulse)( char*, size_t);
+extern char* (*pa_get_home_dir_dylibloader_wrapper_pulse)( char*, size_t);
+extern char* (*pa_get_binary_name_dylibloader_wrapper_pulse)( char*, size_t);
+extern char* (*pa_path_get_filename_dylibloader_wrapper_pulse)(const char*);
+extern int (*pa_msleep_dylibloader_wrapper_pulse)( unsigned long);
+extern int (*pa_thread_make_realtime_dylibloader_wrapper_pulse)( int);
+extern struct timeval* (*pa_gettimeofday_dylibloader_wrapper_pulse)(struct timeval*);
+extern pa_usec_t (*pa_timeval_diff_dylibloader_wrapper_pulse)(struct timeval*,struct timeval*);
+extern int (*pa_timeval_cmp_dylibloader_wrapper_pulse)(struct timeval*,struct timeval*);
+extern pa_usec_t (*pa_timeval_age_dylibloader_wrapper_pulse)(struct timeval*);
+extern struct timeval* (*pa_timeval_add_dylibloader_wrapper_pulse)(struct timeval*, pa_usec_t);
+extern struct timeval* (*pa_timeval_sub_dylibloader_wrapper_pulse)(struct timeval*, pa_usec_t);
+extern struct timeval* (*pa_timeval_store_dylibloader_wrapper_pulse)(struct timeval*, pa_usec_t);
+extern pa_usec_t (*pa_timeval_load_dylibloader_wrapper_pulse)(struct timeval*);
+extern pa_usec_t (*pa_rtclock_now_dylibloader_wrapper_pulse)( void);
+int initialize_pulse(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 6b24a85ff6..4c08380dd0 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -240,6 +240,8 @@ uint8_t FileAccessUnix::get_8() const {
}
int FileAccessUnix::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
int read = fread(p_dst, 1, p_length, f);
check_errors();
diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp
index 19fab1d475..e47046e3ae 100644
--- a/drivers/unix/thread_posix.cpp
+++ b/drivers/unix/thread_posix.cpp
@@ -35,6 +35,10 @@
#include "core/os/thread.h"
#include "core/string/ustring.h"
+#ifdef PTHREAD_BSD_SET_NAME
+#include <pthread_np.h>
+#endif
+
static Error set_name(const String &p_name) {
#ifdef PTHREAD_NO_RENAME
return ERR_UNAVAILABLE;
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index ef331ec4b6..469d80368d 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -74,11 +74,13 @@ RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID
} else if (texture_buffer_owner.owns(p_buffer)) {
if (p_post_barrier & 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) {
r_stage_mask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ r_access_mask |= VK_ACCESS_SHADER_READ_BIT;
}
- r_access_mask |= VK_ACCESS_SHADER_READ_BIT;
+
buffer = &texture_buffer_owner.getornull(p_buffer)->buffer;
} else if (storage_buffer_owner.owns(p_buffer)) {
buffer = storage_buffer_owner.getornull(p_buffer);
@@ -117,7 +119,7 @@ static void update_external_dependency_for_store(VkSubpassDependency &dependency
}
if (is_depth) {
- // Depth resources have addtional stages that may be interested in them
+ // Depth resources have additional stages that may be interested in them
dependency.dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
dependency.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
}
@@ -1627,6 +1629,9 @@ void RenderingDeviceVulkan::_memory_barrier(VkPipelineStageFlags p_src_stage_mas
mem_barrier.srcAccessMask = p_src_access;
mem_barrier.dstAccessMask = p_dst_sccess;
+ if (p_src_stage_mask == 0 || p_dst_stage_mask == 0) {
+ return; //no barrier, since this is invalid
+ }
vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, p_src_stage_mask, p_dst_stage_mask, 0, 1, &mem_barrier, 0, nullptr, 0, nullptr);
}
@@ -2477,6 +2482,10 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
}
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -2496,6 +2505,13 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con
vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
+ if (texture->used_in_frame != frames_drawn) {
+ texture->used_in_raster = false;
+ texture->used_in_compute = false;
+ texture->used_in_frame = frames_drawn;
+ }
+ texture->used_in_transfer = true;
+
return OK;
}
@@ -2844,6 +2860,10 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
}
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
{ //restore src
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
@@ -3011,6 +3031,10 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
}
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
{ //restore src
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
@@ -3084,7 +3108,7 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
VkImageLayout clear_layout = (src_tex->layout == VK_IMAGE_LAYOUT_GENERAL) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- // NOTE: Perhaps the valid stages/accesses for a given onwner should be a property of the owner. (Here and places like _get_buffer_from_owner)
+ // NOTE: Perhaps the valid stages/accesses for a given owner should be a property of the owner. (Here and places like _get_buffer_from_owner)
const VkPipelineStageFlags valid_texture_stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
constexpr VkAccessFlags read_access = VK_ACCESS_SHADER_READ_BIT;
constexpr VkAccessFlags read_write_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
@@ -3143,6 +3167,10 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
}
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -3163,6 +3191,13 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
+ if (src_tex->used_in_frame != frames_drawn) {
+ src_tex->used_in_raster = false;
+ src_tex->used_in_compute = false;
+ src_tex->used_in_frame = frames_drawn;
+ }
+ src_tex->used_in_transfer = true;
+
return OK;
}
@@ -3215,7 +3250,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
Vector<VkAttachmentReference> depth_stencil_references;
Vector<VkAttachmentReference> resolve_references;
- // Set up a dependencies from/to external equivalent to the default (implicit) one, and then amend them
+ // Set up dependencies from/to external equivalent to the default (implicit) one, and then amend them
const VkPipelineStageFlags default_access_mask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
@@ -3244,7 +3279,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
bool is_storage = p_format[i].usage_flags & TEXTURE_USAGE_STORAGE_BIT;
// For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write
- // Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution syncronization vs.
+ // Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs.
// the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that
// stage
switch (is_depth_stencil ? p_initial_depth_action : p_initial_color_action) {
@@ -3289,6 +3324,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
dependency_from_external.srcStageMask |= reading_stages;
}
} break;
+ case INITIAL_ACTION_CLEAR_REGION_CONTINUE:
case INITIAL_ACTION_CONTINUE: {
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
@@ -3296,7 +3332,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; //don't care what is there
+ description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@@ -3388,12 +3424,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
// NOTE: Big Mallet Approach -- any layout transition causes a full barrier
if (reference.layout != description.initialLayout) {
- // NOTE: this should be smarter based on the textures knowledge of it's previous role
+ // NOTE: this should be smarter based on the texture's knowledge of its previous role
dependency_from_external.srcStageMask |= VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
dependency_from_external.srcAccessMask |= VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
}
if (reference.layout != description.finalLayout) {
- // NOTE: this should be smarter based on the textures knowledge of it's subsequent role
+ // NOTE: this should be smarter based on the texture's knowledge of its subsequent role
dependency_to_external.dstStageMask |= VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
dependency_to_external.dstAccessMask |= VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
}
@@ -3425,8 +3461,13 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
render_pass_create_info.pAttachments = attachments.ptr();
render_pass_create_info.subpassCount = 1;
render_pass_create_info.pSubpasses = &subpass;
- render_pass_create_info.dependencyCount = 2;
- render_pass_create_info.pDependencies = dependencies;
+ // Commenting this because it seems it just avoids raster and compute to work at the same time.
+ // Other barriers seem to be protecting the render pass fine.
+ // render_pass_create_info.dependencyCount = 2;
+ // render_pass_create_info.pDependencies = dependencies;
+
+ render_pass_create_info.dependencyCount = 0;
+ render_pass_create_info.pDependencies = nullptr;
VkRenderPass render_pass;
VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass);
@@ -4108,6 +4149,8 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
bool is_compute = false;
+ uint32_t compute_local_size[3] = { 0, 0, 0 };
+
for (int i = 0; i < p_stages.size(); i++) {
if (p_stages[i].shader_stage == SHADER_STAGE_COMPUTE) {
is_compute = true;
@@ -4124,6 +4167,11 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
"Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed parsing shader.");
+ if (is_compute) {
+ compute_local_size[0] = module.entry_points->local_size.x;
+ compute_local_size[1] = module.entry_points->local_size.y;
+ 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, RID(),
@@ -4328,6 +4376,7 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
}
}
}
+
uint32_t pc_count = 0;
result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, nullptr);
ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
@@ -4376,6 +4425,9 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
shader.fragment_outputs = fragment_outputs;
shader.push_constant = push_constant;
shader.is_compute = is_compute;
+ shader.compute_local_size[0] = compute_local_size[0];
+ shader.compute_local_size[1] = compute_local_size[1];
+ shader.compute_local_size[2] = compute_local_size[2];
String error_text;
@@ -5099,7 +5151,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
ERR_FAIL_COND_V_MSG(!buffer, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") is invalid.");
- //if 0, then its sized on link time
+ //if 0, then it's sized on link time
ERR_FAIL_COND_V_MSG(set_uniform.length > 0 && buffer->size != (uint32_t)set_uniform.length, RID(),
"Storage buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " does not match size of shader uniform: (" + itos(set_uniform.length) + ").");
@@ -5216,7 +5268,14 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint
#ifdef FORCE_FULL_BARRIER
_full_barrier(true);
#else
- _buffer_memory_barrier(buffer->buffer, p_offset, p_size, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, true);
+ if (dst_stage_mask == 0) {
+ dst_stage_mask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
+ if (p_post_barrier != RD::BARRIER_MASK_NO_BARRIER) {
+ _buffer_memory_barrier(buffer->buffer, p_offset, p_size, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, true);
+ }
+
#endif
return err;
}
@@ -5255,7 +5314,12 @@ Error RenderingDeviceVulkan::buffer_clear(RID p_buffer, uint32_t p_offset, uint3
#ifdef FORCE_FULL_BARRIER
_full_barrier(true);
#else
- _buffer_memory_barrier(buffer->buffer, p_offset, p_size, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, p_post_barrier);
+ if (dst_stage_mask == 0) {
+ dst_stage_mask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
+ _buffer_memory_barrier(buffer->buffer, p_offset, p_size, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, dst_stage_mask);
+
#endif
return OK;
}
@@ -5272,7 +5336,7 @@ Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_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.
+ // 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);
VkCommandBuffer command_buffer = frames[frame].setup_command_buffer;
@@ -5665,7 +5729,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
#endif
//create ID to associate with this pipeline
RID id = render_pipeline_owner.make_rid(pipeline);
- //now add aall the dependencies
+ //now add all the dependencies
_add_dependency(id, p_shader);
return id;
}
@@ -5710,10 +5774,13 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader) {
pipeline.pipeline_layout = shader->pipeline_layout;
pipeline.shader = p_shader;
pipeline.push_constant_size = shader->push_constant.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];
//create ID to associate with this pipeline
RID id = compute_pipeline_owner.make_rid(pipeline);
- //now add aall the dependencies
+ //now add all the dependencies
_add_dependency(id, p_shader);
return id;
}
@@ -6019,7 +6086,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V_MSG(draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time.");
- ERR_FAIL_COND_V_MSG(compute_list != nullptr, INVALID_ID, "Only one draw/compute list can be active at the same time.");
+ ERR_FAIL_COND_V_MSG(compute_list != nullptr && !compute_list->state.allow_draw_overlap, INVALID_ID, "Only one draw/compute list can be active at the same time.");
Framebuffer *framebuffer = framebuffer_owner.getornull(p_framebuffer);
ERR_FAIL_COND_V(!framebuffer, INVALID_ID);
@@ -6040,7 +6107,14 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
viewport_offset = regioni.position;
viewport_size = regioni.size;
-
+ if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) {
+ needs_clear_color = true;
+ p_initial_color_action = INITIAL_ACTION_CONTINUE;
+ }
+ if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) {
+ needs_clear_depth = true;
+ p_initial_depth_action = INITIAL_ACTION_CONTINUE;
+ }
if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_KEEP;
@@ -6388,6 +6462,19 @@ void RenderingDeviceVulkan::draw_list_bind_uniform_set(DrawListID p_list, RID p_
dl->state.sets[p_index].uniform_set_format = uniform_set->format;
dl->state.sets[p_index].uniform_set = p_uniform_set;
+ uint32_t mst_count = uniform_set->mutable_storage_textures.size();
+ if (mst_count) {
+ Texture **mst_textures = const_cast<UniformSet *>(uniform_set)->mutable_storage_textures.ptrw();
+ for (uint32_t i = 0; i < mst_count; i++) {
+ if (mst_textures[i]->used_in_frame != frames_drawn) {
+ mst_textures[i]->used_in_frame = frames_drawn;
+ mst_textures[i]->used_in_transfer = false;
+ mst_textures[i]->used_in_compute = false;
+ }
+ mst_textures[i]->used_in_raster = true;
+ }
+ }
+
#ifdef DEBUG_ENABLED
{ //validate that textures bound are not attached as framebuffer bindings
uint32_t attachable_count = uniform_set->attachable_textures.size();
@@ -6673,23 +6760,43 @@ void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) {
access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
if (p_post_barrier & 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;
+ 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) {
barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
}
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
draw_list_bound_textures.clear();
- for (int i = 0; i < draw_list_storage_textures.size(); i++) {
+ VkImageMemoryBarrier *image_barriers = nullptr;
+
+ uint32_t image_barrier_count = draw_list_storage_textures.size();
+
+ if (image_barrier_count) {
+ image_barriers = (VkImageMemoryBarrier *)alloca(sizeof(VkImageMemoryBarrier) * draw_list_storage_textures.size());
+ }
+
+ uint32_t src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ uint32_t src_access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ if (image_barrier_count) {
+ src_stage |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ src_access |= VK_ACCESS_SHADER_WRITE_BIT;
+ }
+
+ for (uint32_t i = 0; i < image_barrier_count; i++) {
Texture *texture = texture_owner.getornull(draw_list_storage_textures[i]);
- VkImageMemoryBarrier image_memory_barrier;
+ VkImageMemoryBarrier &image_memory_barrier = image_barriers[i];
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
- image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ image_memory_barrier.srcAccessMask = src_access;
image_memory_barrier.dstAccessMask = access_flags;
image_memory_barrier.oldLayout = texture->layout;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -6703,8 +6810,6 @@ void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) {
image_memory_barrier.subresourceRange.baseArrayLayer = texture->base_layer;
image_memory_barrier.subresourceRange.layerCount = texture->layers;
- vkCmdPipelineBarrier(frames[frame].draw_command_buffer, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
-
texture->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
@@ -6712,12 +6817,22 @@ void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) {
// To ensure proper synchronization, we must make sure rendering is done before:
// * Some buffer is copied
- // * Another render pass happens (since we may be done
+ // * Another render pass happens (since we may be done)
#ifdef FORCE_FULL_BARRIER
_full_barrier(true);
#else
- _memory_barrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, barrier_flags, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, access_flags, true);
+
+ VkMemoryBarrier mem_barrier;
+ mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ mem_barrier.pNext = nullptr;
+ mem_barrier.srcAccessMask = src_access;
+ mem_barrier.dstAccessMask = access_flags;
+
+ if (image_barrier_count > 0 || p_post_barrier != BARRIER_MASK_NO_BARRIER) {
+ vkCmdPipelineBarrier(frames[frame].draw_command_buffer, src_stage, barrier_flags, 0, 1, &mem_barrier, 0, nullptr, image_barrier_count, image_barriers);
+ }
+
#endif
}
@@ -6725,12 +6840,13 @@ void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) {
/**** COMPUTE LISTS ****/
/***********************/
-RenderingDevice::ComputeListID RenderingDeviceVulkan::compute_list_begin() {
- ERR_FAIL_COND_V_MSG(draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time.");
+RenderingDevice::ComputeListID RenderingDeviceVulkan::compute_list_begin(bool p_allow_draw_overlap) {
+ ERR_FAIL_COND_V_MSG(!p_allow_draw_overlap && draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time.");
ERR_FAIL_COND_V_MSG(compute_list != nullptr, INVALID_ID, "Only one draw/compute list can be active at the same time.");
compute_list = memnew(ComputeList);
compute_list->command_buffer = frames[frame].draw_command_buffer;
+ compute_list->state.allow_draw_overlap = p_allow_draw_overlap;
return ID_TYPE_COMPUTE_LIST;
}
@@ -6787,6 +6903,9 @@ void RenderingDeviceVulkan::compute_list_bind_compute_pipeline(ComputeListID p_l
}
cl->state.pipeline_shader = pipeline->shader;
+ cl->state.local_group_size[0] = pipeline->local_group_size[0];
+ cl->state.local_group_size[1] = pipeline->local_group_size[1];
+ cl->state.local_group_size[2] = pipeline->local_group_size[2];
}
#ifdef DEBUG_ENABLED
@@ -6824,11 +6943,24 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
cl->state.sets[p_index].uniform_set = p_uniform_set;
uint32_t textures_to_sampled_count = uniform_set->mutable_sampled_textures.size();
+ uint32_t textures_to_storage_count = uniform_set->mutable_storage_textures.size();
+
Texture **textures_to_sampled = uniform_set->mutable_sampled_textures.ptrw();
+ VkImageMemoryBarrier *texture_barriers = nullptr;
+
+ if (textures_to_sampled_count + textures_to_storage_count) {
+ texture_barriers = (VkImageMemoryBarrier *)alloca(sizeof(VkImageMemoryBarrier) * (textures_to_sampled_count + textures_to_storage_count));
+ }
+ uint32_t texture_barrier_count = 0;
+
+ uint32_t src_stage_flags = 0;
+
for (uint32_t i = 0; i < textures_to_sampled_count; i++) {
if (textures_to_sampled[i]->layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
- VkImageMemoryBarrier image_memory_barrier;
+ src_stage_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+
+ VkImageMemoryBarrier &image_memory_barrier = texture_barriers[texture_barrier_count++];
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
@@ -6845,23 +6977,55 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
image_memory_barrier.subresourceRange.baseArrayLayer = textures_to_sampled[i]->base_layer;
image_memory_barrier.subresourceRange.layerCount = textures_to_sampled[i]->layers;
- vkCmdPipelineBarrier(cl->command_buffer, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
-
textures_to_sampled[i]->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
cl->state.textures_to_sampled_layout.erase(textures_to_sampled[i]);
}
+
+ if (textures_to_sampled[i]->used_in_frame != frames_drawn) {
+ textures_to_sampled[i]->used_in_frame = frames_drawn;
+ textures_to_sampled[i]->used_in_transfer = false;
+ textures_to_sampled[i]->used_in_raster = false;
+ }
+ textures_to_sampled[i]->used_in_compute = true;
}
- uint32_t textures_to_storage_count = uniform_set->mutable_storage_textures.size();
Texture **textures_to_storage = uniform_set->mutable_storage_textures.ptrw();
for (uint32_t i = 0; i < textures_to_storage_count; i++) {
if (textures_to_storage[i]->layout != VK_IMAGE_LAYOUT_GENERAL) {
- VkImageMemoryBarrier image_memory_barrier;
+ uint32_t src_access_flags = 0;
+
+ if (textures_to_storage[i]->used_in_frame == frames_drawn) {
+ if (textures_to_storage[i]->used_in_compute) {
+ src_stage_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ src_access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (textures_to_storage[i]->used_in_raster) {
+ src_stage_flags |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
+ src_access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (textures_to_storage[i]->used_in_transfer) {
+ src_stage_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ src_access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
+ }
+
+ textures_to_storage[i]->used_in_compute = false;
+ textures_to_storage[i]->used_in_raster = false;
+ textures_to_storage[i]->used_in_compute = false;
+
+ } else {
+ src_access_flags = 0;
+ textures_to_storage[i]->used_in_compute = false;
+ textures_to_storage[i]->used_in_raster = false;
+ textures_to_storage[i]->used_in_compute = false;
+ textures_to_storage[i]->used_in_frame = frames_drawn;
+ }
+
+ VkImageMemoryBarrier &image_memory_barrier = texture_barriers[texture_barrier_count++];
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
- image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ image_memory_barrier.srcAccessMask = src_access_flags;
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
image_memory_barrier.oldLayout = textures_to_storage[i]->layout;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
@@ -6875,14 +7039,20 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
image_memory_barrier.subresourceRange.baseArrayLayer = textures_to_storage[i]->base_layer;
image_memory_barrier.subresourceRange.layerCount = textures_to_storage[i]->layers;
- vkCmdPipelineBarrier(cl->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
-
textures_to_storage[i]->layout = VK_IMAGE_LAYOUT_GENERAL;
cl->state.textures_to_sampled_layout.insert(textures_to_storage[i]); //needs to go back to sampled layout afterwards
}
}
+ if (texture_barrier_count) {
+ if (src_stage_flags == 0) {
+ src_stage_flags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ }
+
+ vkCmdPipelineBarrier(cl->command_buffer, src_stage_flags, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, texture_barrier_count, texture_barriers);
+ }
+
#if 0
{ //validate that textures bound are not attached as framebuffer bindings
uint32_t attachable_count = uniform_set->attachable_textures.size();
@@ -6976,6 +7146,27 @@ void RenderingDeviceVulkan::compute_list_dispatch(ComputeListID p_list, uint32_t
vkCmdDispatch(cl->command_buffer, p_x_groups, p_y_groups, p_z_groups);
}
+void RenderingDeviceVulkan::compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads) {
+ ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
+ ERR_FAIL_COND(!compute_list);
+
+ ComputeList *cl = compute_list;
+
+#ifdef DEBUG_ENABLED
+
+ ERR_FAIL_COND_MSG(!cl->validation.pipeline_active, "No compute pipeline was set before attempting to draw.");
+
+ if (cl->validation.pipeline_push_constant_size > 0) {
+ //using push constants, check that they were supplied
+ ERR_FAIL_COND_MSG(!cl->validation.pipeline_push_constant_supplied,
+ "The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
+ }
+
+#endif
+
+ compute_list_dispatch(p_list, (p_x_threads - 1) / cl->state.local_group_size[0] + 1, (p_y_threads - 1) / cl->state.local_group_size[1] + 1, (p_z_threads - 1) / cl->state.local_group_size[2] + 1);
+}
+
void RenderingDeviceVulkan::compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) {
ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
ERR_FAIL_COND(!compute_list);
@@ -7047,7 +7238,7 @@ void RenderingDeviceVulkan::compute_list_end(uint32_t p_post_barrier) {
uint32_t access_flags = 0;
if (p_post_barrier & BARRIER_MASK_COMPUTE) {
barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
if (p_post_barrier & 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;
@@ -7058,8 +7249,22 @@ void RenderingDeviceVulkan::compute_list_end(uint32_t p_post_barrier) {
access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
}
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
+ VkImageMemoryBarrier *image_barriers = nullptr;
+
+ uint32_t image_barrier_count = compute_list->state.textures_to_sampled_layout.size();
+
+ if (image_barrier_count) {
+ image_barriers = (VkImageMemoryBarrier *)alloca(sizeof(VkImageMemoryBarrier) * image_barrier_count);
+ }
+
+ uint32_t barrier_idx = 0;
+
for (Set<Texture *>::Element *E = compute_list->state.textures_to_sampled_layout.front(); E; E = E->next()) {
- VkImageMemoryBarrier image_memory_barrier;
+ VkImageMemoryBarrier &image_memory_barrier = image_barriers[barrier_idx++];
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
@@ -7076,19 +7281,33 @@ void RenderingDeviceVulkan::compute_list_end(uint32_t p_post_barrier) {
image_memory_barrier.subresourceRange.baseArrayLayer = E->get()->base_layer;
image_memory_barrier.subresourceRange.layerCount = E->get()->layers;
- // TODO: Look at the usages in the compute list and determine tighter dst stage and access masks based on some "final" usage equivalent
- vkCmdPipelineBarrier(compute_list->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
-
E->get()->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ if (E->get()->used_in_frame != frames_drawn) {
+ E->get()->used_in_transfer = false;
+ E->get()->used_in_raster = false;
+ E->get()->used_in_compute = false;
+ E->get()->used_in_frame = frames_drawn;
+ }
}
- memdelete(compute_list);
- compute_list = nullptr;
#ifdef FORCE_FULL_BARRIER
_full_barrier(true);
#else
- _memory_barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, barrier_flags, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT, true);
+ VkMemoryBarrier mem_barrier;
+ mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ mem_barrier.pNext = nullptr;
+ mem_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
+ mem_barrier.dstAccessMask = access_flags;
+
+ if (image_barrier_count > 0 || p_post_barrier != BARRIER_MASK_NO_BARRIER) {
+ vkCmdPipelineBarrier(compute_list->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, barrier_flags, 0, 1, &mem_barrier, 0, nullptr, image_barrier_count, image_barriers);
+ }
+
#endif
+
+ memdelete(compute_list);
+ compute_list = nullptr;
}
void RenderingDeviceVulkan::barrier(uint32_t p_from, uint32_t p_to) {
@@ -7107,11 +7326,15 @@ void RenderingDeviceVulkan::barrier(uint32_t p_from, uint32_t p_to) {
src_access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
}
+ if (p_from == 0) {
+ src_barrier_flags = VK_PIPELINE_STAGE_TOP_OF_PIPE_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 | VK_ACCESS_INDIRECT_COMMAND_READ_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;
@@ -7122,6 +7345,10 @@ void RenderingDeviceVulkan::barrier(uint32_t p_from, uint32_t p_to) {
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;
+ }
+
_memory_barrier(src_barrier_flags, dst_barrier_flags, src_access_flags, dst_access_flags, true);
}
@@ -7325,6 +7552,16 @@ void RenderingDeviceVulkan::draw_command_end_label() {
context->command_end_label(frames[frame].draw_command_buffer);
}
+String RenderingDeviceVulkan::get_device_vendor_name() const {
+ return context->get_device_vendor_name();
+}
+String RenderingDeviceVulkan::get_device_name() const {
+ return context->get_device_name();
+}
+String RenderingDeviceVulkan::get_device_pipeline_cache_uuid() const {
+ return context->get_device_pipeline_cache_uuid();
+}
+
void RenderingDeviceVulkan::_finalize_command_bufers() {
if (draw_list) {
ERR_PRINT("Found open draw list at the end of the frame, this should never happen (further drawing will likely not work).");
@@ -7377,6 +7614,7 @@ void RenderingDeviceVulkan::_begin_frame() {
if (frames[frame].timestamp_count) {
vkGetQueryPoolResults(device, frames[frame].timestamp_pool, 0, frames[frame].timestamp_count, sizeof(uint64_t) * max_timestamp_query_elements, frames[frame].timestamp_result_values, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT);
+ vkCmdResetQueryPool(frames[frame].setup_command_buffer, frames[frame].timestamp_pool, 0, frames[frame].timestamp_count);
SWAP(frames[frame].timestamp_names, frames[frame].timestamp_result_names);
SWAP(frames[frame].timestamp_cpu_values, frames[frame].timestamp_cpu_result_values);
}
@@ -7542,7 +7780,7 @@ uint64_t RenderingDeviceVulkan::get_memory_usage() const {
void RenderingDeviceVulkan::_flush(bool p_current_frame) {
if (local_device.is_valid() && !p_current_frame) {
- return; //flushign previous frames has no effect with local device
+ return; //flushing previous frames has no effect with local device
}
//not doing this crashes RADV (undefined behavior)
if (p_current_frame) {
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index 4bea17e4a1..a2527d5c33 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -141,6 +141,11 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkImageLayout layout;
+ uint64_t used_in_frame = 0;
+ bool used_in_transfer = false;
+ bool used_in_raster = false;
+ bool used_in_compute = false;
+
uint32_t read_aspect_mask = 0;
uint32_t barrier_aspect_mask = 0;
bool bound = false; //bound to framebffer
@@ -528,6 +533,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
PushConstant push_constant;
+ uint32_t compute_local_size[3] = { 0, 0, 0 };
+
bool is_compute = false;
int max_output = 0;
Vector<Set> sets;
@@ -686,6 +693,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkPipeline pipeline = VK_NULL_HANDLE;
uint32_t push_constant_size = 0;
uint32_t push_constant_stages = 0;
+ uint32_t local_group_size[3] = { 0, 0, 0 };
};
RID_Owner<ComputePipeline, true> compute_pipeline_owner;
@@ -808,8 +816,10 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t set_count = 0;
RID pipeline;
RID pipeline_shader;
+ uint32_t local_group_size[3] = { 0, 0, 0 };
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
uint32_t pipeline_push_constant_stages = 0;
+ bool allow_draw_overlap;
} state;
#ifdef DEBUG_ENABLED
@@ -1028,13 +1038,14 @@ public:
/**** COMPUTE LISTS ****/
/***********************/
- virtual ComputeListID compute_list_begin();
+ virtual ComputeListID compute_list_begin(bool p_allow_draw_overlap = false);
virtual void compute_list_bind_compute_pipeline(ComputeListID p_list, RID p_compute_pipeline);
virtual void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index);
virtual void compute_list_set_push_constant(ComputeListID p_list, const void *p_data, uint32_t p_data_size);
virtual void compute_list_add_barrier(ComputeListID p_list);
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);
@@ -1085,6 +1096,10 @@ public:
virtual void draw_command_insert_label(String p_label_name, const Color p_color = Color(1, 1, 1, 1));
virtual void draw_command_end_label();
+ virtual String get_device_vendor_name() const;
+ virtual String get_device_name() const;
+ virtual String get_device_pipeline_cache_uuid() const;
+
RenderingDeviceVulkan();
~RenderingDeviceVulkan();
};
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 98966477a5..69517b17ba 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -380,7 +380,8 @@ Error VulkanContext::_create_physical_device() {
ERR_FAIL_V(ERR_CANT_CREATE);
}
/* for now, just grab the first physical device */
- gpu = physical_devices[0];
+ uint32_t device_index = 0;
+ gpu = physical_devices[device_index];
free(physical_devices);
/* Look for device extensions */
@@ -389,6 +390,40 @@ Error VulkanContext::_create_physical_device() {
enabled_extension_count = 0;
memset(extension_names, 0, sizeof(extension_names));
+ /* Get identifier properties */
+ vkGetPhysicalDeviceProperties(gpu, &gpu_props);
+
+ static const struct {
+ uint32_t id;
+ const char *name;
+ } vendor_names[] = {
+ { 0x1002, "AMD" },
+ { 0x1010, "ImgTec" },
+ { 0x10DE, "NVIDIA" },
+ { 0x13B5, "ARM" },
+ { 0x5143, "Qualcomm" },
+ { 0x8086, "INTEL" },
+ { 0, nullptr },
+ };
+ device_name = gpu_props.deviceName;
+ pipeline_cache_id = String::hex_encode_buffer(gpu_props.pipelineCacheUUID, VK_UUID_SIZE);
+ pipeline_cache_id += "-driver-" + itos(gpu_props.driverVersion);
+ {
+ device_vendor = "Unknown";
+ uint32_t vendor_idx = 0;
+ while (vendor_names[vendor_idx].name != nullptr) {
+ if (gpu_props.vendorID == vendor_names[vendor_idx].id) {
+ device_vendor = vendor_names[vendor_idx].name;
+ break;
+ }
+ vendor_idx++;
+ }
+ }
+#ifdef DEBUG_ENABLED
+ print_line("Using Vulkan Device #" + itos(device_index) + ": " + device_vendor + " - " + device_name);
+#endif
+ device_api_version = gpu_props.apiVersion;
+
err = vkEnumerateDeviceExtensionProperties(gpu, nullptr, &device_extension_count, nullptr);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
@@ -498,7 +533,6 @@ Error VulkanContext::_create_physical_device() {
break;
}
}
- vkGetPhysicalDeviceProperties(gpu, &gpu_props);
/* Call with NULL data to get count */
vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, nullptr);
@@ -565,6 +599,7 @@ Error VulkanContext::_create_device() {
}
err = vkCreateDevice(gpu, &sdevice, nullptr, &device);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
+
return OK;
}
@@ -1278,13 +1313,13 @@ Error VulkanContext::swap_buffers() {
DemoUpdateTargetIPD(demo);
// Note: a real application would position its geometry to that it's in
- // the correct locatoin for when the next image is presented. It might
+ // the correct location for when the next image is presented. It might
// also wait, so that there's less latency between any input and when
// the next image is rendered/presented. This demo program is so
// simple that it doesn't do either of those.
}
#endif
- // Wait for the image acquired semaphore to be signaled to ensure
+ // Wait for the image acquired semaphore to be signalled to ensure
// that the image won't be rendered to until the presentation
// engine has fully released ownership to the application, and it is
// okay to render to the image.
@@ -1350,7 +1385,7 @@ Error VulkanContext::swap_buffers() {
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
}
- // If we are using separate queues we have to wait for image ownership,
+ // If we are using separate queues, we have to wait for image ownership,
// otherwise wait for draw complete
VkPresentInfoKHR present = {
/*sType*/ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
@@ -1590,11 +1625,12 @@ void VulkanContext::command_begin_label(VkCommandBuffer p_command_buffer, String
if (!enabled_debug_utils) {
return;
}
+
+ CharString cs = p_label_name.utf8().get_data();
VkDebugUtilsLabelEXT label;
label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
label.pNext = nullptr;
- CharString label_name = p_label_name.utf8();
- label.pLabelName = label_name.get_data();
+ label.pLabelName = cs.get_data();
label.color[0] = p_color[0];
label.color[1] = p_color[1];
label.color[2] = p_color[2];
@@ -1606,11 +1642,11 @@ void VulkanContext::command_insert_label(VkCommandBuffer p_command_buffer, Strin
if (!enabled_debug_utils) {
return;
}
+ CharString cs = p_label_name.utf8().get_data();
VkDebugUtilsLabelEXT label;
label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
label.pNext = nullptr;
- CharString label_name = p_label_name.utf8();
- label.pLabelName = label_name.get_data();
+ label.pLabelName = cs.get_data();
label.color[0] = p_color[0];
label.color[1] = p_color[1];
label.color[2] = p_color[2];
@@ -1629,16 +1665,26 @@ void VulkanContext::set_object_name(VkObjectType p_object_type, uint64_t p_objec
if (!enabled_debug_utils) {
return;
}
+ CharString obj_data = p_object_name.utf8();
VkDebugUtilsObjectNameInfoEXT name_info;
name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
name_info.pNext = nullptr;
name_info.objectType = p_object_type;
name_info.objectHandle = p_object_handle;
- CharString object_name = p_object_name.utf8();
- name_info.pObjectName = object_name.get_data();
+ name_info.pObjectName = obj_data.get_data();
SetDebugUtilsObjectNameEXT(device, &name_info);
}
+String VulkanContext::get_device_vendor_name() const {
+ return device_vendor;
+}
+String VulkanContext::get_device_name() const {
+ return device_name;
+}
+String VulkanContext::get_device_pipeline_cache_uuid() const {
+ return pipeline_cache_id;
+}
+
VulkanContext::VulkanContext() {
use_validation_layers = Engine::get_singleton()->is_validation_layers_enabled();
@@ -1659,7 +1705,7 @@ VulkanContext::~VulkanContext() {
vkDestroySemaphore(device, image_ownership_semaphores[i], nullptr);
}
}
- if (inst_initialized && use_validation_layers) {
+ if (inst_initialized && enabled_debug_utils) {
DestroyDebugUtilsMessengerEXT(inst, dbg_messenger, nullptr);
}
vkDestroyDevice(device, nullptr);
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index 5cb762aca8..dc6b0410bc 100644
--- a/drivers/vulkan/vulkan_context.h
+++ b/drivers/vulkan/vulkan_context.h
@@ -57,6 +57,11 @@ class VulkanContext {
bool device_initialized = false;
bool inst_initialized = false;
+ String device_vendor;
+ String device_name;
+ String pipeline_cache_id;
+ uint32_t device_api_version = 0;
+
bool buffers_prepared = false;
// Present queue.
@@ -215,6 +220,10 @@ public:
void command_end_label(VkCommandBuffer p_command_buffer);
void set_object_name(VkObjectType p_object_type, uint64_t p_object_handle, String p_object_name);
+ String get_device_vendor_name() const;
+ String get_device_name() const;
+ String get_device_pipeline_cache_uuid() const;
+
VulkanContext();
virtual ~VulkanContext();
};
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index f2d541754f..43c8722b06 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -387,7 +387,7 @@ Error AudioDriverWASAPI::finish_capture_device() {
}
Error AudioDriverWASAPI::init() {
- mix_rate = GLOBAL_GET("audio/mix_rate");
+ mix_rate = GLOBAL_GET("audio/driver/mix_rate");
Error err = init_render_device();
if (err != OK) {
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index 35f61c0623..b1b3fc9092 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -253,6 +253,8 @@ uint8_t FileAccessWindows::get_8() const {
}
int FileAccessWindows::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V(!f, -1);
if (flags == READ_WRITE || flags == WRITE_READ) {
if (prev_op == WRITE) {
diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp
index 1bb8da769b..1c7bf5d6c6 100644
--- a/drivers/xaudio2/audio_driver_xaudio2.cpp
+++ b/drivers/xaudio2/audio_driver_xaudio2.cpp
@@ -44,12 +44,12 @@ Error AudioDriverXAudio2::init() {
pcm_open = false;
samples_in = nullptr;
- mix_rate = GLOBAL_GET("audio/mix_rate");
+ mix_rate = GLOBAL_GET("audio/driver/mix_rate");
// FIXME: speaker_mode seems unused in the Xaudio2 driver so far
speaker_mode = SPEAKER_MODE_STEREO;
channels = 2;
- int latency = GLOBAL_GET("audio/output_latency");
+ int latency = GLOBAL_GET("audio/driver/output_latency");
buffer_size = closest_power_of_2(latency * mix_rate / 1000);
samples_in = memnew_arr(int32_t, buffer_size * channels);
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
new file mode 100644
index 0000000000..9949fd8199
--- /dev/null
+++ b/editor/action_map_editor.cpp
@@ -0,0 +1,1167 @@
+/*************************************************************************/
+/* action_map_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "action_map_editor.h"
+#include "core/input/input_map.h"
+#include "core/os/keyboard.h"
+#include "editor/editor_scale.h"
+#include "scene/gui/center_container.h"
+
+/////////////////////////////////////////
+
+// Maps to 2*axis if value is neg, or + 1 if value is pos.
+static const char *_joy_axis_descriptions[JOY_AXIS_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) {
+ ERR_FAIL_COND_V_MSG(p_event.is_null(), String(), "Provided event is not a valid instance of InputEvent");
+
+ // Joypad motion events will display slighlty differently than what the event->as_text() provides. See #43660.
+ Ref<InputEventJoypadMotion> jpmotion = p_event;
+ if (jpmotion.is_valid()) {
+ String desc = TTR("Unknown Joypad Axis");
+ if (jpmotion->get_axis() < JOY_AXIS_MAX) {
+ desc = RTR(_joy_axis_descriptions[2 * jpmotion->get_axis() + (jpmotion->get_axis_value() < 0 ? 0 : 1)]);
+ }
+
+ return vformat("Joypad Axis %s %s (%s)", itos(jpmotion->get_axis()), jpmotion->get_axis_value() < 0 ? "-" : "+", desc);
+ } else {
+ return p_event->as_text();
+ }
+}
+
+void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event) {
+ if (p_event.is_valid()) {
+ event = p_event;
+
+ // Update Label
+ event_as_text->set_text(get_event_text(event));
+
+ Ref<InputEventKey> k = p_event;
+ Ref<InputEventMouseButton> mb = p_event;
+ Ref<InputEventJoypadButton> joyb = p_event;
+ Ref<InputEventJoypadMotion> joym = p_event;
+ Ref<InputEventWithModifiers> mod = p_event;
+
+ // Update option values and visibility
+ bool show_mods = false;
+ bool show_device = false;
+ bool show_phys_key = false;
+
+ if (mod.is_valid()) {
+ show_mods = true;
+ mod_checkboxes[MOD_ALT]->set_pressed(mod->get_alt());
+ mod_checkboxes[MOD_SHIFT]->set_pressed(mod->get_shift());
+ mod_checkboxes[MOD_COMMAND]->set_pressed(mod->get_command());
+ mod_checkboxes[MOD_CONTROL]->set_pressed(mod->get_control());
+ mod_checkboxes[MOD_META]->set_pressed(mod->get_metakey());
+
+ store_command_checkbox->set_pressed(mod->is_storing_command());
+ }
+
+ if (k.is_valid()) {
+ show_phys_key = true;
+ physical_key_checkbox->set_pressed(k->get_physical_keycode() != 0 && k->get_keycode() == 0);
+
+ } else if (joyb.is_valid() || joym.is_valid() || mb.is_valid()) {
+ show_device = true;
+ _set_current_device(event->get_device());
+ }
+
+ mod_container->set_visible(show_mods);
+ device_container->set_visible(show_device);
+ physical_key_checkbox->set_visible(show_phys_key);
+ additional_options_container->show();
+
+ // Update selected item in input list for keys, joybuttons and joyaxis only (since the mouse cannot be "listened" for).
+ if (k.is_valid() || joyb.is_valid() || joym.is_valid()) {
+ TreeItem *category = input_list_tree->get_root()->get_children();
+ while (category) {
+ TreeItem *input_item = category->get_children();
+
+ // has_type this should be always true, unless the tree structure has been misconfigured.
+ bool has_type = input_item->get_parent()->has_meta("__type");
+ int input_type = input_item->get_parent()->get_meta("__type");
+ if (!has_type) {
+ return;
+ }
+
+ // If event type matches input types of this category.
+ if ((k.is_valid() && input_type == INPUT_KEY) || (joyb.is_valid() && input_type == INPUT_JOY_BUTTON) || (joym.is_valid() && input_type == INPUT_JOY_MOTION)) {
+ // Loop through all items of this category until one matches.
+ while (input_item) {
+ bool key_match = k.is_valid() && (Variant(k->get_keycode()) == input_item->get_meta("__keycode") || Variant(k->get_physical_keycode()) == input_item->get_meta("__keycode"));
+ bool joyb_match = joyb.is_valid() && Variant(joyb->get_button_index()) == input_item->get_meta("__index");
+ bool joym_match = joym.is_valid() && Variant(joym->get_axis()) == input_item->get_meta("__axis") && joym->get_axis_value() == (float)input_item->get_meta("__value");
+ if (key_match || joyb_match || joym_match) {
+ category->set_collapsed(false);
+ input_item->select(0);
+ input_list_tree->ensure_cursor_is_visible();
+ return;
+ }
+ input_item = input_item->get_next();
+ }
+ }
+
+ category->set_collapsed(true); // Event not in this category, so collapse;
+ category = category->get_next();
+ }
+ }
+ } else {
+ // Event is not valid, reset dialog
+ event = p_event;
+ Vector<String> strings;
+
+ // Reset message, promp for input according to which input types are allowed.
+ String text = TTR("Perform an Input (%s).");
+
+ if (allowed_input_types & INPUT_KEY) {
+ strings.append(TTR("Key"));
+ }
+ // We don't check for INPUT_MOUSE_BUTTON since it is ignored in the "Listen Window Input" method.
+
+ if (allowed_input_types & INPUT_JOY_BUTTON) {
+ strings.append(TTR("Joypad Button"));
+ }
+ if (allowed_input_types & INPUT_JOY_MOTION) {
+ strings.append(TTR("Joypad Axis"));
+ }
+
+ if (strings.size() == 0) {
+ text = TTR("Input Event dialog has been misconfigured: No input types are allowed.");
+ event_as_text->set_text(text);
+ } else {
+ String insert_text = String(", ").join(strings);
+ event_as_text->set_text(vformat(text, insert_text));
+ }
+
+ additional_options_container->hide();
+ input_list_tree->deselect_all();
+ _update_input_list();
+ }
+}
+
+void InputEventConfigurationDialog::_tab_selected(int p_tab) {
+ Callable signal_method = callable_mp(this, &InputEventConfigurationDialog::_listen_window_input);
+ if (p_tab == 0) {
+ // Start Listening.
+ if (!is_connected("window_input", signal_method)) {
+ connect("window_input", signal_method);
+ }
+ } else {
+ // Stop Listening.
+ if (is_connected("window_input", signal_method)) {
+ disconnect("window_input", signal_method);
+ }
+ input_list_tree->call_deferred("ensure_cursor_is_visible");
+ if (input_list_tree->get_selected() == nullptr) {
+ // If nothing selected, scroll to top.
+ input_list_tree->scroll_to_item(input_list_tree->get_root());
+ }
+ }
+}
+
+void InputEventConfigurationDialog::_listen_window_input(const Ref<InputEvent> &p_event) {
+ // Ignore if echo or not pressed
+ if (p_event->is_echo() || !p_event->is_pressed()) {
+ return;
+ }
+
+ // Ignore mouse
+ Ref<InputEventMouse> m = p_event;
+ if (m.is_valid()) {
+ return;
+ }
+
+ // Check what the type is and if it is allowed.
+ Ref<InputEventKey> k = p_event;
+ Ref<InputEventJoypadButton> joyb = p_event;
+ Ref<InputEventJoypadMotion> joym = p_event;
+
+ int type = k.is_valid() ? INPUT_KEY : joyb.is_valid() ? INPUT_JOY_BUTTON :
+ joym.is_valid() ? INPUT_JOY_MOTION :
+ 0;
+
+ if (!(allowed_input_types & type)) {
+ return;
+ }
+
+ 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(SGN(axis_value));
+ }
+ }
+
+ if (k.is_valid()) {
+ k->set_pressed(false); // to avoid serialisation of 'pressed' property - doesn't matter for actions anyway.
+ // Maintain physical keycode option state
+ if (physical_key_checkbox->is_pressed()) {
+ k->set_physical_keycode(k->get_keycode());
+ k->set_keycode(0);
+ } else {
+ k->set_keycode(k->get_physical_keycode());
+ k->set_physical_keycode(0);
+ }
+ }
+
+ Ref<InputEventWithModifiers> mod = p_event;
+ if (mod.is_valid()) {
+ // Maintain store command option state
+ mod->set_store_command(store_command_checkbox->is_pressed());
+
+ mod->set_window_id(0);
+ }
+
+ _set_event(p_event);
+ set_input_as_handled();
+}
+
+void InputEventConfigurationDialog::_search_term_updated(const String &) {
+ _update_input_list();
+}
+
+void InputEventConfigurationDialog::_update_input_list() {
+ input_list_tree->clear();
+
+ TreeItem *root = input_list_tree->create_item();
+ String search_term = input_list_search->get_text();
+
+ bool collapse = input_list_search->get_text().is_empty();
+
+ if (allowed_input_types & INPUT_KEY) {
+ TreeItem *kb_root = input_list_tree->create_item(root);
+ kb_root->set_text(0, TTR("Keyboard Keys"));
+ kb_root->set_icon(0, icon_cache.keyboard);
+ kb_root->set_collapsed(collapse);
+ kb_root->set_meta("__type", INPUT_KEY);
+
+ for (int i = 0; i < keycode_get_count(); i++) {
+ String name = keycode_get_name_by_index(i);
+
+ if (!search_term.is_empty() && name.findn(search_term) == -1) {
+ continue;
+ }
+
+ TreeItem *item = input_list_tree->create_item(kb_root);
+ item->set_text(0, name);
+ item->set_meta("__keycode", keycode_get_value_by_index(i));
+ }
+ }
+
+ if (allowed_input_types & INPUT_MOUSE_BUTTON) {
+ TreeItem *mouse_root = input_list_tree->create_item(root);
+ mouse_root->set_text(0, TTR("Mouse Buttons"));
+ mouse_root->set_icon(0, icon_cache.mouse);
+ mouse_root->set_collapsed(collapse);
+ mouse_root->set_meta("__type", INPUT_MOUSE_BUTTON);
+
+ MouseButton mouse_buttons[9] = { MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_WHEEL_UP, MOUSE_BUTTON_WHEEL_DOWN, MOUSE_BUTTON_WHEEL_LEFT, MOUSE_BUTTON_WHEEL_RIGHT, MOUSE_BUTTON_XBUTTON1, MOUSE_BUTTON_XBUTTON2 };
+ for (int i = 0; i < 9; i++) {
+ Ref<InputEventMouseButton> mb;
+ mb.instance();
+ mb->set_button_index(mouse_buttons[i]);
+ String desc = get_event_text(mb);
+
+ if (!search_term.is_empty() && desc.findn(search_term) == -1) {
+ continue;
+ }
+
+ TreeItem *item = input_list_tree->create_item(mouse_root);
+ item->set_text(0, desc);
+ item->set_meta("__index", mouse_buttons[i]);
+ }
+ }
+
+ if (allowed_input_types & INPUT_JOY_BUTTON) {
+ TreeItem *joyb_root = input_list_tree->create_item(root);
+ joyb_root->set_text(0, TTR("Joypad Buttons"));
+ joyb_root->set_icon(0, icon_cache.joypad_button);
+ joyb_root->set_collapsed(collapse);
+ joyb_root->set_meta("__type", INPUT_JOY_BUTTON);
+
+ for (int i = 0; i < JOY_BUTTON_MAX; i++) {
+ Ref<InputEventJoypadButton> joyb;
+ joyb.instance();
+ joyb->set_button_index(i);
+ String desc = get_event_text(joyb);
+
+ if (!search_term.is_empty() && desc.findn(search_term) == -1) {
+ continue;
+ }
+
+ TreeItem *item = input_list_tree->create_item(joyb_root);
+ item->set_text(0, desc);
+ item->set_meta("__index", i);
+ }
+ }
+
+ if (allowed_input_types & INPUT_JOY_MOTION) {
+ TreeItem *joya_root = input_list_tree->create_item(root);
+ joya_root->set_text(0, TTR("Joypad Axes"));
+ joya_root->set_icon(0, icon_cache.joypad_axis);
+ joya_root->set_collapsed(collapse);
+ joya_root->set_meta("__type", INPUT_JOY_MOTION);
+
+ for (int i = 0; i < JOY_AXIS_MAX * 2; i++) {
+ int axis = i / 2;
+ int direction = (i & 1) ? 1 : -1;
+ Ref<InputEventJoypadMotion> joym;
+ joym.instance();
+ joym->set_axis(axis);
+ joym->set_axis_value(direction);
+ String desc = get_event_text(joym);
+
+ if (!search_term.is_empty() && desc.findn(search_term) == -1) {
+ continue;
+ }
+
+ TreeItem *item = input_list_tree->create_item(joya_root);
+ item->set_text(0, desc);
+ item->set_meta("__axis", i >> 1);
+ item->set_meta("__value", (i & 1) ? 1 : -1);
+ }
+ }
+}
+
+void InputEventConfigurationDialog::_mod_toggled(bool p_checked, int p_index) {
+ Ref<InputEventWithModifiers> ie = event;
+
+ // Not event with modifiers
+ if (ie.is_null()) {
+ return;
+ }
+
+ if (p_index == 0) {
+ ie->set_alt(p_checked);
+ } else if (p_index == 1) {
+ ie->set_shift(p_checked);
+ } else if (p_index == 2) {
+ ie->set_command(p_checked);
+ } else if (p_index == 3) {
+ ie->set_control(p_checked);
+ } else if (p_index == 4) {
+ ie->set_metakey(p_checked);
+ }
+
+ _set_event(ie);
+}
+
+void InputEventConfigurationDialog::_store_command_toggled(bool p_checked) {
+ Ref<InputEventWithModifiers> ie = event;
+ if (ie.is_valid()) {
+ ie->set_store_command(p_checked);
+ _set_event(ie);
+ }
+
+ if (p_checked) {
+ // If storing Command, show it's checkbox and hide Control (Win/Lin) or Meta (Mac)
+#ifdef APPLE_STYLE_KEYS
+ mod_checkboxes[MOD_META]->hide();
+
+ mod_checkboxes[MOD_COMMAND]->show();
+ mod_checkboxes[MOD_COMMAND]->set_text("Meta (Command)");
+#else
+ mod_checkboxes[MOD_CONTROL]->hide();
+
+ mod_checkboxes[MOD_COMMAND]->show();
+ mod_checkboxes[MOD_COMMAND]->set_text("Control (Command)");
+#endif
+ } else {
+ // If not, hide Command, show Control and Meta.
+ mod_checkboxes[MOD_COMMAND]->hide();
+ mod_checkboxes[MOD_CONTROL]->show();
+ mod_checkboxes[MOD_META]->show();
+ }
+}
+
+void InputEventConfigurationDialog::_physical_keycode_toggled(bool p_checked) {
+ Ref<InputEventKey> k = event;
+
+ if (k.is_null()) {
+ return;
+ }
+
+ if (p_checked) {
+ k->set_physical_keycode(k->get_keycode());
+ k->set_keycode(0);
+ } else {
+ k->set_keycode(k->get_physical_keycode());
+ k->set_physical_keycode(0);
+ }
+
+ _set_event(k);
+}
+
+void InputEventConfigurationDialog::_input_list_item_selected() {
+ TreeItem *selected = input_list_tree->get_selected();
+
+ // Invalid tree selection - type only exists on the "category" items, which are not a valid selection.
+ if (selected->has_meta("__type")) {
+ return;
+ }
+
+ int input_type = selected->get_parent()->get_meta("__type");
+
+ switch (input_type) {
+ case InputEventConfigurationDialog::INPUT_KEY: {
+ int kc = selected->get_meta("__keycode");
+ Ref<InputEventKey> k;
+ k.instance();
+
+ if (physical_key_checkbox->is_pressed()) {
+ k->set_physical_keycode(kc);
+ k->set_keycode(0);
+ } else {
+ k->set_physical_keycode(0);
+ k->set_keycode(kc);
+ }
+
+ // Maintain modifier state from checkboxes
+ k->set_alt(mod_checkboxes[MOD_ALT]->is_pressed());
+ k->set_shift(mod_checkboxes[MOD_SHIFT]->is_pressed());
+ k->set_command(mod_checkboxes[MOD_COMMAND]->is_pressed());
+ k->set_control(mod_checkboxes[MOD_CONTROL]->is_pressed());
+ k->set_metakey(mod_checkboxes[MOD_META]->is_pressed());
+ k->set_store_command(store_command_checkbox->is_pressed());
+
+ _set_event(k);
+ } break;
+ case InputEventConfigurationDialog::INPUT_MOUSE_BUTTON: {
+ int idx = selected->get_meta("__index");
+ Ref<InputEventMouseButton> mb;
+ mb.instance();
+ mb->set_button_index(idx);
+ // Maintain modifier state from checkboxes
+ mb->set_alt(mod_checkboxes[MOD_ALT]->is_pressed());
+ mb->set_shift(mod_checkboxes[MOD_SHIFT]->is_pressed());
+ mb->set_command(mod_checkboxes[MOD_COMMAND]->is_pressed());
+ mb->set_control(mod_checkboxes[MOD_CONTROL]->is_pressed());
+ mb->set_metakey(mod_checkboxes[MOD_META]->is_pressed());
+ mb->set_store_command(store_command_checkbox->is_pressed());
+
+ _set_event(mb);
+ } break;
+ case InputEventConfigurationDialog::INPUT_JOY_BUTTON: {
+ int idx = selected->get_meta("__index");
+ Ref<InputEventJoypadButton> jb = InputEventJoypadButton::create_reference(idx);
+ _set_event(jb);
+ } break;
+ case InputEventConfigurationDialog::INPUT_JOY_MOTION: {
+ int axis = selected->get_meta("__axis");
+ int value = selected->get_meta("__value");
+
+ Ref<InputEventJoypadMotion> jm;
+ jm.instance();
+ jm->set_axis(axis);
+ jm->set_axis_value(value);
+ _set_event(jm);
+ } break;
+ default:
+ break;
+ }
+}
+
+void InputEventConfigurationDialog::_set_current_device(int i_device) {
+ device_id_option->select(i_device + 1);
+}
+
+int InputEventConfigurationDialog::_get_current_device() const {
+ return device_id_option->get_selected() - 1;
+}
+
+String InputEventConfigurationDialog::_get_device_string(int i_device) const {
+ if (i_device == InputMap::ALL_DEVICES) {
+ return TTR("All Devices");
+ }
+ return TTR("Device") + " " + itos(i_device);
+}
+
+void InputEventConfigurationDialog::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ input_list_search->set_right_icon(input_list_search->get_theme_icon("Search", "EditorIcons"));
+
+ physical_key_checkbox->set_icon(get_theme_icon("KeyboardPhysical", "EditorIcons"));
+
+ icon_cache.keyboard = get_theme_icon("Keyboard", "EditorIcons");
+ icon_cache.mouse = get_theme_icon("Mouse", "EditorIcons");
+ icon_cache.joypad_button = get_theme_icon("JoyButton", "EditorIcons");
+ icon_cache.joypad_axis = get_theme_icon("JoyAxis", "EditorIcons");
+
+ _update_input_list();
+ } break;
+ default:
+ break;
+ }
+}
+
+void InputEventConfigurationDialog::popup_and_configure(const Ref<InputEvent> &p_event) {
+ if (p_event.is_valid()) {
+ _set_event(p_event);
+ } else {
+ // Clear Event
+ _set_event(p_event);
+
+ // Clear Checkbox Values
+ for (int i = 0; i < MOD_MAX; i++) {
+ mod_checkboxes[i]->set_pressed(false);
+ }
+ physical_key_checkbox->set_pressed(false);
+ store_command_checkbox->set_pressed(true);
+ _set_current_device(0);
+
+ // Switch to "Listen" tab
+ tab_container->set_current_tab(0);
+ }
+
+ popup_centered();
+}
+
+Ref<InputEvent> InputEventConfigurationDialog::get_event() const {
+ return event;
+}
+
+void InputEventConfigurationDialog::set_allowed_input_types(int p_type_masks) {
+ allowed_input_types = p_type_masks;
+}
+
+InputEventConfigurationDialog::InputEventConfigurationDialog() {
+ allowed_input_types = INPUT_KEY | INPUT_MOUSE_BUTTON | INPUT_JOY_BUTTON | INPUT_JOY_MOTION;
+
+ set_title("Event Configuration");
+ set_min_size(Size2i(550 * EDSCALE, 0)); // Min width
+
+ VBoxContainer *main_vbox = memnew(VBoxContainer);
+ add_child(main_vbox);
+
+ tab_container = memnew(TabContainer);
+ tab_container->set_tab_align(TabContainer::TabAlign::ALIGN_LEFT);
+ tab_container->set_use_hidden_tabs_for_min_size(true);
+ tab_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ tab_container->connect("tab_selected", callable_mp(this, &InputEventConfigurationDialog::_tab_selected));
+ main_vbox->add_child(tab_container);
+
+ CenterContainer *cc = memnew(CenterContainer);
+ cc->set_name("Listen for Input");
+ event_as_text = memnew(Label);
+ event_as_text->set_align(Label::ALIGN_CENTER);
+ cc->add_child(event_as_text);
+ tab_container->add_child(cc);
+
+ // List of all input options to manually select from.
+
+ VBoxContainer *manual_vbox = memnew(VBoxContainer);
+ manual_vbox->set_name("Manual Selection");
+ manual_vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ tab_container->add_child(manual_vbox);
+
+ input_list_search = memnew(LineEdit);
+ input_list_search->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ input_list_search->set_placeholder(TTR("Filter Inputs"));
+ input_list_search->set_clear_button_enabled(true);
+ input_list_search->connect("text_changed", callable_mp(this, &InputEventConfigurationDialog::_search_term_updated));
+ manual_vbox->add_child(input_list_search);
+
+ input_list_tree = memnew(Tree);
+ input_list_tree->set_custom_minimum_size(Size2(0, 100 * EDSCALE)); // Min height for tree
+ input_list_tree->connect("item_selected", callable_mp(this, &InputEventConfigurationDialog::_input_list_item_selected));
+ input_list_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ manual_vbox->add_child(input_list_tree);
+
+ input_list_tree->set_hide_root(true);
+ input_list_tree->set_columns(1);
+
+ _update_input_list();
+
+ // Additional Options
+ additional_options_container = memnew(VBoxContainer);
+ additional_options_container->hide();
+
+ Label *opts_label = memnew(Label);
+ opts_label->set_text("Additional Options");
+ additional_options_container->add_child(opts_label);
+
+ // Device Selection
+ device_container = memnew(HBoxContainer);
+ device_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+ Label *device_label = memnew(Label);
+ device_label->set_text("Device:");
+ device_container->add_child(device_label);
+
+ device_id_option = memnew(OptionButton);
+ device_id_option->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ device_container->add_child(device_id_option);
+
+ for (int i = -1; i < 8; i++) {
+ device_id_option->add_item(_get_device_string(i));
+ }
+ _set_current_device(0);
+ device_container->hide();
+ additional_options_container->add_child(device_container);
+
+ // Modifier Selection
+ mod_container = memnew(HBoxContainer);
+ for (int i = 0; i < MOD_MAX; i++) {
+ String name = mods[i];
+ mod_checkboxes[i] = memnew(CheckBox);
+ mod_checkboxes[i]->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_mod_toggled), varray(i));
+ mod_checkboxes[i]->set_text(name);
+ mod_container->add_child(mod_checkboxes[i]);
+ }
+
+ mod_container->add_child(memnew(VSeparator));
+
+ store_command_checkbox = memnew(CheckBox);
+ store_command_checkbox->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_store_command_toggled));
+ store_command_checkbox->set_pressed(true);
+ store_command_checkbox->set_text(TTR("Store Command"));
+#ifdef APPLE_STYLE_KEYS
+ store_command_checkbox->set_tooltip(TTR("Toggles between serializing 'command' and 'meta'. Used for compatibility with Windows/Linux style keyboard."));
+#else
+ store_command_checkbox->set_tooltip(TTR("Toggles between serializing 'command' and 'control'. Used for compatibility with Apple Style keyboards."));
+#endif
+ mod_container->add_child(store_command_checkbox);
+
+ mod_container->hide();
+ additional_options_container->add_child(mod_container);
+
+ // Physical Key Checkbox
+
+ physical_key_checkbox = memnew(CheckBox);
+ physical_key_checkbox->set_text(TTR("Use Physical Keycode"));
+ physical_key_checkbox->set_tooltip(TTR("Stores the physical position of the key on the keyboard rather than the keys value. Used for compatibility with non-latin layouts."));
+ physical_key_checkbox->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_physical_keycode_toggled));
+ physical_key_checkbox->hide();
+ additional_options_container->add_child(physical_key_checkbox);
+
+ main_vbox->add_child(additional_options_container);
+
+ // Default to first tab
+ tab_container->set_current_tab(0);
+}
+
+/////////////////////////////////////////
+
+static bool _is_action_name_valid(const String &p_name) {
+ const char32_t *cstr = p_name.get_data();
+ for (int i = 0; cstr[i]; i++) {
+ if (cstr[i] == '/' || cstr[i] == ':' || cstr[i] == '"' ||
+ cstr[i] == '=' || cstr[i] == '\\' || cstr[i] < 32) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void ActionMapEditor::_event_config_confirmed() {
+ Ref<InputEvent> ev = event_config_dialog->get_event();
+
+ Dictionary new_action = current_action.duplicate();
+ Array events = new_action["events"];
+
+ if (current_action_event_index == -1) {
+ // Add new event
+ events.push_back(ev);
+ } else {
+ // Edit existing event
+ events[current_action_event_index] = ev;
+ }
+
+ new_action["events"] = events;
+ emit_signal("action_edited", current_action_name, new_action);
+}
+
+void ActionMapEditor::_add_action_pressed() {
+ _add_action(add_edit->get_text());
+}
+
+void ActionMapEditor::_add_action(const String &p_name) {
+ if (!allow_editing_actions) {
+ return;
+ }
+
+ if (p_name == "" || !_is_action_name_valid(p_name)) {
+ show_message(TTR("Invalid action name. it cannot be.is_empty()() nor contain '/', ':', '=', '\\' or '\"'"));
+ return;
+ }
+
+ add_edit->clear();
+ emit_signal("action_added", p_name);
+}
+
+void ActionMapEditor::_action_edited() {
+ if (!allow_editing_actions) {
+ return;
+ }
+
+ TreeItem *ti = action_tree->get_edited();
+ if (!ti) {
+ return;
+ }
+
+ if (action_tree->get_selected_column() == 0) {
+ // Name Edited
+ String new_name = ti->get_text(0);
+ String old_name = ti->get_meta("__name");
+
+ if (new_name == old_name) {
+ return;
+ }
+
+ if (new_name == "" || !_is_action_name_valid(new_name)) {
+ ti->set_text(0, old_name);
+ show_message(TTR("Invalid action name. it cannot be.is_empty()() nor contain '/', ':', '=', '\\' or '\"'"));
+ return;
+ }
+
+ emit_signal("action_renamed", old_name, new_name);
+ } else if (action_tree->get_selected_column() == 1) {
+ // Deadzone Edited
+ String name = ti->get_meta("__name");
+ Dictionary old_action = ti->get_meta("__action");
+ Dictionary new_action = old_action.duplicate();
+ new_action["deadzone"] = ti->get_range(1);
+
+ // Call deferred so that input can finish propagating through tree, allowing re-making of tree to occur.
+ call_deferred("emit_signal", "action_edited", name, new_action);
+ }
+}
+
+void ActionMapEditor::_tree_button_pressed(Object *p_item, int p_column, int p_id) {
+ ItemButton option = (ItemButton)p_id;
+
+ TreeItem *item = Object::cast_to<TreeItem>(p_item);
+ if (!item) {
+ return;
+ }
+
+ switch (option) {
+ case ActionMapEditor::BUTTON_ADD_EVENT: {
+ current_action = item->get_meta("__action");
+ current_action_name = item->get_meta("__name");
+ current_action_event_index = -1;
+
+ event_config_dialog->popup_and_configure();
+
+ } break;
+ case ActionMapEditor::BUTTON_EDIT_EVENT: {
+ // Action and Action name is located on the parent of the event.
+ current_action = item->get_parent()->get_meta("__action");
+ current_action_name = item->get_parent()->get_meta("__name");
+
+ current_action_event_index = item->get_meta("__index");
+
+ Ref<InputEvent> ie = item->get_meta("__event");
+ if (ie.is_valid()) {
+ event_config_dialog->popup_and_configure(ie);
+ }
+
+ } break;
+ case ActionMapEditor::BUTTON_REMOVE_ACTION: {
+ if (!allow_editing_actions) {
+ break;
+ }
+
+ // Send removed action name
+ String name = item->get_meta("__name");
+ emit_signal("action_removed", name);
+ } break;
+ case ActionMapEditor::BUTTON_REMOVE_EVENT: {
+ // Remove event and send updated action
+ Dictionary action = item->get_parent()->get_meta("__action");
+ String action_name = item->get_parent()->get_meta("__name");
+
+ int event_index = item->get_meta("__index");
+
+ Array events = action["events"];
+ events.remove(event_index);
+ action["events"] = events;
+
+ emit_signal("action_edited", action_name, action);
+ } break;
+ default:
+ break;
+ }
+}
+
+void ActionMapEditor::_tree_item_activated() {
+ TreeItem *item = action_tree->get_selected();
+
+ if (!item || !item->has_meta("__event")) {
+ return;
+ }
+
+ _tree_button_pressed(item, 2, BUTTON_EDIT_EVENT);
+}
+
+void ActionMapEditor::set_show_uneditable(bool p_show) {
+ show_uneditable = p_show;
+ show_uneditable_actions_checkbox->set_pressed(p_show);
+
+ // Prevent unnecessary updates of action list when cache is.is_empty()().
+ if (!actions_cache.is_empty()) {
+ update_action_list();
+ }
+}
+
+void ActionMapEditor::_search_term_updated(const String &) {
+ update_action_list();
+}
+
+Variant ActionMapEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
+ TreeItem *selected = action_tree->get_selected();
+ if (!selected) {
+ return Variant();
+ }
+
+ String name = selected->get_text(0);
+ Label *label = memnew(Label(name));
+ label->set_modulate(Color(1, 1, 1, 1.0f));
+ action_tree->set_drag_preview(label);
+
+ Dictionary drag_data;
+
+ if (selected->has_meta("__action")) {
+ drag_data["input_type"] = "action";
+ }
+
+ if (selected->has_meta("__event")) {
+ drag_data["input_type"] = "event";
+ }
+
+ action_tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
+
+ return drag_data;
+}
+
+bool ActionMapEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+ Dictionary d = p_data;
+ if (!d.has("input_type")) {
+ return false;
+ }
+
+ TreeItem *selected = action_tree->get_selected();
+ TreeItem *item = action_tree->get_item_at_position(p_point);
+ if (!selected || !item || item == selected) {
+ return false;
+ }
+
+ // Don't allow moving an action in-between events.
+ if (d["input_type"] == "action" && item->has_meta("__event")) {
+ return false;
+ }
+
+ // Don't allow moving an event to a different action.
+ if (d["input_type"] == "event" && item->get_parent() != selected->get_parent()) {
+ return false;
+ }
+
+ return true;
+}
+
+void ActionMapEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+ if (!can_drop_data_fw(p_point, p_data, p_from)) {
+ return;
+ }
+
+ TreeItem *selected = action_tree->get_selected();
+ TreeItem *target = action_tree->get_item_at_position(p_point);
+ bool drop_above = action_tree->get_drop_section_at_position(p_point) == -1;
+
+ if (!target) {
+ return;
+ }
+
+ Dictionary d = p_data;
+ if (d["input_type"] == "action") {
+ // Change action order.
+ String relative_to = target->get_meta("__name");
+ String action_name = selected->get_meta("__name");
+ emit_signal("action_reordered", action_name, relative_to, drop_above);
+
+ } else if (d["input_type"] == "event") {
+ // Change event order
+ int current_index = selected->get_meta("__index");
+ int target_index = target->get_meta("__index");
+
+ // Construct new events array.
+ Dictionary new_action = selected->get_parent()->get_meta("__action");
+
+ Array events = new_action["events"];
+ Array new_events;
+
+ // The following method was used to perform the array changes since `remove` followed by `insert` was not working properly at time of writing.
+ // Loop thought existing events
+ for (int i = 0; i < events.size(); i++) {
+ // If you come across the current index, just skip it, as it has been moved.
+ if (i == current_index) {
+ continue;
+ } else if (i == target_index) {
+ // We are at the target index. If drop above, add selected event there first, then target, so moved event goes on top.
+ if (drop_above) {
+ new_events.push_back(events[current_index]);
+ new_events.push_back(events[target_index]);
+ } else {
+ new_events.push_back(events[target_index]);
+ new_events.push_back(events[current_index]);
+ }
+ } else {
+ new_events.push_back(events[i]);
+ }
+ }
+
+ new_action["events"] = new_events;
+ emit_signal("action_edited", selected->get_parent()->get_meta("__name"), new_action);
+ }
+}
+
+void ActionMapEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ action_list_search->set_right_icon(get_theme_icon("Search", "EditorIcons"));
+ } break;
+ default:
+ break;
+ }
+}
+
+void ActionMapEditor::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ActionMapEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ActionMapEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &ActionMapEditor::drop_data_fw);
+
+ ADD_SIGNAL(MethodInfo("action_added", PropertyInfo(Variant::STRING, "name")));
+ ADD_SIGNAL(MethodInfo("action_edited", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::DICTIONARY, "new_action")));
+ 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")));
+}
+
+LineEdit *ActionMapEditor::get_search_box() const {
+ return action_list_search;
+}
+
+InputEventConfigurationDialog *ActionMapEditor::get_configuration_dialog() {
+ return event_config_dialog;
+}
+
+void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_infos) {
+ if (!p_action_infos.is_empty()) {
+ actions_cache = p_action_infos;
+ }
+
+ action_tree->clear();
+ TreeItem *root = action_tree->create_item();
+
+ int uneditable_count = 0;
+
+ for (int i = 0; i < actions_cache.size(); i++) {
+ ActionInfo action_info = actions_cache[i];
+
+ if (!action_info.editable) {
+ uneditable_count++;
+ }
+
+ String search_term = action_list_search->get_text();
+ if (!search_term.is_empty() && action_info.name.findn(search_term) == -1) {
+ continue;
+ }
+
+ if (!action_info.editable && !show_uneditable) {
+ continue;
+ }
+
+ const Array events = action_info.action["events"];
+ const Variant deadzone = action_info.action["deadzone"];
+
+ // Update Tree...
+
+ TreeItem *action_item = action_tree->create_item(root);
+ action_item->set_meta("__action", action_info.action);
+ action_item->set_meta("__name", action_info.name);
+
+ // First Column - Action Name
+ action_item->set_text(0, action_info.name);
+ action_item->set_editable(0, action_info.editable);
+ action_item->set_icon(0, action_info.icon);
+
+ // Second Column - Deadzone
+ action_item->set_editable(1, true);
+ action_item->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
+ action_item->set_range_config(1, 0.0, 1.0, 0.01);
+ action_item->set_range(1, deadzone);
+
+ // Third column - buttons
+ action_item->add_button(2, action_tree->get_theme_icon("Add", "EditorIcons"), BUTTON_ADD_EVENT, false, TTR("Add Event"));
+ action_item->add_button(2, action_tree->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_ACTION, !action_info.editable, action_info.editable ? "Remove Action" : "Cannot Remove Action");
+
+ action_item->set_custom_bg_color(0, action_tree->get_theme_color("prop_subsection", "Editor"));
+ action_item->set_custom_bg_color(1, action_tree->get_theme_color("prop_subsection", "Editor"));
+
+ for (int evnt_idx = 0; evnt_idx < events.size(); evnt_idx++) {
+ Ref<InputEvent> event = events[evnt_idx];
+ if (event.is_null()) {
+ continue;
+ }
+
+ TreeItem *event_item = action_tree->create_item(action_item);
+
+ // First Column - Text
+ event_item->set_text(0, event_config_dialog->get_event_text(event)); // Need to us the special description for JoypadMotion here, so don't use as_text() directly.
+ event_item->set_meta("__event", event);
+ event_item->set_meta("__index", evnt_idx);
+
+ // Third Column - Buttons
+ event_item->add_button(2, action_tree->get_theme_icon("Edit", "EditorIcons"), BUTTON_EDIT_EVENT, false, TTR("Edit Event"));
+ event_item->add_button(2, action_tree->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_EVENT, false, TTR("Remove Event"));
+ event_item->set_button_color(2, 0, Color(1, 1, 1, 0.75));
+ event_item->set_button_color(2, 1, Color(1, 1, 1, 0.75));
+ }
+ }
+}
+
+void ActionMapEditor::show_message(const String &p_message) {
+ message->set_text(p_message);
+ message->popup_centered(Size2(300, 100) * EDSCALE);
+}
+
+void ActionMapEditor::set_allow_editing_actions(bool p_allow) {
+ allow_editing_actions = p_allow;
+ add_hbox->set_visible(p_allow);
+}
+
+void ActionMapEditor::set_toggle_editable_label(const String &p_label) {
+ show_uneditable_actions_checkbox->set_text(p_label);
+}
+
+void ActionMapEditor::use_external_search_box(LineEdit *p_searchbox) {
+ memdelete(action_list_search);
+ action_list_search = p_searchbox;
+ action_list_search->connect("text_changed", callable_mp(this, &ActionMapEditor::_search_term_updated));
+}
+
+ActionMapEditor::ActionMapEditor() {
+ allow_editing_actions = true;
+ show_uneditable = true;
+
+ // Main Vbox Container
+ VBoxContainer *main_vbox = memnew(VBoxContainer);
+ main_vbox->set_anchors_and_offsets_preset(PRESET_WIDE);
+ add_child(main_vbox);
+
+ HBoxContainer *top_hbox = memnew(HBoxContainer);
+ main_vbox->add_child(top_hbox);
+
+ action_list_search = memnew(LineEdit);
+ action_list_search->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ action_list_search->set_placeholder(TTR("Filter Actions"));
+ action_list_search->set_clear_button_enabled(true);
+ action_list_search->connect("text_changed", callable_mp(this, &ActionMapEditor::_search_term_updated));
+ top_hbox->add_child(action_list_search);
+
+ show_uneditable_actions_checkbox = memnew(CheckBox);
+ show_uneditable_actions_checkbox->set_pressed(false);
+ show_uneditable_actions_checkbox->set_text(TTR("Show Uneditable Actions"));
+ show_uneditable_actions_checkbox->connect("toggled", callable_mp(this, &ActionMapEditor::set_show_uneditable));
+ top_hbox->add_child(show_uneditable_actions_checkbox);
+
+ // Adding Action line edit + button
+ add_hbox = memnew(HBoxContainer);
+ add_hbox->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+ add_edit = memnew(LineEdit);
+ add_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ add_edit->set_placeholder(TTR("Add New Action"));
+ add_edit->set_clear_button_enabled(true);
+ add_edit->connect("text_entered", callable_mp(this, &ActionMapEditor::_add_action));
+ add_hbox->add_child(add_edit);
+
+ Button *add_button = memnew(Button);
+ add_button->set_text("Add");
+ add_button->connect("pressed", callable_mp(this, &ActionMapEditor::_add_action_pressed));
+ add_hbox->add_child(add_button);
+
+ main_vbox->add_child(add_hbox);
+
+ // Action Editor Tree
+ action_tree = memnew(Tree);
+ action_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ action_tree->set_columns(3);
+ action_tree->set_hide_root(true);
+ action_tree->set_column_titles_visible(true);
+ action_tree->set_column_title(0, TTR("Action"));
+ action_tree->set_column_title(1, TTR("Deadzone"));
+ action_tree->set_column_expand(1, false);
+ action_tree->set_column_min_width(1, 80 * EDSCALE);
+ action_tree->set_column_expand(2, false);
+ action_tree->set_column_min_width(2, 50 * EDSCALE);
+ action_tree->connect("item_edited", callable_mp(this, &ActionMapEditor::_action_edited));
+ action_tree->connect("item_activated", callable_mp(this, &ActionMapEditor::_tree_item_activated));
+ action_tree->connect("button_pressed", callable_mp(this, &ActionMapEditor::_tree_button_pressed));
+ main_vbox->add_child(action_tree);
+
+ action_tree->set_drag_forwarding(this);
+
+ // Adding event dialog
+ event_config_dialog = memnew(InputEventConfigurationDialog);
+ event_config_dialog->connect("confirmed", callable_mp(this, &ActionMapEditor::_event_config_confirmed));
+ add_child(event_config_dialog);
+
+ message = memnew(AcceptDialog);
+ add_child(message);
+}
diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h
new file mode 100644
index 0000000000..f1f7bffef4
--- /dev/null
+++ b/editor/action_map_editor.h
@@ -0,0 +1,203 @@
+/*************************************************************************/
+/* action_map_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 ACTION_MAP_EDITOR_H
+#define ACTION_MAP_EDITOR_H
+
+#include "editor/editor_data.h"
+
+// Confirmation Dialog used when configuring an input event.
+// Separate from ActionMapEditor for code cleanliness and separation of responsibilities.
+class InputEventConfigurationDialog : public ConfirmationDialog {
+ GDCLASS(InputEventConfigurationDialog, ConfirmationDialog);
+
+public:
+ enum InputType {
+ INPUT_KEY = 1,
+ INPUT_MOUSE_BUTTON = 2,
+ INPUT_JOY_BUTTON = 4,
+ INPUT_JOY_MOTION = 8
+ };
+
+private:
+ struct IconCache {
+ Ref<Texture2D> keyboard;
+ Ref<Texture2D> mouse;
+ Ref<Texture2D> joypad_button;
+ Ref<Texture2D> joypad_axis;
+ } icon_cache;
+
+ Ref<InputEvent> event = Ref<InputEvent>();
+
+ TabContainer *tab_container;
+
+ // Listening for input
+ Label *event_as_text;
+
+ // List of All Key/Mouse/Joypad input options.
+ int allowed_input_types;
+ Tree *input_list_tree;
+ LineEdit *input_list_search;
+
+ // Additional Options, shown depending on event selected
+ VBoxContainer *additional_options_container;
+
+ HBoxContainer *device_container;
+ OptionButton *device_id_option;
+
+ HBoxContainer *mod_container; // Contains the subcontainer and the store command checkbox.
+
+ enum ModCheckbox {
+ MOD_ALT,
+ MOD_SHIFT,
+ MOD_COMMAND,
+ MOD_CONTROL,
+ MOD_META,
+ MOD_MAX
+ };
+ String mods[MOD_MAX] = { "Alt", "Shift", "Command", "Control", "Meta" };
+
+ CheckBox *mod_checkboxes[MOD_MAX];
+ CheckBox *store_command_checkbox;
+
+ CheckBox *physical_key_checkbox;
+
+ void _set_event(const Ref<InputEvent> &p_event);
+
+ void _tab_selected(int p_tab);
+ void _listen_window_input(const Ref<InputEvent> &p_event);
+
+ void _search_term_updated(const String &p_term);
+ void _update_input_list();
+ void _input_list_item_selected();
+
+ void _mod_toggled(bool p_checked, int p_index);
+ void _store_command_toggled(bool p_checked);
+ void _physical_keycode_toggled(bool p_checked);
+
+ void _set_current_device(int i_device);
+ int _get_current_device() const;
+ String _get_device_string(int i_device) const;
+
+protected:
+ void _notification(int p_what);
+
+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);
+
+ void set_allowed_input_types(int p_type_masks);
+
+ InputEventConfigurationDialog();
+};
+
+class ActionMapEditor : public Control {
+ GDCLASS(ActionMapEditor, Control);
+
+public:
+ struct ActionInfo {
+ String name = String();
+ Dictionary action = Dictionary();
+
+ Ref<Texture2D> icon = Ref<Texture2D>();
+ bool editable = true;
+ };
+
+private:
+ enum ItemButton {
+ BUTTON_ADD_EVENT,
+ BUTTON_EDIT_EVENT,
+ BUTTON_REMOVE_ACTION,
+ BUTTON_REMOVE_EVENT,
+ };
+
+ Vector<ActionInfo> actions_cache;
+ Tree *action_tree;
+
+ // Storing which action/event is currently being edited in the InputEventConfigurationDialog.
+
+ Dictionary current_action = Dictionary();
+ String current_action_name = String();
+ int current_action_event_index = -1;
+
+ // Popups
+
+ InputEventConfigurationDialog *event_config_dialog;
+ AcceptDialog *message;
+
+ // Filtering and Adding actions
+
+ bool show_uneditable;
+ CheckBox *show_uneditable_actions_checkbox;
+ LineEdit *action_list_search;
+
+ bool allow_editing_actions;
+ HBoxContainer *add_hbox;
+ LineEdit *add_edit;
+
+ void _event_config_confirmed();
+
+ void _add_action_pressed();
+ void _add_action(const String &p_name);
+ void _action_edited();
+
+ void _tree_button_pressed(Object *p_item, int p_column, int p_id);
+ void _tree_item_activated();
+ void _search_term_updated(const String &p_search_term);
+
+ 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);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ LineEdit *get_search_box() const;
+ InputEventConfigurationDialog *get_configuration_dialog();
+
+ // Dictionary represents an Action with "events" (Array) and "deadzone" (float) items. Pass with no param to update list from cached action map.
+ void update_action_list(const Vector<ActionInfo> &p_action_infos = Vector<ActionInfo>());
+ void show_message(const String &p_message);
+
+ void set_show_uneditable(bool p_show);
+ void set_allow_editing_actions(bool p_allow);
+
+ void set_toggle_editable_label(const String &p_label);
+
+ void use_external_search_box(LineEdit *p_searchbox);
+
+ ActionMapEditor();
+};
+
+#endif
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 5d2b825c4f..92b4683018 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -615,7 +615,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
float v_zoom_orig = v_zoom;
if (mb->get_command()) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05);
@@ -628,7 +628,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
update();
}
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
float v_zoom_orig = v_zoom;
if (mb->get_command()) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05);
@@ -641,7 +641,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
update();
}
- if (mb.is_valid() && mb->get_button_index() == BUTTON_MIDDLE) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_MIDDLE) {
if (mb->is_pressed()) {
int x = mb->get_position().x - timeline->get_name_limit();
panning_timeline_from = x / timeline->get_zoom_scale();
@@ -652,7 +652,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) {
menu_insert_key = mb->get_position();
if (menu_insert_key.x >= timeline->get_name_limit() && menu_insert_key.x <= get_size().width - timeline->get_buttons_width()) {
Vector2 popup_pos = get_global_transform().xform(mb->get_position());
@@ -672,7 +672,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (close_icon_rect.has_point(mb->get_position())) {
emit_signal("close_request");
return;
@@ -789,7 +789,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (box_selecting_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (box_selecting_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (box_selecting) {
//do actual select
if (!box_selecting_add) {
@@ -819,7 +819,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
update();
}
- if (moving_handle != 0 && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (moving_handle != 0 && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
undo_redo->create_action(TTR("Move Bezier Points"));
undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_in_handle", track, moving_handle_key, moving_handle_left);
undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_out_handle", track, moving_handle_key, moving_handle_right);
@@ -831,7 +831,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
update();
}
- if (moving_selection_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (moving_selection_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (moving_selection) {
//combit it
@@ -927,7 +927,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_MIDDLE) {
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) {
v_scroll += mm->get_relative().y * v_zoom;
if (v_scroll > 100000) {
v_scroll = 100000;
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 5d49290612..4274fb993f 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -634,7 +634,7 @@ public:
bool use_fps = false;
void notify_change() {
- _change_notify();
+ notify_property_list_changed();
}
Node *get_root_path() {
@@ -643,7 +643,7 @@ public:
void set_use_fps(bool p_enable) {
use_fps = p_enable;
- _change_notify();
+ notify_property_list_changed();
}
};
@@ -1276,7 +1276,7 @@ public:
UndoRedo *undo_redo = nullptr;
void notify_change() {
- _change_notify();
+ notify_property_list_changed();
}
Node *get_root_path() {
@@ -1285,7 +1285,7 @@ public:
void set_use_fps(bool p_enable) {
use_fps = p_enable;
- _change_notify();
+ notify_property_list_changed();
}
};
@@ -1643,24 +1643,24 @@ void AnimationTimelineEdit::_play_position_draw() {
void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && hsize_rect.has_point(mb->get_position())) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && hsize_rect.has_point(mb->get_position())) {
dragging_hsize = true;
dragging_hsize_from = mb->get_position().x;
dragging_hsize_at = name_limit;
}
- if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && dragging_hsize) {
+ if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && dragging_hsize) {
dragging_hsize = false;
}
if (mb.is_valid() && mb->get_position().x > get_name_limit() && mb->get_position().x < (get_size().width - get_buttons_width())) {
- if (!panning_timeline && mb->get_button_index() == BUTTON_LEFT) {
+ if (!panning_timeline && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
int x = mb->get_position().x - get_name_limit();
float ofs = x / get_zoom_scale() + get_value();
emit_signal("timeline_changed", ofs, false);
dragging_timeline = true;
}
- if (!dragging_timeline && mb->get_button_index() == BUTTON_MIDDLE) {
+ if (!dragging_timeline && mb->get_button_index() == MOUSE_BUTTON_MIDDLE) {
int x = mb->get_position().x - get_name_limit();
panning_timeline_from = x / get_zoom_scale();
panning_timeline = true;
@@ -1668,11 +1668,11 @@ void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (dragging_timeline && mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) {
+ if (dragging_timeline && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) {
dragging_timeline = false;
}
- if (panning_timeline && mb.is_valid() && mb->get_button_index() == BUTTON_MIDDLE && !mb->is_pressed()) {
+ if (panning_timeline && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_MIDDLE && !mb->is_pressed()) {
panning_timeline = false;
}
@@ -2540,7 +2540,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
Point2 pos = mb->get_position();
if (check_rect.has_point(pos)) {
@@ -2683,7 +2683,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
Point2 pos = mb->get_position();
if (pos.x >= timeline->get_name_limit() && pos.x <= get_size().width - timeline->get_buttons_width()) {
// Can do something with menu too! show insert key.
@@ -2713,7 +2713,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && clicking_on_name) {
+ if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && clicking_on_name) {
if (!path) {
path_popup = memnew(Popup);
path_popup->set_wrap_controls(true);
@@ -2735,7 +2735,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
if (mb.is_valid() && moving_selection_attempt) {
- if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
moving_selection_attempt = false;
if (moving_selection) {
emit_signal("move_selection_commit");
@@ -2746,7 +2746,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
select_single_attempt = -1;
}
- if (moving_selection && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ if (moving_selection && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
moving_selection_attempt = false;
moving_selection = false;
emit_signal("move_selection_cancel");
@@ -2754,7 +2754,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT && moving_selection_attempt) {
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && moving_selection_attempt) {
if (!moving_selection) {
moving_selection = true;
emit_signal("move_selection_begin");
@@ -4283,7 +4283,6 @@ void AnimationTrackEditor::_animation_update() {
_update_step_spinbox();
emit_signal("animation_step_changed", animation->get_step());
emit_signal("animation_len_changed", animation->get_length());
- EditorNode::get_singleton()->get_inspector()->refresh();
animation_changing_awaiting_update = false;
}
@@ -4440,6 +4439,8 @@ void AnimationTrackEditor::_add_track(int p_type) {
}
adding_track_type = p_type;
pick_track->popup_scenetree_dialog();
+ pick_track->get_filter_line_edit()->clear();
+ pick_track->get_filter_line_edit()->grab_focus();
}
void AnimationTrackEditor::_new_track_property_selected(String p_name) {
@@ -4954,17 +4955,17 @@ void AnimationTrackEditor::_box_selection_draw() {
void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_UP) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05);
scroll->accept_event();
}
- if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05);
scroll->accept_event();
}
- if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
box_selecting = true;
box_selecting_from = scroll->get_global_transform().xform(mb->get_position());
@@ -4992,12 +4993,12 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_MIDDLE) {
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) {
timeline->set_value(timeline->get_value() - mm->get_relative().x / timeline->get_zoom_scale());
}
if (mm.is_valid() && box_selecting) {
- if (!(mm->get_button_mask() & BUTTON_MASK_LEFT)) {
+ if (!(mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT)) {
//no longer
box_selection->hide();
box_selecting = false;
@@ -5636,6 +5637,70 @@ void AnimationTrackEditor::_bind_methods() {
ADD_SIGNAL(MethodInfo("animation_step_changed", PropertyInfo(Variant::FLOAT, "step")));
}
+void AnimationTrackEditor::_pick_track_filter_text_changed(const String &p_newtext) {
+ TreeItem *root_item = pick_track->get_scene_tree()->get_scene_tree()->get_root();
+
+ Vector<Node *> select_candidates;
+ Node *to_select = nullptr;
+
+ String filter = pick_track->get_filter_line_edit()->get_text();
+
+ _pick_track_select_recursive(root_item, filter, select_candidates);
+
+ if (!select_candidates.is_empty()) {
+ for (int i = 0; i < select_candidates.size(); ++i) {
+ Node *candidate = select_candidates[i];
+
+ if (((String)candidate->get_name()).to_lower().begins_with(filter.to_lower())) {
+ to_select = candidate;
+ break;
+ }
+ }
+
+ if (!to_select) {
+ to_select = select_candidates[0];
+ }
+ }
+
+ pick_track->get_scene_tree()->set_selected(to_select);
+}
+
+void AnimationTrackEditor::_pick_track_select_recursive(TreeItem *p_item, const String &p_filter, Vector<Node *> &p_select_candidates) {
+ if (!p_item) {
+ return;
+ }
+
+ NodePath np = p_item->get_metadata(0);
+ Node *node = get_node(np);
+
+ if (p_filter != String() && ((String)node->get_name()).findn(p_filter) != -1) {
+ p_select_candidates.push_back(node);
+ }
+
+ TreeItem *c = p_item->get_children();
+
+ while (c) {
+ _pick_track_select_recursive(c, p_filter, p_select_candidates);
+ c = c->get_next();
+ }
+}
+
+void AnimationTrackEditor::_pick_track_filter_input(const Ref<InputEvent> &p_ie) {
+ Ref<InputEventKey> k = p_ie;
+
+ if (k.is_valid()) {
+ switch (k->get_keycode()) {
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_PAGEUP:
+ case KEY_PAGEDOWN: {
+ pick_track->get_scene_tree()->get_scene_tree()->call("_gui_input", k);
+ pick_track->get_filter_line_edit()->accept_event();
+ } break;
+ }
+ }
+}
+
AnimationTrackEditor::AnimationTrackEditor() {
root = nullptr;
@@ -5806,8 +5871,12 @@ AnimationTrackEditor::AnimationTrackEditor() {
pick_track = memnew(SceneTreeDialog);
add_child(pick_track);
+ pick_track->register_text_enter(pick_track->get_filter_line_edit());
pick_track->set_title(TTR("Pick a node to animate:"));
pick_track->connect("selected", callable_mp(this, &AnimationTrackEditor::_new_track_node_selected));
+ pick_track->get_filter_line_edit()->connect("text_changed", callable_mp(this, &AnimationTrackEditor::_pick_track_filter_text_changed));
+ pick_track->get_filter_line_edit()->connect("gui_input", callable_mp(this, &AnimationTrackEditor::_pick_track_filter_input));
+
prop_selector = memnew(PropertySelector);
add_child(prop_selector);
prop_selector->connect("selected", callable_mp(this, &AnimationTrackEditor::_new_track_property_selected));
@@ -5886,7 +5955,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
optimize_max_angle->set_value(22);
optimize_dialog->get_ok_button()->set_text(TTR("Optimize"));
- optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_CLEAN_UP_ANIMATION_CONFIRM));
+ optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_OPTIMIZE_ANIMATION_CONFIRM));
//
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index e8e4f915fa..c25865effb 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -499,6 +499,10 @@ class AnimationTrackEditor : public VBoxContainer {
void _insert_animation_key(NodePath p_path, const Variant &p_value);
+ void _pick_track_filter_text_changed(const String &p_newtext);
+ void _pick_track_select_recursive(TreeItem *p_item, const String &p_filter, Vector<Node *> &p_select_candidates);
+ void _pick_track_filter_input(const Ref<InputEvent> &p_ie);
+
protected:
static void _bind_methods();
void _notification(int p_what);
diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp
index 0c0ee2856e..fa27dfb3e5 100644
--- a/editor/animation_track_editor_plugins.cpp
+++ b/editor/animation_track_editor_plugins.cpp
@@ -1076,7 +1076,7 @@ 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() == BUTTON_LEFT && get_default_cursor_shape() == CURSOR_HSIZE) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && get_default_cursor_shape() == CURSOR_HSIZE) {
len_resizing = true;
len_resizing_start = mb->get_shift();
len_resizing_from_px = mb->get_position().x;
@@ -1086,7 +1086,7 @@ void AnimationTrackEditTypeAudio::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
- if (len_resizing && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (len_resizing && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
float ofs_local = -len_resizing_rel / get_timeline()->get_zoom_scale();
if (len_resizing_start) {
float prev_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), len_resizing_index);
diff --git a/editor/array_property_edit.cpp b/editor/array_property_edit.cpp
index 3daee4587c..09defac354 100644
--- a/editor/array_property_edit.cpp
+++ b/editor/array_property_edit.cpp
@@ -49,11 +49,7 @@ Variant ArrayPropertyEdit::get_array() const {
}
void ArrayPropertyEdit::_notif_change() {
- _change_notify();
-}
-
-void ArrayPropertyEdit::_notif_changev(const String &p_v) {
- _change_notify(p_v.utf8().get_data());
+ notify_property_list_changed();
}
void ArrayPropertyEdit::_set_size(int p_size) {
@@ -120,7 +116,7 @@ bool ArrayPropertyEdit::_set(const StringName &p_name, const Variant &p_value) {
}
if (pn == "array/page") {
page = p_value;
- _change_notify();
+ notify_property_list_changed();
return true;
}
@@ -159,8 +155,6 @@ bool ArrayPropertyEdit::_set(const StringName &p_name, const Variant &p_value) {
ur->create_action(TTR("Change Array Value"));
ur->add_do_method(this, "_set_value", idx, p_value);
ur->add_undo_method(this, "_set_value", idx, value);
- ur->add_do_method(this, "_notif_changev", p_name);
- ur->add_undo_method(this, "_notif_changev", p_name);
ur->commit_action();
return true;
}
@@ -288,7 +282,6 @@ void ArrayPropertyEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_size"), &ArrayPropertyEdit::_set_size);
ClassDB::bind_method(D_METHOD("_set_value"), &ArrayPropertyEdit::_set_value);
ClassDB::bind_method(D_METHOD("_notif_change"), &ArrayPropertyEdit::_notif_change);
- ClassDB::bind_method(D_METHOD("_notif_changev"), &ArrayPropertyEdit::_notif_changev);
ClassDB::bind_method(D_METHOD("_dont_undo_redo"), &ArrayPropertyEdit::_dont_undo_redo);
}
diff --git a/editor/array_property_edit.h b/editor/array_property_edit.h
index dd495b57f4..fa3dcbe038 100644
--- a/editor/array_property_edit.h
+++ b/editor/array_property_edit.h
@@ -47,7 +47,6 @@ class ArrayPropertyEdit : public Reference {
Variant::Type default_type;
void _notif_change();
- void _notif_changev(const String &p_v);
void _set_size(int p_size);
void _set_value(int p_idx, const Variant &p_value);
diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp
index 8be8735f3e..539657afd7 100644
--- a/editor/audio_stream_preview.cpp
+++ b/editor/audio_stream_preview.cpp
@@ -155,7 +155,7 @@ void AudioStreamPreviewGenerator::_preview_thread(void *p_preview) {
preview->playback->stop();
- preview->generating = false;
+ preview->generating.clear();
}
Ref<AudioStreamPreview> AudioStreamPreviewGenerator::generate_preview(const Ref<AudioStream> &p_stream) {
@@ -172,7 +172,7 @@ Ref<AudioStreamPreview> AudioStreamPreviewGenerator::generate_preview(const Ref<
Preview *preview = &previews[p_stream->get_instance_id()];
preview->base_stream = p_stream;
preview->playback = preview->base_stream->instance_playback();
- preview->generating = true;
+ preview->generating.set();
preview->id = p_stream->get_instance_id();
float len_s = preview->base_stream->get_length();
@@ -217,7 +217,7 @@ void AudioStreamPreviewGenerator::_notification(int p_what) {
if (p_what == NOTIFICATION_PROCESS) {
List<ObjectID> to_erase;
for (Map<ObjectID, Preview>::Element *E = previews.front(); E; E = E->next()) {
- if (!E->get().generating) {
+ if (!E->get().generating.is_set()) {
if (E->get().thread) {
E->get().thread->wait_to_finish();
memdelete(E->get().thread);
diff --git a/editor/audio_stream_preview.h b/editor/audio_stream_preview.h
index 21c9ea203e..accc7275c0 100644
--- a/editor/audio_stream_preview.h
+++ b/editor/audio_stream_preview.h
@@ -32,6 +32,7 @@
#define AUDIO_STREAM_PREVIEW_H
#include "core/os/thread.h"
+#include "core/templates/safe_refcount.h"
#include "scene/main/node.h"
#include "servers/audio/audio_stream.h"
@@ -60,9 +61,20 @@ class AudioStreamPreviewGenerator : public Node {
Ref<AudioStreamPreview> preview;
Ref<AudioStream> base_stream;
Ref<AudioStreamPlayback> playback;
- volatile bool generating = false;
+ SafeFlag generating;
ObjectID id;
Thread *thread = nullptr;
+
+ // Needed for the bookkeeping of the Map
+ Preview &operator=(const Preview &p_rhs) {
+ preview = p_rhs.preview;
+ base_stream = p_rhs.base_stream;
+ playback = p_rhs.playback;
+ generating.set_to(generating.is_set());
+ id = p_rhs.id;
+ thread = p_rhs.thread;
+ return *this;
+ }
};
Map<ObjectID, Preview> previews;
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index f4717830bc..11be365f0a 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -723,9 +723,9 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid()) {
if (mb->is_pressed() && mb->get_command()) {
- if (mb->get_button_index() == BUTTON_WHEEL_UP) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
_zoom_in();
- } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
_zoom_out();
}
}
@@ -1548,7 +1548,7 @@ void CodeTextEditor::validate_script() {
void CodeTextEditor::_warning_label_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
_warning_button_pressed();
}
}
@@ -1572,7 +1572,7 @@ void CodeTextEditor::_toggle_scripts_pressed() {
void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
goto_error();
}
}
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 01fa094d38..0c1fb6fe4d 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -98,7 +98,7 @@ public:
}
void notify_changed() {
- _change_notify();
+ notify_property_list_changed();
}
ConnectDialogBinds() {
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 3a63100012..711072f4b2 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -170,6 +170,7 @@ void CreateDialog::_update_search() {
root->set_text(0, base_type);
root->set_icon(0, search_options->get_theme_icon(icon_fallback, "EditorIcons"));
search_options_types[base_type] = root;
+ _configure_search_option_item(root, base_type, ClassDB::class_exists(base_type));
const String search_text = search_box->get_text();
bool empty_search = search_text == "";
@@ -236,7 +237,10 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String
bool can_instance = (p_cpp_type && ClassDB::can_instance(p_type)) || !p_cpp_type;
if (!can_instance) {
r_item->set_custom_color(0, search_options->get_theme_color("disabled_font_color", "Editor"));
+ r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, "NodeDisabled"));
r_item->set_selectable(0, false);
+ } else {
+ r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, icon_fallback));
}
if (search_box->get_text() != "") {
@@ -253,7 +257,6 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String
const String &description = DTR(EditorHelp::get_doc_data()->class_list[p_type].brief_description);
r_item->set_tooltip(0, description);
- r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, icon_fallback));
if (!p_cpp_type && !script_type) {
Ref<Texture2D> icon = EditorNode::get_editor_data().get_custom_types()[custom_type_parents[p_type]][custom_type_indices[p_type]].icon;
diff --git a/editor/debugger/editor_debugger_inspector.h b/editor/debugger/editor_debugger_inspector.h
index cf2d81cbf1..6648c99c03 100644
--- a/editor/debugger/editor_debugger_inspector.h
+++ b/editor/debugger/editor_debugger_inspector.h
@@ -58,7 +58,7 @@ public:
prop_values.clear();
}
- void update() { _change_notify(); }
+ void update() { notify_property_list_changed(); }
EditorDebuggerRemoteObject() {}
};
diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp
index 6db3b94aee..ec92edc795 100644
--- a/editor/debugger/editor_debugger_tree.cpp
+++ b/editor/debugger/editor_debugger_tree.cpp
@@ -129,6 +129,8 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int
updating_scene_tree = true;
const String last_path = get_selected_path();
const String filter = EditorNode::get_singleton()->get_scene_tree_dock()->get_filter();
+ bool filter_changed = filter != last_filter;
+ TreeItem *scroll_item = nullptr;
// Nodes are in a flatten list, depth first. Use a stack of parents, avoid recursion.
List<Pair<TreeItem *, int>> parents;
@@ -162,11 +164,17 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int
if (debugger_id == p_debugger) { // Can use remote id.
if (node.id == inspected_object_id) {
item->select(0);
+ if (filter_changed) {
+ scroll_item = item;
+ }
}
} else { // Must use path
if (last_path == _get_path(item)) {
updating_scene_tree = false; // Force emission of new selection
item->select(0);
+ if (filter_changed) {
+ scroll_item = item;
+ }
updating_scene_tree = true;
}
}
@@ -183,6 +191,9 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int
}
parent->remove_child(item);
memdelete(item);
+ if (scroll_item == item) {
+ scroll_item = nullptr;
+ }
if (had_siblings) {
break; // Parent must survive.
}
@@ -199,6 +210,10 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int
}
}
debugger_id = p_debugger; // Needed by hook, could be avoided if every debugger had its own tree
+ if (scroll_item) {
+ call_deferred("scroll_to_item", scroll_item);
+ }
+ last_filter = filter;
updating_scene_tree = false;
}
diff --git a/editor/debugger/editor_debugger_tree.h b/editor/debugger/editor_debugger_tree.h
index 8c966dffd5..13193344f1 100644
--- a/editor/debugger/editor_debugger_tree.h
+++ b/editor/debugger/editor_debugger_tree.h
@@ -51,6 +51,7 @@ private:
Set<ObjectID> unfold_cache;
PopupMenu *item_menu = nullptr;
EditorFileDialog *file_dialog = nullptr;
+ String last_filter;
String _get_path(TreeItem *p_item);
void _scene_tree_folded(Object *p_obj);
diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp
index 33d08a2f6b..fc0104c07a 100644
--- a/editor/debugger/editor_performance_profiler.cpp
+++ b/editor/debugger/editor_performance_profiler.cpp
@@ -249,7 +249,7 @@ TreeItem *EditorPerformanceProfiler::_create_monitor_item(const StringName &p_mo
void EditorPerformanceProfiler::_marker_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
Vector<StringName> active;
for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) {
if (i.value().item->is_checked(0)) {
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index 9304b116d0..c4290b7cca 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -482,7 +482,7 @@ void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventMouseMotion> mm = p_ev;
if (
- (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) ||
+ (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) ||
(mm.is_valid())) {
int x = me->get_position().x;
x = x * frame_metrics.size() / graph->get_size().width;
@@ -510,7 +510,7 @@ void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) {
hover_metric = -1;
}
- if (mb.is_valid() || mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mb.is_valid() || mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
//cursor_metric=x;
updating_frame = true;
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index d825a980c7..5bb10b3794 100644
--- a/editor/debugger/editor_visual_profiler.cpp
+++ b/editor/debugger/editor_visual_profiler.cpp
@@ -517,7 +517,7 @@ void EditorVisualProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventMouseMotion> mm = p_ev;
if (
- (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) ||
+ (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) ||
(mm.is_valid())) {
int half_w = graph->get_size().width / 2;
int x = me->get_position().x;
@@ -549,7 +549,7 @@ void EditorVisualProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) {
hover_metric = -1;
}
- if (mb.is_valid() || mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mb.is_valid() || mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
//cursor_metric=x;
updating_frame = true;
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index be2b98bf1a..c92e94270e 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -343,7 +343,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
DebuggerMarshalls::ResourceUsage usage;
usage.deserialize(p_data);
- int total = 0;
+ uint64_t total = 0;
for (List<DebuggerMarshalls::ResourceInfo>::Element *E = usage.infos.front(); E; E = E->next()) {
TreeItem *it = vmem_tree->create_item(root);
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 2780b74469..25e155aafe 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -480,8 +480,8 @@ void DependencyRemoveDialog::ok_pressed() {
if (files_to_delete[i] == String(ProjectSettings::get_singleton()->get("application/boot_splash/image"))) {
ProjectSettings::get_singleton()->set("application/boot_splash/image", "");
}
- if (files_to_delete[i] == String(ProjectSettings::get_singleton()->get("rendering/environment/default_environment"))) {
- ProjectSettings::get_singleton()->set("rendering/environment/default_environment", "");
+ if (files_to_delete[i] == String(ProjectSettings::get_singleton()->get("rendering/environment/defaults/default_environment"))) {
+ ProjectSettings::get_singleton()->set("rendering/environment/defaults/default_environment", "");
}
if (files_to_delete[i] == String(ProjectSettings::get_singleton()->get("display/mouse_cursor/custom_image"))) {
ProjectSettings::get_singleton()->set("display/mouse_cursor/custom_image", "");
@@ -492,8 +492,8 @@ void DependencyRemoveDialog::ok_pressed() {
if (files_to_delete[i] == String(ProjectSettings::get_singleton()->get("gui/theme/custom_font"))) {
ProjectSettings::get_singleton()->set("gui/theme/custom_font", "");
}
- if (files_to_delete[i] == String(ProjectSettings::get_singleton()->get("audio/default_bus_layout"))) {
- ProjectSettings::get_singleton()->set("audio/default_bus_layout", "");
+ if (files_to_delete[i] == String(ProjectSettings::get_singleton()->get("audio/buses/default_bus_layout"))) {
+ ProjectSettings::get_singleton()->set("audio/buses/default_bus_layout", "");
}
String path = OS::get_singleton()->get_resource_dir() + files_to_delete[i].replace_first("res://", "/");
diff --git a/editor/dictionary_property_edit.cpp b/editor/dictionary_property_edit.cpp
index 9683003d89..408177e523 100644
--- a/editor/dictionary_property_edit.cpp
+++ b/editor/dictionary_property_edit.cpp
@@ -32,11 +32,7 @@
#include "editor_node.h"
void DictionaryPropertyEdit::_notif_change() {
- _change_notify();
-}
-
-void DictionaryPropertyEdit::_notif_changev(const String &p_v) {
- _change_notify(p_v.utf8().get_data());
+ notify_property_list_changed();
}
void DictionaryPropertyEdit::_set_key(const Variant &p_old_key, const Variant &p_new_key) {
@@ -107,7 +103,6 @@ void DictionaryPropertyEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_key"), &DictionaryPropertyEdit::_set_key);
ClassDB::bind_method(D_METHOD("_set_value"), &DictionaryPropertyEdit::_set_value);
ClassDB::bind_method(D_METHOD("_notif_change"), &DictionaryPropertyEdit::_notif_change);
- ClassDB::bind_method(D_METHOD("_notif_changev"), &DictionaryPropertyEdit::_notif_changev);
ClassDB::bind_method(D_METHOD("_dont_undo_redo"), &DictionaryPropertyEdit::_dont_undo_redo);
}
@@ -128,8 +123,6 @@ bool DictionaryPropertyEdit::_set(const StringName &p_name, const Variant &p_val
ur->create_action(TTR("Change Dictionary Key"));
ur->add_do_method(this, "_set_key", key, p_value);
ur->add_undo_method(this, "_set_key", p_value, key);
- ur->add_do_method(this, "_notif_changev", p_name);
- ur->add_undo_method(this, "_notif_changev", p_name);
ur->commit_action();
return true;
@@ -142,8 +135,6 @@ bool DictionaryPropertyEdit::_set(const StringName &p_name, const Variant &p_val
ur->create_action(TTR("Change Dictionary Value"));
ur->add_do_method(this, "_set_value", key, p_value);
ur->add_undo_method(this, "_set_value", key, value);
- ur->add_do_method(this, "_notif_changev", p_name);
- ur->add_undo_method(this, "_notif_changev", p_name);
ur->commit_action();
return true;
diff --git a/editor/dictionary_property_edit.h b/editor/dictionary_property_edit.h
index 564bbf205b..e0fd945491 100644
--- a/editor/dictionary_property_edit.h
+++ b/editor/dictionary_property_edit.h
@@ -40,7 +40,6 @@ class DictionaryPropertyEdit : public Reference {
StringName property;
void _notif_change();
- void _notif_changev(const String &p_v);
void _set_key(const Variant &p_old_key, const Variant &p_new_key);
void _set_value(const Variant &p_key, const Variant &p_value);
diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp
index 47ea8cbe2a..e29c9593c3 100644
--- a/editor/doc_tools.cpp
+++ b/editor/doc_tools.cpp
@@ -394,13 +394,22 @@ void DocTools::generate(bool p_basic_types) {
method.qualifiers += " ";
}
method.qualifiers += "const";
- } else if (E->get().flags & METHOD_FLAG_VARARG) {
+ }
+
+ if (E->get().flags & METHOD_FLAG_VARARG) {
if (method.qualifiers != "") {
method.qualifiers += " ";
}
method.qualifiers += "vararg";
}
+ if (E->get().flags & METHOD_FLAG_STATIC) {
+ if (method.qualifiers != "") {
+ method.qualifiers += " ";
+ }
+ method.qualifiers += "static";
+ }
+
for (int i = -1; i < E->get().arguments.size(); i++) {
if (i == -1) {
#ifdef DEBUG_METHODS_ENABLED
@@ -647,6 +656,20 @@ void DocTools::generate(bool p_basic_types) {
method.qualifiers += "vararg";
}
+ if (mi.flags & METHOD_FLAG_CONST) {
+ if (method.qualifiers != "") {
+ method.qualifiers += " ";
+ }
+ method.qualifiers += "const";
+ }
+
+ if (mi.flags & METHOD_FLAG_STATIC) {
+ if (method.qualifiers != "") {
+ method.qualifiers += " ";
+ }
+ method.qualifiers += "static";
+ }
+
c.methods.push_back(method);
}
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 2eef4636d6..3a5ebe8e85 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -532,7 +532,7 @@ void EditorAudioBus::_effect_add(int p_which) {
void EditorAudioBus::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) {
Vector2 pos = Vector2(mb->get_position().x, mb->get_position().y);
bus_popup->set_position(get_global_position() + pos);
bus_popup->popup();
@@ -1191,9 +1191,9 @@ void EditorAudioBuses::_load_layout() {
}
void EditorAudioBuses::_load_default_layout() {
- String layout_path = ProjectSettings::get_singleton()->get("audio/default_bus_layout");
+ String layout_path = ProjectSettings::get_singleton()->get("audio/buses/default_bus_layout");
- Ref<AudioBusLayout> state = ResourceLoader::load(layout_path, "", true);
+ Ref<AudioBusLayout> state = ResourceLoader::load(layout_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE);
if (state.is_null()) {
EditorNode::get_singleton()->show_warning(vformat(TTR("There is no '%s' file."), layout_path));
return;
@@ -1209,7 +1209,7 @@ void EditorAudioBuses::_load_default_layout() {
void EditorAudioBuses::_file_dialog_callback(const String &p_string) {
if (file_dialog->get_file_mode() == EditorFileDialog::FILE_MODE_OPEN_FILE) {
- Ref<AudioBusLayout> state = ResourceLoader::load(p_string, "", true);
+ Ref<AudioBusLayout> state = ResourceLoader::load(p_string, "", ResourceFormatLoader::CACHE_MODE_IGNORE);
if (state.is_null()) {
EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an audio bus layout."));
return;
@@ -1257,7 +1257,7 @@ EditorAudioBuses::EditorAudioBuses() {
add_child(top_hb);
file = memnew(Label);
- String layout_path = ProjectSettings::get_singleton()->get("audio/default_bus_layout");
+ String layout_path = ProjectSettings::get_singleton()->get("audio/buses/default_bus_layout");
file->set_text(String(TTR("Layout")) + ": " + layout_path.get_file());
file->set_clip_text(true);
file->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1313,7 +1313,7 @@ EditorAudioBuses::EditorAudioBuses() {
set_v_size_flags(SIZE_EXPAND_FILL);
- edited_path = ProjectSettings::get_singleton()->get("audio/default_bus_layout");
+ edited_path = ProjectSettings::get_singleton()->get("audio/buses/default_bus_layout");
file_dialog = memnew(EditorFileDialog);
List<String> ext;
@@ -1330,7 +1330,7 @@ EditorAudioBuses::EditorAudioBuses() {
void EditorAudioBuses::open_layout(const String &p_path) {
EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
- Ref<AudioBusLayout> state = ResourceLoader::load(p_path, "", true);
+ Ref<AudioBusLayout> state = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE);
if (state.is_null()) {
EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an audio bus layout."));
return;
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 336bf26607..fa4703d425 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -500,6 +500,7 @@ int EditorData::add_edited_scene(int p_at_pos) {
EditedScene es;
es.root = nullptr;
es.path = String();
+ es.file_modified_time = 0;
es.history_current = -1;
es.version = 0;
es.live_edit_root = NodePath(String("/root"));
@@ -656,6 +657,10 @@ void EditorData::set_edited_scene_root(Node *p_root) {
p_root->set_filename(edited_scene[current_edited_scene].path);
}
}
+
+ if (edited_scene[current_edited_scene].path != "") {
+ edited_scene.write[current_edited_scene].file_modified_time = FileAccess::get_modified_time(edited_scene[current_edited_scene].path);
+ }
}
int EditorData::get_edited_scene_count() const {
@@ -687,6 +692,21 @@ uint64_t EditorData::get_scene_version(int p_idx) const {
return edited_scene[p_idx].version;
}
+void EditorData::set_scene_modified_time(int p_idx, uint64_t p_time) {
+ if (p_idx == -1) {
+ p_idx = current_edited_scene;
+ }
+
+ ERR_FAIL_INDEX(p_idx, edited_scene.size());
+
+ edited_scene.write[p_idx].file_modified_time = p_time;
+}
+
+uint64_t EditorData::get_scene_modified_time(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), 0);
+ return edited_scene[p_idx].file_modified_time;
+}
+
String EditorData::get_scene_type(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), String());
if (!edited_scene[p_idx].root) {
@@ -721,7 +741,7 @@ Ref<Script> EditorData::get_scene_root_script(int p_idx) const {
return s;
}
-String EditorData::get_scene_title(int p_idx) const {
+String EditorData::get_scene_title(int p_idx, bool p_always_strip_extension) const {
ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), String());
if (!edited_scene[p_idx].root) {
return TTR("[empty]");
@@ -729,12 +749,28 @@ String EditorData::get_scene_title(int p_idx) const {
if (edited_scene[p_idx].root->get_filename() == "") {
return TTR("[unsaved]");
}
- bool show_ext = EDITOR_DEF("interface/scene_tabs/show_extension", false);
- String name = edited_scene[p_idx].root->get_filename().get_file();
- if (!show_ext) {
- name = name.get_basename();
+
+ const String filename = edited_scene[p_idx].root->get_filename().get_file();
+ const String basename = filename.get_basename();
+
+ if (p_always_strip_extension) {
+ return basename;
+ }
+
+ // Return the filename including the extension if there's ambiguity (e.g. both `foo.tscn` and `foo.scn` are being edited).
+ for (int i = 0; i < edited_scene.size(); i++) {
+ if (i == p_idx) {
+ // Don't compare the edited scene against itself.
+ continue;
+ }
+
+ if (edited_scene[i].root && basename == edited_scene[i].root->get_filename().get_file().get_basename()) {
+ return filename;
+ }
}
- return name;
+
+ // Else, return just the basename as there's no ambiguity.
+ return basename;
}
void EditorData::set_scene_path(int p_idx, const String &p_path) {
@@ -922,6 +958,14 @@ void EditorData::script_class_save_icon_paths() {
}
}
+ Dictionary old;
+ if (ProjectSettings::get_singleton()->has_setting("_global_script_class_icons")) {
+ old = ProjectSettings::get_singleton()->get("_global_script_class_icons");
+ }
+ if ((!old.is_empty() || d.is_empty()) && d.hash() == old.hash()) {
+ return;
+ }
+
if (d.is_empty()) {
if (ProjectSettings::get_singleton()->has_setting("_global_script_class_icons")) {
ProjectSettings::get_singleton()->clear("_global_script_class_icons");
diff --git a/editor/editor_data.h b/editor/editor_data.h
index f14a3fb4e0..dbe729d9d9 100644
--- a/editor/editor_data.h
+++ b/editor/editor_data.h
@@ -111,6 +111,7 @@ public:
struct EditedScene {
Node *root = nullptr;
String path;
+ uint64_t file_modified_time = 0;
Dictionary editor_states;
List<Node *> selection;
Vector<EditorHistory::History> history_stored;
@@ -183,13 +184,15 @@ public:
Node *get_edited_scene_root(int p_idx = -1);
int get_edited_scene_count() const;
Vector<EditedScene> get_edited_scenes() const;
- String get_scene_title(int p_idx) const;
+ String get_scene_title(int p_idx, bool p_always_strip_extension = false) const;
String get_scene_path(int p_idx) const;
String get_scene_type(int p_idx) const;
void set_scene_path(int p_idx, const String &p_path);
Ref<Script> get_scene_root_script(int p_idx) const;
void set_edited_scene_version(uint64_t version, int p_scene_idx = -1);
uint64_t get_scene_version(int p_idx) const;
+ void set_scene_modified_time(int p_idx, uint64_t p_time);
+ uint64_t get_scene_modified_time(int p_idx) const;
void clear_edited_scenes();
void set_edited_scene_live_edit_root(const NodePath &p_root);
NodePath get_edited_scene_live_edit_root();
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index 24256b843e..3c0fe1571c 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -301,6 +301,8 @@ void EditorExportPlatform::gen_debug_flags(Vector<String> &r_flags, int p_flags)
}
Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) {
+ ERR_FAIL_COND_V_MSG(p_total < 1, ERR_PARAMETER_RANGE_ERROR, "Must select at least one file to export.");
+
PackData *pd = (PackData *)p_userdata;
SavedData sd;
@@ -368,6 +370,8 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa
}
Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) {
+ ERR_FAIL_COND_V_MSG(p_total < 1, ERR_PARAMETER_RANGE_ERROR, "Must select at least one file to export.");
+
String path = p_path.replace_first("res://", "");
ZipData *zd = (ZipData *)p_userdata;
@@ -507,6 +511,11 @@ void EditorExportPlatform::_edit_files_with_filter(DirAccess *da, const Vector<S
if (dir.begins_with(".")) {
continue;
}
+
+ if (EditorFileSystem::_should_skip_directory(cur_dir + dir)) {
+ continue;
+ }
+
da->change_dir(dir);
_edit_files_with_filter(da, p_filters, r_list, exclude);
da->change_dir("..");
@@ -819,17 +828,25 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
}
}
+ Error err = OK;
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
+
for (int i = 0; i < export_plugins.size(); i++) {
export_plugins.write[i]->set_export_preset(p_preset);
if (p_so_func) {
for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) {
- p_so_func(p_udata, export_plugins[i]->shared_objects[j]);
+ err = p_so_func(p_udata, export_plugins[i]->shared_objects[j]);
+ if (err != OK) {
+ return err;
+ }
}
}
for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) {
- p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size(), enc_in_filters, enc_ex_filters, key);
+ err = p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size(), enc_in_filters, enc_ex_filters, key);
+ if (err != OK) {
+ return err;
+ }
}
export_plugins.write[i]->_clear();
@@ -851,12 +868,26 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
//file is imported, replace by what it imports
Ref<ConfigFile> config;
config.instance();
- Error err = config->load(path + ".import");
+ err = config->load(path + ".import");
if (err != OK) {
ERR_PRINT("Could not parse: '" + path + "', not exported.");
continue;
}
+ String importer_type = config->get_value("remap", "importer");
+
+ if (importer_type == "keep") {
+ //just keep file as-is
+ Vector<uint8_t> array = FileAccess::get_file_as_array(path);
+ err = p_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key);
+
+ if (err != OK) {
+ return err;
+ }
+
+ continue;
+ }
+
List<String> remaps;
config->get_section_keys("remap", &remaps);
@@ -915,12 +946,18 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
}
if (p_so_func) {
for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) {
- p_so_func(p_udata, export_plugins[i]->shared_objects[j]);
+ err = p_so_func(p_udata, export_plugins[i]->shared_objects[j]);
+ if (err != OK) {
+ return err;
+ }
}
}
for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) {
- p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total, enc_in_filters, enc_ex_filters, key);
+ err = p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total, enc_in_filters, enc_ex_filters, key);
+ if (err != OK) {
+ return err;
+ }
if (export_plugins[i]->extra_files[j].remap) {
do_export = false; //if remap, do not
path_remaps.push_back(path);
@@ -940,7 +977,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
//just store it as it comes
if (do_export) {
Vector<uint8_t> array = FileAccess::get_file_as_array(path);
- p_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key);
+ err = p_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key);
+ if (err != OK) {
+ return err;
+ }
}
}
@@ -976,7 +1016,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
new_file.write[j] = utf8[j];
}
- p_func(p_udata, from + ".remap", new_file, idx, total, enc_in_filters, enc_ex_filters, key);
+ err = p_func(p_udata, from + ".remap", new_file, idx, total, enc_in_filters, enc_ex_filters, key);
+ if (err != OK) {
+ return err;
+ }
}
} else {
//old remap mode, will still work, but it's unused because it's not multiple pck export friendly
@@ -989,11 +1032,17 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
String splash = ProjectSettings::get_singleton()->get("application/boot_splash/image");
if (icon != String() && FileAccess::exists(icon)) {
Vector<uint8_t> array = FileAccess::get_file_as_array(icon);
- p_func(p_udata, icon, array, idx, total, enc_in_filters, enc_ex_filters, key);
+ err = p_func(p_udata, icon, array, idx, total, enc_in_filters, enc_ex_filters, key);
+ if (err != OK) {
+ return err;
+ }
}
if (splash != String() && FileAccess::exists(splash) && icon != splash) {
Vector<uint8_t> array = FileAccess::get_file_as_array(splash);
- p_func(p_udata, splash, array, idx, total, enc_in_filters, enc_ex_filters, key);
+ err = p_func(p_udata, splash, array, idx, total, enc_in_filters, enc_ex_filters, key);
+ if (err != OK) {
+ return err;
+ }
}
// Store text server data if exists.
@@ -1001,7 +1050,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
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);
- p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key);
+ err = p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key);
+ if (err != OK) {
+ return err;
+ }
}
}
@@ -1011,9 +1063,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb);
DirAccess::remove_file_or_error(engine_cfb);
- p_func(p_udata, "res://" + config_file, data, idx, total, enc_in_filters, enc_ex_filters, key);
-
- return OK;
+ return p_func(p_udata, "res://" + config_file, data, idx, total, enc_in_filters, enc_ex_filters, key);
}
Error EditorExportPlatform::_add_shared_object(void *p_userdata, const SharedObject &p_so) {
@@ -1047,6 +1097,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
if (err != OK) {
DirAccess::remove_file_or_error(tmppath);
+ ERR_PRINT("Failed to export project files");
return err;
}
@@ -1403,9 +1454,9 @@ void EditorExport::add_export_preset(const Ref<EditorExportPreset> &p_preset, in
}
String EditorExportPlatform::test_etc2() const {
- String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name");
- bool etc_supported = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc");
- bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2");
+ String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
+ bool etc_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc");
+ bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2");
if (driver == "GLES2" && !etc_supported) {
return TTR("Target platform requires 'ETC' texture compression for GLES2. Enable 'Import Etc' in Project Settings.");
@@ -1417,9 +1468,9 @@ String EditorExportPlatform::test_etc2() const {
}
String EditorExportPlatform::test_etc2_or_pvrtc() const {
- String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name");
- bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2");
- bool pvrtc_supported = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_pvrtc");
+ String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
+ bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2");
+ bool pvrtc_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_pvrtc");
if (driver == "GLES2" && !pvrtc_supported) {
return TTR("Target platform requires 'PVRTC' texture compression for GLES2. Enable 'Import Pvrtc' in Project Settings.");
@@ -1902,7 +1953,7 @@ void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, con
return;
}
- bool convert = GLOBAL_GET("editor/convert_text_resources_to_binary_on_export");
+ bool convert = GLOBAL_GET("editor/export/convert_text_resources_to_binary");
if (!convert) {
return;
}
@@ -1922,5 +1973,5 @@ void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, con
}
EditorExportTextSceneToBinaryPlugin::EditorExportTextSceneToBinaryPlugin() {
- GLOBAL_DEF("editor/convert_text_resources_to_binary_on_export", false);
+ GLOBAL_DEF("editor/export/convert_text_resources_to_binary", false);
}
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index af02fcaf3c..bd00d86ec8 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -277,11 +277,7 @@ void EditorFeatureProfile::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_MAX);
}
-EditorFeatureProfile::EditorFeatureProfile() {
- for (int i = 0; i < FEATURE_MAX; i++) {
- features_disabled[i] = false;
- }
-}
+EditorFeatureProfile::EditorFeatureProfile() {}
//////////////////////////
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 01aad0c41b..f78da9569f 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -1076,9 +1076,9 @@ EditorFileDialog::Access EditorFileDialog::get_access() const {
}
void EditorFileDialog::_make_dir_confirm() {
- Error err = dir_access->make_dir(makedirname->get_text());
+ Error err = dir_access->make_dir(makedirname->get_text().strip_edges());
if (err == OK) {
- dir_access->change_dir(makedirname->get_text());
+ dir_access->change_dir(makedirname->get_text().strip_edges());
invalidate();
update_filters();
update_dir();
@@ -1150,7 +1150,6 @@ void EditorFileDialog::_update_drives() {
void EditorFileDialog::_favorite_selected(int p_idx) {
dir_access->change_dir(favorites->get_item_metadata(p_idx));
- file->set_text("");
update_dir();
invalidate();
_push_history();
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 4b68de26e7..fb0dc57501 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -405,6 +405,10 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
memdelete(f);
+ if (importer_name == "keep") {
+ return false; //keep mode, do not reimport
+ }
+
Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
if (importer->get_format_version() > version) {
@@ -669,10 +673,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
continue;
}
- if (FileAccess::exists(cd.plus_file(f).plus_file("project.godot"))) { // skip if another project inside this
- continue;
- }
- if (FileAccess::exists(cd.plus_file(f).plus_file(".gdignore"))) { // skip if another project inside this
+ if (_should_skip_directory(cd.plus_file(f))) {
continue;
}
@@ -874,10 +875,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
int idx = p_dir->find_dir_index(f);
if (idx == -1) {
- if (FileAccess::exists(cd.plus_file(f).plus_file("project.godot"))) { // skip if another project inside this
- continue;
- }
- if (FileAccess::exists(cd.plus_file(f).plus_file(".gdignore"))) { // skip if another project inside this
+ if (_should_skip_directory(cd.plus_file(f))) {
continue;
}
@@ -1413,11 +1411,11 @@ void EditorFileSystem::_scan_script_classes(EditorFileSystemDirectory *p_dir) {
}
void EditorFileSystem::update_script_classes() {
- if (!update_script_classes_queued) {
+ if (!update_script_classes_queued.is_set()) {
return;
}
- update_script_classes_queued = false;
+ update_script_classes_queued.clear();
ScriptServer::global_classes_clear();
if (get_filesystem()) {
_scan_script_classes(get_filesystem());
@@ -1436,11 +1434,11 @@ void EditorFileSystem::update_script_classes() {
}
void EditorFileSystem::_queue_update_script_classes() {
- if (update_script_classes_queued) {
+ if (update_script_classes_queued.is_set()) {
return;
}
- update_script_classes_queued = true;
+ update_script_classes_queued.set();
call_deferred("update_script_classes");
}
@@ -1538,6 +1536,10 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
source_file_options[p_files[i]] = Map<StringName, Variant>();
importer_name = file_importer_name;
+ if (importer_name == "keep") {
+ continue; //do nothing
+ }
+
Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
ERR_FAIL_COND_V(!importer.is_valid(), ERR_FILE_CORRUPT);
List<ResourceImporter::ImportOption> options;
@@ -1561,6 +1563,10 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
base_paths[p_files[i]] = ResourceFormatImporter::get_singleton()->get_import_base_path(p_files[i]);
}
+ if (importer_name == "keep") {
+ return OK; // (do nothing)
+ }
+
ERR_FAIL_COND_V(importer_name == String(), ERR_UNCONFIGURED);
Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
@@ -1674,7 +1680,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
return err;
}
-void EditorFileSystem::_reimport_file(const String &p_file) {
+void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName, Variant> *p_custom_options, const String &p_custom_importer) {
EditorFileSystemDirectory *fs = nullptr;
int cpos = -1;
bool found = _find_file(p_file, &fs, cpos);
@@ -1683,23 +1689,32 @@ void EditorFileSystem::_reimport_file(const String &p_file) {
//try to obtain existing params
Map<StringName, Variant> params;
- String importer_name;
+ String importer_name; //empty by default though
+
+ if (p_custom_importer != String()) {
+ importer_name = p_custom_importer;
+ }
+ if (p_custom_options != nullptr) {
+ params = *p_custom_options;
+ }
if (FileAccess::exists(p_file + ".import")) {
//use existing
- Ref<ConfigFile> cf;
- cf.instance();
- Error err = cf->load(p_file + ".import");
- if (err == OK) {
- if (cf->has_section("params")) {
- List<String> sk;
- cf->get_section_keys("params", &sk);
- for (List<String>::Element *E = sk.front(); E; E = E->next()) {
- params[E->get()] = cf->get_value("params", E->get());
+ if (p_custom_options == nullptr) {
+ Ref<ConfigFile> cf;
+ cf.instance();
+ Error err = cf->load(p_file + ".import");
+ if (err == OK) {
+ if (cf->has_section("params")) {
+ List<String> sk;
+ cf->get_section_keys("params", &sk);
+ for (List<String>::Element *E = sk.front(); E; E = E->next()) {
+ params[E->get()] = cf->get_value("params", E->get());
+ }
+ }
+ if (p_custom_importer == String() && cf->has_section("remap")) {
+ importer_name = cf->get_value("remap", "importer");
}
- }
- if (cf->has_section("remap")) {
- importer_name = cf->get_value("remap", "importer");
}
}
@@ -1707,6 +1722,16 @@ void EditorFileSystem::_reimport_file(const String &p_file) {
late_added_files.insert(p_file); //imported files do not call update_file(), but just in case..
}
+ if (importer_name == "keep") {
+ //keep files, do nothing.
+ fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file);
+ fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file + ".import");
+ fs->files[cpos]->deps.clear();
+ fs->files[cpos]->type = "";
+ fs->files[cpos]->import_valid = false;
+ EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
+ return;
+ }
Ref<ResourceImporter> importer;
bool load_default = false;
//find the importer
@@ -1893,6 +1918,10 @@ void EditorFileSystem::_find_group_files(EditorFileSystemDirectory *efd, Map<Str
}
}
+void EditorFileSystem::reimport_file_with_custom_parameters(const String &p_file, const String &p_importer, const Map<StringName, Variant> &p_custom_params) {
+ _reimport_file(p_file, &p_custom_params, p_importer);
+}
+
void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
{
// Ensure that ProjectSettings::IMPORTED_FILES_PATH exists.
@@ -1979,6 +2008,20 @@ Error EditorFileSystem::_resource_import(const String &p_path) {
return OK;
}
+bool EditorFileSystem::_should_skip_directory(const String &p_path) {
+ if (FileAccess::exists(p_path.plus_file("project.godot"))) {
+ // skip if another project inside this
+ return true;
+ }
+
+ if (FileAccess::exists(p_path.plus_file(".gdignore"))) {
+ // skip if a `.gdignore` file is inside this
+ return true;
+ }
+
+ return false;
+}
+
bool EditorFileSystem::is_group_file(const String &p_path) const {
return group_file_cache.has(p_path);
}
@@ -2067,7 +2110,7 @@ void EditorFileSystem::_update_extensions() {
EditorFileSystem::EditorFileSystem() {
ResourceLoader::import = _resource_import;
- reimport_on_missing_imported_files = GLOBAL_DEF("editor/reimport_missing_imported_files", true);
+ reimport_on_missing_imported_files = GLOBAL_DEF("editor/import/reimport_missing_imported_files", true);
singleton = this;
filesystem = memnew(EditorFileSystemDirectory); //like, empty
@@ -2091,7 +2134,7 @@ EditorFileSystem::EditorFileSystem() {
memdelete(da);
scan_total = 0;
- update_script_classes_queued = false;
+ update_script_classes_queued.clear();
first_scan = true;
scan_changes_pending = false;
revalidate_import_files = false;
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index fa0b89e667..6f4f058503 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -34,6 +34,7 @@
#include "core/os/dir_access.h"
#include "core/os/thread.h"
#include "core/os/thread_safe.h"
+#include "core/templates/safe_refcount.h"
#include "core/templates/set.h"
#include "scene/main/node.h"
class FileAccess;
@@ -202,7 +203,7 @@ class EditorFileSystem : public Node {
void _update_extensions();
- void _reimport_file(const String &p_file);
+ void _reimport_file(const String &p_file, const Map<StringName, Variant> *p_custom_options = nullptr, const String &p_custom_importer = String());
Error _reimport_group(const String &p_group_file, const Vector<String> &p_files);
bool _test_for_reimport(const String &p_path, bool p_only_imported_files);
@@ -220,7 +221,7 @@ class EditorFileSystem : public Node {
};
void _scan_script_classes(EditorFileSystemDirectory *p_dir);
- volatile bool update_script_classes_queued;
+ SafeFlag update_script_classes_queued;
void _queue_update_script_classes();
String _get_global_script_class(const String &p_type, const String &p_path, String *r_extends, String *r_icon_path) const;
@@ -256,11 +257,15 @@ public:
void reimport_files(const Vector<String> &p_files);
+ void reimport_file_with_custom_parameters(const String &p_file, const String &p_importer, const Map<StringName, Variant> &p_custom_params);
+
void update_script_classes();
bool is_group_file(const String &p_path) const;
void move_group_file(const String &p_path, const String &p_new_path);
+ static bool _should_skip_directory(const String &p_path);
+
EditorFileSystem();
~EditorFileSystem();
};
diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp
index 9f98795e16..97a2c67c26 100644
--- a/editor/editor_folding.cpp
+++ b/editor/editor_folding.cpp
@@ -259,13 +259,17 @@ void EditorFolding::_do_object_unfolds(Object *p_object, Set<RES> &resources) {
}
}
}
- }
- if (E->get().type == Variant::OBJECT) {
- RES res = p_object->get(E->get().name);
- if (res.is_valid() && !resources.has(res) && res->get_path() != String() && !res->get_path().is_resource_file()) {
- resources.insert(res);
- _do_object_unfolds(res.ptr(), resources);
+ if (E->get().type == Variant::OBJECT) {
+ RES res = p_object->get(E->get().name);
+ print_line("res: " + String(E->get().name) + " valid " + itos(res.is_valid()));
+ if (res.is_valid()) {
+ print_line("path " + res->get_path());
+ }
+ if (res.is_valid() && !resources.has(res) && res->get_path() != String() && !res->get_path().is_resource_file()) {
+ resources.insert(res);
+ _do_object_unfolds(res.ptr(), resources);
+ }
}
}
}
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index ac36b7e762..70d1a514b5 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -81,7 +81,7 @@ Size2 EditorProperty::get_minimum_size() const {
}
if (bottom_editor != nullptr && bottom_editor->is_visible()) {
- ms.height += get_theme_constant("vseparation", "Tree");
+ ms.height += get_theme_constant("vseparation");
Size2 bems = bottom_editor->get_combined_minimum_size();
//bems.width += get_constant("item_margin", "Tree");
ms.height += bems.height;
@@ -95,6 +95,7 @@ void EditorProperty::emit_changed(const StringName &p_property, const Variant &p
Variant args[4] = { p_property, p_value, p_field, p_changing };
const Variant *argptrs[4] = { &args[0], &args[1], &args[2], &args[3] };
+ cache[p_property] = p_value;
emit_signal("property_changed", (const Variant **)argptrs, 4);
}
@@ -148,7 +149,7 @@ void EditorProperty::_notification(int p_what) {
if (bottom_editor) {
int m = 0; //get_constant("item_margin", "Tree");
- bottom_rect = Rect2(m, rect.size.height + get_theme_constant("vseparation", "Tree"), size.width - m, bottom_editor->get_combined_minimum_size().height);
+ bottom_rect = Rect2(m, rect.size.height + get_theme_constant("vseparation"), size.width - m, bottom_editor->get_combined_minimum_size().height);
}
if (keying) {
@@ -225,11 +226,15 @@ void EditorProperty::_notification(int p_what) {
size.height = label_reference->get_size().height;
}
+ Ref<StyleBox> sb;
if (selected) {
- Ref<StyleBox> sb = get_theme_stylebox("selected", "Tree");
- draw_style_box(sb, Rect2(Vector2(), size));
+ sb = get_theme_stylebox("bg_selected");
+ } else {
+ sb = get_theme_stylebox("bg");
}
+ draw_style_box(sb, Rect2(Vector2(), size));
+
if (draw_top_bg && right_child_rect != Rect2()) {
draw_rect(right_child_rect, dark_color);
}
@@ -239,15 +244,15 @@ void EditorProperty::_notification(int p_what) {
Color color;
if (draw_red) {
- color = get_theme_color("error_color", "Editor");
+ color = get_theme_color("error_color");
} else {
- color = get_theme_color("property_color", "Editor");
+ color = get_theme_color("property_color");
}
if (label.find(".") != -1) {
color.a = 0.5; //this should be un-hacked honestly, as it's used for editor overrides
}
- int ofs = 0;
+ int ofs = get_theme_constant("font_offset");
int text_limit = text_size;
if (checkable) {
@@ -688,7 +693,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
if (is_layout_rtl()) {
mpos.x = get_size().x - mpos.x;
}
- bool button_left = me->get_button_mask() & BUTTON_MASK_LEFT;
+ bool button_left = me->get_button_mask() & MOUSE_BUTTON_MASK_LEFT;
bool new_keying_hover = keying_rect.has_point(mpos) && !button_left;
if (new_keying_hover != keying_hover) {
@@ -717,7 +722,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
Vector2 mpos = mb->get_position();
if (is_layout_rtl()) {
mpos.x = get_size().x - mpos.x;
@@ -805,6 +810,28 @@ void EditorProperty::set_bottom_editor(Control *p_control) {
bottom_editor = p_control;
}
+bool EditorProperty::is_cache_valid() const {
+ if (object) {
+ for (Map<StringName, Variant>::Element *E = cache.front(); E; E = E->next()) {
+ bool valid;
+ Variant value = object->get(E->key(), &valid);
+ if (!valid || value != E->get()) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+void EditorProperty::update_cache() {
+ cache.clear();
+ if (object && property != StringName()) {
+ bool valid;
+ Variant value = object->get(property, &valid);
+ if (valid) {
+ cache[property] = value;
+ }
+ }
+}
Variant EditorProperty::get_drag_data(const Point2 &p_point) {
if (property == StringName()) {
return Variant();
@@ -1332,7 +1359,7 @@ 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() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
Ref<Font> font = get_theme_font("font", "Tree");
int font_size = get_theme_font_size("font_size", "Tree");
if (mb->get_position().y > font->get_height(font_size)) { //clicked outside
@@ -1524,6 +1551,7 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit
ep->update_property();
ep->update_reload_status();
ep->set_deletable(deletable_properties);
+ ep->update_cache();
}
}
ped->added_editors.clear();
@@ -1661,7 +1689,7 @@ void EditorInspector::update_tree() {
bool valid = true;
//if no properties in category, skip
while (N) {
- if (N->get().usage & PROPERTY_USAGE_EDITOR) {
+ if (N->get().usage & PROPERTY_USAGE_EDITOR && (!restrict_to_basic || (N->get().usage & PROPERTY_USAGE_EDITOR_BASIC_SETTING))) {
break;
}
if (N->get().usage & PROPERTY_USAGE_CATEGORY) {
@@ -1729,10 +1757,14 @@ void EditorInspector::update_tree() {
continue;
- } else if (!(p.usage & PROPERTY_USAGE_EDITOR) || _is_property_disabled_by_feature_profile(p.name)) {
+ } else if (!(p.usage & PROPERTY_USAGE_EDITOR) || _is_property_disabled_by_feature_profile(p.name) || (restrict_to_basic && !(p.usage & PROPERTY_USAGE_EDITOR_BASIC_SETTING))) {
continue;
}
+ if (p.name == "script") {
+ category_vbox = nullptr; // script should go into its own category
+ }
+
if (p.usage & PROPERTY_USAGE_HIGH_END_GFX && RS::get_singleton()->is_low_end()) {
continue; //do not show this property in low end gfx
}
@@ -1982,6 +2014,7 @@ void EditorInspector::update_tree() {
}
ep->update_property();
ep->update_reload_status();
+ ep->update_cache();
if (current_selected && ep->property == current_selected) {
ep->select(current_focusable);
@@ -2012,6 +2045,7 @@ void EditorInspector::update_property(const String &p_prop) {
for (List<EditorProperty *>::Element *E = editor_property_map[p_prop].front(); E; E = E->next()) {
E->get()->update_property();
E->get()->update_reload_status();
+ E->get()->update_cache();
}
}
@@ -2027,13 +2061,6 @@ void EditorInspector::_clear() {
restart_request_props.clear();
}
-void EditorInspector::refresh() {
- if (refresh_countdown > 0 || changing) {
- return;
- }
- refresh_countdown = EditorSettings::get_singleton()->get("docks/property_editor/auto_refresh_interval");
-}
-
Object *EditorInspector::get_edited_object() {
return object;
}
@@ -2044,7 +2071,7 @@ void EditorInspector::edit(Object *p_object) {
}
if (object) {
_clear();
- object->remove_change_receptor(this);
+ object->disconnect("property_list_changed", callable_mp(this, &EditorInspector::_changed_callback));
}
object = p_object;
@@ -2054,7 +2081,7 @@ void EditorInspector::edit(Object *p_object) {
if (scroll_cache.has(object->get_instance_id())) { //if exists, set something else
update_scroll_request = scroll_cache[object->get_instance_id()]; //done this way because wait until full size is accommodated
}
- object->add_change_receptor(this);
+ object->connect("property_list_changed", callable_mp(this, &EditorInspector::_changed_callback));
update_tree();
}
}
@@ -2161,17 +2188,30 @@ void EditorInspector::set_use_wide_editors(bool p_enable) {
wide_editors = p_enable;
}
+void EditorInspector::_update_inspector_bg() {
+ if (sub_inspector) {
+ int count_subinspectors = 0;
+ Node *n = get_parent();
+ while (n) {
+ EditorInspector *ei = Object::cast_to<EditorInspector>(n);
+ if (ei && ei->sub_inspector) {
+ count_subinspectors++;
+ }
+ n = n->get_parent();
+ }
+ count_subinspectors = MIN(15, count_subinspectors);
+ add_theme_style_override("bg", get_theme_stylebox("sub_inspector_bg" + itos(count_subinspectors), "Editor"));
+ } else {
+ add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
+ }
+}
void EditorInspector::set_sub_inspector(bool p_enable) {
sub_inspector = p_enable;
if (!is_inside_tree()) {
return;
}
- if (sub_inspector) {
- add_theme_style_override("bg", get_theme_stylebox("sub_inspector_bg", "Editor"));
- } else {
- add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
- }
+ _update_inspector_bg();
}
void EditorInspector::set_use_deletable_properties(bool p_enabled) {
@@ -2351,6 +2391,7 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
for (List<EditorProperty *>::Element *E = editor_property_map[p_path].front(); E; E = E->next()) {
E->get()->update_property();
E->get()->update_reload_status();
+ E->get()->update_cache();
}
}
@@ -2394,13 +2435,12 @@ void EditorInspector::_node_removed(Node *p_node) {
void EditorInspector::_notification(int p_what) {
if (p_what == NOTIFICATION_READY) {
EditorFeatureProfileManager::get_singleton()->connect("current_feature_profile_changed", callable_mp(this, &EditorInspector::_feature_profile_changed));
+ set_process(is_visible_in_tree());
+ _update_inspector_bg();
}
if (p_what == NOTIFICATION_ENTER_TREE) {
- if (sub_inspector) {
- add_theme_style_override("bg", get_theme_stylebox("sub_inspector_bg", "Editor"));
- } else {
- add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
+ if (!sub_inspector) {
get_tree()->connect("node_removed", callable_mp(this, &EditorInspector::_node_removed));
}
}
@@ -2414,6 +2454,10 @@ void EditorInspector::_notification(int p_what) {
edit(nullptr);
}
+ if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
+ set_process(is_visible_in_tree());
+ }
+
if (p_what == NOTIFICATION_PROCESS) {
if (update_scroll_request >= 0) {
get_v_scrollbar()->call_deferred("set_value", update_scroll_request);
@@ -2424,10 +2468,14 @@ void EditorInspector::_notification(int p_what) {
if (refresh_countdown <= 0) {
for (Map<StringName, List<EditorProperty *>>::Element *F = editor_property_map.front(); F; F = F->next()) {
for (List<EditorProperty *>::Element *E = F->get().front(); E; E = E->next()) {
- E->get()->update_property();
- E->get()->update_reload_status();
+ if (!E->get()->is_cache_valid()) {
+ E->get()->update_property();
+ E->get()->update_reload_status();
+ E->get()->update_cache();
+ }
}
}
+ refresh_countdown = float(EditorSettings::get_singleton()->get("docks/property_editor/auto_refresh_interval"));
}
}
@@ -2445,6 +2493,7 @@ void EditorInspector::_notification(int p_what) {
for (List<EditorProperty *>::Element *E = editor_property_map[prop].front(); E; E = E->next()) {
E->get()->update_property();
E->get()->update_reload_status();
+ E->get()->update_cache();
}
}
pending.erase(pending.front());
@@ -2455,19 +2504,17 @@ void EditorInspector::_notification(int p_what) {
}
if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
- if (sub_inspector) {
- add_theme_style_override("bg", get_theme_stylebox("sub_inspector_bg", "Editor"));
- } else if (is_inside_tree()) {
- add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
- }
+ _update_inspector_bg();
update_tree();
}
}
-void EditorInspector::_changed_callback(Object *p_changed, const char *p_prop) {
- //this is called when property change is notified via _change_notify()
- _edit_request_change(p_changed, p_prop);
+void EditorInspector::_changed_callback() {
+ //this is called when property change is notified via notify_property_list_changed()
+ if (object != nullptr) {
+ _edit_request_change(object, String());
+ }
}
void EditorInspector::_vscroll_changed(double p_offset) {
@@ -2577,11 +2624,14 @@ void EditorInspector::_update_script_class_properties(const Object &p_object, Li
r_list.erase(bottom);
}
+void EditorInspector::set_restrict_to_basic_settings(bool p_restrict) {
+ restrict_to_basic = p_restrict;
+ update_tree();
+}
+
void EditorInspector::_bind_methods() {
ClassDB::bind_method("_edit_request_change", &EditorInspector::_edit_request_change);
- ClassDB::bind_method("refresh", &EditorInspector::refresh);
-
ADD_SIGNAL(MethodInfo("property_selected", PropertyInfo(Variant::STRING, "property")));
ADD_SIGNAL(MethodInfo("property_keyed", PropertyInfo(Variant::STRING, "property")));
ADD_SIGNAL(MethodInfo("property_deleted", PropertyInfo(Variant::STRING, "property")));
@@ -2613,16 +2663,21 @@ EditorInspector::EditorInspector() {
use_folding = false;
update_all_pending = false;
update_tree_pending = false;
- refresh_countdown = 0;
read_only = false;
search_box = nullptr;
keying = false;
_prop_edited = "property_edited";
- set_process(true);
+ set_process(false);
property_focusable = -1;
sub_inspector = false;
deletable_properties = false;
get_v_scrollbar()->connect("value_changed", callable_mp(this, &EditorInspector::_vscroll_changed));
update_scroll_request = -1;
+ if (EditorSettings::get_singleton()) {
+ refresh_countdown = float(EditorSettings::get_singleton()->get("docks/property_editor/auto_refresh_interval"));
+ } else {
+ //used when class is created by the docgen to dump default values of everything bindable, editorsettings may not be created
+ refresh_countdown = 0.33;
+ }
}
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index 81a22d4ff1..18250780be 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -98,6 +98,8 @@ private:
mutable String tooltip_text;
+ Map<StringName, Variant> cache;
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -152,6 +154,8 @@ public:
virtual void collapse_all_folding();
virtual Variant get_drag_data(const Point2 &p_point) override;
+ virtual void update_cache();
+ virtual bool is_cache_valid() const;
void set_selectable(bool p_selectable);
bool is_selectable() const;
@@ -309,6 +313,8 @@ class EditorInspector : public ScrollContainer {
String property_prefix; //used for sectioned inspector
String object_class;
+ bool restrict_to_basic = false;
+
void _edit_set(const String &p_name, const Variant &p_value, bool p_refresh_all, const String &p_changed_field);
void _property_changed(const String &p_path, const Variant &p_value, const String &p_name = "", bool p_changing = false);
@@ -326,7 +332,7 @@ class EditorInspector : public ScrollContainer {
void _node_removed(Node *p_node);
- void _changed_callback(Object *p_changed, const char *p_prop) override;
+ void _changed_callback();
void _edit_request_change(Object *p_object, const String &p_prop);
void _filter_changed(const String &p_text);
@@ -339,6 +345,8 @@ class EditorInspector : public ScrollContainer {
bool _is_property_disabled_by_feature_profile(const StringName &p_property);
+ void _update_inspector_bg();
+
protected:
static void _bind_methods();
void _notification(int p_what);
@@ -356,9 +364,6 @@ public:
void update_tree();
void update_property(const String &p_prop);
-
- void refresh();
-
void edit(Object *p_object);
Object *get_edited_object();
@@ -393,9 +398,12 @@ public:
void set_use_wide_editors(bool p_enable);
void set_sub_inspector(bool p_enable);
+ bool is_sub_inspector() const { return sub_inspector; }
void set_use_deletable_properties(bool p_enabled);
+ void set_restrict_to_basic_settings(bool p_restrict);
+
EditorInspector();
};
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 040f1b1640..756f1d208f 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -102,6 +102,7 @@
#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/scene_importer_mesh_node_3d.h"
#include "editor/import_dock.h"
#include "editor/multi_node_edit.h"
@@ -430,6 +431,74 @@ void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) {
}
}
+void EditorNode::_update_from_settings() {
+ int current_filter = GLOBAL_GET("rendering/textures/canvas_textures/default_texture_filter");
+ if (current_filter != scene_root->get_default_canvas_item_texture_filter()) {
+ Viewport::DefaultCanvasItemTextureFilter tf = (Viewport::DefaultCanvasItemTextureFilter)current_filter;
+ scene_root->set_default_canvas_item_texture_filter(tf);
+ }
+ int current_repeat = GLOBAL_GET("rendering/textures/canvas_textures/default_texture_repeat");
+ if (current_repeat != scene_root->get_default_canvas_item_texture_repeat()) {
+ Viewport::DefaultCanvasItemTextureRepeat tr = (Viewport::DefaultCanvasItemTextureRepeat)current_repeat;
+ scene_root->set_default_canvas_item_texture_repeat(tr);
+ }
+
+ RS::DOFBokehShape dof_shape = RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape")));
+ RS::get_singleton()->camera_effects_set_dof_blur_bokeh_shape(dof_shape);
+ RS::DOFBlurQuality dof_quality = RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality")));
+ bool dof_jitter = GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_use_jitter");
+ RS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter);
+ RS::get_singleton()->environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to"));
+ RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/enabled"), GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/amount"), GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/limit"));
+ bool glow_bicubic = int(GLOBAL_GET("rendering/environment/glow/upscale_mode")) > 0;
+ 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")));
+ RS::get_singleton()->sub_surface_scattering_set_quality(sss_quality);
+ float sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale");
+ float sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale");
+ RS::get_singleton()->sub_surface_scattering_set_scale(sss_scale, sss_depth_scale);
+
+ uint32_t directional_shadow_size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
+ uint32_t directional_shadow_16_bits = GLOBAL_GET("rendering/shadows/directional_shadow/16_bits");
+ RS::get_singleton()->directional_shadow_atlas_set_size(directional_shadow_size, directional_shadow_16_bits);
+
+ RS::ShadowQuality shadows_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/shadows/soft_shadow_quality")));
+ RS::get_singleton()->shadows_quality_set(shadows_quality);
+ RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_quality")));
+ RS::get_singleton()->directional_shadow_quality_set(directional_shadow_quality);
+ float probe_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed");
+ RS::get_singleton()->lightmap_set_probe_capture_update_speed(probe_update_speed);
+ RS::EnvironmentSDFGIFramesToConverge frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(int(GLOBAL_GET("rendering/global_illumination/sdfgi/frames_to_converge")));
+ RS::get_singleton()->environment_set_sdfgi_frames_to_converge(frames_to_converge);
+ RS::EnvironmentSDFGIRayCount ray_count = RS::EnvironmentSDFGIRayCount(int(GLOBAL_GET("rendering/global_illumination/sdfgi/probe_ray_count")));
+ RS::get_singleton()->environment_set_sdfgi_ray_count(ray_count);
+ RS::GIProbeQuality gi_probe_quality = RS::GIProbeQuality(int(GLOBAL_GET("rendering/global_illumination/gi_probes/quality")));
+ RS::get_singleton()->gi_probe_set_quality(gi_probe_quality);
+ RS::get_singleton()->environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth"));
+ RS::get_singleton()->environment_set_volumetric_fog_filter_active(bool(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter")));
+ RS::get_singleton()->canvas_set_shadow_texture_size(GLOBAL_GET("rendering/2d/shadow_atlas/size"));
+
+ bool use_half_res_gi = GLOBAL_DEF("rendering/global_illumination/gi/use_half_resolution", false);
+ RS::get_singleton()->gi_set_use_half_resolution(use_half_res_gi);
+
+ bool snap_2d_transforms = GLOBAL_GET("rendering/2d/snap/snap_2d_transforms_to_pixel");
+ scene_root->set_snap_2d_transforms_to_pixel(snap_2d_transforms);
+ bool snap_2d_vertices = GLOBAL_GET("rendering/2d/snap/snap_2d_vertices_to_pixel");
+ scene_root->set_snap_2d_vertices_to_pixel(snap_2d_vertices);
+
+ Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_GET("rendering/2d/sdf/oversize")));
+ scene_root->set_sdf_oversize(sdf_oversize);
+ Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_GET("rendering/2d/sdf/scale")));
+ scene_root->set_sdf_scale(sdf_scale);
+
+ float lod_threshold = GLOBAL_GET("rendering/mesh_lod/lod_change/threshold_pixels");
+ scene_root->set_lod_threshold(lod_threshold);
+}
+
void EditorNode::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_PROCESS: {
@@ -468,77 +537,13 @@ void EditorNode::_notification(int p_what) {
editor_selection->update();
- { //TODO should only happen on settings changed
- int current_filter = GLOBAL_GET("rendering/canvas_textures/default_texture_filter");
- if (current_filter != scene_root->get_default_canvas_item_texture_filter()) {
- Viewport::DefaultCanvasItemTextureFilter tf = (Viewport::DefaultCanvasItemTextureFilter)current_filter;
- scene_root->set_default_canvas_item_texture_filter(tf);
- }
- int current_repeat = GLOBAL_GET("rendering/canvas_textures/default_texture_repeat");
- if (current_repeat != scene_root->get_default_canvas_item_texture_repeat()) {
- Viewport::DefaultCanvasItemTextureRepeat tr = (Viewport::DefaultCanvasItemTextureRepeat)current_repeat;
- scene_root->set_default_canvas_item_texture_repeat(tr);
- }
+ ResourceImporterTexture::get_singleton()->update_imports();
- RS::DOFBokehShape dof_shape = RS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_shape")));
- RS::get_singleton()->camera_effects_set_dof_blur_bokeh_shape(dof_shape);
- RS::DOFBlurQuality dof_quality = RS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_quality")));
- bool dof_jitter = GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_use_jitter");
- RS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter);
- RS::get_singleton()->environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size"), GLOBAL_GET("rendering/quality/ssao/adaptive_target"), GLOBAL_GET("rendering/quality/ssao/blur_passes"), GLOBAL_GET("rendering/quality/ssao/fadeout_from"), GLOBAL_GET("rendering/quality/ssao/fadeout_to"));
- RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_enabled"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_amount"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_limit"));
- bool glow_bicubic = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0;
- RS::get_singleton()->environment_glow_set_use_bicubic_upscale(glow_bicubic);
- bool glow_high_quality = GLOBAL_GET("rendering/quality/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/quality/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/quality/subsurface_scattering/subsurface_scattering_quality")));
- RS::get_singleton()->sub_surface_scattering_set_quality(sss_quality);
- float sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale");
- float sss_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale");
- RS::get_singleton()->sub_surface_scattering_set_scale(sss_scale, sss_depth_scale);
-
- uint32_t directional_shadow_size = GLOBAL_GET("rendering/quality/directional_shadow/size");
- uint32_t directional_shadow_16_bits = GLOBAL_GET("rendering/quality/directional_shadow/16_bits");
- RS::get_singleton()->directional_shadow_atlas_set_size(directional_shadow_size, directional_shadow_16_bits);
-
- RS::ShadowQuality shadows_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/shadows/soft_shadow_quality")));
- RS::get_singleton()->shadows_quality_set(shadows_quality);
- RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/directional_shadow/soft_shadow_quality")));
- RS::get_singleton()->directional_shadow_quality_set(directional_shadow_quality);
- float probe_update_speed = GLOBAL_GET("rendering/lightmapper/probe_capture_update_speed");
- RS::get_singleton()->lightmap_set_probe_capture_update_speed(probe_update_speed);
- RS::EnvironmentSDFGIFramesToConverge frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(int(GLOBAL_GET("rendering/sdfgi/frames_to_converge")));
- RS::get_singleton()->environment_set_sdfgi_frames_to_converge(frames_to_converge);
- RS::EnvironmentSDFGIRayCount ray_count = RS::EnvironmentSDFGIRayCount(int(GLOBAL_GET("rendering/sdfgi/probe_ray_count")));
- RS::get_singleton()->environment_set_sdfgi_ray_count(ray_count);
- RS::GIProbeQuality gi_probe_quality = RS::GIProbeQuality(int(GLOBAL_GET("rendering/quality/gi_probes/quality")));
- RS::get_singleton()->gi_probe_set_quality(gi_probe_quality);
- RS::get_singleton()->environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/volumetric_fog/volume_size"), GLOBAL_GET("rendering/volumetric_fog/volume_depth"));
- RS::get_singleton()->environment_set_volumetric_fog_filter_active(bool(GLOBAL_GET("rendering/volumetric_fog/use_filter")));
- RS::get_singleton()->environment_set_volumetric_fog_directional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/directional_shadow_shrink"));
- RS::get_singleton()->environment_set_volumetric_fog_positional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/positional_shadow_shrink"));
- RS::get_singleton()->canvas_set_shadow_texture_size(GLOBAL_GET("rendering/quality/2d_shadow_atlas/size"));
-
- bool use_half_res_gi = GLOBAL_DEF("rendering/quality/gi/use_half_resolution", false);
- RS::get_singleton()->gi_set_use_half_resolution(use_half_res_gi);
-
- bool snap_2d_transforms = GLOBAL_GET("rendering/quality/2d/snap_2d_transforms_to_pixel");
- scene_root->set_snap_2d_transforms_to_pixel(snap_2d_transforms);
- bool snap_2d_vertices = GLOBAL_GET("rendering/quality/2d/snap_2d_vertices_to_pixel");
- scene_root->set_snap_2d_vertices_to_pixel(snap_2d_vertices);
-
- Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_GET("rendering/quality/2d_sdf/oversize")));
- scene_root->set_sdf_oversize(sdf_oversize);
- Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_GET("rendering/quality/2d_sdf/scale")));
- scene_root->set_sdf_scale(sdf_scale);
-
- float lod_threshold = GLOBAL_GET("rendering/quality/mesh_lod/threshold_pixels");
- scene_root->set_lod_threshold(lod_threshold);
+ if (settings_changed) {
+ _update_from_settings();
+ settings_changed = false;
+ emit_signal("project_settings_changed");
}
-
- ResourceImporterTexture::get_singleton()->update_imports();
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -596,6 +601,7 @@ void EditorNode::_notification(int p_what) {
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec")));
EditorFileSystem::get_singleton()->scan_changes();
+ _scan_external_changes();
} break;
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
@@ -888,6 +894,83 @@ void EditorNode::_sources_changed(bool p_exist) {
}
}
+void EditorNode::_scan_external_changes() {
+ disk_changed_list->clear();
+ TreeItem *r = disk_changed_list->create_item();
+ disk_changed_list->set_hide_root(true);
+ bool need_reload = false;
+
+ // Check if any edited scene has changed.
+
+ for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (editor_data.get_scene_path(i) == "" || !da->file_exists(editor_data.get_scene_path(i))) {
+ continue;
+ }
+
+ uint64_t last_date = editor_data.get_scene_modified_time(i);
+ uint64_t date = FileAccess::get_modified_time(editor_data.get_scene_path(i));
+
+ if (date > last_date) {
+ TreeItem *ti = disk_changed_list->create_item(r);
+ ti->set_text(0, editor_data.get_scene_path(i).get_file());
+ need_reload = true;
+ }
+ }
+
+ String project_settings_path = ProjectSettings::get_singleton()->get_resource_path().plus_file("project.godot");
+ if (FileAccess::get_modified_time(project_settings_path) > ProjectSettings::get_singleton()->get_last_saved_time()) {
+ TreeItem *ti = disk_changed_list->create_item(r);
+ ti->set_text(0, "project.godot");
+ need_reload = true;
+ }
+
+ if (need_reload) {
+ disk_changed->call_deferred("popup_centered_ratio", 0.5);
+ }
+}
+
+void EditorNode::_resave_scenes(String p_str) {
+ save_all_scenes();
+ ProjectSettings::get_singleton()->save();
+ disk_changed->hide();
+}
+
+void EditorNode::_reload_modified_scenes() {
+ int current_idx = editor_data.get_edited_scene();
+
+ for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
+ if (editor_data.get_scene_path(i) == "") {
+ continue;
+ }
+
+ uint64_t last_date = editor_data.get_scene_modified_time(i);
+ uint64_t date = FileAccess::get_modified_time(editor_data.get_scene_path(i));
+
+ if (date > last_date) {
+ String filename = editor_data.get_scene_path(i);
+ editor_data.set_edited_scene(i);
+ _remove_edited_scene(false);
+
+ Error err = load_scene(filename, false, false, true, false, true);
+ if (err != OK) {
+ ERR_PRINT(vformat("Failed to load scene: %s", filename));
+ }
+ editor_data.move_edited_scene_to_index(i);
+ }
+ }
+
+ get_undo_redo()->clear_history(false);
+ set_current_scene(current_idx);
+ _update_scene_tabs();
+ disk_changed->hide();
+}
+
+void EditorNode::_reload_project_settings() {
+ ProjectSettings::get_singleton()->setup(ProjectSettings::get_singleton()->get_resource_path(), String(), true);
+ settings_changed = true;
+}
+
void EditorNode::_vp_resized() {
}
@@ -929,7 +1012,7 @@ Error EditorNode::load_resource(const String &p_resource, bool p_ignore_broken_d
dependency_errors.clear();
Error err;
- RES res = ResourceLoader::load(p_resource, "", false, &err);
+ RES res = ResourceLoader::load(p_resource, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err);
ERR_FAIL_COND_V(!res.is_valid(), ERR_CANT_OPEN);
if (!p_ignore_broken_deps && dependency_errors.has(p_resource)) {
@@ -1007,13 +1090,23 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String
file->clear_filters();
List<String> preferred;
- for (int i = 0; i < extensions.size(); i++) {
- if (p_resource->is_class("Script") && (extensions[i] == "tres" || extensions[i] == "res" || extensions[i] == "xml")) {
+ for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
+ if (p_resource->is_class("Script") && (E->get() == "tres" || E->get() == "res")) {
//this serves no purpose and confused people
continue;
}
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
- preferred.push_back(extensions[i]);
+ file->add_filter("*." + E->get() + " ; " + E->get().to_upper());
+ preferred.push_back(E->get());
+ }
+ // Lowest priority extension
+ List<String>::Element *res_element = preferred.find("res");
+ if (res_element) {
+ preferred.move_to_back(res_element);
+ }
+ // Highest priority extension
+ List<String>::Element *tres_element = preferred.find("tres");
+ if (tres_element) {
+ preferred.move_to_front(tres_element);
}
if (p_at_path != String()) {
@@ -1513,6 +1606,7 @@ void EditorNode::_save_scene(String p_file, int idx) {
} else {
editor_data.set_edited_scene_version(0, idx);
}
+ editor_data.set_scene_modified_time(idx, FileAccess::get_modified_time(p_file));
editor_folding.save_scene_folding(scene, p_file);
@@ -1716,7 +1810,7 @@ void EditorNode::_dialog_action(String p_file) {
ObjectID current = editor_history.get_current();
Object *current_obj = current.is_valid() ? ObjectDB::get_instance(current) : nullptr;
ERR_FAIL_COND(!current_obj);
- current_obj->_change_notify();
+ current_obj->notify_property_list_changed();
} break;
case SETTINGS_LAYOUT_SAVE: {
if (p_file.is_empty()) {
@@ -2178,7 +2272,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
List<String> breakpoints;
editor_data.get_editor_breakpoints(&breakpoints);
- args = ProjectSettings::get_singleton()->get("editor/main_run_args");
+ args = ProjectSettings::get_singleton()->get("editor/run/main_run_args");
skip_breakpoints = EditorDebuggerNode::get_singleton()->is_skip_breakpoints();
EditorDebuggerNode::get_singleton()->start();
@@ -2304,11 +2398,14 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
_scene_tab_changed(tab_closing);
if (unsaved_cache || p_option == FILE_CLOSE_ALL_AND_QUIT || p_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) {
- String scene_filename = editor_data.get_edited_scene_root(tab_closing)->get_filename();
- save_confirmation->get_ok_button()->set_text(TTR("Save & Close"));
- save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene"));
- save_confirmation->popup_centered();
- break;
+ Node *scene_root = editor_data.get_edited_scene_root(tab_closing);
+ if (scene_root) {
+ String scene_filename = scene_root->get_filename();
+ save_confirmation->get_ok_button()->set_text(TTR("Save & Close"));
+ save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene"));
+ save_confirmation->popup_centered();
+ break;
+ }
}
} else if (p_option == FILE_CLOSE) {
tab_closing = editor_data.get_edited_scene();
@@ -2438,16 +2535,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
- case FILE_IMPORT_SUBSCENE: {
- if (!editor_data.get_edited_scene_root()) {
- show_accept(TTR("This operation can't be done without a selected node."), TTR("OK"));
- break;
- }
-
- scene_tree_dock->import_subscene();
-
- } break;
-
case FILE_EXTERNAL_OPEN_SCENE: {
if (unsaved_cache && !p_confirmed) {
confirmation->get_ok_button()->set_text(TTR("Open"));
@@ -2717,7 +2804,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case SET_VIDEO_DRIVER_SAVE_AND_RESTART: {
- ProjectSettings::get_singleton()->set("rendering/quality/driver/driver_name", video_driver_request);
+ ProjectSettings::get_singleton()->set("rendering/driver/driver_name", video_driver_request);
ProjectSettings::get_singleton()->save();
save_all_scenes();
@@ -3328,7 +3415,7 @@ int EditorNode::new_scene() {
return idx;
}
-Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, bool p_set_inherited, bool p_clear_errors, bool p_force_open_imported) {
+Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, bool p_set_inherited, bool p_clear_errors, bool p_force_open_imported, bool p_silent_change_tab) {
if (!is_inside_tree()) {
defer_load_scene = p_scene;
return OK;
@@ -3368,14 +3455,16 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
if (!editor_data.get_edited_scene_root() && editor_data.get_edited_scene_count() == 2) {
_remove_edited_scene();
- } else {
+ } else if (!p_silent_change_tab) {
_scene_tab_changed(idx);
+ } else {
+ set_current_scene(idx);
}
dependency_errors.clear();
Error err;
- Ref<PackedScene> sdata = ResourceLoader::load(lpath, "", true, &err);
+ Ref<PackedScene> sdata = ResourceLoader::load(lpath, "", ResourceFormatLoader::CACHE_MODE_REPLACE, &err);
if (!sdata.is_valid()) {
_dialog_display_load_error(lpath, err);
opening_prev = false;
@@ -4747,15 +4836,15 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) {
if (mb.is_valid()) {
if (scene_tabs->get_hovered_tab() >= 0) {
- if (mb->get_button_index() == BUTTON_MIDDLE && mb->is_pressed()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_MIDDLE && mb->is_pressed()) {
_scene_tab_closed(scene_tabs->get_hovered_tab());
}
} else {
- if ((mb->get_button_index() == BUTTON_LEFT && mb->is_doubleclick()) || (mb->get_button_index() == BUTTON_MIDDLE && mb->is_pressed())) {
+ if ((mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_doubleclick()) || (mb->get_button_index() == MOUSE_BUTTON_MIDDLE && mb->is_pressed())) {
_menu_option_confirm(FILE_NEW_SCENE, true);
}
}
- if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) {
// context menu
scene_tabs_context_menu->clear();
scene_tabs_context_menu->set_size(Size2(1, 1));
@@ -5197,6 +5286,8 @@ void EditorNode::_file_access_close_error_notify(const String &p_str) {
}
void EditorNode::reload_scene(const String &p_path) {
+ /*
+ * No longer necesary since scenes now reset and reload their internal resource if needed.
//first of all, reload internal textures, materials, meshes, etc. as they might have changed on disk
List<Ref<Resource>> cached;
@@ -5214,6 +5305,8 @@ void EditorNode::reload_scene(const String &p_path) {
to_clear.pop_front();
}
+ */
+
int scene_idx = -1;
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
if (editor_data.get_scene_path(i) == p_path) {
@@ -5457,6 +5550,7 @@ void EditorNode::_bind_methods() {
ADD_SIGNAL(MethodInfo("request_help_search"));
ADD_SIGNAL(MethodInfo("script_add_function_request", PropertyInfo(Variant::OBJECT, "obj"), PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::PACKED_STRING_ARRAY, "args")));
ADD_SIGNAL(MethodInfo("resource_saved", PropertyInfo(Variant::OBJECT, "obj")));
+ ADD_SIGNAL(MethodInfo("project_settings_changed"));
}
static Node *_resource_get_edited_scene() {
@@ -5476,7 +5570,8 @@ static void _execute_thread(void *p_ud) {
eta->exitcode = err;
}
- eta->done = true;
+ eta->done.set();
+ ;
}
int EditorNode::execute_and_show_output(const String &p_title, const String &p_path, const List<String> &p_arguments, bool p_close_on_ok, bool p_close_on_errors) {
@@ -5490,13 +5585,12 @@ int EditorNode::execute_and_show_output(const String &p_title, const String &p_p
eta.path = p_path;
eta.args = p_arguments;
eta.exitcode = 255;
- eta.done = false;
int prev_len = 0;
eta.execute_output_thread.start(_execute_thread, &eta);
- while (!eta.done) {
+ while (!eta.done.is_set()) {
{
MutexLock lock(eta.execute_output_mutex);
if (prev_len != eta.output.length()) {
@@ -5524,6 +5618,10 @@ int EditorNode::execute_and_show_output(const String &p_title, const String &p_p
return eta.exitcode;
}
+void EditorNode::notify_settings_changed() {
+ settings_changed = true;
+}
+
EditorNode::EditorNode() {
Input::get_singleton()->set_use_accumulated_input(true);
Resource::_get_local_scene_func = _resource_get_edited_scene;
@@ -5594,6 +5692,10 @@ EditorNode::EditorNode() {
if (DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).y >= 1400) {
// hiDPI display.
scale = 2.0;
+ } else if (DisplayServer::get_singleton()->screen_get_size(screen).y >= 1700) {
+ // Likely a hiDPI display, but we aren't certain due to the returned DPI.
+ // Use an intermediate scale to handle this situation.
+ scale = 1.5;
} else if (DisplayServer::get_singleton()->screen_get_size(screen).y <= 800) {
// Small loDPI display. Use a smaller display scale so that editor elements fit more easily.
// Icons won't look great, but this is better than having editor elements overflow from its window.
@@ -5752,7 +5854,7 @@ EditorNode::EditorNode() {
register_exporters();
- GLOBAL_DEF("editor/main_run_args", "");
+ GLOBAL_DEF("editor/run/main_run_args", "");
ClassDB::set_class_enabled("RootMotionView", true);
@@ -5777,7 +5879,7 @@ EditorNode::EditorNode() {
EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false);
EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true);
EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true);
- EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "StandardMaterial3D,ORMMaterial3D,Script,MeshLibrary,TileSet");
+ EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "Script,MeshLibrary,TileSet");
EDITOR_DEF("interface/inspector/default_color_picker_mode", 0);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW", PROPERTY_USAGE_DEFAULT));
EDITOR_DEF("run/auto_save/save_before_running", true);
@@ -6078,6 +6180,9 @@ EditorNode::EditorNode() {
project_settings = memnew(ProjectSettingsEditor(&editor_data));
gui_base->add_child(project_settings);
+ scene_import_settings = memnew(SceneImportSettings);
+ gui_base->add_child(scene_import_settings);
+
export_template_manager = memnew(ExportTemplateManager);
gui_base->add_child(export_template_manager);
@@ -6128,8 +6233,8 @@ EditorNode::EditorNode() {
pm_export->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option));
p->add_separator();
- p->add_shortcut(ED_SHORTCUT("editor/undo", TTR("Undo"), KEY_MASK_CMD + KEY_Z), EDIT_UNDO, true);
- p->add_shortcut(ED_SHORTCUT("editor/redo", TTR("Redo"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_Z), EDIT_REDO, true);
+ p->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO, true);
+ p->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO, true);
p->add_separator();
p->add_shortcut(ED_SHORTCUT("editor/reload_saved_scene", TTR("Reload Saved Scene")), EDIT_RELOAD_SAVED_SCENE);
@@ -6265,7 +6370,11 @@ EditorNode::EditorNode() {
p = help_menu->get_popup();
p->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option));
- p->add_icon_shortcut(gui_base->get_theme_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search"), KEY_MASK_SHIFT | KEY_F1), HELP_SEARCH);
+#ifdef OSX_ENABLED
+ p->add_icon_shortcut(gui_base->get_theme_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_MASK_ALT | KEY_SPACE), HELP_SEARCH);
+#else
+ p->add_icon_shortcut(gui_base->get_theme_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_F1), HELP_SEARCH);
+#endif
p->add_separator();
p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/online_docs", TTR("Online Docs")), HELP_DOCS);
p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/q&a", TTR("Q&A")), HELP_QA);
@@ -6370,7 +6479,7 @@ EditorNode::EditorNode() {
#warning needs to be reimplemented
#endif
#if 0
- String video_drivers = ProjectSettings::get_singleton()->get_custom_property_info()["rendering/quality/driver/driver_name"].hint_string;
+ String video_drivers = ProjectSettings::get_singleton()->get_custom_property_info()["rendering/driver/driver_name"].hint_string;
String current_video_driver = OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver());
video_driver_current = 0;
for (int i = 0; i < video_drivers.get_slice_count(","); i++) {
@@ -6603,6 +6712,30 @@ EditorNode::EditorNode() {
//plugin stuff
add_editor_plugin(memnew(DebuggerEditorPlugin(this, debug_menu)));
+
+ disk_changed = memnew(ConfirmationDialog);
+ {
+ VBoxContainer *vbc = memnew(VBoxContainer);
+ disk_changed->add_child(vbc);
+
+ Label *dl = memnew(Label);
+ dl->set_text(TTR("The following files are newer on disk.\nWhat action should be taken?"));
+ vbc->add_child(dl);
+
+ disk_changed_list = memnew(Tree);
+ vbc->add_child(disk_changed_list);
+ disk_changed_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+
+ disk_changed->connect("confirmed", callable_mp(this, &EditorNode::_reload_modified_scenes));
+ disk_changed->connect("confirmed", callable_mp(this, &EditorNode::_reload_project_settings));
+ disk_changed->get_ok_button()->set_text(TTR("Reload"));
+
+ disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave");
+ disk_changed->connect("custom_action", callable_mp(this, &EditorNode::_resave_scenes));
+ }
+
+ gui_base->add_child(disk_changed);
+
add_editor_plugin(memnew(AnimationPlayerEditorPlugin(this)));
add_editor_plugin(memnew(CanvasItemEditorPlugin(this)));
add_editor_plugin(memnew(Node3DEditorPlugin(this)));
@@ -6832,14 +6965,12 @@ EditorNode::EditorNode() {
ED_SHORTCUT("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_ALT | KEY_2);
ED_SHORTCUT("editor/editor_script", TTR("Open Script Editor"), KEY_MASK_ALT | KEY_3);
ED_SHORTCUT("editor/editor_assetlib", TTR("Open Asset Library"), KEY_MASK_ALT | KEY_4);
- ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_MASK_ALT | KEY_SPACE);
#else
// Use the Ctrl modifier so F2 can be used to rename nodes in the scene tree dock.
ED_SHORTCUT("editor/editor_2d", TTR("Open 2D Editor"), KEY_MASK_CTRL | KEY_F1);
ED_SHORTCUT("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_CTRL | KEY_F2);
ED_SHORTCUT("editor/editor_script", TTR("Open Script Editor"), KEY_MASK_CTRL | KEY_F3);
ED_SHORTCUT("editor/editor_assetlib", TTR("Open Asset Library"), KEY_MASK_CTRL | KEY_F4);
- ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_F1);
#endif
ED_SHORTCUT("editor/editor_next", TTR("Open the next Editor"));
ED_SHORTCUT("editor/editor_prev", TTR("Open the previous Editor"));
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 356ac0caac..7e16936f5d 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -31,6 +31,7 @@
#ifndef EDITOR_NODE_H
#define EDITOR_NODE_H
+#include "core/templates/safe_refcount.h"
#include "editor/editor_data.h"
#include "editor/editor_export.h"
#include "editor/editor_folding.h"
@@ -87,6 +88,7 @@ class Button;
class VSplitContainer;
class Window;
class SubViewport;
+class SceneImportSettings;
class EditorNode : public Node {
GDCLASS(EditorNode, Node);
@@ -111,7 +113,7 @@ public:
Thread execute_output_thread;
Mutex execute_output_mutex;
int exitcode = 0;
- volatile bool done = false;
+ SafeFlag done;
};
private:
@@ -128,7 +130,6 @@ private:
FILE_SAVE_ALL_SCENES,
FILE_SAVE_AND_RUN,
FILE_SHOW_IN_FILESYSTEM,
- FILE_IMPORT_SUBSCENE,
FILE_EXPORT_PROJECT,
FILE_EXPORT_MESH_LIBRARY,
FILE_INSTALL_ANDROID_SOURCE,
@@ -312,6 +313,9 @@ private:
EditorSettingsDialog *settings_config_dialog;
ProjectSettingsEditor *project_settings;
+ bool settings_changed = true; //make it update settings on first frame
+ void _update_from_settings();
+
PopupMenu *vcs_actions_menu;
EditorFileDialog *file;
ExportTemplateManager *export_template_manager;
@@ -407,6 +411,7 @@ private:
EditorResourcePreview *resource_preview;
EditorFolding editor_folding;
+ SceneImportSettings *scene_import_settings;
struct BottomPanelItem {
String name;
Control *control = nullptr;
@@ -422,6 +427,9 @@ private:
Label *version_label;
Button *bottom_panel_raise;
+ Tree *disk_changed_list;
+ ConfirmationDialog *disk_changed;
+
void _bottom_panel_raise_toggled(bool);
EditorInterface *editor_interface;
@@ -641,6 +649,10 @@ private:
static void _resource_loaded(RES p_resource, const String &p_path);
void _resources_changed(const Vector<String> &p_resources);
+ void _scan_external_changes();
+ void _reload_modified_scenes();
+ void _reload_project_settings();
+ void _resave_scenes(String p_str);
void _feature_profile_changed();
bool _is_class_editor_disabled_by_feature_profile(const StringName &p_class);
@@ -709,8 +721,6 @@ public:
void save_resource(const Ref<Resource> &p_resource);
void save_resource_as(const Ref<Resource> &p_resource, const String &p_at_path = String());
- void merge_from_scene() { _menu_option_confirm(FILE_IMPORT_SUBSCENE, false); }
-
void show_about() { _menu_option_confirm(HELP_ABOUT, false); }
static bool has_unsaved_changes() { return singleton->unsaved_cache; }
@@ -741,7 +751,7 @@ public:
void fix_dependencies(const String &p_for_file);
void clear_scene() { _cleanup_scene(); }
int new_scene();
- Error load_scene(const String &p_scene, bool p_ignore_broken_deps = false, bool p_set_inherited = false, bool p_clear_errors = true, bool p_force_open_imported = false);
+ Error load_scene(const String &p_scene, bool p_ignore_broken_deps = false, bool p_set_inherited = false, bool p_clear_errors = true, bool p_force_open_imported = false, bool p_silent_change_tab = false);
Error load_resource(const String &p_resource, bool p_ignore_broken_deps = false);
bool is_scene_open(const String &p_path);
@@ -840,6 +850,8 @@ public:
void save_scene_list(Vector<String> p_scene_filenames);
void restart_editor();
+ void notify_settings_changed();
+
void dim_editor(bool p_dimming, bool p_force_dim = false);
bool is_editor_dimmed() const;
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 840bae35bf..c0cecbc651 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -756,7 +756,6 @@ int find(const PackedStringArray &a, const String &v) {
void EditorPlugin::enable_plugin() {
// Called when the plugin gets enabled in project settings, after it's added to the tree.
// You can implement it to register autoloads.
-
if (get_script_instance() && get_script_instance()->has_method("enable_plugin")) {
get_script_instance()->call("enable_plugin");
}
@@ -819,6 +818,18 @@ void EditorPlugin::remove_debugger_plugin(const Ref<Script> &p_script) {
EditorDebuggerNode::get_singleton()->remove_debugger_plugin(p_script);
}
+void EditorPlugin::_editor_project_settings_changed() {
+ emit_signal("project_settings_changed");
+}
+void EditorPlugin::_notification(int p_what) {
+ if (p_what == NOTIFICATION_ENTER_TREE) {
+ EditorNode::get_singleton()->connect("project_settings_changed", callable_mp(this, &EditorPlugin::_editor_project_settings_changed));
+ }
+ if (p_what == NOTIFICATION_EXIT_TREE) {
+ EditorNode::get_singleton()->disconnect("project_settings_changed", callable_mp(this, &EditorPlugin::_editor_project_settings_changed));
+ }
+}
+
void EditorPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_control_to_container", "container", "control"), &EditorPlugin::add_control_to_container);
ClassDB::bind_method(D_METHOD("add_control_to_bottom_panel", "control", "title"), &EditorPlugin::add_control_to_bottom_panel);
@@ -890,6 +901,7 @@ void EditorPlugin::_bind_methods() {
ADD_SIGNAL(MethodInfo("scene_closed", PropertyInfo(Variant::STRING, "filepath")));
ADD_SIGNAL(MethodInfo("main_screen_changed", PropertyInfo(Variant::STRING, "screen_name")));
ADD_SIGNAL(MethodInfo("resource_saved", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
+ ADD_SIGNAL(MethodInfo("project_settings_changed"));
BIND_ENUM_CONSTANT(CONTAINER_TOOLBAR);
BIND_ENUM_CONSTANT(CONTAINER_SPATIAL_EDITOR_MENU);
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 3b741a2f22..ae9fcfb28a 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -130,7 +130,11 @@ class EditorPlugin : public Node {
String last_main_screen_name;
+ void _editor_project_settings_changed();
+
protected:
+ void _notification(int p_what);
+
static void _bind_methods();
UndoRedo &get_undo_redo() { return *undo_redo; }
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 4d8a4f46b2..d09e3726fb 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -621,7 +621,7 @@ public:
const Ref<InputEventMouseButton> mb = p_ev;
- if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed() && hovered_index >= 0) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed() && hovered_index >= 0) {
// Toggle the flag.
// We base our choice on the hovered flag, so that it always matches the hovered flag.
if (value & (1 << hovered_index)) {
@@ -716,12 +716,18 @@ void EditorPropertyLayers::setup(LayerType p_layer_type) {
case LAYER_PHYSICS_2D:
basename = "layer_names/2d_physics";
break;
+ case LAYER_NAVIGATION_2D:
+ basename = "layer_names/2d_navigation";
+ break;
case LAYER_RENDER_3D:
basename = "layer_names/3d_render";
break;
case LAYER_PHYSICS_3D:
basename = "layer_names/3d_physics";
break;
+ case LAYER_NAVIGATION_3D:
+ basename = "layer_names/3d_navigation";
+ break;
}
Vector<String> names;
@@ -921,11 +927,11 @@ EditorPropertyFloat::EditorPropertyFloat() {
void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) {
const Ref<InputEventMouseButton> mb = p_ev;
if (mb.is_valid()) {
- if (mb->is_doubleclick() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->is_doubleclick() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
_setup_spin();
}
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
preset->set_position(easing_draw->get_screen_transform().xform(mb->get_position()));
preset->popup();
@@ -934,7 +940,7 @@ void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) {
easing_draw->update();
}
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
dragging = mb->is_pressed();
// Update to display the correct dragging color
easing_draw->update();
@@ -943,7 +949,7 @@ void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) {
const Ref<InputEventMouseMotion> mm = p_ev;
- if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
float rel = mm->get_relative().x;
if (rel == 0) {
return;
@@ -1267,16 +1273,20 @@ void EditorPropertyRect2::setup(double p_min, double p_max, double p_step, bool
EditorPropertyRect2::EditorPropertyRect2(bool p_force_wide) {
bool horizontal = p_force_wide || bool(EDITOR_GET("interface/inspector/horizontal_vector_types_editing"));
-
+ bool grid = false;
BoxContainer *bc;
if (p_force_wide) {
bc = memnew(HBoxContainer);
add_child(bc);
} else if (horizontal) {
- bc = memnew(HBoxContainer);
+ bc = memnew(VBoxContainer);
add_child(bc);
set_bottom_editor(bc);
+
+ bc->add_child(memnew(HBoxContainer));
+ bc->add_child(memnew(HBoxContainer));
+ grid = true;
} else {
bc = memnew(VBoxContainer);
add_child(bc);
@@ -1287,7 +1297,13 @@ EditorPropertyRect2::EditorPropertyRect2(bool p_force_wide) {
spin[i] = memnew(EditorSpinSlider);
spin[i]->set_label(desc[i]);
spin[i]->set_flat(true);
- bc->add_child(spin[i]);
+
+ if (grid) {
+ bc->get_child(i / 2)->add_child(spin[i]);
+ } else {
+ bc->add_child(spin[i]);
+ }
+
add_focusable(spin[i]);
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyRect2::_value_changed), varray(desc[i]));
if (horizontal) {
@@ -1530,16 +1546,20 @@ void EditorPropertyRect2i::setup(int p_min, int p_max, bool p_no_slider) {
EditorPropertyRect2i::EditorPropertyRect2i(bool p_force_wide) {
bool horizontal = p_force_wide || bool(EDITOR_GET("interface/inspector/horizontal_vector_types_editing"));
-
+ bool grid = false;
BoxContainer *bc;
if (p_force_wide) {
bc = memnew(HBoxContainer);
add_child(bc);
} else if (horizontal) {
- bc = memnew(HBoxContainer);
+ bc = memnew(VBoxContainer);
add_child(bc);
set_bottom_editor(bc);
+
+ bc->add_child(memnew(HBoxContainer));
+ bc->add_child(memnew(HBoxContainer));
+ grid = true;
} else {
bc = memnew(VBoxContainer);
add_child(bc);
@@ -1550,7 +1570,13 @@ EditorPropertyRect2i::EditorPropertyRect2i(bool p_force_wide) {
spin[i] = memnew(EditorSpinSlider);
spin[i]->set_label(desc[i]);
spin[i]->set_flat(true);
- bc->add_child(spin[i]);
+
+ if (grid) {
+ bc->get_child(i / 2)->add_child(spin[i]);
+ } else {
+ bc->add_child(spin[i]);
+ }
+
add_focusable(spin[i]);
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyRect2i::_value_changed), varray(desc[i]));
if (horizontal) {
@@ -2788,7 +2814,7 @@ void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) {
void EditorPropertyResource::_button_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
_update_menu_items();
Vector2 pos = get_screen_position() + mb->get_position();
//pos = assign->get_global_transform().xform(pos);
@@ -2839,6 +2865,41 @@ void EditorPropertyResource::_fold_other_editors(Object *p_self) {
}
}
+void EditorPropertyResource::_update_property_bg() {
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ updating_theme = true;
+ if (sub_inspector != nullptr) {
+ int count_subinspectors = 0;
+ Node *n = get_parent();
+ while (n) {
+ EditorInspector *ei = Object::cast_to<EditorInspector>(n);
+ if (ei && ei->is_sub_inspector()) {
+ count_subinspectors++;
+ }
+ n = n->get_parent();
+ }
+ count_subinspectors = MIN(15, count_subinspectors);
+
+ add_theme_color_override("property_color", get_theme_color("sub_inspector_property_color", "Editor"));
+ add_theme_style_override("bg_selected", get_theme_stylebox("sub_inspector_property_bg_selected" + itos(count_subinspectors), "Editor"));
+ add_theme_style_override("bg", get_theme_stylebox("sub_inspector_property_bg" + itos(count_subinspectors), "Editor"));
+
+ add_theme_constant_override("font_offset", get_theme_constant("sub_inspector_font_offset", "Editor"));
+ add_theme_constant_override("vseparation", 0);
+ } else {
+ add_theme_color_override("property_color", get_theme_color("property_color", "EditorProperty"));
+ add_theme_style_override("bg_selected", get_theme_stylebox("bg_selected", "EditorProperty"));
+ add_theme_style_override("bg", get_theme_stylebox("bg", "EditorProperty"));
+ add_theme_constant_override("vseparation", get_theme_constant("vseparation", "EditorProperty"));
+ add_theme_constant_override("font_offset", get_theme_constant("font_offset", "EditorProperty"));
+ }
+
+ updating_theme = false;
+ update();
+}
void EditorPropertyResource::update_property() {
RES res = get_edited_object()->get(get_edited_property());
@@ -2854,7 +2915,7 @@ void EditorPropertyResource::update_property() {
sub_inspector->set_use_doc_hints(true);
sub_inspector->set_sub_inspector(true);
- sub_inspector->set_enable_capitalize_paths(true);
+ sub_inspector->set_enable_capitalize_paths(bool(EDITOR_GET("interface/inspector/capitalize_properties")));
sub_inspector->connect("property_keyed", callable_mp(this, &EditorPropertyResource::_sub_inspector_property_keyed));
sub_inspector->connect("resource_selected", callable_mp(this, &EditorPropertyResource::_sub_inspector_resource_selected));
@@ -2887,13 +2948,14 @@ void EditorPropertyResource::update_property() {
}
opened_editor = true;
}
+
+ _update_property_bg();
}
if (res.ptr() != sub_inspector->get_edited_object()) {
sub_inspector->edit(res.ptr());
}
- sub_inspector->refresh();
} else {
if (sub_inspector) {
set_bottom_editor(nullptr);
@@ -2904,6 +2966,7 @@ void EditorPropertyResource::update_property() {
EditorNode::get_singleton()->hide_top_editors();
opened_editor = false;
}
+ _update_property_bg();
}
}
}
@@ -2957,8 +3020,12 @@ void EditorPropertyResource::setup(const String &p_base_type) {
void EditorPropertyResource::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
+ if (updating_theme) {
+ return;
+ }
Ref<Texture2D> t = get_theme_icon("select_arrow", "Tree");
edit->set_icon(t);
+ _update_property_bg();
}
if (p_what == NOTIFICATION_DRAG_BEGIN) {
@@ -3239,7 +3306,12 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
editor->setup(options);
add_property_editor(p_path, editor);
- } else if (p_hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || p_hint == PROPERTY_HINT_LAYERS_2D_RENDER || p_hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || p_hint == PROPERTY_HINT_LAYERS_3D_RENDER) {
+ } else if (p_hint == PROPERTY_HINT_LAYERS_2D_PHYSICS ||
+ p_hint == PROPERTY_HINT_LAYERS_2D_RENDER ||
+ p_hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION ||
+ p_hint == PROPERTY_HINT_LAYERS_3D_PHYSICS ||
+ p_hint == PROPERTY_HINT_LAYERS_3D_RENDER ||
+ p_hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) {
EditorPropertyLayers::LayerType lt = EditorPropertyLayers::LAYER_RENDER_2D;
switch (p_hint) {
case PROPERTY_HINT_LAYERS_2D_RENDER:
@@ -3248,12 +3320,18 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
case PROPERTY_HINT_LAYERS_2D_PHYSICS:
lt = EditorPropertyLayers::LAYER_PHYSICS_2D;
break;
+ case PROPERTY_HINT_LAYERS_2D_NAVIGATION:
+ lt = EditorPropertyLayers::LAYER_NAVIGATION_2D;
+ break;
case PROPERTY_HINT_LAYERS_3D_RENDER:
lt = EditorPropertyLayers::LAYER_RENDER_3D;
break;
case PROPERTY_HINT_LAYERS_3D_PHYSICS:
lt = EditorPropertyLayers::LAYER_PHYSICS_3D;
break;
+ case PROPERTY_HINT_LAYERS_3D_NAVIGATION:
+ lt = EditorPropertyLayers::LAYER_NAVIGATION_3D;
+ break;
default: {
} //compiler could be smarter here and realize this can't happen
}
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index 4775259111..07a1e72319 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -239,8 +239,10 @@ public:
enum LayerType {
LAYER_PHYSICS_2D,
LAYER_RENDER_2D,
+ LAYER_NAVIGATION_2D,
LAYER_PHYSICS_3D,
LAYER_RENDER_3D,
+ LAYER_NAVIGATION_3D,
};
private:
@@ -654,6 +656,9 @@ class EditorPropertyResource : public EditorProperty {
bool opened_editor;
+ bool updating_theme = false;
+ void _update_property_bg();
+
protected:
static void _bind_methods();
void _notification(int p_what);
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index a798344973..de688f2709 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -573,8 +573,7 @@ void EditorPropertyArray::_bind_methods() {
EditorPropertyArray::EditorPropertyArray() {
object.instance();
- page_idx = 0;
- page_len = 10;
+ page_len = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
edit = memnew(Button);
edit->set_flat(true);
edit->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1069,8 +1068,7 @@ void EditorPropertyDictionary::_bind_methods() {
EditorPropertyDictionary::EditorPropertyDictionary() {
object.instance();
- page_idx = 0;
- page_len = 10;
+ page_len = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
edit = memnew(Button);
edit->set_flat(true);
edit->set_h_size_flags(SIZE_EXPAND_FILL);
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
index 0359f3d9bc..fa5adc788d 100644
--- a/editor/editor_properties_array_dict.h
+++ b/editor/editor_properties_array_dict.h
@@ -84,8 +84,8 @@ class EditorPropertyArray : public EditorProperty {
bool dropping;
Ref<EditorPropertyArrayObject> object;
- int page_len;
- int page_idx;
+ int page_len = 20;
+ int page_idx = 0;
int changing_type_idx;
Button *edit;
VBoxContainer *vbox;
@@ -129,8 +129,8 @@ class EditorPropertyDictionary : public EditorProperty {
bool updating;
Ref<EditorPropertyDictionaryObject> object;
- int page_len;
- int page_idx;
+ int page_len = 20;
+ int page_idx = 0;
int changing_type_idx;
Button *edit;
VBoxContainer *vbox;
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 8056846f52..77288be614 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -206,8 +206,8 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
}
void EditorResourcePreview::_thread() {
- exited = false;
- while (!exit) {
+ exited.clear();
+ while (!exit.is_set()) {
preview_sem.wait();
preview_mutex.lock();
@@ -326,7 +326,7 @@ void EditorResourcePreview::_thread() {
preview_mutex.unlock();
}
}
- exited = true;
+ exited.set();
}
void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource> &p_res, Object *p_receiver, const StringName &p_receiver_func, const Variant &p_userdata) {
@@ -430,9 +430,9 @@ void EditorResourcePreview::start() {
void EditorResourcePreview::stop() {
if (thread.is_started()) {
- exit = true;
+ exit.set();
preview_sem.post();
- while (!exited) {
+ while (!exited.is_set()) {
OS::get_singleton()->delay_usec(10000);
RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server
}
@@ -443,8 +443,6 @@ void EditorResourcePreview::stop() {
EditorResourcePreview::EditorResourcePreview() {
singleton = this;
order = 0;
- exit = false;
- exited = false;
}
EditorResourcePreview::~EditorResourcePreview() {
diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h
index 99c48967d8..c4e796dcf1 100644
--- a/editor/editor_resource_preview.h
+++ b/editor/editor_resource_preview.h
@@ -33,6 +33,7 @@
#include "core/os/semaphore.h"
#include "core/os/thread.h"
+#include "core/templates/safe_refcount.h"
#include "scene/main/node.h"
#include "scene/resources/texture.h"
@@ -71,8 +72,8 @@ class EditorResourcePreview : public Node {
Mutex preview_mutex;
Semaphore preview_sem;
Thread thread;
- volatile bool exit;
- volatile bool exited;
+ SafeFlag exit;
+ SafeFlag exited;
struct Item {
Ref<Texture2D> preview;
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index a2627f51ac..f81c87be9e 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -116,12 +116,12 @@ public:
void set_section(const String &p_section, bool p_allow_sub) {
section = p_section;
allow_sub = p_allow_sub;
- _change_notify();
+ notify_property_list_changed();
}
void set_edited(Object *p_edited) {
edited = p_edited;
- _change_notify();
+ notify_property_list_changed();
}
};
@@ -226,7 +226,7 @@ void SectionedInspector::update_category_list() {
if (pi.usage & PROPERTY_USAGE_CATEGORY) {
continue;
- } else if (!(pi.usage & PROPERTY_USAGE_EDITOR)) {
+ } else if (!(pi.usage & PROPERTY_USAGE_EDITOR) || (restrict_to_basic && !(pi.usage & PROPERTY_USAGE_EDITOR_BASIC_SETTING))) {
continue;
}
@@ -294,6 +294,12 @@ EditorInspector *SectionedInspector::get_inspector() {
return inspector;
}
+void SectionedInspector::set_restrict_to_basic_settings(bool p_restrict) {
+ restrict_to_basic = p_restrict;
+ update_category_list();
+ inspector->set_restrict_to_basic_settings(p_restrict);
+}
+
SectionedInspector::SectionedInspector() :
sections(memnew(Tree)),
filter(memnew(SectionedInspectorFilter)),
diff --git a/editor/editor_sectioned_inspector.h b/editor/editor_sectioned_inspector.h
index 55fb94fecc..1068a4f932 100644
--- a/editor/editor_sectioned_inspector.h
+++ b/editor/editor_sectioned_inspector.h
@@ -51,6 +51,8 @@ class SectionedInspector : public HSplitContainer {
String selected_category;
+ bool restrict_to_basic = false;
+
static void _bind_methods();
void _section_selected();
@@ -65,6 +67,7 @@ public:
void set_current_section(const String &p_section);
String get_current_section() const;
+ void set_restrict_to_basic_settings(bool p_restrict);
void update_category_list();
SectionedInspector();
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 9908f5727e..4ddae7c062 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -31,6 +31,7 @@
#include "editor_settings.h"
#include "core/config/project_settings.h"
+#include "core/input/input_map.h"
#include "core/io/certs_compressed.gen.h"
#include "core/io/compression.h"
#include "core/io/config_file.h"
@@ -70,7 +71,7 @@ bool EditorSettings::_set(const StringName &p_name, const Variant &p_value) {
bool EditorSettings::_set_only(const StringName &p_name, const Variant &p_value) {
_THREAD_SAFE_METHOD_
- if (p_name.operator String() == "shortcuts") {
+ if (p_name == "shortcuts") {
Array arr = p_value;
ERR_FAIL_COND_V(arr.size() && arr.size() & 1, true);
for (int i = 0; i < arr.size(); i += 2) {
@@ -84,6 +85,24 @@ bool EditorSettings::_set_only(const StringName &p_name, const Variant &p_value)
}
return false;
+ } else if (p_name == "builtin_action_overrides") {
+ Array actions_arr = p_value;
+ for (int i = 0; i < actions_arr.size(); i++) {
+ Dictionary action_dict = actions_arr[i];
+
+ String name = action_dict["name"];
+ Array events = action_dict["events"];
+
+ InputMap *im = InputMap::get_singleton();
+ im->action_erase_events(name);
+
+ builtin_action_overrides[name].clear();
+ for (int ev_idx = 0; ev_idx < events.size(); ev_idx++) {
+ im->action_add_event(name, events[ev_idx]);
+ builtin_action_overrides[name].push_back(events[ev_idx]);
+ }
+ }
+ return false;
}
bool changed = false;
@@ -118,11 +137,16 @@ bool EditorSettings::_set_only(const StringName &p_name, const Variant &p_value)
bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const {
_THREAD_SAFE_METHOD_
- if (p_name.operator String() == "shortcuts") {
+ if (p_name == "shortcuts") {
Array arr;
for (const Map<String, Ref<Shortcut>>::Element *E = shortcuts.front(); E; E = E->next()) {
Ref<Shortcut> sc = E->get();
+ if (builtin_action_overrides.has(E->key())) {
+ // This shortcut was auto-generated from built in actions: don't save.
+ continue;
+ }
+
if (optimize_save) {
if (!sc->has_meta("original")) {
continue; //this came from settings but is not any longer used
@@ -139,6 +163,27 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const {
}
r_ret = arr;
return true;
+ } else if (p_name == "builtin_action_overrides") {
+ Array actions_arr;
+ for (Map<String, List<Ref<InputEvent>>>::Element *E = builtin_action_overrides.front(); E; E = E->next()) {
+ List<Ref<InputEvent>> events = E->get();
+
+ // TODO: skip actions which are the same as the builtin.
+ Dictionary action_dict;
+ action_dict["name"] = E->key();
+
+ Array events_arr;
+ for (List<Ref<InputEvent>>::Element *I = events.front(); I; I = I->next()) {
+ events_arr.push_back(I->get());
+ }
+
+ action_dict["events"] = events_arr;
+
+ actions_arr.push_back(action_dict);
+ }
+
+ r_ret = actions_arr;
+ return true;
}
const VariantContainer *v = props.getptr(p_name);
@@ -220,6 +265,7 @@ void EditorSettings::_get_property_list(List<PropertyInfo> *p_list) const {
}
p_list->push_back(PropertyInfo(Variant::ARRAY, "shortcuts", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); //do not edit
+ p_list->push_back(PropertyInfo(Variant::ARRAY, "builtin_action_overrides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
}
void EditorSettings::_add_property_info_bind(const Dictionary &p_info) {
@@ -337,6 +383,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
if (DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).y >= 1400) {
// hiDPI display.
scale = 2.0;
+ } else if (DisplayServer::get_singleton()->screen_get_size(screen).y >= 1700) {
+ // Likely a hiDPI display, but we aren't certain due to the returned DPI.
+ // Use an intermediate scale to handle this situation.
+ scale = 1.5;
} else if (DisplayServer::get_singleton()->screen_get_size(screen).y <= 800) {
// Small loDPI display. Use a smaller display scale so that editor elements fit more easily.
// Icons won't look great, but this is better than having editor elements overflow from its window.
@@ -381,6 +431,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("interface/editor/hide_console_window", false);
_initial_set("interface/editor/save_each_scene_on_quit", true); // Regression
+ // Inspector
+ _initial_set("interface/inspector/max_array_dictionary_items_per_page", 20);
+ hints["interface/inspector/max_array_dictionary_items_per_page"] = PropertyInfo(Variant::INT, "interface/inspector/max_array_dictionary_items_per_page", PROPERTY_HINT_RANGE, "10,100,1", PROPERTY_USAGE_DEFAULT);
+
// Theme
_initial_set("interface/theme/preset", "Default");
hints["interface/theme/preset"] = PropertyInfo(Variant::STRING, "interface/theme/preset", PROPERTY_HINT_ENUM, "Default,Alien,Arc,Godot 2,Grey,Light,Solarized (Dark),Solarized (Light),Custom", PROPERTY_USAGE_DEFAULT);
@@ -392,6 +446,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["interface/theme/accent_color"] = PropertyInfo(Variant::COLOR, "interface/theme/accent_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT);
_initial_set("interface/theme/contrast", 0.25);
hints["interface/theme/contrast"] = PropertyInfo(Variant::FLOAT, "interface/theme/contrast", PROPERTY_HINT_RANGE, "0.01, 1, 0.01");
+ _initial_set("interface/theme/icon_saturation", 1.0);
+ hints["interface/theme/icon_saturation"] = PropertyInfo(Variant::FLOAT, "interface/theme/icon_saturation", PROPERTY_HINT_RANGE, "0,2,0.01", PROPERTY_USAGE_DEFAULT);
_initial_set("interface/theme/relationship_line_opacity", 0.1);
hints["interface/theme/relationship_line_opacity"] = PropertyInfo(Variant::FLOAT, "interface/theme/relationship_line_opacity", PROPERTY_HINT_RANGE, "0.00, 1, 0.01");
_initial_set("interface/theme/highlight_tabs", false);
@@ -404,7 +460,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["interface/theme/custom_theme"] = PropertyInfo(Variant::STRING, "interface/theme/custom_theme", PROPERTY_HINT_GLOBAL_FILE, "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT);
// Scene tabs
- _initial_set("interface/scene_tabs/show_extension", false);
_initial_set("interface/scene_tabs/show_thumbnail_on_hover", true);
_initial_set("interface/scene_tabs/resize_if_many_tabs", true);
_initial_set("interface/scene_tabs/minimum_width", 50);
@@ -441,7 +496,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("docks/filesystem/always_show_folders", true);
// Property editor
- _initial_set("docks/property_editor/auto_refresh_interval", 0.3);
+ _initial_set("docks/property_editor/auto_refresh_interval", 0.2); //update 5 times per second by default
+ _initial_set("docks/property_editor/subresource_hue_tint", 0.75);
+ hints["docks/property_editor/subresource_hue_tint"] = PropertyInfo(Variant::FLOAT, "docks/property_editor/subresource_hue_tint", PROPERTY_HINT_RANGE, "0,1,0.01", PROPERTY_USAGE_DEFAULT);
/* Text editor */
@@ -562,8 +619,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// is increased significantly more than it really should need to be.
hints["editors/3d/grid_division_level_max"] = PropertyInfo(Variant::INT, "editors/3d/grid_division_level_max", PROPERTY_HINT_RANGE, "-1,3,1", PROPERTY_USAGE_DEFAULT);
- // Default smallest grid size is 1cm, 10^-2.
- _initial_set("editors/3d/grid_division_level_min", -2);
+ // Default smallest grid size is 1m, 10^0.
+ _initial_set("editors/3d/grid_division_level_min", 0);
// Lower values produce graphical artifacts regardless of view clipping planes, so limit to -2 as a lower bound.
hints["editors/3d/grid_division_level_min"] = PropertyInfo(Variant::INT, "editors/3d/grid_division_level_min", PROPERTY_HINT_RANGE, "-2,2,1", PROPERTY_USAGE_DEFAULT);
@@ -1277,7 +1334,7 @@ String EditorSettings::get_script_templates_dir() const {
}
String EditorSettings::get_project_script_templates_dir() const {
- return ProjectSettings::get_singleton()->get("editor/script_templates_search_path");
+ return ProjectSettings::get_singleton()->get("editor/script/templates_search_path");
}
// Cache directory
@@ -1531,12 +1588,39 @@ bool EditorSettings::is_shortcut(const String &p_name, const Ref<InputEvent> &p_
}
Ref<Shortcut> EditorSettings::get_shortcut(const String &p_name) const {
- const Map<String, Ref<Shortcut>>::Element *E = shortcuts.find(p_name);
- if (!E) {
- return Ref<Shortcut>();
+ const Map<String, Ref<Shortcut>>::Element *SC = shortcuts.find(p_name);
+ if (SC) {
+ return SC->get();
}
- return E->get();
+ // If no shortcut with the provided name is found in the list, check the built-in shortcuts.
+ // Use the first item in the action list for the shortcut event, since a shortcut can only have 1 linked event.
+
+ Ref<Shortcut> sc;
+ const Map<String, List<Ref<InputEvent>>>::Element *builtin_override = builtin_action_overrides.find(p_name);
+ if (builtin_override) {
+ sc.instance();
+ sc->set_shortcut(builtin_override->get().front()->get());
+ sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name));
+ }
+
+ // If there was no override, check the default builtins to see if it has an InputEvent for the provided name.
+ if (sc.is_null()) {
+ const OrderedHashMap<String, List<Ref<InputEvent>>>::ConstElement builtin_default = InputMap::get_singleton()->get_builtins().find(p_name);
+ if (builtin_default) {
+ sc.instance();
+ sc->set_shortcut(builtin_default.get().front()->get());
+ sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name));
+ }
+ }
+
+ if (sc.is_valid()) {
+ // Add the shortcut to the list.
+ shortcuts[p_name] = sc;
+ return sc;
+ }
+
+ return Ref<Shortcut>();
}
void EditorSettings::get_shortcut_list(List<String> *r_shortcuts) {
@@ -1602,6 +1686,66 @@ Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p
return sc;
}
+void EditorSettings::set_builtin_action_override(const String &p_name, const Array &p_events) {
+ List<Ref<InputEvent>> event_list;
+
+ // Override the whole list, since events may have their order changed or be added, removed or edited.
+ InputMap::get_singleton()->action_erase_events(p_name);
+ for (int i = 0; i < p_events.size(); i++) {
+ event_list.push_back(p_events[i]);
+ InputMap::get_singleton()->action_add_event(p_name, p_events[i]);
+ }
+
+ // Check if the provided event array is same as built-in. If it is, it does not need to be added to the overrides.
+ // Note that event order must also be the same.
+ bool same_as_builtin = true;
+ OrderedHashMap<String, List<Ref<InputEvent>>>::ConstElement builtin_default = InputMap::get_singleton()->get_builtins().find(p_name);
+ if (builtin_default) {
+ List<Ref<InputEvent>> builtin_events = builtin_default.get();
+
+ if (p_events.size() == builtin_events.size()) {
+ int event_idx = 0;
+
+ // Check equality of each event.
+ for (List<Ref<InputEvent>>::Element *E = builtin_events.front(); E; E = E->next()) {
+ if (!E->get()->shortcut_match(p_events[event_idx])) {
+ same_as_builtin = false;
+ break;
+ }
+ event_idx++;
+ }
+ } else {
+ same_as_builtin = false;
+ }
+ }
+
+ if (same_as_builtin && builtin_action_overrides.has(p_name)) {
+ builtin_action_overrides.erase(p_name);
+ } else {
+ builtin_action_overrides[p_name] = event_list;
+ }
+
+ // Update the shortcut (if it is used somewhere in the editor) to be the first event of the new list.
+ if (shortcuts.has(p_name)) {
+ shortcuts[p_name]->set_shortcut(event_list.front()->get());
+ }
+}
+
+const Array EditorSettings::get_builtin_action_overrides(const String &p_name) const {
+ const Map<String, List<Ref<InputEvent>>>::Element *AO = builtin_action_overrides.find(p_name);
+ if (AO) {
+ Array event_array;
+
+ List<Ref<InputEvent>> events_list = AO->get();
+ for (List<Ref<InputEvent>>::Element *E = events_list.front(); E; E = E->next()) {
+ event_array.push_back(E->get());
+ }
+ return event_array;
+ }
+
+ return Array();
+}
+
void EditorSettings::notify_changes() {
_THREAD_SAFE_METHOD_
@@ -1640,6 +1784,8 @@ void EditorSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_recent_dirs", "dirs"), &EditorSettings::set_recent_dirs);
ClassDB::bind_method(D_METHOD("get_recent_dirs"), &EditorSettings::get_recent_dirs);
+ ClassDB::bind_method(D_METHOD("set_builtin_action_override", "name", "actions_list"), &EditorSettings::set_builtin_action_override);
+
ADD_SIGNAL(MethodInfo("settings_changed"));
BIND_CONSTANT(NOTIFICATION_EDITOR_SETTINGS_CHANGED);
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index 616a938a86..e5f8527faf 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -84,7 +84,8 @@ private:
int last_order;
Ref<Resource> clipboard;
- Map<String, Ref<Shortcut>> shortcuts;
+ mutable Map<String, Ref<Shortcut>> shortcuts;
+ Map<String, List<Ref<InputEvent>>> builtin_action_overrides;
String resource_path;
String settings_dir;
@@ -186,6 +187,9 @@ public:
Ref<Shortcut> get_shortcut(const String &p_name) const;
void get_shortcut_list(List<String> *r_shortcuts);
+ void set_builtin_action_override(const String &p_name, const Array &p_events);
+ const Array get_builtin_action_overrides(const String &p_name) const;
+
void notify_changes();
EditorSettings();
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index 618d953c56..c09d78826c 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -53,7 +53,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
if (updown_offset != -1 && mb->get_position().x > updown_offset) {
//there is an updown, so use it.
@@ -84,7 +84,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
grabbing_spinner_attempt = false;
}
}
- } else if (mb->get_button_index() == BUTTON_WHEEL_UP || mb->get_button_index() == BUTTON_WHEEL_DOWN) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP || mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
if (grabber->is_visible()) {
call_deferred("update");
}
@@ -146,17 +146,17 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
if (grabbing_grabber) {
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_WHEEL_UP) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
set_value(get_value() + get_step());
mousewheel_over_grabber = true;
- } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
set_value(get_value() - get_step());
mousewheel_over_grabber = true;
}
}
}
- if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
grabbing_grabber = true;
if (!mousewheel_over_grabber) {
@@ -175,7 +175,9 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
return;
}
- float grabbing_ofs = (grabber->get_transform().xform(mm->get_position()).x - grabbing_from) / float(grabber_range);
+ float scale_x = get_global_transform_with_canvas().get_scale().x;
+ ERR_FAIL_COND(Math::is_zero_approx(scale_x));
+ float grabbing_ofs = (grabber->get_transform().xform(mm->get_position()).x - grabbing_from) / float(grabber_range) / scale_x;
set_as_ratio(grabbing_ratio + grabbing_ofs);
update();
}
@@ -300,8 +302,10 @@ void EditorSpinSlider::_notification(int p_what) {
grabber->set_texture(grabber_tex);
}
+ Vector2 scale = get_global_transform_with_canvas().get_scale();
+ grabber->set_scale(scale);
grabber->set_size(Size2(0, 0));
- grabber->set_position(get_global_position() + grabber_rect.position + grabber_rect.size * 0.5 - grabber->get_size() * 0.5);
+ grabber->set_position(get_global_position() + (grabber_rect.position + grabber_rect.size * 0.5 - grabber->get_size() * 0.5) * scale);
if (mousewheel_over_grabber) {
Input::get_singleton()->warp_mouse_position(grabber->get_position() + grabber_rect.size);
diff --git a/editor/editor_sub_scene.cpp b/editor/editor_sub_scene.cpp
deleted file mode 100644
index e319fbff52..0000000000
--- a/editor/editor_sub_scene.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-/*************************************************************************/
-/* editor_sub_scene.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "editor_sub_scene.h"
-
-#include "editor/editor_node.h"
-#include "scene/gui/margin_container.h"
-#include "scene/resources/packed_scene.h"
-
-void EditorSubScene::_path_selected(const String &p_path) {
- path->set_text(p_path);
- _path_changed(p_path);
-}
-
-void EditorSubScene::_path_changed(const String &p_path) {
- tree->clear();
-
- if (scene) {
- memdelete(scene);
- scene = nullptr;
- }
-
- if (p_path == "") {
- return;
- }
-
- Ref<PackedScene> ps = ResourceLoader::load(p_path, "PackedScene");
-
- if (ps.is_null()) {
- return;
- }
-
- scene = ps->instance();
- if (!scene) {
- return;
- }
-
- _fill_tree(scene, nullptr);
-}
-
-void EditorSubScene::_path_browse() {
- file_dialog->popup_file_dialog();
-}
-
-void EditorSubScene::_notification(int p_what) {
- if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
- if (is_visible() && scene == nullptr) {
- _path_browse();
- }
- }
-}
-
-void EditorSubScene::_fill_tree(Node *p_node, TreeItem *p_parent) {
- TreeItem *it = tree->create_item(p_parent);
- it->set_metadata(0, p_node);
- it->set_text(0, p_node->get_name());
- it->set_editable(0, false);
- it->set_selectable(0, true);
- it->set_icon(0, EditorNode::get_singleton()->get_object_icon(p_node, "Node"));
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
- Node *c = p_node->get_child(i);
- if (c->get_owner() != scene) {
- continue;
- }
- _fill_tree(c, it);
- }
-}
-
-void EditorSubScene::_selected_changed() {
- TreeItem *item = tree->get_selected();
- ERR_FAIL_COND(!item);
- Node *n = item->get_metadata(0);
-
- if (!n || !selection.find(n)) {
- selection.clear();
- is_root = false;
- }
-}
-
-void EditorSubScene::_item_multi_selected(Object *p_object, int p_cell, bool p_selected) {
- if (!is_root) {
- TreeItem *item = Object::cast_to<TreeItem>(p_object);
- ERR_FAIL_COND(!item);
-
- Node *n = item->get_metadata(0);
-
- if (!n) {
- return;
- }
- if (p_selected) {
- if (n == scene) {
- is_root = true;
- selection.clear();
- }
- selection.push_back(n);
- } else {
- List<Node *>::Element *E = selection.find(n);
-
- if (E) {
- selection.erase(E);
- }
- }
- }
-}
-
-void EditorSubScene::_item_activated() {
- _ok_pressed(); // From AcceptDialog.
-}
-
-void EditorSubScene::_remove_selection_child(Node *p_node) {
- if (p_node->get_child_count() > 0) {
- for (int i = 0; i < p_node->get_child_count(); i++) {
- Node *c = p_node->get_child(i);
- List<Node *>::Element *E = selection.find(c);
- if (E) {
- selection.move_to_back(E);
- selection.pop_back();
- }
- if (c->get_child_count() > 0) {
- _remove_selection_child(c);
- }
- }
- }
-}
-
-void EditorSubScene::ok_pressed() {
- if (selection.size() <= 0) {
- return;
- }
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node *c = E->get();
- _remove_selection_child(c);
- }
- emit_signal("subscene_selected");
- hide();
- clear();
-}
-
-void EditorSubScene::_reown(Node *p_node, List<Node *> *p_to_reown) {
- if (p_node == scene) {
- scene->set_filename("");
- p_to_reown->push_back(p_node);
- } else if (p_node->get_owner() == scene) {
- p_to_reown->push_back(p_node);
- }
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
- Node *c = p_node->get_child(i);
- _reown(c, p_to_reown);
- }
-}
-
-void EditorSubScene::move(Node *p_new_parent, Node *p_new_owner) {
- if (!scene) {
- return;
- }
-
- if (selection.size() <= 0) {
- return;
- }
-
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node *selnode = E->get();
- if (!selnode) {
- return;
- }
- List<Node *> to_reown;
- _reown(selnode, &to_reown);
- if (selnode != scene) {
- selnode->get_parent()->remove_child(selnode);
- }
-
- p_new_parent->add_child(selnode);
- for (List<Node *>::Element *F = to_reown.front(); F; F = F->next()) {
- F->get()->set_owner(p_new_owner);
- }
- }
- if (!is_root) {
- memdelete(scene);
- }
- scene = nullptr;
- //return selnode;
-}
-
-void EditorSubScene::clear() {
- path->set_text("");
- _path_changed("");
-}
-
-void EditorSubScene::_bind_methods() {
- ADD_SIGNAL(MethodInfo("subscene_selected"));
-}
-
-EditorSubScene::EditorSubScene() {
- scene = nullptr;
- is_root = false;
-
- set_title(TTR("Select Node(s) to Import"));
- set_hide_on_ok(false);
-
- VBoxContainer *vb = memnew(VBoxContainer);
- add_child(vb);
- //set_child_rect(vb);
-
- HBoxContainer *hb = memnew(HBoxContainer);
- path = memnew(LineEdit);
- path->connect("text_entered", callable_mp(this, &EditorSubScene::_path_changed));
- hb->add_child(path);
- path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- Button *b = memnew(Button);
- b->set_text(TTR("Browse"));
- hb->add_child(b);
- b->connect("pressed", callable_mp(this, &EditorSubScene::_path_browse));
- vb->add_margin_child(TTR("Scene Path:"), hb);
-
- tree = memnew(Tree);
- tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- vb->add_margin_child(TTR("Import From Node:"), tree, true);
- tree->set_select_mode(Tree::SELECT_MULTI);
- tree->connect("multi_selected", callable_mp(this, &EditorSubScene::_item_multi_selected));
- //tree->connect("nothing_selected", this, "_deselect_items");
- tree->connect("cell_selected", callable_mp(this, &EditorSubScene::_selected_changed));
-
- tree->connect("item_activated", callable_mp(this, &EditorSubScene::_item_activated), make_binds(), CONNECT_DEFERRED);
-
- file_dialog = memnew(EditorFileDialog);
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions);
-
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- file_dialog->add_filter("*." + E->get());
- }
-
- file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
- add_child(file_dialog);
- file_dialog->connect("file_selected", callable_mp(this, &EditorSubScene::_path_selected));
-}
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 8f877a4762..9aad1aa8d9 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -106,7 +106,7 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false,
}
#ifdef MODULE_SVG_ENABLED
-static Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color, float p_scale = EDSCALE, bool p_force_filter = false) {
+static Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color, float p_scale = EDSCALE, float p_saturation = 1.0) {
Ref<ImageTexture> icon = memnew(ImageTexture);
Ref<Image> img = memnew(Image);
@@ -116,6 +116,9 @@ static Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color,
const bool upsample = !Math::is_equal_approx(Math::round(p_scale), p_scale);
ImageLoaderSVG::create_image_from_string(img, editor_icons_sources[p_index], p_scale, upsample, p_convert_color);
+ if (p_saturation != 1.0) {
+ img->adjust_bcs(1.0, 1.0, p_saturation);
+ }
icon->create_from_image(img); // in this case filter really helps
return icon;
@@ -126,7 +129,7 @@ static Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color,
#define ADD_CONVERT_COLOR(dictionary, old_color, new_color) dictionary[Color::html(old_color)] = Color::html(new_color)
#endif
-void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = true, int p_thumb_size = 32, bool p_only_thumbs = false) {
+void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = true, int p_thumb_size = 32, bool p_only_thumbs = false, float p_icon_saturation = 1.0) {
#ifdef MODULE_SVG_ENABLED
// The default icon theme is designed to be used for a dark theme.
// This dictionary stores color codes to convert to other colors
@@ -238,15 +241,14 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
// Generate icons.
if (!p_only_thumbs) {
for (int i = 0; i < editor_icons_count; i++) {
- float icon_scale = EDSCALE;
+ float saturation = p_icon_saturation;
- // Always keep the DefaultProjectIcon at the default size
- if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0) {
- icon_scale = 1.0f;
+ if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0 || strcmp(editor_icons_names[i], "Godot") == 0 || strcmp(editor_icons_names[i], "Logo") == 0) {
+ saturation = 1.0;
}
const int is_exception = exceptions.has(editor_icons_names[i]);
- const Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception, icon_scale);
+ const Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception, EDSCALE, saturation);
p_theme->set_icon(editor_icons_names[i], "EditorIcons", icon);
}
@@ -290,6 +292,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");
+ float icon_saturation = EDITOR_GET("interface/theme/icon_saturation");
float relationship_line_opacity = EDITOR_GET("interface/theme/relationship_line_opacity");
String preset = EDITOR_GET("interface/theme/preset");
@@ -393,6 +396,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color highlight_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.2);
+ float prev_icon_saturation = theme->has_color("icon_saturation", "Editor") ? theme->get_color("icon_saturation", "Editor").r : 1.0;
+
+ theme->set_color("icon_saturation", "Editor", Color(icon_saturation, icon_saturation, icon_saturation)); //can't save single float in theme, so using color
theme->set_color("accent_color", "Editor", accent_color);
theme->set_color("highlight_color", "Editor", highlight_color);
theme->set_color("base_color", "Editor", base_color);
@@ -444,13 +450,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
//Register icons + font
// the resolution and the icon color (dark_theme bool) has not changed, so we do not regenerate the icons
- if (p_theme != nullptr && fabs(p_theme->get_constant("scale", "Editor") - EDSCALE) < 0.00001 && (bool)p_theme->get_constant("dark_theme", "Editor") == dark_theme) {
+ if (p_theme != nullptr && fabs(p_theme->get_constant("scale", "Editor") - EDSCALE) < 0.00001 && (bool)p_theme->get_constant("dark_theme", "Editor") == dark_theme && prev_icon_saturation == icon_saturation) {
// register already generated icons
for (int i = 0; i < editor_icons_count; i++) {
theme->set_icon(editor_icons_names[i], "EditorIcons", p_theme->get_icon(editor_icons_names[i], "EditorIcons"));
}
} else {
- editor_register_and_generate_icons(theme, dark_theme, thumb_size);
+ editor_register_and_generate_icons(theme, dark_theme, thumb_size, false, icon_saturation);
}
// thumbnail size has changed, so we regenerate the medium sizes
if (p_theme != nullptr && fabs((double)p_theme->get_constant("thumb_size", "Editor") - thumb_size) > 0.00001) {
@@ -698,9 +704,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// PopupMenu
const int popup_menu_margin_size = default_margin_size * 1.5 * EDSCALE;
Ref<StyleBoxFlat> style_popup_menu = style_popup->duplicate();
- style_popup_menu->set_default_margin(SIDE_LEFT, popup_menu_margin_size);
+ // Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn
+ // on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted,
+ // and it looks weird. 1px solves this.
+ style_popup_menu->set_default_margin(SIDE_LEFT, 1 * EDSCALE);
style_popup_menu->set_default_margin(SIDE_TOP, popup_menu_margin_size);
- style_popup_menu->set_default_margin(SIDE_RIGHT, popup_menu_margin_size);
+ style_popup_menu->set_default_margin(SIDE_RIGHT, 1 * EDSCALE);
style_popup_menu->set_default_margin(SIDE_BOTTOM, popup_menu_margin_size);
theme->set_stylebox("panel", "PopupMenu", style_popup_menu);
@@ -722,16 +731,63 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("visibility_hidden", "PopupMenu", theme->get_icon("GuiVisibilityHidden", "EditorIcons"));
theme->set_icon("visibility_visible", "PopupMenu", theme->get_icon("GuiVisibilityVisible", "EditorIcons"));
theme->set_icon("visibility_xray", "PopupMenu", theme->get_icon("GuiVisibilityXray", "EditorIcons"));
+
theme->set_constant("vseparation", "PopupMenu", (extra_spacing + default_margin_size + 1) * EDSCALE);
+ theme->set_constant("item_start_padding", "PopupMenu", popup_menu_margin_size * EDSCALE);
+ theme->set_constant("item_end_padding", "PopupMenu", popup_menu_margin_size * EDSCALE);
+
+ for (int i = 0; i < 16; i++) {
+ Color si_base_color = accent_color;
+
+ float hue_rotate = (i * 2 % 16) / 16.0;
+ si_base_color.set_hsv(Math::fmod(float(si_base_color.get_h() + hue_rotate), float(1.0)), si_base_color.get_s(), si_base_color.get_v());
+ si_base_color = accent_color.lerp(si_base_color, float(EDITOR_GET("docks/property_editor/subresource_hue_tint")));
+
+ Ref<StyleBoxFlat> sub_inspector_bg;
- Ref<StyleBoxFlat> sub_inspector_bg = make_flat_stylebox(dark_color_1.lerp(accent_color, 0.08), 2, 0, 2, 2);
- sub_inspector_bg->set_border_width(SIDE_LEFT, 2);
- sub_inspector_bg->set_border_width(SIDE_RIGHT, 2);
- sub_inspector_bg->set_border_width(SIDE_BOTTOM, 2);
- sub_inspector_bg->set_border_color(accent_color * Color(1, 1, 1, 0.3));
- sub_inspector_bg->set_draw_center(true);
+ sub_inspector_bg = make_flat_stylebox(dark_color_1.lerp(si_base_color, 0.08), 2, 0, 2, 2);
+
+ sub_inspector_bg->set_border_width(SIDE_LEFT, 2);
+ sub_inspector_bg->set_border_width(SIDE_RIGHT, 2);
+ sub_inspector_bg->set_border_width(SIDE_BOTTOM, 2);
+ sub_inspector_bg->set_border_width(SIDE_TOP, 2);
+ sub_inspector_bg->set_default_margin(SIDE_LEFT, 3);
+ sub_inspector_bg->set_default_margin(SIDE_RIGHT, 3);
+ sub_inspector_bg->set_default_margin(SIDE_BOTTOM, 10);
+ sub_inspector_bg->set_default_margin(SIDE_TOP, 5);
+ sub_inspector_bg->set_border_color(si_base_color * Color(0.7, 0.7, 0.7, 0.8));
+ sub_inspector_bg->set_draw_center(true);
+
+ theme->set_stylebox("sub_inspector_bg" + itos(i), "Editor", sub_inspector_bg);
+
+ Ref<StyleBoxFlat> bg_color;
+ bg_color.instance();
+ bg_color->set_bg_color(si_base_color * Color(0.7, 0.7, 0.7, 0.8));
+ bg_color->set_border_width_all(0);
+
+ Ref<StyleBoxFlat> bg_color_selected;
+ bg_color_selected.instance();
+ bg_color_selected->set_border_width_all(0);
+ bg_color_selected->set_bg_color(si_base_color * Color(0.8, 0.8, 0.8, 0.8));
+
+ theme->set_stylebox("sub_inspector_property_bg" + itos(i), "Editor", bg_color);
+ theme->set_stylebox("sub_inspector_property_bg_selected" + itos(i), "Editor", bg_color_selected);
+ }
+
+ theme->set_color("sub_inspector_property_color", "Editor", dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1));
+ theme->set_constant("sub_inspector_font_offset", "Editor", 4 * EDSCALE);
+
+ Ref<StyleBoxFlat> style_property_bg = style_default->duplicate();
+ style_property_bg->set_bg_color(highlight_color);
+ style_property_bg->set_border_width_all(0);
+
+ theme->set_constant("font_offset", "EditorProperty", 1 * EDSCALE);
+ theme->set_stylebox("bg_selected", "EditorProperty", style_property_bg);
+ theme->set_stylebox("bg", "EditorProperty", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
+ theme->set_constant("vseparation", "EditorProperty", (extra_spacing + default_margin_size) * EDSCALE);
+ theme->set_color("error_color", "EditorProperty", error_color);
+ theme->set_color("property_color", "EditorProperty", property_color);
- theme->set_stylebox("sub_inspector_bg", "Editor", sub_inspector_bg);
theme->set_constant("inspector_margin", "Editor", 8 * EDSCALE);
// Tree & ItemList background
@@ -790,7 +846,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Ref<StyleBoxFlat> style_tree_cursor = style_default->duplicate();
style_tree_cursor->set_draw_center(false);
- style_tree_cursor->set_border_width_all(border_width);
+ style_tree_cursor->set_border_width_all(MAX(1, border_width));
style_tree_cursor->set_border_color(contrast_color_1);
Ref<StyleBoxFlat> style_tree_title = style_default->duplicate();
@@ -1221,6 +1277,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("add_preset", "ColorPicker", theme->get_icon("Add", "EditorIcons"));
theme->set_icon("preset_bg", "ColorPicker", theme->get_icon("GuiMiniCheckerboard", "EditorIcons"));
theme->set_icon("overbright_indicator", "ColorPicker", theme->get_icon("OverbrightIndicator", "EditorIcons"));
+ theme->set_icon("bar_arrow", "ColorPicker", theme->get_icon("ColorPickerBarArrow", "EditorIcons"));
theme->set_icon("bg", "ColorPickerButton", theme->get_icon("GuiMiniCheckerboard", "EditorIcons"));
@@ -1335,3 +1392,15 @@ Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) {
return theme;
}
+
+Ref<ImageTexture> create_unscaled_default_project_icon() {
+#ifdef MODULE_SVG_ENABLED
+ for (int i = 0; i < editor_icons_count; i++) {
+ // ESCALE should never affect size of the icon
+ if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0) {
+ return editor_generate_icon(i, false, 1.0);
+ }
+ }
+#endif
+ return Ref<ImageTexture>(memnew(ImageTexture));
+}
diff --git a/editor/editor_themes.h b/editor/editor_themes.h
index 852edf7669..c040654220 100644
--- a/editor/editor_themes.h
+++ b/editor/editor_themes.h
@@ -31,10 +31,13 @@
#ifndef EDITOR_THEMES_H
#define EDITOR_THEMES_H
+#include "scene/resources/texture.h"
#include "scene/resources/theme.h"
Ref<Theme> create_editor_theme(Ref<Theme> p_theme = nullptr);
Ref<Theme> create_custom_theme(Ref<Theme> p_theme = nullptr);
+Ref<ImageTexture> create_unscaled_default_project_icon();
+
#endif
diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp
index 07edae833d..d80003a12a 100644
--- a/editor/fileserver/editor_file_server.cpp
+++ b/editor/fileserver/editor_file_server.cpp
@@ -43,7 +43,7 @@ void EditorFileServer::_close_client(ClientData *cd) {
cd->connection->disconnect_from_host();
{
MutexLock lock(cd->efs->wait_mutex);
- cd->efs->to_wait.insert(&cd->thread);
+ cd->efs->to_wait.insert(cd->thread);
}
while (cd->files.size()) {
memdelete(cd->files.front()->get());
@@ -278,7 +278,8 @@ void EditorFileServer::_thread_start(void *s) {
cd->connection = self->server->take_connection();
cd->efs = self;
cd->quit = false;
- cd->thread.start(_subthread_start, cd);
+ cd->thread = memnew(Thread);
+ cd->thread->start(_subthread_start, cd);
}
}
diff --git a/editor/fileserver/editor_file_server.h b/editor/fileserver/editor_file_server.h
index e4c8327d76..8ffd4f9692 100644
--- a/editor/fileserver/editor_file_server.h
+++ b/editor/fileserver/editor_file_server.h
@@ -47,7 +47,7 @@ class EditorFileServer : public Object {
};
struct ClientData {
- Thread thread;
+ Thread *thread;
Ref<StreamPeerTCP> connection;
Map<int, FileAccess *> files;
EditorFileServer *efs = nullptr;
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index e1c66f43b9..772eff5f45 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -945,7 +945,25 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit
}
} else if (fpath != "Favorites") {
if (ResourceLoader::get_resource_type(fpath) == "PackedScene") {
- editor->open_request(fpath);
+ bool is_imported = false;
+
+ {
+ List<String> importer_exts;
+ ResourceImporterScene::get_singleton()->get_recognized_extensions(&importer_exts);
+ String extension = fpath.get_extension();
+ for (List<String>::Element *E = importer_exts.front(); E; E = E->next()) {
+ if (extension.nocasecmp_to(E->get())) {
+ is_imported = true;
+ break;
+ }
+ }
+ }
+
+ if (is_imported) {
+ ResourceImporterScene::get_singleton()->show_advanced_options(fpath);
+ } else {
+ editor->open_request(fpath);
+ }
} else {
editor->load_resource(fpath);
}
@@ -1411,14 +1429,26 @@ void FileSystemDock::_make_scene_confirm() {
void FileSystemDock::_file_removed(String p_file) {
emit_signal("file_removed", p_file);
- path = "res://";
+ // Find the closest parent directory available, in case multiple items were deleted along the same path.
+ path = p_file.get_base_dir();
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ while (!da->dir_exists(path)) {
+ path = path.get_base_dir();
+ }
+
current_path->set_text(path);
}
void FileSystemDock::_folder_removed(String p_folder) {
emit_signal("folder_removed", p_folder);
- path = "res://";
+ // Find the closest parent directory available, in case multiple items were deleted along the same path.
+ path = p_folder.get_base_dir();
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ while (!da->dir_exists(path)) {
+ path = path.get_base_dir();
+ }
+
current_path->set_text(path);
}
@@ -1586,7 +1616,7 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_ove
print_verbose("FileSystem: saving moved scenes.");
_save_scenes_after_move(file_renames);
- path = "res://";
+ path = p_to_path;
current_path->set_text(path);
}
}
@@ -2706,7 +2736,22 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
// `KEY_MASK_CMD | KEY_C` conflicts with other editor shortcuts.
ED_SHORTCUT("filesystem_dock/copy_path", TTR("Copy Path"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_C);
ED_SHORTCUT("filesystem_dock/duplicate", TTR("Duplicate..."), KEY_MASK_CMD | KEY_D);
+
+#if defined(WINDOWS_ENABLED)
+ // TRANSLATORS: This string is only used on Windows, as it refers to the system trash
+ // as "Recycle Bin" instead of "Trash". Make sure to use the translation of "Recycle Bin"
+ // recommended by Microsoft for the target language.
+ ED_SHORTCUT("filesystem_dock/delete", TTR("Move to Recycle Bin"), KEY_DELETE);
+#elif defined(OSX_ENABLED)
+ // TRANSLATORS: This string is only used on macOS, as it refers to the system trash
+ // as "Bin" instead of "Trash". Make sure to use the translation of "Bin"
+ // recommended by Apple for the target language.
+ ED_SHORTCUT("filesystem_dock/delete", TTR("Move to Bin"), KEY_DELETE);
+#else
+ // TRANSLATORS: This string is only used on platforms other than Windows and macOS.
ED_SHORTCUT("filesystem_dock/delete", TTR("Move to Trash"), KEY_DELETE);
+#endif
+
ED_SHORTCUT("filesystem_dock/rename", TTR("Rename..."), KEY_F2);
VBoxContainer *top_vbc = memnew(VBoxContainer);
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index c2f2254023..47079a92b7 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -463,7 +463,7 @@ void FindInFilesDialog::_notification(int p_what) {
for (int i = 0; i < _filters_container->get_child_count(); i++) {
_filters_container->get_child(i)->queue_delete();
}
- Array exts = ProjectSettings::get_singleton()->get("editor/search_in_file_extensions");
+ Array exts = ProjectSettings::get_singleton()->get("editor/script/search_in_file_extensions");
for (int i = 0; i < exts.size(); ++i) {
CheckBox *cb = memnew(CheckBox);
cb->set_text(exts[i]);
@@ -687,6 +687,9 @@ void FindInFilesPanel::stop_search() {
void FindInFilesPanel::_notification(int p_what) {
if (p_what == NOTIFICATION_PROCESS) {
_progress_bar->set_as_ratio(_finder->get_progress());
+ } else if (p_what == NOTIFICATION_THEME_CHANGED) {
+ _search_text_label->add_theme_font_override("font", get_theme_font("source", "EditorFonts"));
+ _results_display->add_theme_font_override("font", get_theme_font("source", "EditorFonts"));
}
}
diff --git a/editor/icons/ColorPickerBarArrow.svg b/editor/icons/ColorPickerBarArrow.svg
new file mode 100644
index 0000000000..9d034106ee
--- /dev/null
+++ b/editor/icons/ColorPickerBarArrow.svg
@@ -0,0 +1 @@
+<svg height="20" viewBox="0 0 16 20" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 16h12l-6-6z" fill="#e0e0e0" stroke-width="2"/></svg>
diff --git a/editor/icons/GPUParticlesAttractorBox.svg b/editor/icons/GPUParticlesAttractorBox.svg
new file mode 100644
index 0000000000..3c27b2d3cb
--- /dev/null
+++ b/editor/icons/GPUParticlesAttractorBox.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#fc9c9c" fill-opacity=".996078" r="1"/><g fill="none" stroke="#fc9c9c" 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>
diff --git a/editor/icons/GPUParticlesAttractorSphere.svg b/editor/icons/GPUParticlesAttractorSphere.svg
new file mode 100644
index 0000000000..5473a23854
--- /dev/null
+++ b/editor/icons/GPUParticlesAttractorSphere.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="-8" cy="-7.999999" fill="none" rx="6.499003" ry="6.499001" stroke="#fc9c9c" stroke-opacity=".996078" stroke-width="1.002" transform="scale(-1)"/><circle cx="8" cy="8" fill="#fc9c9c" fill-opacity=".996078" r="1"/><g fill="none" stroke="#fc9c9c" 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>
diff --git a/editor/icons/GPUParticlesAttractorVectorField.svg b/editor/icons/GPUParticlesAttractorVectorField.svg
new file mode 100644
index 0000000000..93a29789e3
--- /dev/null
+++ b/editor/icons/GPUParticlesAttractorVectorField.svg
@@ -0,0 +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="#fc9c9c" fill-opacity=".996078" rx="1.030661" ry=".998146"/><ellipse cx="-6.672815" cy="-9.387111" fill="none" rx="2.408711" ry="5.096776" stroke="#fc9c9c" 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="#fc9c9c" stroke-opacity=".996078" stroke-width="1.0297" transform="matrix(-.00104887 .99999945 -.99999945 .00104887 0 0)"/><g fill="#fc9c9c" 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>
diff --git a/editor/icons/GPUParticlesCollisionBox.svg b/editor/icons/GPUParticlesCollisionBox.svg
new file mode 100644
index 0000000000..f7296b34c3
--- /dev/null
+++ b/editor/icons/GPUParticlesCollisionBox.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc9c9c" 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>
diff --git a/editor/icons/GPUParticlesCollisionHeightField.svg b/editor/icons/GPUParticlesCollisionHeightField.svg
new file mode 100644
index 0000000000..b483f299e9
--- /dev/null
+++ b/editor/icons/GPUParticlesCollisionHeightField.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc9c9c"><path d="m1 10c1-1 3-2 3-4s2-4 4-4 4 2 4 4 2 3 3 4l-7 5z"/><circle cx="2" cy="6" r="1"/><circle cx="14" cy="6" r="1"/><circle cx="12" cy="2" r="1"/><circle cx="4" cy="2" r="1"/></g></svg>
diff --git a/editor/icons/GPUParticlesCollisionSDF.svg b/editor/icons/GPUParticlesCollisionSDF.svg
new file mode 100644
index 0000000000..6279990f3a
--- /dev/null
+++ b/editor/icons/GPUParticlesCollisionSDF.svg
@@ -0,0 +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="#fc9c9c" stroke-linejoin="round" stroke-opacity=".996078" stroke-width="2"/><g fill="#fc9c9c" 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>
diff --git a/editor/icons/GPUParticlesCollisionSphere.svg b/editor/icons/GPUParticlesCollisionSphere.svg
new file mode 100644
index 0000000000..fc7715445c
--- /dev/null
+++ b/editor/icons/GPUParticlesCollisionSphere.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc9c9c" 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>
diff --git a/editor/icons/Logo.svg b/editor/icons/Logo.svg
index d7aef39cc9..a4ad488396 100644
--- a/editor/icons/Logo.svg
+++ b/editor/icons/Logo.svg
@@ -1 +1 @@
-<svg height="69" viewBox="0 0 187 69" width="187" xmlns="http://www.w3.org/2000/svg"><path d="m91.912 19.51c-3.5233 0-6.278 1.1097-8.2676 3.3281-1.9911 2.2193-2.9844 5.1004-2.9844 8.6465 0 4.1636 1.0165 7.3207 3.0508 9.4707 2.0379 2.1497 4.7123 3.2227 8.0293 3.2227 1.7838 0 3.3686-.15384 4.752-.46289 1.3848-.30784 2.3038-.62367 2.7617-.94336l.13867-10.736c0-.62388-1.6471-.90785-3.4941-.93945-1.847-.02857-3.9609.35742-3.9609.35742v3.6055h2.125l-.023438 1.6055c0 .59532-.59062.89453-1.7676.89453-1.1785 0-2.2182-.4989-3.1211-1.4941-.90498-.99645-1.3555-2.4517-1.3555-4.3711 0-1.9233.43964-3.3428 1.3203-4.2578.87885-.9141 2.0322-1.3711 3.4492-1.3711.59532 0 1.2107.095008 1.8516.29102.64121.19418 1.0686.37639 1.2871.54688.21667.17534.42435.25781.61914.25781.19388 0 .50715-.22698.94141-.68555.43487-.45735.82427-1.1501 1.168-2.0742.34218-.92899.51367-1.6414.51367-2.1465 0-.50111-.011023-.84501-.033203-1.0273-.48045-.52573-1.3668-.94394-2.6602-1.2539-1.2909-.30906-2.7387-.46289-4.3398-.46289zm21.049 0c-3.2367 0-5.8788 1.0413-7.9258 3.1211-2.0464 2.0826-3.0703 5.1404-3.0703 9.1797 0 4.0369 1.0128 7.1085 3.0352 9.2129 2.0251 2.1026 4.6444 3.1543 7.8574 3.1543 3.2145 0 5.8383-1.0111 7.875-3.0332 2.0367-2.0263 3.0527-5.1142 3.0527-9.2656 0-4.1484-.99433-7.2508-2.9863-9.2969-1.9884-2.05-4.6018-3.0723-7.8379-3.0723zm45.504 0c-3.2379 0-5.8792 1.0413-7.9277 3.1211-2.0461 2.0826-3.0684 5.1404-3.0684 9.1797 0 4.0369 1.0104 7.1085 3.0352 9.2129 2.0233 2.1026 4.6432 3.1543 7.8574 3.1543 3.213 0 5.8373-1.0111 7.873-3.0332 2.0364-2.0263 3.0547-5.1142 3.0547-9.2656 0-4.1484-.9939-7.2508-2.9844-9.2969-1.9908-2.05-4.6031-3.0723-7.8398-3.0723zm-30.105.30859c-.45888 0-.82988.16637-1.1152.49609-.28717.33489-.42969.78715-.42969 1.3594v20.584c0 1.053.58624 1.5781 1.752 1.5781h5.8652c7.1824-.000001 10.773-4.2092 10.773-12.627 0-3.9348-.94335-6.8151-2.832-8.6445-1.8853-1.83-4.6472-2.7461-8.2832-2.7461h-5.7305zm42.807 0c-.38928 0-.66468.52801-.82422 1.5801-.0687.50294-.10157 1.0191-.10157 1.543 0 .52694.03287 1.0409.10157 1.543.15954 1.0548.43494 1.5801.82422 1.5801h4.1152v17.225c0 .45462 1.1351.68555 3.3984.68555 2.2655 0 3.3965-.23093 3.3965-.68555v-17.225h4.0137c.38868 0 .66225-.52528.82422-1.5801.0672-.50202.10156-1.016.10156-1.543.00001-.52391-.03436-1.04-.10156-1.543-.16197-1.0521-.43554-1.5801-.82422-1.5801h-14.924zm-58.291 6.2793c1.0989 0 2.0193.49244 2.7617 1.4746.74331.98339 1.1152 2.3913 1.1152 4.2207 0 1.8309-.35955 3.2363-1.0801 4.2188-.72053.98612-1.6597 1.4785-2.8145 1.4785-1.1554 0-2.0859-.48441-2.7949-1.459-.71019-.97154-1.0644-2.3663-1.0644-4.1875 0-1.8173.37148-3.2302 1.1133-4.2363.74574-1.0053 1.6663-1.5098 2.7637-1.5098zm45.504 0c1.0989 0 2.0181.49244 2.7617 1.4746.74331.98339 1.1152 2.3913 1.1152 4.2207 0 1.8309-.3612 3.2363-1.082 4.2188-.71961.98612-1.6574 1.4785-2.8125 1.4785-1.1554 0-2.0888-.48441-2.7969-1.459-.70806-.97154-1.0625-2.3663-1.0625-4.1875 0-1.8173.37179-3.2302 1.1133-4.2363.74453-1.0053 1.666-1.5098 2.7637-1.5098zm-24.977.23828h.34375c1.4638 0 2.5334.33466 3.209.99805.6722.66157 1.0098 2.0859 1.0098 4.2715 0 2.1847-.32289 3.7447-.97656 4.6816-.65214.9378-1.6059 1.4082-2.8652 1.4082-.34218 0-.54909-.063339-.61719-.18945-.06873-.12672-.10352-.42897-.10352-.9082v-10.262z" fill="#fff"/><path d="m137.91 48.551v1.2109h.85938v-1.2109zm-52.396.58984c-.99736 0-1.7963.32424-2.3926.96484-.59745.64576-.89453 1.5712-.89453 2.7773v3.0742c0 1.2329.31639 2.1765.94727 2.832.6333.66066 1.467.98828 2.5039.98828.78586 0 1.4321-.16147 1.9414-.48633.50993-.32273.8592-.67938 1.0488-1.0684v-3.6875h-3.0059v.74805h2.1465v2.6934c-.13766.30115-.38143.55386-.73242.76172-.34978.2109-.8171.31445-1.3984.31445-.79619 0-1.4265-.2632-1.8945-.78711-.46799-.52786-.70312-1.2936-.70312-2.2988v-3.0918c0-.96941.21778-1.7078.65234-2.2168.43578-.51023 1.0297-.76367 1.7812-.76367.74271 0 1.3056.19019 1.6836.56641.38017.37925.58276.91542.61133 1.6113h.79492l.013672-.041016c-.024311-.90802-.30456-1.6179-.83789-2.127-.53484-.50719-1.2907-.76367-2.2656-.76367zm7.6133 2.6641c-.719 0-1.3111.22524-1.7715.67773-.46222.45371-.68069.96571-.6582 1.5449l.013672.041015.79688.007813c0-.42696.14768-.78487.44336-1.0781.2966-.29508.67455-.44141 1.1328-.44141.4926 0 .87459.15388 1.1523.45898.27198.30906.41016.73655.41016 1.2793v.94531h-1.3418c-.85666 0-1.5379.21084-2.0391.63477-.50142.42392-.75195.99502-.75195 1.707 0 .67372.17358 1.2075.51758 1.6035.34613.39445.83497.5918 1.4707.5918.45462 0 .86723-.12355 1.2383-.37305.37166-.24767.67317-.56424.90625-.94531 0 .17413.01089.34527.03125.51758.02097.16927.053163.38614.095703.65234h.88867c-.062302-.24767-.10234-.49621-.12695-.75391-.02401-.25436-.037109-.52051-.037109-.79492v-3.7676c0-.80622-.21809-1.4265-.65234-1.8613-.43669-.43061-1.0083-.64648-1.7188-.64648zm7.1152 0c-.45462 0-.85109.11505-1.1875.3457-.33519.23369-.60486.56357-.80664.99023l-.074219-1.1934h-.75195v7.6816h.85352v-5.5293c.11791-.47346.31244-.84655.58594-1.1191.27168-.27107.63379-.4082 1.082-.4082.4689 0 .83314.19466 1.0957.58789.26378.39323.39258 1.0508.39258 1.9707v4.498h.85351v-4.6211-.19922c.0623-.64455.23396-1.1785.51172-1.6055.27927-.42696.66855-.63672 1.166-.63672.47285 0 .83879.19223 1.0938.57422.25345.38138.38281 1.0443.38281 1.9863v4.502h.85742v-4.4863c0-1.1332-.18468-1.9728-.55664-2.5195-.37044-.54548-.89268-.81836-1.5664-.81836-.48897 0-.91182.1465-1.2598.43945-.34796.29234-.61537.69589-.80469 1.207-.148-.55369-.38151-.966-.69726-1.2383-.31543-.2732-.70589-.4082-1.1699-.4082zm10.316 0c-.74423-.000001-1.3797.32125-1.9082.96094-.52725.64273-.78906 1.4505-.78906 2.4199v1.2754c0 .96758.26259 1.762.7871 2.3828.52604.62206 1.2032.93359 2.0312.93359.5157 0 .95833-.090281 1.3242-.26562.36679-.17626.66658-.41287.89844-.70703l-.34961-.60547c-.21728.27441-.4784.4836-.7832.63281-.3048.14586-.66987.2207-1.0898.2207-.60443 0-1.0864-.24489-1.4414-.74023-.35433-.49412-.53321-1.1138-.53321-1.8574v-.63867h4.3965v-.84375c0-.96667-.22381-1.7371-.66992-2.3105-.44519-.57253-1.0684-.85742-1.873-.85742zm9.4727 0c-.74423-.000001-1.3782.32125-1.9082.96094-.52603.64273-.79101 1.4505-.79101 2.4199v1.2754c0 .96758.26241 1.762.78906 2.3828.52512.62206 1.2028.93359 2.0312.93359.51601 0 .95639-.090281 1.3223-.26562.36741-.17626.66822-.41287.90039-.70703l-.34766-.60547c-.21972.27441-.4811.4836-.78711.63281-.30389.14586-.66639.2207-1.0879.2207-.60656 0-1.0883-.24489-1.4414-.74023-.35646-.49412-.5332-1.1138-.5332-1.8574v-.63867h4.3945v-.84375c0-.96667-.22338-1.7371-.66797-2.3105-.44398-.57253-1.0699-.85742-1.873-.85742zm6.8672 0c-.45614 0-.85274.12451-1.1894.36914-.33975.24342-.60962.5923-.81445 1.043l-.07031-1.2695h-.76172v7.6816h.85351v-5.4824c.14617-.47923.36569-.85918.66016-1.1445.29325-.28809.65767-.42969 1.0938-.42969.48622 0 .85922.17765 1.1133.5332.25557.35555.38477.96807.38477 1.8457v4.6777h.85937v-4.6855c0-1.0736-.18381-1.866-.55273-2.375-.36497-.50993-.89-.76367-1.5762-.76367zm6.2539 0c-.77674 0-1.386.32888-1.8242.98437-.44186.65883-.66211 1.5326-.66211 2.6211l.00196 1.0508c0 1.0031.21834 1.8072.65625 2.4102.43699.60413 1.0429.90625 1.8144.90625.41602 0 .78387-.091234 1.0996-.27539.31695-.18324.58484-.4491.80273-.79492v.92969c0 .75881-.14785 1.3303-.4414 1.7266-.29235.39111-.74301.58789-1.3535.58789-.30359 0-.59763-.04082-.88086-.125-.28565-.081443-.54279-.19619-.77344-.3457l-.23632.74805c.27047.15164.57916.27315.92773.36523.34795.092075.67388.13867.97656.13867.84208 0 1.494-.27297 1.9531-.81055.45857-.53971.68554-1.3009.68554-2.2852v-7.6895h-.72265l-.08399 1.0684c-.21485-.38533-.48269-.68758-.80664-.89453-.32334-.2109-.70159-.31641-1.1328-.31641zm10.467 0c-.45401 0-.85062.12451-1.1895.36914-.33914.24342-.60902.5923-.81445 1.043l-.07031-1.2695h-.75977v7.6816h.85352v-5.4824c.14556-.47923.3663-.85918.66016-1.1445.29295-.28809.65797-.42969 1.0937-.42969.48775 0 .85711.17765 1.1133.5332.25496.35555.38476.96807.38476 1.8457v4.6777h.85742v-4.6855c0-1.0736-.18081-1.866-.54882-2.375-.36588-.50993-.8939-.76367-1.5801-.76367zm6.4043 0c-.74271-.000001-1.3778.32125-1.9062.96094-.52724.64273-.79101 1.4505-.79101 2.4199v1.2754c0 .96758.26334 1.762.78906 2.3828.52361.62206 1.2007.93359 2.0312.93359.5154 0 .9567-.090281 1.3223-.26562.3668-.17626.6667-.41287.90039-.70703l-.34961-.60547c-.2194.27441-.47958.4836-.78711.63281-.30359.14586-.66597.2207-1.0859.2207-.60717 0-1.089-.24489-1.4434-.74023-.35464-.49412-.5332-1.1138-.5332-1.8574v-.63867h4.3965v-.84375c0-.96667-.22369-1.7371-.66797-2.3105-.44551-.57253-1.0709-.85742-1.875-.85742zm-12.113.14258v7.6816h.85938v-7.6816zm-27.352.60938c.53029 0 .9445.20789 1.2441.62695.29781.41876.44531.94616.44531 1.5801v.33008h-3.543c.01429-.71688.19281-1.3186.53711-1.8066.34401-.48622.78217-.73047 1.3164-.73047zm9.4727 0c.52998 0 .94406.20789 1.2422.62695.29963.41876.44727.94616.44727 1.5801v.33008h-3.543c.0155-.71688.19298-1.3186.53516-1.8066.3437-.48622.7826-.73047 1.3184-.73047zm29.992 0c.53089 0 .94602.20789 1.2441.62695.29902.41876.44532.94616.44532 1.5801v.33008h-3.543c.01519-.71688.19402-1.3186.53711-1.8066.34218-.48622.78064-.73047 1.3164-.73047zm-16.686.015625c.42119 0 .77033.1246 1.0469.375.27684.25466.4967.58706.65625.99609v3.8047c-.16593.39718-.39.70872-.67383.93359-.28475.22488-.63089.33594-1.043.33594-.6014 0-1.0536-.22975-1.3496-.69531-.29964-.4613-.44727-1.0819-.44727-1.8613v-1.0508c0-.84177.15149-1.527.45508-2.0527.30146-.52482.75528-.78516 1.3555-.78516zm-40.057 3.3281h1.3652v1.6621c-.15286.42089-.40964.76752-.77734 1.041-.3671.27228-.78783.40625-1.2598.40625-.39262 0-.69782-.12824-.91602-.38867-.2185-.25952-.32617-.59591-.32617-1.0059 0-.48531.17262-.89402.52148-1.2207.34795-.32881.81215-.49414 1.3926-.49414z" fill="#e0e0e0"/><path d="m27 3c-3.0948.68801-6.1571 1.6452-9.0273 3.0898.06564 2.5344.23035 4.963.5625 7.4297-1.1147.71414-2.287 1.3281-3.3281 2.1641-1.0578.81382-2.1378 1.5912-3.0957 2.543-1.9136-1.2657-3.9389-2.454-6.0254-3.5039-2.2491 2.4205-4.3524 5.0317-6.0703 7.9551 1.2924 2.0908 2.6428 4.0523 4.0996 5.9121h.041016v14.438 1.834 1.6699c.03282.000304.06514.000806.097656.003906l11 1.0605c.57617.05561 1.0282.52027 1.0684 1.0977l.33789 4.8555 9.5957.68359.66016-4.4805c.0857-.58104.58415-1.0117 1.1719-1.0117h11.605c.58742 0 1.0862.43068 1.1719 1.0117l.66016 4.4805 9.5957-.68359.33789-4.8555c.04042-.57739.49219-1.0417 1.0684-1.0977l10.996-1.0605c.032519-.003.064836-.003606.097656-.003906v-1.4316l.003906-.001953v-16.508h.041016c1.4571-1.8598 2.8066-3.8214 4.0996-5.9121-1.7173-2.9234-3.8232-5.5346-6.0723-7.9551-2.0859 1.0499-4.1118 2.2382-6.0254 3.5039-.95756-.95178-2.0363-1.7292-3.0957-2.543-1.0408-.836-2.2136-1.4499-3.3262-2.1641.33124-2.4667.49656-4.8952.5625-7.4297-2.8706-1.4447-5.933-2.4018-9.0293-3.0898-1.2362 2.0777-2.367 4.3278-3.3516 6.5273-1.1675-.1951-2.3391-.26727-3.5137-.28125v-.0019532c-.0082 0-.016447.0019531-.023437.0019532-.0073 0-.014194-.0019532-.021484-.0019532v.0019532c-1.1767.013979-2.3497.086153-3.5176.28125-.98399-2.1996-2.1135-4.4497-3.3516-6.5273zm-22.863 45.904c.0045599 1.063.019531 2.2271.019531 2.459 0 10.446 13.251 15.468 29.715 15.525h.019531.019531c16.464-.05774 29.711-5.0795 29.711-15.525 0-.23612.014661-1.3954.019531-2.459l-9.8867.95312-.3418 4.8809c-.04102.58833-.50933 1.0574-1.0977 1.0996l-11.717.83594c-.02857.0021-.055724.003906-.083984.003906-.58225 0-1.0859-.42704-1.1719-1.0117l-.67188-4.5566h-9.5586l-.67188 4.5566c-.09025.61325-.63836 1.0531-1.2559 1.0078l-11.717-.83594c-.58833-.04224-1.0566-.51128-1.0977-1.0996l-.3418-4.8809-9.8906-.95312z" fill="#478cbf"/><path d="m18.299 29.246c-3.6594 0-6.6289 2.9669-6.6289 6.627 0 3.6625 2.9695 6.6289 6.6289 6.6289 3.6613 0 6.627-2.9664 6.627-6.6289 0-3.66-2.9657-6.627-6.627-6.627zm31.186 0c-3.6619 0-6.6289 2.9669-6.6289 6.627 0 3.6625 2.967 6.6289 6.6289 6.6289 3.6591 0 6.627-2.9664 6.627-6.6289 0-3.66-2.9678-6.627-6.627-6.627zm-15.594 3.8789c-1.1785 0-2.1348.86781-2.1348 1.9375v6.1035c0 1.0706.95628 1.9395 2.1348 1.9395s2.1348-.86885 2.1348-1.9395v-6.1035c0-1.0697-.95628-1.9375-2.1348-1.9375z" fill="#f6f6f6"/><path d="m18.932 31.865c-2.4299 0-4.4004 1.9711-4.4004 4.4004s1.9705 4.3984 4.4004 4.3984c2.4311 0 4.4004-1.9691 4.4004-4.3984s-1.9693-4.4004-4.4004-4.4004zm29.916 0c-2.4293 0-4.3984 1.9711-4.3984 4.4004s1.9691 4.3984 4.3984 4.3984c2.4317 0 4.4004-1.9691 4.4004-4.3984s-1.9687-4.4004-4.4004-4.4004z" fill="#414042"/></svg>
+<svg height="69" viewBox="0 0 187 69" width="187" xmlns="http://www.w3.org/2000/svg"><path d="m91.912 19.51c-3.5233 0-6.278 1.1097-8.2676 3.3281-1.9911 2.2193-2.9844 5.1004-2.9844 8.6465 0 4.1636 1.0165 7.3207 3.0508 9.4707 2.0379 2.1497 4.7123 3.2227 8.0293 3.2227 1.7838 0 3.3686-.15384 4.752-.46289 1.3848-.30784 2.3038-.62367 2.7617-.94336l.13867-10.736c0-.62388-1.6471-.90785-3.4941-.93945-1.847-.02857-3.9609.35742-3.9609.35742v3.6055h2.125l-.023438 1.6055c0 .59532-.59062.89453-1.7676.89453-1.1785 0-2.2182-.4989-3.1211-1.4941-.90498-.99645-1.3555-2.4517-1.3555-4.3711 0-1.9233.43964-3.3428 1.3203-4.2578.87885-.9141 2.0322-1.3711 3.4492-1.3711.59532 0 1.2107.095008 1.8516.29102.64121.19418 1.0686.37639 1.2871.54688.21667.17534.42435.25781.61914.25781.19388 0 .50715-.22698.94141-.68555.43487-.45735.82427-1.1501 1.168-2.0742.34218-.92899.51367-1.6414.51367-2.1465 0-.50111-.011023-.84501-.033203-1.0273-.48045-.52573-1.3668-.94394-2.6602-1.2539-1.2909-.30906-2.7387-.46289-4.3398-.46289zm21.049 0c-3.2367 0-5.8788 1.0413-7.9258 3.1211-2.0464 2.0826-3.0703 5.1404-3.0703 9.1797 0 4.0369 1.0128 7.1085 3.0352 9.2129 2.0251 2.1026 4.6444 3.1543 7.8574 3.1543 3.2145 0 5.8383-1.0111 7.875-3.0332 2.0367-2.0263 3.0527-5.1142 3.0527-9.2656 0-4.1484-.99433-7.2508-2.9863-9.2969-1.9884-2.05-4.6018-3.0723-7.8379-3.0723zm45.504 0c-3.2379 0-5.8792 1.0413-7.9277 3.1211-2.0461 2.0826-3.0684 5.1404-3.0684 9.1797 0 4.0369 1.0104 7.1085 3.0352 9.2129 2.0233 2.1026 4.6432 3.1543 7.8574 3.1543 3.213 0 5.8373-1.0111 7.873-3.0332 2.0364-2.0263 3.0547-5.1142 3.0547-9.2656 0-4.1484-.9939-7.2508-2.9844-9.2969-1.9908-2.05-4.6031-3.0723-7.8398-3.0723zm-30.105.30859c-.45888 0-.82988.16637-1.1152.49609-.28717.33489-.42969.78715-.42969 1.3594v20.584c0 1.053.58624 1.5781 1.752 1.5781h5.8652c7.1824-.000001 10.773-4.2092 10.773-12.627 0-3.9348-.94335-6.8151-2.832-8.6445-1.8853-1.83-4.6472-2.7461-8.2832-2.7461h-5.7305zm42.807 0c-.38928 0-.66468.52801-.82422 1.5801-.0687.50294-.10157 1.0191-.10157 1.543 0 .52694.03287 1.0409.10157 1.543.15954 1.0548.43494 1.5801.82422 1.5801h4.1152v17.225c0 .45462 1.1351.68555 3.3984.68555 2.2655 0 3.3965-.23093 3.3965-.68555v-17.225h4.0137c.38868 0 .66225-.52528.82422-1.5801.0672-.50202.10156-1.016.10156-1.543.00001-.52391-.03436-1.04-.10156-1.543-.16197-1.0521-.43554-1.5801-.82422-1.5801h-14.924zm-58.291 6.2793c1.0989 0 2.0193.49244 2.7617 1.4746.74331.98339 1.1152 2.3913 1.1152 4.2207 0 1.8309-.35955 3.2363-1.0801 4.2188-.72053.98612-1.6597 1.4785-2.8145 1.4785-1.1554 0-2.0859-.48441-2.7949-1.459-.71019-.97154-1.0644-2.3663-1.0644-4.1875 0-1.8173.37148-3.2302 1.1133-4.2363.74574-1.0053 1.6663-1.5098 2.7637-1.5098zm45.504 0c1.0989 0 2.0181.49244 2.7617 1.4746.74331.98339 1.1152 2.3913 1.1152 4.2207 0 1.8309-.3612 3.2363-1.082 4.2188-.71961.98612-1.6574 1.4785-2.8125 1.4785-1.1554 0-2.0888-.48441-2.7969-1.459-.70806-.97154-1.0625-2.3663-1.0625-4.1875 0-1.8173.37179-3.2302 1.1133-4.2363.74453-1.0053 1.666-1.5098 2.7637-1.5098zm-24.977.23828h.34375c1.4638 0 2.5334.33466 3.209.99805.6722.66157 1.0098 2.0859 1.0098 4.2715 0 2.1847-.32289 3.7447-.97656 4.6816-.65214.9378-1.6059 1.4082-2.8652 1.4082-.34218 0-.54909-.063339-.61719-.18945-.06873-.12672-.10352-.42897-.10352-.9082v-10.262z" fill="#fff"/><path d="m137.91 48.551v1.2109h.85938v-1.2109zm-52.396.58984c-.99736 0-1.7963.32424-2.3926.96484-.59745.64576-.89453 1.5712-.89453 2.7773v3.0742c0 1.2329.31639 2.1765.94727 2.832.6333.66066 1.467.98828 2.5039.98828.78586 0 1.4321-.16147 1.9414-.48633.50993-.32273.8592-.67938 1.0488-1.0684v-3.6875h-3.0059v.74805h2.1465v2.6934c-.13766.30115-.38143.55386-.73242.76172-.34978.2109-.8171.31445-1.3984.31445-.79619 0-1.4265-.2632-1.8945-.78711-.46799-.52786-.70312-1.2936-.70312-2.2988v-3.0918c0-.96941.21778-1.7078.65234-2.2168.43578-.51023 1.0297-.76367 1.7812-.76367.74271 0 1.3056.19019 1.6836.56641.38017.37925.58276.91542.61133 1.6113h.79492l.013672-.041016c-.024311-.90802-.30456-1.6179-.83789-2.127-.53484-.50719-1.2907-.76367-2.2656-.76367zm7.6133 2.6641c-.719 0-1.3111.22524-1.7715.67773-.46222.45371-.68069.96571-.6582 1.5449l.013672.041015.79688.007813c0-.42696.14768-.78487.44336-1.0781.2966-.29508.67455-.44141 1.1328-.44141.4926 0 .87459.15388 1.1523.45898.27198.30906.41016.73655.41016 1.2793v.94531h-1.3418c-.85666 0-1.5379.21084-2.0391.63477-.50142.42392-.75195.99502-.75195 1.707 0 .67372.17358 1.2075.51758 1.6035.34613.39445.83497.5918 1.4707.5918.45462 0 .86723-.12355 1.2383-.37305.37166-.24767.67317-.56424.90625-.94531 0 .17413.01089.34527.03125.51758.02097.16927.053163.38614.095703.65234h.88867c-.062302-.24767-.10234-.49621-.12695-.75391-.02401-.25436-.037109-.52051-.037109-.79492v-3.7676c0-.80622-.21809-1.4265-.65234-1.8613-.43669-.43061-1.0083-.64648-1.7188-.64648zm7.1152 0c-.45462 0-.85109.11505-1.1875.3457-.33519.23369-.60486.56357-.80664.99023l-.074219-1.1934h-.75195v7.6816h.85352v-5.5293c.11791-.47346.31244-.84655.58594-1.1191.27168-.27107.63379-.4082 1.082-.4082.4689 0 .83314.19466 1.0957.58789.26378.39323.39258 1.0508.39258 1.9707v4.498h.85351v-4.6211-.19922c.0623-.64455.23396-1.1785.51172-1.6055.27927-.42696.66855-.63672 1.166-.63672.47285 0 .83879.19223 1.0938.57422.25345.38138.38281 1.0443.38281 1.9863v4.502h.85742v-4.4863c0-1.1332-.18468-1.9728-.55664-2.5195-.37044-.54548-.89268-.81836-1.5664-.81836-.48897 0-.91182.1465-1.2598.43945-.34796.29234-.61537.69589-.80469 1.207-.148-.55369-.38151-.966-.69726-1.2383-.31543-.2732-.70589-.4082-1.1699-.4082zm10.316 0c-.74423-.000001-1.3797.32125-1.9082.96094-.52725.64273-.78906 1.4505-.78906 2.4199v1.2754c0 .96758.26259 1.762.7871 2.3828.52604.62206 1.2032.93359 2.0312.93359.5157 0 .95833-.090281 1.3242-.26562.36679-.17626.66658-.41287.89844-.70703l-.34961-.60547c-.21728.27441-.4784.4836-.7832.63281-.3048.14586-.66987.2207-1.0898.2207-.60443 0-1.0864-.24489-1.4414-.74023-.35433-.49412-.53321-1.1138-.53321-1.8574v-.63867h4.3965v-.84375c0-.96667-.22381-1.7371-.66992-2.3105-.44519-.57253-1.0684-.85742-1.873-.85742zm9.4727 0c-.74423-.000001-1.3782.32125-1.9082.96094-.52603.64273-.79101 1.4505-.79101 2.4199v1.2754c0 .96758.26241 1.762.78906 2.3828.52512.62206 1.2028.93359 2.0312.93359.51601 0 .95639-.090281 1.3223-.26562.36741-.17626.66822-.41287.90039-.70703l-.34766-.60547c-.21972.27441-.4811.4836-.78711.63281-.30389.14586-.66639.2207-1.0879.2207-.60656 0-1.0883-.24489-1.4414-.74023-.35646-.49412-.5332-1.1138-.5332-1.8574v-.63867h4.3945v-.84375c0-.96667-.22338-1.7371-.66797-2.3105-.44398-.57253-1.0699-.85742-1.873-.85742zm6.8672 0c-.45614 0-.85274.12451-1.1894.36914-.33975.24342-.60962.5923-.81445 1.043l-.07031-1.2695h-.76172v7.6816h.85351v-5.4824c.14617-.47923.36569-.85918.66016-1.1445.29325-.28809.65767-.42969 1.0938-.42969.48622 0 .85922.17765 1.1133.5332.25557.35555.38477.96807.38477 1.8457v4.6777h.85937v-4.6855c0-1.0736-.18381-1.866-.55273-2.375-.36497-.50993-.89-.76367-1.5762-.76367zm6.2539 0c-.77674 0-1.386.32888-1.8242.98437-.44186.65883-.66211 1.5326-.66211 2.6211l.00196 1.0508c0 1.0031.21834 1.8072.65625 2.4102.43699.60413 1.0429.90625 1.8144.90625.41602 0 .78387-.091234 1.0996-.27539.31695-.18324.58484-.4491.80273-.79492v.92969c0 .75881-.14785 1.3303-.4414 1.7266-.29235.39111-.74301.58789-1.3535.58789-.30359 0-.59763-.04082-.88086-.125-.28565-.081443-.54279-.19619-.77344-.3457l-.23632.74805c.27047.15164.57916.27315.92773.36523.34795.092075.67388.13867.97656.13867.84208 0 1.494-.27297 1.9531-.81055.45857-.53971.68554-1.3009.68554-2.2852v-7.6895h-.72265l-.08399 1.0684c-.21485-.38533-.48269-.68758-.80664-.89453-.32334-.2109-.70159-.31641-1.1328-.31641zm10.467 0c-.45401 0-.85062.12451-1.1895.36914-.33914.24342-.60902.5923-.81445 1.043l-.07031-1.2695h-.75977v7.6816h.85352v-5.4824c.14556-.47923.3663-.85918.66016-1.1445.29295-.28809.65797-.42969 1.0937-.42969.48775 0 .85711.17765 1.1133.5332.25496.35555.38476.96807.38476 1.8457v4.6777h.85742v-4.6855c0-1.0736-.18081-1.866-.54882-2.375-.36588-.50993-.8939-.76367-1.5801-.76367zm6.4043 0c-.74271-.000001-1.3778.32125-1.9062.96094-.52724.64273-.79101 1.4505-.79101 2.4199v1.2754c0 .96758.26334 1.762.78906 2.3828.52361.62206 1.2007.93359 2.0312.93359.5154 0 .9567-.090281 1.3223-.26562.3668-.17626.6667-.41287.90039-.70703l-.34961-.60547c-.2194.27441-.47958.4836-.78711.63281-.30359.14586-.66597.2207-1.0859.2207-.60717 0-1.089-.24489-1.4434-.74023-.35464-.49412-.5332-1.1138-.5332-1.8574v-.63867h4.3965v-.84375c0-.96667-.22369-1.7371-.66797-2.3105-.44551-.57253-1.0709-.85742-1.875-.85742zm-12.113.14258v7.6816h.85938v-7.6816zm-27.352.60938c.53029 0 .9445.20789 1.2441.62695.29781.41876.44531.94616.44531 1.5801v.33008h-3.543c.01429-.71688.19281-1.3186.53711-1.8066.34401-.48622.78217-.73047 1.3164-.73047zm9.4727 0c.52998 0 .94406.20789 1.2422.62695.29963.41876.44727.94616.44727 1.5801v.33008h-3.543c.0155-.71688.19298-1.3186.53516-1.8066.3437-.48622.7826-.73047 1.3184-.73047zm29.992 0c.53089 0 .94602.20789 1.2441.62695.29902.41876.44532.94616.44532 1.5801v.33008h-3.543c.01519-.71688.19402-1.3186.53711-1.8066.34218-.48622.78064-.73047 1.3164-.73047zm-16.686.015625c.42119 0 .77033.1246 1.0469.375.27684.25466.4967.58706.65625.99609v3.8047c-.16593.39718-.39.70872-.67383.93359-.28475.22488-.63089.33594-1.043.33594-.6014 0-1.0536-.22975-1.3496-.69531-.29964-.4613-.44727-1.0819-.44727-1.8613v-1.0508c0-.84177.15149-1.527.45508-2.0527.30146-.52482.75528-.78516 1.3555-.78516zm-40.057 3.3281h1.3652v1.6621c-.15286.42089-.40964.76752-.77734 1.041-.3671.27228-.78783.40625-1.2598.40625-.39262 0-.69782-.12824-.91602-.38867-.2185-.25952-.32617-.59591-.32617-1.0059 0-.48531.17262-.89402.52148-1.2207.34795-.32881.81215-.49414 1.3926-.49414z" fill="#e0e0e0"/><path d="m0 0s-.325 1.994-.515 1.976l-36.182-3.491c-2.879-.278-5.115-2.574-5.317-5.459l-.994-14.247-27.992-1.997-1.904 12.912c-.424 2.872-2.932 5.037-5.835 5.037h-38.188c-2.902 0-5.41-2.165-5.834-5.037l-1.905-12.912-27.992 1.997-.994 14.247c-.202 2.886-2.438 5.182-5.317 5.46l-36.2 3.49c-.187.018-.324-1.978-.511-1.978l-.049-7.83 30.658-4.944 1.004-14.374c.203-2.91 2.551-5.263 5.463-5.472l38.551-2.75c.146-.01.29-.016.434-.016 2.897 0 5.401 2.166 5.825 5.038l1.959 13.286h28.005l1.959-13.286c.423-2.871 2.93-5.037 5.831-5.037.142 0 .284.005.423.015l38.556 2.75c2.911.209 5.26 2.562 5.463 5.472l1.003 14.374 30.645 4.966z" fill="#fff" transform="matrix(.30389749 0 0 -.30389749 63.620953 46.532114)"/><path d="m0 0v-47.514-6.035-5.492c.108-.001.216-.005.323-.015l36.196-3.49c1.896-.183 3.382-1.709 3.514-3.609l1.116-15.978 31.574-2.253 2.175 14.747c.282 1.912 1.922 3.329 3.856 3.329h38.188c1.933 0 3.573-1.417 3.855-3.329l2.175-14.747 31.575 2.253 1.115 15.978c.133 1.9 1.618 3.425 3.514 3.609l36.182 3.49c.107.01.214.014.322.015v4.711l.015.005v54.325c5.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.642-7.702.88-11.567.926v.006c-.027 0-.052-.006-.075-.006-.024 0-.049.006-.073.006v-.006c-3.872-.046-7.729-.284-11.572-.926-3.238 7.238-6.956 14.642-11.03 21.479-10.184-2.264-20.258-5.416-29.703-10.17.216-8.34.755-16.331 1.848-24.448-3.668-2.35-7.523-4.367-10.949-7.118-3.481-2.678-7.036-5.24-10.188-8.372-6.297 4.165-12.962 8.079-19.828 11.534-7.401-7.965-14.321-16.562-19.974-26.182 4.4426579-6.973692 9.2079702-13.9828876 13.621-19.449z" fill="#478cbf" transform="matrix(.30389749 0 0 -.30389749 4.154146 28.589689)"/><path d="m0 0-1.121-16.063c-.135-1.936-1.675-3.477-3.611-3.616l-38.555-2.751c-.094-.007-.188-.01-.281-.01-1.916 0-3.569 1.406-3.852 3.33l-2.211 14.994h-31.459l-2.211-14.994c-.297-2.018-2.101-3.469-4.133-3.32l-38.555 2.751c-1.936.139-3.476 1.68-3.611 3.616l-1.121 16.063-32.547 3.138c.015-3.498.06-7.33.06-8.093 0-34.374 43.605-50.896 97.781-51.086h.066.067c54.176.19 97.766 16.712 97.766 51.086 0 .777.047 4.593.063 8.093z" fill="#478cbf" transform="matrix(.30389749 0 0 -.30389749 53.752732 49.859089)"/><path d="m0 0c0-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 12.048 0 21.813-9.758 21.813-21.802" fill="#fff" transform="matrix(.30389749 0 0 -.30389749 24.925648 35.87311)"/><path d="m0 0c0-7.994-6.479-14.473-14.479-14.473-7.996 0-14.479 6.479-14.479 14.473s6.483 14.479 14.479 14.479c8 0 14.479-6.485 14.479-14.479" fill="#414042" transform="matrix(.30389749 0 0 -.30389749 23.330605 36.266305)"/><path d="m0 0c-3.878 0-7.021 2.858-7.021 6.381v20.081c0 3.52 3.143 6.381 7.021 6.381s7.028-2.861 7.028-6.381v-20.081c0-3.523-3.15-6.381-7.028-6.381" fill="#fff" transform="matrix(.30389749 0 0 -.30389749 33.889273 43.105751)"/><path d="m0 0c0-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-12.05 0-21.815-9.758-21.815-21.802" fill="#fff" transform="matrix(.30389749 0 0 -.30389749 42.854008 35.87311)"/><path d="m0 0c0-7.994 6.477-14.473 14.471-14.473 8.002 0 14.479 6.479 14.479 14.473s-6.477 14.479-14.479 14.479c-7.994 0-14.471-6.485-14.471-14.479" fill="#414042" transform="matrix(.30389749 0 0 -.30389749 44.449454 36.266305)"/></svg>
diff --git a/editor/icons/NodeDisabled.svg b/editor/icons/NodeDisabled.svg
new file mode 100644
index 0000000000..b2d51fc4fb
--- /dev/null
+++ b/editor/icons/NodeDisabled.svg
@@ -0,0 +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="#999"/></svg>
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index 50b13673fa..080393e570 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -79,6 +79,9 @@ struct ColladaImport {
Vector<int> valid_animated_properties;
Map<String, bool> bones_with_animation;
+ Set<String> mesh_unique_names;
+ Set<String> material_unique_names;
+
Error _populate_skeleton(Skeleton3D *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent);
Error _create_scene_skeletons(Collada::Node *p_node);
Error _create_scene(Collada::Node *p_node, Node3D *p_parent);
@@ -326,12 +329,25 @@ Error ColladaImport::_create_material(const String &p_target) {
Ref<StandardMaterial3D> material = memnew(StandardMaterial3D);
+ String base_name;
if (src_mat.name != "") {
- material->set_name(src_mat.name);
+ base_name = src_mat.name;
} else if (effect.name != "") {
- material->set_name(effect.name);
+ base_name = effect.name;
+ } else {
+ base_name = "Material";
}
+ String name = base_name;
+ int counter = 2;
+ while (material_unique_names.has(name)) {
+ name = base_name + itos(counter++);
+ }
+
+ material_unique_names.insert(name);
+
+ material->set_name(name);
+
// DIFFUSE
if (effect.diffuse.texture != "") {
@@ -681,7 +697,8 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor
int vertex_index = p.indices[src + vertex_ofs]; //used for index field (later used by controllers)
int vertex_pos = (vertex_src->stride ? vertex_src->stride : 3) * vertex_index;
- ERR_FAIL_INDEX_V(vertex_pos, vertex_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(vertex_pos + 0, vertex_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(vertex_pos + 2, vertex_src->array.size(), ERR_INVALID_DATA);
vertex.vertex = Vector3(vertex_src->array[vertex_pos + 0], vertex_src->array[vertex_pos + 1], vertex_src->array[vertex_pos + 2]);
if (pre_weights.has(vertex_index)) {
@@ -690,16 +707,19 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor
if (normal_src) {
int normal_pos = (normal_src->stride ? normal_src->stride : 3) * p.indices[src + normal_ofs];
- ERR_FAIL_INDEX_V(normal_pos, normal_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(normal_pos + 0, normal_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(normal_pos + 2, normal_src->array.size(), ERR_INVALID_DATA);
vertex.normal = Vector3(normal_src->array[normal_pos + 0], normal_src->array[normal_pos + 1], normal_src->array[normal_pos + 2]);
if (tangent_src && binormal_src) {
int binormal_pos = (binormal_src->stride ? binormal_src->stride : 3) * p.indices[src + binormal_ofs];
- ERR_FAIL_INDEX_V(binormal_pos, binormal_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(binormal_pos + 0, binormal_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(binormal_pos + 2, binormal_src->array.size(), ERR_INVALID_DATA);
Vector3 binormal = Vector3(binormal_src->array[binormal_pos + 0], binormal_src->array[binormal_pos + 1], binormal_src->array[binormal_pos + 2]);
int tangent_pos = (tangent_src->stride ? tangent_src->stride : 3) * p.indices[src + tangent_ofs];
- ERR_FAIL_INDEX_V(tangent_pos, tangent_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(tangent_pos + 0, tangent_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(tangent_pos + 2, tangent_src->array.size(), ERR_INVALID_DATA);
Vector3 tangent = Vector3(tangent_src->array[tangent_pos + 0], tangent_src->array[tangent_pos + 1], tangent_src->array[tangent_pos + 2]);
vertex.tangent.normal = tangent;
@@ -709,19 +729,22 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor
if (uv_src) {
int uv_pos = (uv_src->stride ? uv_src->stride : 2) * p.indices[src + uv_ofs];
- ERR_FAIL_INDEX_V(uv_pos, uv_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(uv_pos + 0, uv_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(uv_pos + 1, uv_src->array.size(), ERR_INVALID_DATA);
vertex.uv = Vector3(uv_src->array[uv_pos + 0], 1.0 - uv_src->array[uv_pos + 1], 0);
}
if (uv2_src) {
int uv2_pos = (uv2_src->stride ? uv2_src->stride : 2) * p.indices[src + uv2_ofs];
- ERR_FAIL_INDEX_V(uv2_pos, uv2_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(uv2_pos + 0, uv2_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(uv2_pos + 1, uv2_src->array.size(), ERR_INVALID_DATA);
vertex.uv2 = Vector3(uv2_src->array[uv2_pos + 0], 1.0 - uv2_src->array[uv2_pos + 1], 0);
}
if (color_src) {
int color_pos = (color_src->stride ? color_src->stride : 3) * p.indices[src + color_ofs]; // colors are RGB in collada..
- ERR_FAIL_INDEX_V(color_pos, color_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(color_pos + 0, color_src->array.size(), ERR_INVALID_DATA);
+ ERR_FAIL_INDEX_V(color_pos + ((color_src->stride > 3) ? 3 : 2), color_src->array.size(), ERR_INVALID_DATA);
vertex.color = Color(color_src->array[color_pos + 0], color_src->array[color_pos + 1], color_src->array[color_pos + 2], (color_src->stride > 3) ? color_src->array[color_pos + 3] : 1.0);
}
@@ -1121,7 +1144,22 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
ERR_FAIL_COND_V(!collada.state.mesh_data_map.has(meshid), ERR_INVALID_DATA);
mesh = Ref<EditorSceneImporterMesh>(memnew(EditorSceneImporterMesh));
const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid];
- mesh->set_name(meshdata.name);
+ String name = meshdata.name;
+ if (name == "") {
+ name = "Mesh";
+ }
+ int counter = 2;
+ while (mesh_unique_names.has(name)) {
+ name = meshdata.name;
+ if (name == "") {
+ name = "Mesh";
+ }
+ name += itos(counter++);
+ }
+
+ mesh_unique_names.insert(name);
+
+ mesh->set_name(name);
Error err = _create_mesh_surfaces(morphs.size() == 0, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, morph, morphs, p_use_compression, use_mesh_builtin_materials);
ERR_FAIL_COND_V_MSG(err, err, "Cannot create mesh surface.");
@@ -1638,16 +1676,23 @@ void EditorSceneImporterCollada::get_extensions(List<String> *r_extensions) cons
}
Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+ if (r_err) {
+ *r_err = OK;
+ }
ColladaImport state;
uint32_t flags = Collada::IMPORT_FLAG_SCENE;
if (p_flags & IMPORT_ANIMATION) {
flags |= Collada::IMPORT_FLAG_ANIMATION;
}
- state.use_mesh_builtin_materials = !(p_flags & IMPORT_MATERIALS_IN_INSTANCES);
+ state.use_mesh_builtin_materials = true;
state.bake_fps = p_bake_fps;
- Error err = state.load(p_path, flags, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, p_flags & EditorSceneImporter::IMPORT_USE_COMPRESSION);
+ Error err = state.load(p_path, flags, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, 0);
+
+ if (r_err) {
+ *r_err = err;
+ }
ERR_FAIL_COND_V_MSG(err != OK, nullptr, "Cannot load scene from file '" + p_path + "'.");
@@ -1667,7 +1712,7 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_
}
if (p_flags & IMPORT_ANIMATION) {
- state.create_animations(p_flags & IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS, p_flags & EditorSceneImporter::IMPORT_ANIMATION_KEEP_VALUE_TRACKS);
+ state.create_animations(true, true);
AnimationPlayer *ap = memnew(AnimationPlayer);
for (int i = 0; i < state.animations.size(); i++) {
String name;
@@ -1677,12 +1722,6 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_
name = state.animations[i]->get_name();
}
- if (p_flags & IMPORT_ANIMATION_DETECT_LOOP) {
- if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
- state.animations.write[i]->set_loop(true);
- }
- }
-
ap->add_animation(name, state.animations[i]);
}
state.scene->add_child(ap);
@@ -1700,7 +1739,7 @@ Ref<Animation> EditorSceneImporterCollada::import_animation(const String &p_path
Error err = state.load(p_path, Collada::IMPORT_FLAG_ANIMATION, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS);
ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot load animation from file '" + p_path + "'.");
- state.create_animations(p_flags & EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS, p_flags & EditorSceneImporter::IMPORT_ANIMATION_KEEP_VALUE_TRACKS);
+ state.create_animations(true, true);
if (state.scene) {
memdelete(state.scene);
}
@@ -1709,12 +1748,6 @@ Ref<Animation> EditorSceneImporterCollada::import_animation(const String &p_path
return Ref<Animation>();
}
Ref<Animation> anim = state.animations[0];
- String base = p_path.get_basename().to_lower();
- if (p_flags & IMPORT_ANIMATION_DETECT_LOOP) {
- if (base.begins_with("loop") || base.ends_with("loop") || base.begins_with("cycle") || base.ends_with("cycle")) {
- anim->set_loop(true);
- }
- }
return anim;
}
diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp
index 7ea39ab3ef..4a4d9d8f06 100644
--- a/editor/import/resource_importer_csv_translation.cpp
+++ b/editor/import/resource_importer_csv_translation.cpp
@@ -32,7 +32,7 @@
#include "core/io/resource_saver.h"
#include "core/os/file_access.h"
-#include "core/string/compressed_translation.h"
+#include "core/string/optimized_translation.h"
#include "core/string/translation.h"
String ResourceImporterCSVTranslation::get_importer_name() const {
@@ -126,7 +126,7 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const
Ref<Translation> xlt = translations[i];
if (compress) {
- Ref<PHashTranslation> cxl = memnew(PHashTranslation);
+ Ref<OptimizedTranslation> cxl = memnew(OptimizedTranslation);
cxl->generate(xlt);
xlt = cxl;
}
diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp
index 3139ef5146..6d2215c379 100644
--- a/editor/import/resource_importer_layered_texture.cpp
+++ b/editor/import/resource_importer_layered_texture.cpp
@@ -391,8 +391,8 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const
bool ok_on_pc = false;
bool is_hdr = (image->get_format() >= Image::FORMAT_RF && image->get_format() <= Image::FORMAT_RGBE9995);
bool is_ldr = (image->get_format() >= Image::FORMAT_L8 && image->get_format() <= Image::FORMAT_RGB565);
- bool can_bptc = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_bptc");
- bool can_s3tc = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_s3tc");
+ bool can_bptc = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_bptc");
+ bool can_s3tc = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_s3tc");
if (can_bptc) {
formats_imported.push_back("bptc"); //needs to be aded anyway
@@ -447,13 +447,13 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const
ok_on_pc = true;
}
- if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2")) {
+ if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2")) {
_save_tex(slices, p_save_path + ".etc2." + extension, compress_mode, lossy, Image::COMPRESS_ETC2, csource, used_channels, mipmaps, true);
r_platform_variants->push_back("etc2");
formats_imported.push_back("etc2");
}
- if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_pvrtc")) {
+ if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_pvrtc")) {
_save_tex(slices, p_save_path + ".etc2." + extension, compress_mode, lossy, Image::COMPRESS_ETC2, csource, used_channels, mipmaps, true);
r_platform_variants->push_back("pvrtc");
formats_imported.push_back("pvrtc");
@@ -492,7 +492,7 @@ String ResourceImporterLayeredTexture::get_import_settings_string() const {
int index = 0;
while (compression_formats[index]) {
- String setting_path = "rendering/vram_compression/import_" + String(compression_formats[index]);
+ String setting_path = "rendering/textures/vram_compression/import_" + String(compression_formats[index]);
bool test = ProjectSettings::get_singleton()->get(setting_path);
if (test) {
s += String(compression_formats[index]);
@@ -524,7 +524,7 @@ bool ResourceImporterLayeredTexture::are_import_settings_valid(const String &p_p
int index = 0;
bool valid = true;
while (compression_formats[index]) {
- String setting_path = "rendering/vram_compression/import_" + String(compression_formats[index]);
+ String setting_path = "rendering/textures/vram_compression/import_" + String(compression_formats[index]);
bool test = ProjectSettings::get_singleton()->get(setting_path);
if (test) {
if (formats_imported.find(compression_formats[index]) == -1) {
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index 9111252943..5c522e3176 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -427,7 +427,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, 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, p_flags & IMPORT_USE_COMPRESSION, Vector3(1, 1, 1), Vector3(0, 0, 0), r_missing_deps);
+ Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, 0, Vector3(1, 1, 1), Vector3(0, 0, 0), r_missing_deps);
if (err != OK) {
if (r_err) {
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 9944712931..c6ef9b61d7 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -32,10 +32,12 @@
#include "core/io/resource_saver.h"
#include "editor/editor_node.h"
+#include "editor/import/scene_import_settings.h"
#include "editor/import/scene_importer_mesh_node_3d.h"
+#include "scene/3d/area_3d.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/mesh_instance_3d.h"
-#include "scene/3d/navigation_3d.h"
+#include "scene/3d/navigation_region_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/3d/vehicle_body_3d.h"
#include "scene/animation/animation_player.h"
@@ -111,20 +113,14 @@ void EditorSceneImporter::_bind_methods() {
BIND_CONSTANT(IMPORT_SCENE);
BIND_CONSTANT(IMPORT_ANIMATION);
- BIND_CONSTANT(IMPORT_ANIMATION_DETECT_LOOP);
- BIND_CONSTANT(IMPORT_ANIMATION_OPTIMIZE);
- BIND_CONSTANT(IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
- BIND_CONSTANT(IMPORT_ANIMATION_KEEP_VALUE_TRACKS);
- BIND_CONSTANT(IMPORT_GENERATE_TANGENT_ARRAYS);
BIND_CONSTANT(IMPORT_FAIL_ON_MISSING_DEPENDENCIES);
- BIND_CONSTANT(IMPORT_MATERIALS_IN_INSTANCES);
- BIND_CONSTANT(IMPORT_USE_COMPRESSION);
+ BIND_CONSTANT(IMPORT_GENERATE_TANGENT_ARRAYS);
+ BIND_CONSTANT(IMPORT_USE_NAMED_SKIN_BINDS);
}
/////////////////////////////////
void EditorScenePostImport::_bind_methods() {
BIND_VMETHOD(MethodInfo(Variant::OBJECT, "post_import", PropertyInfo(Variant::OBJECT, "scene")));
- ClassDB::bind_method(D_METHOD("get_source_folder"), &EditorScenePostImport::get_source_folder);
ClassDB::bind_method(D_METHOD("get_source_file"), &EditorScenePostImport::get_source_file);
}
@@ -136,16 +132,11 @@ Node *EditorScenePostImport::post_import(Node *p_scene) {
return p_scene;
}
-String EditorScenePostImport::get_source_folder() const {
- return source_folder;
-}
-
String EditorScenePostImport::get_source_file() const {
return source_file;
}
-void EditorScenePostImport::init(const String &p_source_folder, const String &p_source_file) {
- source_folder = p_source_folder;
+void EditorScenePostImport::init(const String &p_source_file) {
source_file = p_source_file;
}
@@ -183,29 +174,9 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const
if (p_option != "animation/import" && !bool(p_options["animation/import"])) {
return false;
}
-
- if (p_option == "animation/keep_custom_tracks" && int(p_options["animation/storage"]) == 0) {
- return false;
- }
-
- if (p_option.begins_with("animation/optimizer/") && p_option != "animation/optimizer/enabled" && !bool(p_options["animation/optimizer/enabled"])) {
- return false;
- }
-
- if (p_option.begins_with("animation/clip_")) {
- int max_clip = p_options["animation/clips/amount"];
- int clip = p_option.get_slice("/", 1).get_slice("_", 1).to_int() - 1;
- if (clip >= max_clip) {
- return false;
- }
- }
- }
-
- if (p_option == "materials/keep_on_reimport" && int(p_options["materials/storage"]) == 0) {
- return false;
}
- if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) < 2) {
+ if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) < 3) {
return false;
}
@@ -213,34 +184,11 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const
}
int ResourceImporterScene::get_preset_count() const {
- return PRESET_MAX;
+ return 0;
}
String ResourceImporterScene::get_preset_name(int p_idx) const {
- switch (p_idx) {
- case PRESET_SINGLE_SCENE:
- return TTR("Import as Single Scene");
- case PRESET_SEPARATE_ANIMATIONS:
- return TTR("Import with Separate Animations");
- case PRESET_SEPARATE_MATERIALS:
- return TTR("Import with Separate Materials");
- case PRESET_SEPARATE_MESHES:
- return TTR("Import with Separate Objects");
- case PRESET_SEPARATE_MESHES_AND_MATERIALS:
- return TTR("Import with Separate Objects+Materials");
- case PRESET_SEPARATE_MESHES_AND_ANIMATIONS:
- return TTR("Import with Separate Objects+Animations");
- case PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS:
- return TTR("Import with Separate Materials+Animations");
- case PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS:
- return TTR("Import with Separate Objects+Materials+Animations");
- case PRESET_MULTIPLE_SCENES:
- return TTR("Import as Multiple Scenes");
- case PRESET_MULTIPLE_SCENES_AND_MATERIALS:
- return TTR("Import as Multiple Scenes+Materials");
- }
-
- return "";
+ return String();
}
static bool _teststr(const String &p_what, const String &p_str) {
@@ -299,10 +247,24 @@ static void _gen_shape_list(const Ref<Mesh> &mesh, List<Ref<Shape3D>> &r_shape_l
}
}
-Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape3D>>> &collision_map, LightBakeMode p_light_bake_mode) {
+static void _pre_gen_shape_list(const Ref<EditorSceneImporterMesh> &mesh, List<Ref<Shape3D>> &r_shape_list, bool p_convex) {
+ if (!p_convex) {
+ Ref<Shape3D> shape = mesh->create_trimesh_shape();
+ r_shape_list.push_back(shape);
+ } else {
+ Vector<Ref<Shape3D>> cd = mesh->convex_decompose();
+ if (cd.size()) {
+ for (int i = 0; i < cd.size(); i++) {
+ r_shape_list.push_back(cd[i]);
+ }
+ }
+ }
+}
+
+Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map) {
// children first
for (int i = 0; i < p_node->get_child_count(); i++) {
- Node *r = _fix_node(p_node->get_child(i), p_root, collision_map, p_light_bake_mode);
+ Node *r = _pre_fix_node(p_node->get_child(i), p_root, collision_map);
if (!r) {
i--; //was erased
}
@@ -317,33 +279,29 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>
return nullptr;
}
- if (Object::cast_to<MeshInstance3D>(p_node)) {
- MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node);
+ if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) {
+ EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
- Ref<ArrayMesh> m = mi->get_mesh();
+ Ref<EditorSceneImporterMesh> m = mi->get_mesh();
if (m.is_valid()) {
for (int i = 0; i < m->get_surface_count(); i++) {
- Ref<StandardMaterial3D> mat = m->surface_get_material(i);
+ Ref<BaseMaterial3D> mat = m->get_surface_material(i);
if (!mat.is_valid()) {
continue;
}
if (_teststr(mat->get_name(), "alpha")) {
- mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+ mat->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA);
mat->set_name(_fixstr(mat->get_name(), "alpha"));
}
if (_teststr(mat->get_name(), "vcol")) {
- mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+ mat->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ mat->set_flag(BaseMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
mat->set_name(_fixstr(mat->get_name(), "vcol"));
}
}
}
-
- if (p_light_bake_mode != LIGHT_BAKE_DISABLED) {
- mi->set_gi_mode(GeometryInstance3D::GI_MODE_BAKED);
- }
}
if (Object::cast_to<AnimationPlayer>(p_node)) {
@@ -367,6 +325,17 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>
}
}
}
+
+ String animname = E->get();
+ const int loop_string_count = 3;
+ static const char *loop_strings[loop_string_count] = { "loops", "loop", "cycle" };
+ for (int i = 0; i < loop_string_count; i++) {
+ if (_teststr(animname, loop_strings[i])) {
+ anim->set_loop(true);
+ animname = _fixstr(animname, loop_strings[i]);
+ ap->rename_animation(E->get(), animname);
+ }
+ }
}
}
@@ -374,9 +343,9 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>
if (isroot) {
return p_node;
}
- MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node);
+ EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
if (mi) {
- Ref<Mesh> mesh = mi->get_mesh();
+ Ref<EditorSceneImporterMesh> mesh = mi->get_mesh();
if (mesh.is_valid()) {
List<Ref<Shape3D>> shapes;
@@ -384,10 +353,10 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>
if (collision_map.has(mesh)) {
shapes = collision_map[mesh];
} else if (_teststr(name, "colonly")) {
- _gen_shape_list(mesh, shapes, false);
+ _pre_gen_shape_list(mesh, shapes, false);
collision_map[mesh] = shapes;
} else if (_teststr(name, "convcolonly")) {
- _gen_shape_list(mesh, shapes, true);
+ _pre_gen_shape_list(mesh, shapes, true);
collision_map[mesh] = shapes;
}
@@ -407,16 +376,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>
memdelete(p_node);
p_node = col;
- int idx = 0;
- for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) {
- CollisionShape3D *cshape = memnew(CollisionShape3D);
- cshape->set_shape(E->get());
- col->add_child(cshape);
-
- cshape->set_name("shape" + itos(idx));
- cshape->set_owner(col->get_owner());
- idx++;
- }
+ _add_shapes(col, shapes);
}
}
@@ -433,34 +393,30 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>
BoxShape3D *boxShape = memnew(BoxShape3D);
boxShape->set_size(Vector3(2, 2, 2));
colshape->set_shape(boxShape);
- colshape->set_name("BoxShape3D");
} else if (empty_draw_type == "SINGLE_ARROW") {
RayShape3D *rayShape = memnew(RayShape3D);
rayShape->set_length(1);
colshape->set_shape(rayShape);
- colshape->set_name("RayShape3D");
Object::cast_to<Node3D>(sb)->rotate_x(Math_PI / 2);
} else if (empty_draw_type == "IMAGE") {
WorldMarginShape3D *world_margin_shape = memnew(WorldMarginShape3D);
colshape->set_shape(world_margin_shape);
- colshape->set_name("WorldMarginShape3D");
} else {
SphereShape3D *sphereShape = memnew(SphereShape3D);
sphereShape->set_radius(1);
colshape->set_shape(sphereShape);
- colshape->set_name("SphereShape3D");
}
sb->add_child(colshape);
colshape->set_owner(sb->get_owner());
}
- } else if (_teststr(name, "rigid") && Object::cast_to<MeshInstance3D>(p_node)) {
+ } else if (_teststr(name, "rigid") && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) {
if (isroot) {
return p_node;
}
- MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node);
- Ref<Mesh> mesh = mi->get_mesh();
+ EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
+ Ref<EditorSceneImporterMesh> mesh = mi->get_mesh();
if (mesh.is_valid()) {
List<Ref<Shape3D>> shapes;
@@ -475,27 +431,17 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>
p_node->replace_by(rigid_body);
rigid_body->set_transform(mi->get_transform());
p_node = rigid_body;
- mi->set_name("mesh");
mi->set_transform(Transform());
rigid_body->add_child(mi);
mi->set_owner(rigid_body->get_owner());
- int idx = 0;
- for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) {
- CollisionShape3D *cshape = memnew(CollisionShape3D);
- cshape->set_shape(E->get());
- rigid_body->add_child(cshape);
-
- cshape->set_name("shape" + itos(idx));
- cshape->set_owner(p_node->get_owner());
- idx++;
- }
+ _add_shapes(rigid_body, shapes);
}
- } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<MeshInstance3D>(p_node)) {
- MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node);
+ } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) {
+ EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
- Ref<Mesh> mesh = mi->get_mesh();
+ Ref<EditorSceneImporterMesh> mesh = mi->get_mesh();
if (mesh.is_valid()) {
List<Ref<Shape3D>> shapes;
@@ -524,89 +470,38 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>
if (shapes.size()) {
StaticBody3D *col = memnew(StaticBody3D);
- col->set_name("static_collision");
mi->add_child(col);
col->set_owner(mi->get_owner());
- int idx = 0;
- for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) {
- CollisionShape3D *cshape = memnew(CollisionShape3D);
- cshape->set_shape(E->get());
- col->add_child(cshape);
-
- cshape->set_name("shape" + itos(idx));
- cshape->set_owner(p_node->get_owner());
-
- idx++;
- }
+ _add_shapes(col, shapes);
}
}
- } else if (_teststr(name, "navmesh") && Object::cast_to<MeshInstance3D>(p_node)) {
+ } else if (_teststr(name, "navmesh") && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) {
if (isroot) {
return p_node;
}
- MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node);
+ EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
- Ref<ArrayMesh> mesh = mi->get_mesh();
+ Ref<EditorSceneImporterMesh> mesh = mi->get_mesh();
ERR_FAIL_COND_V(mesh.is_null(), nullptr);
NavigationRegion3D *nmi = memnew(NavigationRegion3D);
nmi->set_name(_fixstr(name, "navmesh"));
- Ref<NavigationMesh> nmesh = memnew(NavigationMesh);
- nmesh->create_from_mesh(mesh);
+ Ref<NavigationMesh> nmesh = mesh->create_navigation_mesh();
nmi->set_navigation_mesh(nmesh);
Object::cast_to<Node3D>(nmi)->set_transform(mi->get_transform());
p_node->replace_by(nmi);
memdelete(p_node);
p_node = nmi;
- } else if (_teststr(name, "vehicle")) {
- if (isroot) {
- return p_node;
- }
-
- Node *owner = p_node->get_owner();
- Node3D *s = Object::cast_to<Node3D>(p_node);
- VehicleBody3D *bv = memnew(VehicleBody3D);
- String n = _fixstr(p_node->get_name(), "vehicle");
- bv->set_name(n);
- p_node->replace_by(bv);
- p_node->set_name(n);
- bv->add_child(p_node);
- bv->set_owner(owner);
- p_node->set_owner(owner);
- bv->set_transform(s->get_transform());
- s->set_transform(Transform());
-
- p_node = bv;
-
- } else if (_teststr(name, "wheel")) {
- if (isroot) {
- return p_node;
- }
- Node *owner = p_node->get_owner();
- Node3D *s = Object::cast_to<Node3D>(p_node);
- VehicleWheel3D *bv = memnew(VehicleWheel3D);
- String n = _fixstr(p_node->get_name(), "wheel");
- bv->set_name(n);
- p_node->replace_by(bv);
- p_node->set_name(n);
- bv->add_child(p_node);
- bv->set_owner(owner);
- p_node->set_owner(owner);
- bv->set_transform(s->get_transform());
- s->set_transform(Transform());
-
- p_node = bv;
-
- } else if (Object::cast_to<MeshInstance3D>(p_node)) {
+ } else if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) {
//last attempt, maybe collision inside the mesh data
- MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node);
+ EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
- Ref<ArrayMesh> mesh = mi->get_mesh();
+ Ref<EditorSceneImporterMesh> mesh = mi->get_mesh();
if (!mesh.is_null()) {
List<Ref<Shape3D>> shapes;
if (collision_map.has(mesh)) {
@@ -623,19 +518,268 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>
if (shapes.size()) {
StaticBody3D *col = memnew(StaticBody3D);
- col->set_name("static_collision");
p_node->add_child(col);
col->set_owner(p_node->get_owner());
- int idx = 0;
- for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) {
- CollisionShape3D *cshape = memnew(CollisionShape3D);
- cshape->set_shape(E->get());
- col->add_child(cshape);
+ _add_shapes(col, shapes);
+ }
+ }
+ }
+
+ return p_node;
+}
+
+Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) {
+ // children first
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps);
+ if (!r) {
+ i--; //was erased
+ }
+ }
+
+ bool isroot = p_node == p_root;
+
+ String import_id;
+
+ if (p_node->has_meta("import_id")) {
+ import_id = p_node->get_meta("import_id");
+ } else {
+ import_id = "PATH:" + p_root->get_path_to(p_node);
+ }
+
+ Dictionary node_settings;
+ if (p_node_data.has(import_id)) {
+ node_settings = p_node_data[import_id];
+ }
+
+ if (!isroot && (node_settings.has("import/skip_import") && bool(node_settings["import/skip_import"]))) {
+ memdelete(p_node);
+ return nullptr;
+ }
+
+ if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) {
+ EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
+
+ Ref<EditorSceneImporterMesh> m = mi->get_mesh();
+
+ if (m.is_valid()) {
+ if (!r_scanned_meshes.has(m)) {
+ for (int i = 0; i < m->get_surface_count(); i++) {
+ Ref<Material> mat = m->get_surface_material(i);
+ if (mat.is_valid()) {
+ String mat_id;
+ if (mat->has_meta("import_id")) {
+ mat_id = mat->get_meta("import_id");
+ } else {
+ mat_id = mat->get_name();
+ }
+
+ if (mat_id != String() && p_material_data.has(mat_id)) {
+ Dictionary matdata = p_material_data[mat_id];
+ if (matdata.has("use_external/enabled") && bool(matdata["use_external/enabled"]) && matdata.has("use_external/path")) {
+ String path = matdata["use_external/path"];
+ Ref<Material> external_mat = ResourceLoader::load(path);
+ if (external_mat.is_valid()) {
+ m->set_surface_material(i, external_mat);
+ }
+ }
+ }
+ }
+ }
+
+ r_scanned_meshes.insert(m);
+ }
+
+ if (node_settings.has("generate/physics")) {
+ int mesh_physics_mode = node_settings["generate/physics"];
+
+ if (mesh_physics_mode != MESH_PHYSICS_DISABLED) {
+ List<Ref<Shape3D>> shapes;
+
+ if (collision_map.has(m)) {
+ shapes = collision_map[m];
+ } else {
+ switch (mesh_physics_mode) {
+ case MESH_PHYSICS_MESH_AND_STATIC_COLLIDER: {
+ _pre_gen_shape_list(m, shapes, false);
+ } break;
+ case MESH_PHYSICS_RIGID_BODY_AND_MESH: {
+ _pre_gen_shape_list(m, shapes, true);
+ } break;
+ case MESH_PHYSICS_STATIC_COLLIDER_ONLY: {
+ _pre_gen_shape_list(m, shapes, false);
+ } break;
+ case MESH_PHYSICS_AREA_ONLY: {
+ _pre_gen_shape_list(m, shapes, true);
+ } break;
+ }
+ }
+
+ if (shapes.size()) {
+ CollisionObject3D *base = nullptr;
+ switch (mesh_physics_mode) {
+ case MESH_PHYSICS_MESH_AND_STATIC_COLLIDER: {
+ StaticBody3D *col = memnew(StaticBody3D);
+ p_node->add_child(col);
+ base = col;
+ } break;
+ case MESH_PHYSICS_RIGID_BODY_AND_MESH: {
+ RigidBody3D *rigid_body = memnew(RigidBody3D);
+ rigid_body->set_name(p_node->get_name());
+ p_node->replace_by(rigid_body);
+ rigid_body->set_transform(mi->get_transform());
+ p_node = rigid_body;
+ mi->set_transform(Transform());
+ rigid_body->add_child(mi);
+ mi->set_owner(rigid_body->get_owner());
+ base = rigid_body;
+ } break;
+ case MESH_PHYSICS_STATIC_COLLIDER_ONLY: {
+ StaticBody3D *col = memnew(StaticBody3D);
+ col->set_transform(mi->get_transform());
+ col->set_name(p_node->get_name());
+ p_node->replace_by(col);
+ memdelete(p_node);
+ p_node = col;
+ base = col;
+ } break;
+ case MESH_PHYSICS_AREA_ONLY: {
+ Area3D *area = memnew(Area3D);
+ area->set_transform(mi->get_transform());
+ area->set_name(p_node->get_name());
+ p_node->replace_by(area);
+ memdelete(p_node);
+ p_node = area;
+ base = area;
+
+ } break;
+ }
+
+ int idx = 0;
+ for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) {
+ CollisionShape3D *cshape = memnew(CollisionShape3D);
+ cshape->set_shape(E->get());
+ base->add_child(cshape);
+
+ cshape->set_owner(base->get_owner());
+ idx++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //navmesh (node may have changed type above)
+ if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) {
+ EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
- cshape->set_name("shape" + itos(idx));
- cshape->set_owner(p_node->get_owner());
- idx++;
+ Ref<EditorSceneImporterMesh> m = mi->get_mesh();
+
+ if (m.is_valid()) {
+ if (node_settings.has("generate/navmesh")) {
+ int navmesh_mode = node_settings["generate/navmesh"];
+
+ if (navmesh_mode != NAVMESH_DISABLED) {
+ NavigationRegion3D *nmi = memnew(NavigationRegion3D);
+
+ Ref<NavigationMesh> nmesh = m->create_navigation_mesh();
+ nmi->set_navigation_mesh(nmesh);
+
+ if (navmesh_mode == NAVMESH_NAVMESH_ONLY) {
+ nmi->set_transform(mi->get_transform());
+ p_node->replace_by(nmi);
+ memdelete(p_node);
+ p_node = nmi;
+ } else {
+ mi->add_child(nmi);
+ nmi->set_owner(mi->get_owner());
+ }
+ }
+ }
+ }
+ }
+
+ if (Object::cast_to<AnimationPlayer>(p_node)) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
+
+ {
+ //make sure this is unique
+ node_settings = node_settings.duplicate(true);
+ //fill node settings for this node with default values
+ List<ImportOption> iopts;
+ get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, &iopts);
+ for (List<ImportOption>::Element *E = iopts.front(); E; E = E->next()) {
+ if (!node_settings.has(E->get().option.name)) {
+ node_settings[E->get().option.name] = E->get().default_value;
+ }
+ }
+ }
+
+ bool use_optimizer = node_settings["optimizer/enabled"];
+ float anim_optimizer_linerr = node_settings["optimizer/max_linear_error"];
+ float anim_optimizer_angerr = node_settings["optimizer/max_angular_error"];
+ float anim_optimizer_maxang = node_settings["optimizer/max_angle"];
+
+ if (use_optimizer) {
+ _optimize_animations(ap, anim_optimizer_linerr, anim_optimizer_angerr, anim_optimizer_maxang);
+ }
+
+ Array animation_clips;
+ {
+ int clip_count = node_settings["clips/amount"];
+
+ for (int i = 0; i < clip_count; i++) {
+ String name = node_settings["clip_" + itos(i + 1) + "/name"];
+ int from_frame = node_settings["clip_" + itos(i + 1) + "/start_frame"];
+ int end_frame = node_settings["clip_" + itos(i + 1) + "/end_frame"];
+ bool loop = node_settings["clip_" + itos(i + 1) + "/loops"];
+ bool save_to_file = node_settings["clip_" + itos(i + 1) + "/save_to_file/enabled"];
+ bool save_to_path = node_settings["clip_" + itos(i + 1) + "/save_to_file/path"];
+ bool save_to_file_keep_custom = node_settings["clip_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"];
+
+ animation_clips.push_back(name);
+ animation_clips.push_back(from_frame / p_animation_fps);
+ animation_clips.push_back(end_frame / p_animation_fps);
+ animation_clips.push_back(loop);
+ animation_clips.push_back(save_to_file);
+ animation_clips.push_back(save_to_path);
+ animation_clips.push_back(save_to_file_keep_custom);
+ }
+ }
+
+ if (animation_clips.size()) {
+ _create_clips(ap, animation_clips, true);
+ } else {
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ for (List<StringName>::Element *E = anims.front(); E; E = E->next()) {
+ String name = E->get();
+ Ref<Animation> anim = ap->get_animation(name);
+ if (p_animation_data.has(name)) {
+ Dictionary anim_settings = p_animation_data[name];
+ {
+ //fill with default values
+ List<ImportOption> iopts;
+ get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION, &iopts);
+ for (List<ImportOption>::Element *F = iopts.front(); F; F = F->next()) {
+ if (!anim_settings.has(F->get().option.name)) {
+ anim_settings[F->get().option.name] = F->get().default_value;
+ }
+ }
+ }
+
+ anim->set_loop(anim_settings["settings/loops"]);
+ bool save = anim_settings["save_to_file/enabled"];
+ String path = anim_settings["save_to_file/path"];
+ bool keep_custom = anim_settings["save_to_file/keep_custom_tracks"];
+
+ Ref<Animation> saved_anim = _save_animation_to_file(anim, save, path, keep_custom);
+
+ if (saved_anim != anim) {
+ ap->add_animation(name, saved_anim); //replace
+ }
}
}
}
@@ -644,27 +788,52 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>
return p_node;
}
-void ResourceImporterScene::_create_clips(Node *scene, const Array &p_clips, bool p_bake_all) {
- if (!scene->has_node(String("AnimationPlayer"))) {
- return;
+Ref<Animation> ResourceImporterScene::_save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks) {
+ if (!p_save_to_file || !p_save_to_path.is_resource_file()) {
+ return anim;
}
- Node *n = scene->get_node(String("AnimationPlayer"));
- ERR_FAIL_COND(!n);
- AnimationPlayer *anim = Object::cast_to<AnimationPlayer>(n);
- ERR_FAIL_COND(!anim);
+ if (FileAccess::exists(p_save_to_path) && p_keep_custom_tracks) {
+ // Copy custom animation tracks from previously imported files.
+ Ref<Animation> old_anim = ResourceLoader::load(p_save_to_path, "Animation", ResourceFormatLoader::CACHE_MODE_IGNORE);
+ if (old_anim.is_valid()) {
+ for (int i = 0; i < old_anim->get_track_count(); i++) {
+ if (!old_anim->track_is_imported(i)) {
+ old_anim->copy_track(i, anim);
+ }
+ }
+ anim->set_loop(old_anim->has_loop());
+ }
+ }
+ if (ResourceCache::has(p_save_to_path)) {
+ Ref<Animation> old_anim = Ref<Resource>(ResourceCache::get(p_save_to_path));
+ if (old_anim.is_valid()) {
+ old_anim->copy_from(anim);
+ anim = old_anim;
+ }
+ }
+ anim->set_path(p_save_to_path, true); // Set path to save externally.
+ Error err = ResourceSaver::save(p_save_to_path, anim, ResourceSaver::FLAG_CHANGE_PATH);
+ ERR_FAIL_COND_V_MSG(err != OK, anim, "Saving of animation failed: " + p_save_to_path);
+ return anim;
+}
+
+void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all) {
if (!anim->has_animation("default")) {
return;
}
Ref<Animation> default_anim = anim->get_animation("default");
- for (int i = 0; i < p_clips.size(); i += 4) {
+ for (int i = 0; i < p_clips.size(); i += 7) {
String name = p_clips[i];
float from = p_clips[i + 1];
float to = p_clips[i + 2];
bool loop = p_clips[i + 3];
+ bool save_to_file = p_clips[i + 4];
+ String save_to_path = p_clips[i + 5];
+ bool keep_current = p_clips[i + 6];
if (from >= to) {
continue;
}
@@ -752,141 +921,17 @@ void ResourceImporterScene::_create_clips(Node *scene, const Array &p_clips, boo
new_anim->set_loop(loop);
new_anim->set_length(to - from);
anim->add_animation(name, new_anim);
- }
-
- anim->remove_animation("default"); //remove default (no longer needed)
-}
-
-void ResourceImporterScene::_filter_anim_tracks(Ref<Animation> anim, Set<String> &keep) {
- Ref<Animation> a = anim;
- ERR_FAIL_COND(!a.is_valid());
-
- for (int j = 0; j < a->get_track_count(); j++) {
- String path = a->track_get_path(j);
- if (!keep.has(path)) {
- a->remove_track(j);
- j--;
+ Ref<Animation> saved_anim = _save_animation_to_file(new_anim, save_to_file, save_to_path, keep_current);
+ if (saved_anim != new_anim) {
+ anim->add_animation(name, saved_anim);
}
}
-}
-
-void ResourceImporterScene::_filter_tracks(Node *scene, const String &p_text) {
- if (!scene->has_node(String("AnimationPlayer"))) {
- return;
- }
- Node *n = scene->get_node(String("AnimationPlayer"));
- ERR_FAIL_COND(!n);
- AnimationPlayer *anim = Object::cast_to<AnimationPlayer>(n);
- ERR_FAIL_COND(!anim);
-
- Vector<String> strings = p_text.split("\n");
- for (int i = 0; i < strings.size(); i++) {
- strings.write[i] = strings[i].strip_edges();
- }
-
- List<StringName> anim_names;
- anim->get_animation_list(&anim_names);
- for (List<StringName>::Element *E = anim_names.front(); E; E = E->next()) {
- String name = E->get();
- bool valid_for_this = false;
- bool valid = false;
-
- Set<String> keep;
- Set<String> keep_local;
-
- for (int i = 0; i < strings.size(); i++) {
- if (strings[i].begins_with("@")) {
- valid_for_this = false;
- for (Set<String>::Element *F = keep_local.front(); F; F = F->next()) {
- keep.insert(F->get());
- }
- keep_local.clear();
-
- Vector<String> filters = strings[i].substr(1, strings[i].length()).split(",");
- for (int j = 0; j < filters.size(); j++) {
- String fname = filters[j].strip_edges();
- if (fname == "") {
- continue;
- }
- int fc = fname[0];
- bool plus;
- if (fc == '+') {
- plus = true;
- } else if (fc == '-') {
- plus = false;
- } else {
- continue;
- }
- String filter = fname.substr(1, fname.length()).strip_edges();
-
- if (!name.matchn(filter)) {
- continue;
- }
- valid_for_this = plus;
- }
-
- if (valid_for_this) {
- valid = true;
- }
-
- } else if (valid_for_this) {
- Ref<Animation> a = anim->get_animation(name);
- if (!a.is_valid()) {
- continue;
- }
-
- for (int j = 0; j < a->get_track_count(); j++) {
- String path = a->track_get_path(j);
-
- String tname = strings[i];
- if (tname == "") {
- continue;
- }
- int fc = tname[0];
- bool plus;
- if (fc == '+') {
- plus = true;
- } else if (fc == '-') {
- plus = false;
- } else {
- continue;
- }
-
- String filter = tname.substr(1, tname.length()).strip_edges();
-
- if (!path.matchn(filter)) {
- continue;
- }
-
- if (plus) {
- keep_local.insert(path);
- } else if (!keep.has(path)) {
- keep_local.erase(path);
- }
- }
- }
- }
-
- if (valid) {
- for (Set<String>::Element *F = keep_local.front(); F; F = F->next()) {
- keep.insert(F->get());
- }
- _filter_anim_tracks(anim->get_animation(name), keep);
- }
- }
+ anim->remove_animation("default"); //remove default (no longer needed)
}
-void ResourceImporterScene::_optimize_animations(Node *scene, float p_max_lin_error, float p_max_ang_error, float p_max_angle) {
- if (!scene->has_node(String("AnimationPlayer"))) {
- return;
- }
- Node *n = scene->get_node(String("AnimationPlayer"));
- ERR_FAIL_COND(!n);
- AnimationPlayer *anim = Object::cast_to<AnimationPlayer>(n);
- ERR_FAIL_COND(!anim);
-
+void ResourceImporterScene::_optimize_animations(AnimationPlayer *anim, float p_max_lin_error, float p_max_ang_error, float p_max_angle) {
List<StringName> anim_names;
anim->get_animation_list(&anim_names);
for (List<StringName>::Element *E = anim_names.front(); E; E = E->next()) {
@@ -895,208 +940,99 @@ void ResourceImporterScene::_optimize_animations(Node *scene, float p_max_lin_er
}
}
-static String _make_extname(const String &p_str) {
- String ext_name = p_str.replace(".", "_");
- ext_name = ext_name.replace(":", "_");
- ext_name = ext_name.replace("\"", "_");
- ext_name = ext_name.replace("<", "_");
- ext_name = ext_name.replace(">", "_");
- ext_name = ext_name.replace("/", "_");
- ext_name = ext_name.replace("|", "_");
- ext_name = ext_name.replace("\\", "_");
- ext_name = ext_name.replace("?", "_");
- ext_name = ext_name.replace("*", "_");
-
- return ext_name;
-}
-
-void ResourceImporterScene::_find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Transform> &meshes) {
- List<PropertyInfo> pi;
- p_node->get_property_list(&pi);
-
- MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node);
-
- if (mi) {
- Ref<ArrayMesh> mesh = mi->get_mesh();
-
- if (mesh.is_valid() && !meshes.has(mesh)) {
- Node3D *s = mi;
- Transform transform;
- while (s) {
- transform = transform * s->get_transform();
- s = Object::cast_to<Node3D>(s->get_parent());
+void ResourceImporterScene::get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const {
+ switch (p_category) {
+ case INTERNAL_IMPORT_CATEGORY_NODE: {
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
+ } break;
+ case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: {
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/physics", PROPERTY_HINT_ENUM, "Disabled,Mesh + Static Collider,Rigid Body + Mesh,Static Collider Only,Area Only"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/navmesh", PROPERTY_HINT_ENUM, "Disabled,Mesh + NavMesh,NavMesh Only"), 0));
+ } break;
+ case INTERNAL_IMPORT_CATEGORY_MESH: {
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "save_to_file/path", PROPERTY_HINT_SAVE_FILE, "*.res,*.tres"), ""));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/make_streamable"), ""));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/shadow_meshes", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/lightmap_uv", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/lods", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0));
+ } break;
+ case INTERNAL_IMPORT_CATEGORY_MATERIAL: {
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "use_external/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "use_external/path", PROPERTY_HINT_FILE, "*.material,*.res,*.tres"), ""));
+ } break;
+ case INTERNAL_IMPORT_CATEGORY_ANIMATION: {
+ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "settings/loops"), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "save_to_file/path", PROPERTY_HINT_SAVE_FILE, "*.res,*.tres"), ""));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/keep_custom_tracks"), ""));
+ } break;
+ case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: {
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "optimizer/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_linear_error"), 0.05));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_angular_error"), 0.01));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_angle"), 22));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slices/amount", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
+
+ for (int i = 0; i < 256; i++) {
+ r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "slice_" + itos(i + 1) + "/name"), ""));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slice_" + itos(i + 1) + "/start_frame"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slice_" + itos(i + 1) + "/end_frame"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/loops"), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "slice_" + itos(i + 1) + "/save_to_file/path", PROPERTY_HINT_SAVE_FILE, ".res,*.tres"), ""));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"), false));
}
-
- meshes[mesh] = transform;
+ } break;
+ default: {
}
}
- for (int i = 0; i < p_node->get_child_count(); i++) {
- _find_meshes(p_node->get_child(i), meshes);
- }
}
-void ResourceImporterScene::_make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_animations_as_text, bool p_keep_animations, bool p_make_materials, bool p_materials_as_text, bool p_keep_materials, bool p_make_meshes, bool p_meshes_as_text, Map<Ref<Animation>, Ref<Animation>> &p_animations, Map<Ref<Material>, Ref<Material>> &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh>> &p_meshes) {
- List<PropertyInfo> pi;
-
- if (p_make_animations) {
- if (Object::cast_to<AnimationPlayer>(p_node)) {
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
-
- List<StringName> anims;
- ap->get_animation_list(&anims);
- for (List<StringName>::Element *E = anims.front(); E; E = E->next()) {
- Ref<Animation> anim = ap->get_animation(E->get());
- ERR_CONTINUE(anim.is_null());
-
- if (!p_animations.has(anim)) {
- // Tracks from source file should be set as imported, anything else is a custom track.
- for (int i = 0; i < anim->get_track_count(); i++) {
- anim->track_set_imported(i, true);
- }
-
- String ext_name;
-
- if (p_animations_as_text) {
- ext_name = p_base_path.plus_file(_make_extname(E->get()) + ".tres");
- } else {
- ext_name = p_base_path.plus_file(_make_extname(E->get()) + ".anim");
- }
-
- if (FileAccess::exists(ext_name) && p_keep_animations) {
- // Copy custom animation tracks from previously imported files.
- Ref<Animation> old_anim = ResourceLoader::load(ext_name, "Animation", true);
- if (old_anim.is_valid()) {
- for (int i = 0; i < old_anim->get_track_count(); i++) {
- if (!old_anim->track_is_imported(i)) {
- old_anim->copy_track(i, anim);
- }
- }
- anim->set_loop(old_anim->has_loop());
- }
- }
-
- anim->set_path(ext_name, true); // Set path to save externally.
- ResourceSaver::save(ext_name, anim, ResourceSaver::FLAG_CHANGE_PATH);
- p_animations[anim] = anim;
- }
+bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const {
+ if (p_options.has("import/skip_import") && p_option != "import/skip_import" && bool(p_options["import/skip_import"])) {
+ return false; //if skip import
+ }
+ switch (p_category) {
+ case INTERNAL_IMPORT_CATEGORY_NODE: {
+ } break;
+ case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: {
+ } break;
+ case INTERNAL_IMPORT_CATEGORY_MESH: {
+ if (p_option == "save_to_file/path" || p_option == "save_to_file/make_streamable") {
+ return p_options["save_to_file/enabled"];
+ }
+ } break;
+ case INTERNAL_IMPORT_CATEGORY_MATERIAL: {
+ if (p_option == "use_external/path") {
+ return p_options["use_external/enabled"];
+ }
+ } break;
+ case INTERNAL_IMPORT_CATEGORY_ANIMATION: {
+ if (p_option == "save_to_file/path" || p_option == "save_to_file/keep_custom_tracks") {
+ return p_options["save_to_file/enabled"];
+ }
+ } break;
+ case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: {
+ if (p_option.begins_with("animation/optimizer/") && p_option != "animation/optimizer/enabled" && !bool(p_options["animation/optimizer/enabled"])) {
+ return false;
}
- }
- }
-
- p_node->get_property_list(&pi);
-
- for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) {
- if (E->get().type == Variant::OBJECT) {
- Ref<Material> mat = p_node->get(E->get().name);
-
- if (p_make_materials && mat.is_valid() && mat->get_name() != "") {
- if (!p_materials.has(mat)) {
- String ext_name;
-
- if (p_materials_as_text) {
- ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".tres");
- } else {
- ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".material");
- }
-
- if (p_keep_materials && FileAccess::exists(ext_name)) {
- //if exists, use it
- p_materials[mat] = ResourceLoader::load(ext_name);
- } else {
- ResourceSaver::save(ext_name, mat, ResourceSaver::FLAG_CHANGE_PATH);
- p_materials[mat] = ResourceLoader::load(ext_name, "", true); // disable loading from the cache.
- }
- }
-
- if (p_materials[mat] != mat) {
- p_node->set(E->get().name, p_materials[mat]);
- }
- } else {
- Ref<ArrayMesh> mesh = p_node->get(E->get().name);
-
- if (mesh.is_valid()) {
- bool mesh_just_added = false;
-
- if (p_make_meshes) {
- if (!p_meshes.has(mesh)) {
- //meshes are always overwritten, keeping them is not practical
- String ext_name;
-
- if (p_meshes_as_text) {
- ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".tres");
- } else {
- ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".mesh");
- }
-
- ResourceSaver::save(ext_name, mesh, ResourceSaver::FLAG_CHANGE_PATH);
- p_meshes[mesh] = ResourceLoader::load(ext_name);
- p_node->set(E->get().name, p_meshes[mesh]);
- mesh_just_added = true;
- }
- }
-
- if (p_make_materials) {
- if (mesh_just_added || !p_meshes.has(mesh)) {
- for (int i = 0; i < mesh->get_surface_count(); i++) {
- mat = mesh->surface_get_material(i);
-
- if (!mat.is_valid()) {
- continue;
- }
- if (mat->get_name() == "") {
- continue;
- }
-
- if (!p_materials.has(mat)) {
- String ext_name;
-
- if (p_materials_as_text) {
- ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".tres");
- } else {
- ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".material");
- }
-
- if (p_keep_materials && FileAccess::exists(ext_name)) {
- //if exists, use it
- p_materials[mat] = ResourceLoader::load(ext_name);
- } else {
- ResourceSaver::save(ext_name, mat, ResourceSaver::FLAG_CHANGE_PATH);
- p_materials[mat] = ResourceLoader::load(ext_name, "", true); // disable loading from the cache.
- }
- }
-
- if (p_materials[mat] != mat) {
- mesh->surface_set_material(i, p_materials[mat]);
-
- //re-save the mesh since a material is now assigned
- if (p_make_meshes) {
- String ext_name;
-
- if (p_meshes_as_text) {
- ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".tres");
- } else {
- ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".mesh");
- }
-
- ResourceSaver::save(ext_name, mesh, ResourceSaver::FLAG_CHANGE_PATH);
- p_meshes[mesh] = ResourceLoader::load(ext_name);
- }
- }
- }
- if (!p_make_meshes) {
- p_meshes[mesh] = Ref<ArrayMesh>(); //save it anyway, so it won't be checked again
- }
- }
- }
+ if (p_option.begins_with("animation/slice_")) {
+ int max_slice = p_options["animation/slices/amount"];
+ int slice = p_option.get_slice("/", 1).get_slice("_", 1).to_int() - 1;
+ if (slice >= max_slice) {
+ return false;
}
}
+ } break;
+ default: {
}
}
- for (int i = 0; i < p_node->get_child_count(); i++) {
- _make_external_resources(p_node->get_child(i), p_base_path, p_make_animations, p_animations_as_text, p_keep_animations, p_make_materials, p_materials_as_text, p_keep_materials, p_make_meshes, p_meshes_as_text, p_animations, p_materials, p_meshes);
- }
+ return true;
}
void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, int p_preset) const {
@@ -1115,42 +1051,18 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
script_ext_hint += "*." + E->get();
}
- bool materials_out = p_preset == PRESET_SEPARATE_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS;
- bool meshes_out = p_preset == PRESET_SEPARATE_MESHES || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS;
- bool scenes_out = p_preset == PRESET_MULTIPLE_SCENES || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS;
- bool animations_out = p_preset == PRESET_SEPARATE_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS;
-
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "nodes/root_scale", PROPERTY_HINT_RANGE, "0.001,1000,0.001"), 1.0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/custom_script", PROPERTY_HINT_FILE, script_ext_hint), ""));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "nodes/storage", PROPERTY_HINT_ENUM, "Single Scene,Instanced Sub-Scenes"), scenes_out ? 1 : 0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/location", PROPERTY_HINT_ENUM, "Node,Mesh"), (meshes_out || materials_out) ? 1 : 0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.material),Files (.tres)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), materials_out ? 1 : 0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "materials/keep_on_reimport"), materials_out));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.mesh),Files (.tres)"), meshes_out ? 1 : 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/generate_lods"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/create_shadow_meshes"), true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Dynamic,Static,Static Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 2));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "external_files/store_in_subdir"), false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 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"), 15));
- r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "animation/filter_script", PROPERTY_HINT_MULTILINE_TEXT), ""));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.anim),Files (.tres)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), animations_out));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/keep_custom_tracks"), animations_out));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/optimizer/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/optimizer/max_linear_error"), 0.05));
- r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/optimizer/max_angular_error"), 0.01));
- r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/optimizer/max_angle"), 22));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/optimizer/remove_unused_tracks"), true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/clips/amount", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
- for (int i = 0; i < 256; i++) {
- r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "animation/clip_" + itos(i + 1) + "/name"), ""));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/clip_" + itos(i + 1) + "/start_frame"), 0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/clip_" + itos(i + 1) + "/end_frame"), 0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/clip_" + itos(i + 1) + "/loops"), 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_NOEDITOR), Dictionary()));
}
void ResourceImporterScene::_replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner) {
@@ -1222,7 +1134,7 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito
return importer->import_animation(p_path, p_flags, p_bake_fps);
}
-void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods, bool p_create_shadow_meshes) {
+void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<uint8_t> &r_dst_lightmap_cache) {
EditorSceneImporterMeshNode3D *src_mesh_node = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
if (src_mesh_node) {
//is mesh
@@ -1235,14 +1147,94 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods,
Ref<ArrayMesh> mesh;
if (!src_mesh_node->get_mesh()->has_mesh()) {
//do mesh processing
- if (p_generate_lods) {
+
+ bool generate_lods = p_generate_lods;
+ bool create_shadow_meshes = p_create_shadow_meshes;
+ bool bake_lightmaps = p_light_bake_mode == LIGHT_BAKE_STATIC_LIGHTMAPS;
+ String save_to_file;
+
+ String mesh_id;
+
+ if (src_mesh_node->get_mesh()->has_meta("import_id")) {
+ mesh_id = src_mesh_node->get_mesh()->get_meta("import_id");
+ } else {
+ mesh_id = src_mesh_node->get_mesh()->get_name();
+ }
+
+ if (mesh_id != String() && p_mesh_data.has(mesh_id)) {
+ Dictionary mesh_settings = p_mesh_data[mesh_id];
+
+ if (mesh_settings.has("generate/shadow_meshes")) {
+ int shadow_meshes = mesh_settings["generate/shadow_meshes"];
+ if (shadow_meshes == MESH_OVERRIDE_ENABLE) {
+ create_shadow_meshes = true;
+ } else if (shadow_meshes == MESH_OVERRIDE_DISABLE) {
+ create_shadow_meshes = false;
+ }
+ }
+
+ if (mesh_settings.has("generate/lightmap_uv")) {
+ int lightmap_uv = mesh_settings["generate/lightmap_uv"];
+ if (lightmap_uv == MESH_OVERRIDE_ENABLE) {
+ bake_lightmaps = true;
+ } else if (lightmap_uv == MESH_OVERRIDE_DISABLE) {
+ bake_lightmaps = false;
+ }
+ }
+
+ if (mesh_settings.has("generate/lods")) {
+ int lods = mesh_settings["generate/lods"];
+ if (lods == MESH_OVERRIDE_ENABLE) {
+ generate_lods = true;
+ } else if (lods == MESH_OVERRIDE_DISABLE) {
+ generate_lods = false;
+ }
+ }
+
+ if (mesh_settings.has("save_to_file/enabled") && bool(mesh_settings["save_to_file/enabled"]) && mesh_settings.has("save_to_file/path")) {
+ save_to_file = mesh_settings["save_to_file/path"];
+ if (!save_to_file.is_resource_file()) {
+ save_to_file = "";
+ }
+ }
+ }
+
+ if (generate_lods) {
src_mesh_node->get_mesh()->generate_lods();
}
- if (p_create_shadow_meshes) {
+ if (create_shadow_meshes) {
src_mesh_node->get_mesh()->create_shadow_mesh();
}
+
+ if (bake_lightmaps) {
+ Transform xf;
+ Node3D *n = src_mesh_node;
+ while (n) {
+ xf = n->get_transform() * xf;
+ n = n->get_parent_spatial();
+ }
+
+ //use xf as transform for mesh, and bake it
+ }
+
+ if (save_to_file != String()) {
+ Ref<Mesh> existing = Ref<Resource>(ResourceCache::get(save_to_file));
+ if (existing.is_valid()) {
+ //if somehow an existing one is useful, create
+ existing->reset_state();
+ }
+ mesh = src_mesh_node->get_mesh()->get_mesh(existing);
+
+ ResourceSaver::save(save_to_file, mesh); //override
+
+ mesh->set_path(save_to_file, true); //takeover existing, if needed
+
+ } else {
+ mesh = src_mesh_node->get_mesh()->get_mesh();
+ }
+ } else {
+ mesh = src_mesh_node->get_mesh()->get_mesh();
}
- mesh = src_mesh_node->get_mesh()->get_mesh();
if (mesh.is_valid()) {
mesh_node->set_mesh(mesh);
@@ -1251,15 +1243,78 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods,
}
}
}
+
+ switch (p_light_bake_mode) {
+ case LIGHT_BAKE_DISABLED: {
+ mesh_node->set_gi_mode(GeometryInstance3D::GI_MODE_DISABLED);
+ } break;
+ case LIGHT_BAKE_DYNAMIC: {
+ mesh_node->set_gi_mode(GeometryInstance3D::GI_MODE_DYNAMIC);
+ } break;
+ case LIGHT_BAKE_STATIC:
+ case LIGHT_BAKE_STATIC_LIGHTMAPS: {
+ mesh_node->set_gi_mode(GeometryInstance3D::GI_MODE_BAKED);
+ } break;
+ }
+
p_node->replace_by(mesh_node);
memdelete(p_node);
p_node = mesh_node;
}
for (int i = 0; i < p_node->get_child_count(); i++) {
- _generate_meshes(p_node->get_child(i), p_generate_lods, p_create_shadow_meshes);
+ _generate_meshes(p_node->get_child(i), p_mesh_data, p_generate_lods, p_create_shadow_meshes, p_light_bake_mode, p_lightmap_texel_size, p_src_lightmap_cache, r_dst_lightmap_cache);
+ }
+}
+
+void ResourceImporterScene::_add_shapes(Node *p_node, const List<Ref<Shape3D>> &p_shapes) {
+ for (const List<Ref<Shape3D>>::Element *E = p_shapes.front(); E; E = E->next()) {
+ CollisionShape3D *cshape = memnew(CollisionShape3D);
+ cshape->set_shape(E->get());
+ p_node->add_child(cshape);
+
+ cshape->set_owner(p_node->get_owner());
}
}
+
+Node *ResourceImporterScene::pre_import(const String &p_source_file) {
+ Ref<EditorSceneImporter> importer;
+ String ext = p_source_file.get_extension().to_lower();
+
+ EditorProgress progress("pre-import", TTR("Pre-Import Scene"), 0);
+ progress.step(TTR("Importing Scene..."), 0);
+
+ for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) {
+ List<String> extensions;
+ E->get()->get_extensions(&extensions);
+
+ for (List<String>::Element *F = extensions.front(); F; F = F->next()) {
+ if (F->get().to_lower() == ext) {
+ importer = E->get();
+ break;
+ }
+ }
+
+ if (importer.is_valid()) {
+ break;
+ }
+ }
+
+ ERR_FAIL_COND_V(!importer.is_valid(), nullptr);
+
+ Error err;
+ Node *scene = importer->import_scene(p_source_file, EditorSceneImporter::IMPORT_ANIMATION | EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, 15, nullptr, &err);
+ if (!scene || err != OK) {
+ return nullptr;
+ }
+
+ Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> collision_map;
+
+ _pre_fix_node(scene, scene, collision_map);
+
+ return scene;
+}
+
Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
const String &src_path = p_source_file;
@@ -1289,27 +1344,21 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
float fps = p_options["animation/fps"];
- int import_flags = EditorSceneImporter::IMPORT_ANIMATION_DETECT_LOOP;
- if (!bool(p_options["animation/optimizer/remove_unused_tracks"])) {
- import_flags |= EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS;
- }
+ int import_flags = 0;
if (bool(p_options["animation/import"])) {
import_flags |= EditorSceneImporter::IMPORT_ANIMATION;
}
- if (bool(p_options["meshes/ensure_tangents"])) {
- import_flags |= EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS;
- }
-
- if (int(p_options["materials/location"]) == 0) {
- import_flags |= EditorSceneImporter::IMPORT_MATERIALS_IN_INSTANCES;
- }
-
if (bool(p_options["skins/use_named_skins"])) {
import_flags |= EditorSceneImporter::IMPORT_USE_NAMED_SKIN_BINDS;
}
+ bool ensure_tangents = p_options["meshes/ensure_tangents"];
+ if (ensure_tangents) {
+ import_flags |= EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS;
+ }
+
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, fps, &missing_deps, &err);
@@ -1317,6 +1366,29 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
return err;
}
+ Dictionary subresources = p_options["_subresources"];
+
+ Dictionary node_data;
+ if (subresources.has("nodes")) {
+ node_data = subresources["nodes"];
+ }
+
+ Dictionary material_data;
+ if (subresources.has("materials")) {
+ material_data = subresources["materials"];
+ }
+
+ Dictionary animation_data;
+ if (subresources.has("animations")) {
+ animation_data = subresources["animations"];
+ }
+
+ Set<Ref<EditorSceneImporterMesh>> scanned_meshes;
+ Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> collision_map;
+
+ _pre_fix_node(scene, scene, collision_map);
+ _post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_data, animation_data, fps);
+
String root_type = p_options["nodes/root_type"];
root_type = root_type.split(" ")[0]; // full root_type is "ClassName (filename.gd)" for a script global class.
@@ -1354,73 +1426,35 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
bool gen_lods = bool(p_options["meshes/generate_lods"]);
bool create_shadow_meshes = bool(p_options["meshes/create_shadow_meshes"]);
-
- _generate_meshes(scene, gen_lods, create_shadow_meshes);
-
- err = OK;
-
- String animation_filter = String(p_options["animation/filter_script"]).strip_edges();
-
- bool use_optimizer = p_options["animation/optimizer/enabled"];
- float anim_optimizer_linerr = p_options["animation/optimizer/max_linear_error"];
- float anim_optimizer_angerr = p_options["animation/optimizer/max_angular_error"];
- float anim_optimizer_maxang = p_options["animation/optimizer/max_angle"];
int light_bake_mode = p_options["meshes/light_baking"];
+ float texel_size = p_options["meshes/lightmap_texel_size"];
+ float lightmap_texel_size = MAX(0.001, texel_size);
- Map<Ref<Mesh>, List<Ref<Shape3D>>> collision_map;
-
- scene = _fix_node(scene, scene, collision_map, LightBakeMode(light_bake_mode));
-
- if (use_optimizer) {
- _optimize_animations(scene, anim_optimizer_linerr, anim_optimizer_angerr, anim_optimizer_maxang);
- }
+ Vector<uint8_t> src_lightmap_cache;
+ Vector<uint8_t> dst_lightmap_cache;
- Array animation_clips;
{
- int clip_count = p_options["animation/clips/amount"];
-
- for (int i = 0; i < clip_count; i++) {
- String name = p_options["animation/clip_" + itos(i + 1) + "/name"];
- int from_frame = p_options["animation/clip_" + itos(i + 1) + "/start_frame"];
- int end_frame = p_options["animation/clip_" + itos(i + 1) + "/end_frame"];
- bool loop = p_options["animation/clip_" + itos(i + 1) + "/loops"];
-
- animation_clips.push_back(name);
- animation_clips.push_back(from_frame / fps);
- animation_clips.push_back(end_frame / fps);
- animation_clips.push_back(loop);
+ src_lightmap_cache = FileAccess::get_file_as_array(p_source_file + ".unwrap_cache", &err);
+ if (err != OK) {
+ src_lightmap_cache.clear();
}
}
- if (animation_clips.size()) {
- _create_clips(scene, animation_clips, !bool(p_options["animation/optimizer/remove_unused_tracks"]));
- }
- if (animation_filter != "") {
- _filter_tracks(scene, animation_filter);
+ Dictionary mesh_data;
+ if (subresources.has("meshes")) {
+ mesh_data = subresources["meshes"];
}
+ _generate_meshes(scene, mesh_data, gen_lods, create_shadow_meshes, LightBakeMode(light_bake_mode), lightmap_texel_size, src_lightmap_cache, dst_lightmap_cache);
- bool external_animations = int(p_options["animation/storage"]) == 1 || int(p_options["animation/storage"]) == 2;
- bool external_animations_as_text = int(p_options["animation/storage"]) == 2;
- bool keep_custom_tracks = p_options["animation/keep_custom_tracks"];
- bool external_materials = int(p_options["materials/storage"]) == 1 || int(p_options["materials/storage"]) == 2;
- bool external_materials_as_text = int(p_options["materials/storage"]) == 2;
- bool external_meshes = int(p_options["meshes/storage"]) == 1 || int(p_options["meshes/storage"]) == 2;
- bool external_meshes_as_text = int(p_options["meshes/storage"]) == 2;
- bool external_scenes = int(p_options["nodes/storage"]) == 1;
-
- String base_path = p_source_file.get_base_dir();
-
- if (external_animations || external_materials || external_meshes || external_scenes) {
- if (bool(p_options["external_files/store_in_subdir"])) {
- String subdir_name = p_source_file.get_file().get_basename();
- DirAccess *da = DirAccess::open(base_path);
- Error err2 = da->make_dir(subdir_name);
- memdelete(da);
- ERR_FAIL_COND_V_MSG(err2 != OK && err2 != ERR_ALREADY_EXISTS, err2, "Cannot make directory '" + subdir_name + "'.");
- base_path = base_path.plus_file(subdir_name);
+ if (dst_lightmap_cache.size()) {
+ FileAccessRef f = FileAccess::open(p_source_file + ".unwrap_cache", FileAccess::WRITE);
+ if (f) {
+ f->store_buffer(dst_lightmap_cache.ptr(), dst_lightmap_cache.size());
}
}
+ err = OK;
+#if 0
if (light_bake_mode == 2 /* || generate LOD */) {
Map<Ref<ArrayMesh>, Transform> meshes;
_find_meshes(scene, meshes);
@@ -1445,9 +1479,6 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
}
}
- float texel_size = p_options["meshes/lightmap_texel_size"];
- texel_size = MAX(0.001, texel_size);
-
Map<String, unsigned int> used_unwraps;
EditorProgress progress2("gen_lightmaps", TTR("Generating Lightmaps"), meshes.size());
@@ -1469,7 +1500,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
if (err2 != OK) {
EditorNode::add_io_error("Mesh '" + name + "' failed lightmap generation. Please fix geometry.");
} else {
- String hash = String::md5((unsigned char *)ret_cache_data);
+` String hash = String::md5((unsigned char *)ret_cache_data);
used_unwraps.insert(hash, ret_cache_size);
if (!ret_used_cache) {
@@ -1482,7 +1513,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
} else {
int current_size = cache_data.size();
cache_data.resize(cache_data.size() + ret_cache_size);
- unsigned char *ptrw = cache_data.ptrw();
+ unsigned char *ptrw = cache_data.ptrw();
memcpy(&ptrw[current_size], ret_cache_data, ret_cache_size);
int *data = (int *)ptrw;
data[0] += 1;
@@ -1530,20 +1561,11 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
file->close();
}
}
-
- if (external_animations || external_materials || external_meshes) {
- Map<Ref<Animation>, Ref<Animation>> anim_map;
- Map<Ref<Material>, Ref<Material>> mat_map;
- Map<Ref<ArrayMesh>, Ref<ArrayMesh>> mesh_map;
-
- bool keep_materials = bool(p_options["materials/keep_on_reimport"]);
-
- _make_external_resources(scene, base_path, external_animations, external_animations_as_text, keep_custom_tracks, external_materials, external_materials_as_text, keep_materials, external_meshes, external_meshes_as_text, anim_map, mat_map, mesh_map);
- }
+#endif
progress.step(TTR("Running Custom Script..."), 2);
- String post_import_script_path = p_options["nodes/custom_script"];
+ String post_import_script_path = p_options["import_script/path"];
Ref<EditorScenePostImport> post_import_script;
if (post_import_script_path != "") {
@@ -1562,7 +1584,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
}
if (post_import_script.is_valid()) {
- post_import_script->init(base_path, p_source_file);
+ post_import_script->init(p_source_file);
scene = post_import_script->post_import(scene);
if (!scene) {
EditorNode::add_io_error(
@@ -1574,29 +1596,6 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
progress.step(TTR("Saving..."), 104);
- if (external_scenes) {
- //save sub-scenes as instances!
- for (int i = 0; i < scene->get_child_count(); i++) {
- Node *child = scene->get_child(i);
- if (child->get_owner() != scene) {
- continue; //not a real child probably created by scene type (ig, a scrollbar)
- }
- _replace_owner(child, scene, child);
-
- String cn = String(child->get_name()).strip_edges().replace(".", "_").replace(":", "_");
- if (cn == String()) {
- cn = "ChildNode" + itos(i);
- }
- String path = base_path.plus_file(cn + ".scn");
- child->set_filename(path);
-
- Ref<PackedScene> packer = memnew(PackedScene);
- packer->pack(child);
- err = ResourceSaver::save(path, packer); //do not take over, let the changed files reload themselves
- ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + path + "'.");
- }
- }
-
Ref<PackedScene> packer = memnew(PackedScene);
packer->pack(scene);
print_verbose("Saving scene to: " + p_save_path + ".scn");
@@ -1613,6 +1612,13 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
ResourceImporterScene *ResourceImporterScene::singleton = nullptr;
+bool ResourceImporterScene::ResourceImporterScene::has_advanced_options() const {
+ return true;
+}
+void ResourceImporterScene::ResourceImporterScene::show_advanced_options(const String &p_path) {
+ SceneImportSettings::get_singleton()->open_settings(p_path);
+}
+
ResourceImporterScene::ResourceImporterScene() {
singleton = this;
}
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index aced0226ff..6c6af57c4c 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -39,7 +39,9 @@
#include "scene/resources/skin.h"
class Material;
+class AnimationPlayer;
+class EditorSceneImporterMesh;
class EditorSceneImporter : public Reference {
GDCLASS(EditorSceneImporter, Reference);
@@ -53,15 +55,9 @@ public:
enum ImportFlags {
IMPORT_SCENE = 1,
IMPORT_ANIMATION = 2,
- IMPORT_ANIMATION_DETECT_LOOP = 4,
- IMPORT_ANIMATION_OPTIMIZE = 8,
- IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS = 16,
- IMPORT_ANIMATION_KEEP_VALUE_TRACKS = 32,
- IMPORT_GENERATE_TANGENT_ARRAYS = 256,
- IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 512,
- IMPORT_MATERIALS_IN_INSTANCES = 1024,
- IMPORT_USE_COMPRESSION = 2048,
- IMPORT_USE_NAMED_SKIN_BINDS = 4096,
+ IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 4,
+ IMPORT_GENERATE_TANGENT_ARRAYS = 8,
+ IMPORT_USE_NAMED_SKIN_BINDS = 16,
};
@@ -76,17 +72,15 @@ public:
class EditorScenePostImport : public Reference {
GDCLASS(EditorScenePostImport, Reference);
- String source_folder;
String source_file;
protected:
static void _bind_methods();
public:
- String get_source_folder() const;
String get_source_file() const;
virtual Node *post_import(Node *p_scene);
- virtual void init(const String &p_source_folder, const String &p_source_file);
+ virtual void init(const String &p_source_file);
EditorScenePostImport();
};
@@ -97,31 +91,36 @@ class ResourceImporterScene : public ResourceImporter {
static ResourceImporterScene *singleton;
- enum Presets {
- PRESET_SEPARATE_MATERIALS,
- PRESET_SEPARATE_MESHES,
- PRESET_SEPARATE_ANIMATIONS,
-
- PRESET_SINGLE_SCENE,
+ enum LightBakeMode {
+ LIGHT_BAKE_DISABLED,
+ LIGHT_BAKE_DYNAMIC,
+ LIGHT_BAKE_STATIC,
+ LIGHT_BAKE_STATIC_LIGHTMAPS
+ };
- PRESET_SEPARATE_MESHES_AND_MATERIALS,
- PRESET_SEPARATE_MESHES_AND_ANIMATIONS,
- PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS,
- PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS,
+ enum MeshPhysicsMode {
+ MESH_PHYSICS_DISABLED,
+ MESH_PHYSICS_MESH_AND_STATIC_COLLIDER,
+ MESH_PHYSICS_RIGID_BODY_AND_MESH,
+ MESH_PHYSICS_STATIC_COLLIDER_ONLY,
+ MESH_PHYSICS_AREA_ONLY,
+ };
- PRESET_MULTIPLE_SCENES,
- PRESET_MULTIPLE_SCENES_AND_MATERIALS,
- PRESET_MAX
+ enum NavMeshMode {
+ NAVMESH_DISABLED,
+ NAVMESH_MESH_AND_NAVMESH,
+ NAVMESH_NAVMESH_ONLY,
};
- enum LightBakeMode {
- LIGHT_BAKE_DISABLED,
- LIGHT_BAKE_ENABLE,
- LIGHT_BAKE_LIGHTMAPS
+ enum MeshOverride {
+ MESH_OVERRIDE_DEFAULT,
+ MESH_OVERRIDE_ENABLE,
+ MESH_OVERRIDE_DISABLE,
};
void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner);
- void _generate_meshes(Node *p_node, bool p_generate_lods, bool p_create_shadow_meshes);
+ void _generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<uint8_t> &r_dst_lightmap_cache);
+ void _add_shapes(Node *p_node, const List<Ref<Shape3D>> &p_shapes);
public:
static ResourceImporterScene *get_singleton() { return singleton; }
@@ -141,26 +140,39 @@ public:
virtual int get_preset_count() const override;
virtual String get_preset_name(int p_idx) const override;
+ enum InternalImportCategory {
+ INTERNAL_IMPORT_CATEGORY_NODE,
+ INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE,
+ INTERNAL_IMPORT_CATEGORY_MESH,
+ INTERNAL_IMPORT_CATEGORY_MATERIAL,
+ INTERNAL_IMPORT_CATEGORY_ANIMATION,
+ INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE,
+ INTERNAL_IMPORT_CATEGORY_MAX
+ };
+
+ void get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const;
+ bool get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const;
+
virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override;
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override;
virtual int get_import_order() const override { return 100; } //after everything
- void _find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Transform> &meshes);
+ Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map);
+ Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps);
- void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_animations_as_text, bool p_keep_animations, bool p_make_materials, bool p_materials_as_text, bool p_keep_materials, bool p_make_meshes, bool p_meshes_as_text, Map<Ref<Animation>, Ref<Animation>> &p_animations, Map<Ref<Material>, Ref<Material>> &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh>> &p_meshes);
-
- Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape3D>>> &collision_map, LightBakeMode p_light_bake_mode);
-
- void _create_clips(Node *scene, const Array &p_clips, bool p_bake_all);
- void _filter_anim_tracks(Ref<Animation> anim, Set<String> &keep);
- void _filter_tracks(Node *scene, const String &p_text);
- void _optimize_animations(Node *scene, float p_max_lin_error, float p_max_ang_error, float p_max_angle);
+ Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks);
+ void _create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all);
+ void _optimize_animations(AnimationPlayer *anim, float p_max_lin_error, float p_max_ang_error, float p_max_angle);
+ Node *pre_import(const String &p_source_file);
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;
Node *import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps);
Ref<Animation> import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps);
+ virtual bool has_advanced_options() const override;
+ virtual void show_advanced_options(const String &p_path) override;
+
ResourceImporterScene();
};
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index eb16e873e6..de8031af35 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -172,7 +172,7 @@ bool ResourceImporterTexture::get_option_visibility(const String &p_option, cons
if (compress_mode < COMPRESS_VRAM_COMPRESSED) {
return false;
}
- if (!ProjectSettings::get_singleton()->get("rendering/vram_compression/import_bptc")) {
+ if (!ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_bptc")) {
return false;
}
}
@@ -473,8 +473,8 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
bool ok_on_pc = false;
bool is_hdr = (image->get_format() >= Image::FORMAT_RF && image->get_format() <= Image::FORMAT_RGBE9995);
bool is_ldr = (image->get_format() >= Image::FORMAT_L8 && image->get_format() <= Image::FORMAT_RGB565);
- bool can_bptc = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_bptc");
- bool can_s3tc = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_s3tc");
+ bool can_bptc = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_bptc");
+ bool can_s3tc = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_s3tc");
if (can_bptc) {
//add to the list anyway
@@ -524,19 +524,19 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
ok_on_pc = true;
}
- if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2")) {
+ if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2")) {
_save_stex(image, p_save_path + ".etc2.stex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
r_platform_variants->push_back("etc2");
formats_imported.push_back("etc2");
}
- if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc")) {
+ if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc")) {
_save_stex(image, p_save_path + ".etc.stex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
r_platform_variants->push_back("etc");
formats_imported.push_back("etc");
}
- if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_pvrtc")) {
+ if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_pvrtc")) {
_save_stex(image, p_save_path + ".pvrtc.stex", compress_mode, lossy, Image::COMPRESS_PVRTC1_4, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
r_platform_variants->push_back("pvrtc");
formats_imported.push_back("pvrtc");
@@ -574,7 +574,7 @@ String ResourceImporterTexture::get_import_settings_string() const {
int index = 0;
while (compression_formats[index]) {
- String setting_path = "rendering/vram_compression/import_" + String(compression_formats[index]);
+ String setting_path = "rendering/textures/vram_compression/import_" + String(compression_formats[index]);
bool test = ProjectSettings::get_singleton()->get(setting_path);
if (test) {
s += String(compression_formats[index]);
@@ -606,7 +606,7 @@ bool ResourceImporterTexture::are_import_settings_valid(const String &p_path) co
int index = 0;
bool valid = true;
while (compression_formats[index]) {
- String setting_path = "rendering/vram_compression/import_" + String(compression_formats[index]);
+ String setting_path = "rendering/textures/vram_compression/import_" + String(compression_formats[index]);
bool test = ProjectSettings::get_singleton()->get(setting_path);
if (test) {
if (formats_imported.find(compression_formats[index]) == -1) {
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
new file mode 100644
index 0000000000..48340ac242
--- /dev/null
+++ b/editor/import/scene_import_settings.cpp
@@ -0,0 +1,1199 @@
+/*************************************************************************/
+/* scene_import_settings.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "scene_import_settings.h"
+#include "editor/editor_node.h"
+#include "editor/editor_scale.h"
+#include "editor/import/scene_importer_mesh_node_3d.h"
+#include "scene/resources/surface_tool.h"
+
+class SceneImportSettingsData : public Object {
+ GDCLASS(SceneImportSettingsData, Object)
+ friend class SceneImportSettings;
+ Map<StringName, Variant> *settings = nullptr;
+ Map<StringName, Variant> current;
+ Map<StringName, Variant> defaults;
+ List<ResourceImporter::ImportOption> options;
+
+ ResourceImporterScene::InternalImportCategory category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX;
+
+ bool _set(const StringName &p_name, const Variant &p_value) {
+ if (settings) {
+ if (defaults.has(p_name) && defaults[p_name] == p_value) {
+ settings->erase(p_name);
+ } else {
+ (*settings)[p_name] = p_value;
+ }
+
+ current[p_name] = p_value;
+ return true;
+ }
+ return false;
+ }
+ bool _get(const StringName &p_name, Variant &r_ret) const {
+ if (settings) {
+ if (settings->has(p_name)) {
+ r_ret = (*settings)[p_name];
+ return true;
+ }
+ }
+ if (defaults.has(p_name)) {
+ r_ret = defaults[p_name];
+ return true;
+ }
+ return false;
+ }
+ void _get_property_list(List<PropertyInfo> *p_list) const {
+ for (const List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
+ if (ResourceImporterScene::get_singleton()->get_internal_option_visibility(category, E->get().option.name, current)) {
+ p_list->push_back(E->get().option);
+ }
+ }
+ }
+};
+
+void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_material, TreeItem *p_parent) {
+ String import_id;
+ bool has_import_id = false;
+
+ if (p_material->has_meta("import_id")) {
+ import_id = p_material->get_meta("import_id");
+ has_import_id = true;
+ } else if (p_material->get_name() != "") {
+ import_id = p_material->get_name();
+ has_import_id = true;
+ } else {
+ import_id = "@MATERIAL:" + itos(material_set.size());
+ }
+
+ if (!material_map.has(import_id)) {
+ MaterialData md;
+ md.has_import_id = has_import_id;
+ md.material = p_material;
+
+ _load_default_subresource_settings(md.settings, "materials", import_id, ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MATERIAL);
+
+ material_map[import_id] = md;
+ }
+
+ MaterialData &material_data = material_map[import_id];
+
+ Ref<Texture2D> icon = get_theme_icon("StandardMaterial3D", "EditorIcons");
+
+ TreeItem *item = p_tree->create_item(p_parent);
+ item->set_text(0, p_material->get_name());
+ item->set_icon(0, icon);
+
+ bool created = false;
+ if (!material_set.has(p_material)) {
+ material_set.insert(p_material);
+ created = true;
+ }
+
+ item->set_meta("type", "Material");
+ item->set_meta("import_id", import_id);
+ item->set_tooltip(0, vformat(TTR("Import ID: %s"), import_id));
+ item->set_selectable(0, true);
+
+ if (p_tree == scene_tree) {
+ material_data.scene_node = item;
+ } else if (p_tree == mesh_tree) {
+ material_data.mesh_node = item;
+ } else {
+ material_data.material_node = item;
+ }
+
+ if (created) {
+ _fill_material(material_tree, p_material, material_tree->get_root());
+ }
+}
+
+void SceneImportSettings::_fill_mesh(Tree *p_tree, const Ref<Mesh> &p_mesh, TreeItem *p_parent) {
+ String import_id;
+
+ bool has_import_id = false;
+ if (p_mesh->has_meta("import_id")) {
+ import_id = p_mesh->get_meta("import_id");
+ has_import_id = true;
+ } else if (p_mesh->get_name() != String()) {
+ import_id = p_mesh->get_name();
+ has_import_id = true;
+ } else {
+ import_id = "@MESH:" + itos(mesh_set.size());
+ }
+
+ if (!mesh_map.has(import_id)) {
+ MeshData md;
+ md.has_import_id = has_import_id;
+ md.mesh = p_mesh;
+
+ _load_default_subresource_settings(md.settings, "meshes", import_id, ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH);
+
+ mesh_map[import_id] = md;
+ }
+
+ MeshData &mesh_data = mesh_map[import_id];
+
+ Ref<Texture2D> icon = get_theme_icon("Mesh", "EditorIcons");
+
+ TreeItem *item = p_tree->create_item(p_parent);
+ item->set_text(0, p_mesh->get_name());
+ item->set_icon(0, icon);
+
+ bool created = false;
+ if (!mesh_set.has(p_mesh)) {
+ mesh_set.insert(p_mesh);
+ created = true;
+ }
+
+ item->set_meta("type", "Mesh");
+ item->set_meta("import_id", import_id);
+ item->set_tooltip(0, vformat(TTR("Import ID: %s"), import_id));
+
+ item->set_selectable(0, true);
+
+ if (p_tree == scene_tree) {
+ mesh_data.scene_node = item;
+ } else {
+ mesh_data.mesh_node = item;
+ }
+
+ item->set_collapsed(true);
+
+ for (int i = 0; i < p_mesh->get_surface_count(); i++) {
+ Ref<Material> mat = p_mesh->surface_get_material(i);
+ if (mat.is_valid()) {
+ _fill_material(p_tree, mat, item);
+ }
+ }
+
+ if (created) {
+ _fill_mesh(mesh_tree, p_mesh, mesh_tree->get_root());
+ }
+}
+
+void SceneImportSettings::_fill_animation(Tree *p_tree, const Ref<Animation> &p_anim, const String &p_name, TreeItem *p_parent) {
+ if (!animation_map.has(p_name)) {
+ AnimationData ad;
+ ad.animation = p_anim;
+
+ _load_default_subresource_settings(ad.settings, "animations", p_name, ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION);
+
+ animation_map[p_name] = ad;
+ }
+
+ AnimationData &animation_data = animation_map[p_name];
+
+ Ref<Texture2D> icon = get_theme_icon("Animation", "EditorIcons");
+
+ TreeItem *item = p_tree->create_item(p_parent);
+ item->set_text(0, p_name);
+ item->set_icon(0, icon);
+
+ item->set_meta("type", "Animation");
+ item->set_meta("import_id", p_name);
+
+ item->set_selectable(0, true);
+
+ animation_data.scene_node = item;
+}
+
+void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) {
+ String import_id;
+
+ if (p_node->has_meta("import_id")) {
+ import_id = p_node->get_meta("import_id");
+ } else {
+ import_id = "PATH:" + String(scene->get_path_to(p_node));
+ p_node->set_meta("import_id", import_id);
+ }
+
+ EditorSceneImporterMeshNode3D *src_mesh_node = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
+
+ if (src_mesh_node) {
+ MeshInstance3D *mesh_node = memnew(MeshInstance3D);
+ mesh_node->set_name(src_mesh_node->get_name());
+ mesh_node->set_transform(src_mesh_node->get_transform());
+ mesh_node->set_skin(src_mesh_node->get_skin());
+ mesh_node->set_skeleton_path(src_mesh_node->get_skeleton_path());
+ if (src_mesh_node->get_mesh().is_valid()) {
+ Ref<EditorSceneImporterMesh> editor_mesh = src_mesh_node->get_mesh();
+ mesh_node->set_mesh(editor_mesh->get_mesh());
+ }
+
+ p_node->replace_by(mesh_node);
+ memdelete(p_node);
+ p_node = mesh_node;
+ }
+
+ String type = p_node->get_class();
+
+ if (!has_theme_icon(type, "EditorIcons")) {
+ type = "Node3D";
+ }
+
+ Ref<Texture2D> icon = get_theme_icon(type, "EditorIcons");
+
+ TreeItem *item = scene_tree->create_item(p_parent_item);
+ item->set_text(0, p_node->get_name());
+
+ if (p_node == scene) {
+ icon = get_theme_icon("PackedScene", "EditorIcons");
+ item->set_text(0, "Scene");
+ }
+
+ item->set_icon(0, icon);
+
+ item->set_meta("type", "Node");
+ item->set_meta("class", type);
+ item->set_meta("import_id", import_id);
+ item->set_tooltip(0, vformat(TTR("Type: %s\nImport ID: %s"), type, import_id));
+
+ item->set_selectable(0, true);
+
+ if (!node_map.has(import_id)) {
+ NodeData nd;
+
+ if (p_node != scene) {
+ ResourceImporterScene::InternalImportCategory category;
+ if (src_mesh_node) {
+ category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE;
+ } else if (Object::cast_to<AnimationPlayer>(p_node)) {
+ category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE;
+ } else {
+ category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE;
+ }
+
+ _load_default_subresource_settings(nd.settings, "nodes", import_id, category);
+ }
+
+ node_map[import_id] = nd;
+ }
+ NodeData &node_data = node_map[import_id];
+
+ node_data.node = p_node;
+ node_data.scene_node = item;
+
+ AnimationPlayer *anim_node = Object::cast_to<AnimationPlayer>(p_node);
+ if (anim_node) {
+ List<StringName> animations;
+ anim_node->get_animation_list(&animations);
+ for (List<StringName>::Element *E = animations.front(); E; E = E->next()) {
+ _fill_animation(scene_tree, anim_node->get_animation(E->get()), E->get(), item);
+ }
+ }
+
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _fill_scene(p_node->get_child(i), item);
+ }
+ MeshInstance3D *mesh_node = Object::cast_to<MeshInstance3D>(p_node);
+ if (mesh_node && mesh_node->get_mesh().is_valid()) {
+ _fill_mesh(scene_tree, mesh_node->get_mesh(), item);
+
+ Transform accum_xform;
+ Node3D *base = mesh_node;
+ while (base) {
+ accum_xform = base->get_transform() * accum_xform;
+ base = Object::cast_to<Node3D>(base->get_parent());
+ }
+
+ AABB aabb = accum_xform.xform(mesh_node->get_mesh()->get_aabb());
+ if (first_aabb) {
+ contents_aabb = aabb;
+ first_aabb = false;
+ } else {
+ contents_aabb.merge_with(aabb);
+ }
+ }
+}
+
+void SceneImportSettings::_update_scene() {
+ scene_tree->clear();
+ material_tree->clear();
+ mesh_tree->clear();
+
+ //hiden roots
+ material_tree->create_item();
+ mesh_tree->create_item();
+
+ _fill_scene(scene, nullptr);
+}
+
+void SceneImportSettings::_update_camera() {
+ AABB camera_aabb;
+
+ float rot_x = cam_rot_x;
+ float rot_y = cam_rot_y;
+ float zoom = cam_zoom;
+
+ if (selected_type == "Node" || selected_type == "") {
+ camera_aabb = contents_aabb;
+ } else {
+ if (mesh_preview->get_mesh().is_valid()) {
+ camera_aabb = mesh_preview->get_transform().xform(mesh_preview->get_mesh()->get_aabb());
+ } else {
+ camera_aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
+ }
+ if (selected_type == "Mesh" && mesh_map.has(selected_id)) {
+ const MeshData &md = mesh_map[selected_id];
+ rot_x = md.cam_rot_x;
+ rot_y = md.cam_rot_y;
+ zoom = md.cam_zoom;
+ } else if (selected_type == "Material" && material_map.has(selected_id)) {
+ const MaterialData &md = material_map[selected_id];
+ rot_x = md.cam_rot_x;
+ rot_y = md.cam_rot_y;
+ zoom = md.cam_zoom;
+ }
+ }
+
+ Vector3 center = camera_aabb.position + camera_aabb.size * 0.5;
+ float camera_size = camera_aabb.get_longest_axis_size();
+
+ camera->set_orthogonal(camera_size * zoom, 0.0001, camera_size * 2);
+
+ Transform xf;
+ xf.basis = Basis(Vector3(0, 1, 0), rot_y) * Basis(Vector3(1, 0, 0), rot_x);
+ xf.origin = center;
+ xf.translate(0, 0, camera_size);
+
+ camera->set_transform(xf);
+}
+
+void SceneImportSettings::_load_default_subresource_settings(Map<StringName, Variant> &settings, const String &p_type, const String &p_import_id, ResourceImporterScene::InternalImportCategory p_category) {
+ if (base_subresource_settings.has(p_type)) {
+ Dictionary d = base_subresource_settings[p_type];
+ if (d.has(p_import_id)) {
+ d = d[p_import_id];
+ List<ResourceImporterScene::ImportOption> options;
+ ResourceImporterScene::get_singleton()->get_internal_import_options(p_category, &options);
+ for (List<ResourceImporterScene::ImportOption>::Element *E = options.front(); E; E = E->next()) {
+ String key = E->get().option.name;
+ if (d.has(key)) {
+ settings[key] = d[key];
+ }
+ }
+ }
+ }
+}
+
+void SceneImportSettings::open_settings(const String &p_path) {
+ if (scene) {
+ memdelete(scene);
+ scene = nullptr;
+ }
+ scene = ResourceImporterScene::get_singleton()->pre_import(p_path);
+ if (scene == nullptr) {
+ EditorNode::get_singleton()->show_warning(TTR("Error opening scene"));
+ return;
+ }
+
+ base_path = p_path;
+
+ material_set.clear();
+ mesh_set.clear();
+ material_map.clear();
+ mesh_map.clear();
+ node_map.clear();
+ defaults.clear();
+
+ selected_id = "";
+ selected_type = "";
+
+ cam_rot_x = -Math_PI / 4;
+ cam_rot_y = -Math_PI / 4;
+ cam_zoom = 1;
+
+ {
+ base_subresource_settings.clear();
+
+ Ref<ConfigFile> config;
+ config.instance();
+ Error err = config->load(p_path + ".import");
+ if (err == OK) {
+ List<String> keys;
+ config->get_section_keys("params", &keys);
+ for (List<String>::Element *E = keys.front(); E; E = E->next()) {
+ Variant value = config->get_value("params", E->get());
+ if (E->get() == "_subresources") {
+ base_subresource_settings = value;
+ } else {
+ defaults[E->get()] = value;
+ }
+ }
+ }
+ }
+
+ first_aabb = true;
+
+ _update_scene();
+
+ base_viewport->add_child(scene);
+
+ if (first_aabb) {
+ contents_aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
+ first_aabb = false;
+ }
+
+ popup_centered_ratio();
+ _update_camera();
+
+ set_title(vformat(TTR("Advanced Import Settings for '%s'"), base_path.get_file()));
+}
+
+SceneImportSettings *SceneImportSettings::singleton = nullptr;
+
+SceneImportSettings *SceneImportSettings::get_singleton() {
+ return singleton;
+}
+
+void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) {
+ selecting = true;
+
+ if (p_type == "Node") {
+ node_selected->hide(); //always hide just in case
+ mesh_preview->hide();
+ if (Object::cast_to<Node3D>(scene)) {
+ Object::cast_to<Node3D>(scene)->show();
+ }
+ //NodeData &nd=node_map[p_id];
+ material_tree->deselect_all();
+ mesh_tree->deselect_all();
+ NodeData &nd = node_map[p_id];
+
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(nd.node);
+ if (mi) {
+ Ref<Mesh> base_mesh = mi->get_mesh();
+ if (base_mesh.is_valid()) {
+ AABB aabb = base_mesh->get_aabb();
+ Transform aabb_xf;
+ aabb_xf.basis.scale(aabb.size);
+ aabb_xf.origin = aabb.position;
+
+ aabb_xf = mi->get_global_transform() * aabb_xf;
+ node_selected->set_transform(aabb_xf);
+ node_selected->show();
+ }
+ }
+
+ if (nd.node == scene) {
+ scene_import_settings_data->settings = &defaults;
+ scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX;
+ } else {
+ scene_import_settings_data->settings = &nd.settings;
+ if (mi) {
+ scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE;
+ } else if (Object::cast_to<AnimationPlayer>(nd.node)) {
+ scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE;
+ } else {
+ scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE;
+ }
+ }
+ } else if (p_type == "Animation") {
+ node_selected->hide(); //always hide just in case
+ mesh_preview->hide();
+ if (Object::cast_to<Node3D>(scene)) {
+ Object::cast_to<Node3D>(scene)->show();
+ }
+ //NodeData &nd=node_map[p_id];
+ material_tree->deselect_all();
+ mesh_tree->deselect_all();
+ AnimationData &ad = animation_map[p_id];
+
+ scene_import_settings_data->settings = &ad.settings;
+ scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION;
+ } else if (p_type == "Mesh") {
+ node_selected->hide();
+ if (Object::cast_to<Node3D>(scene)) {
+ Object::cast_to<Node3D>(scene)->hide();
+ }
+
+ MeshData &md = mesh_map[p_id];
+ if (p_from != mesh_tree) {
+ md.mesh_node->uncollapse_tree();
+ md.mesh_node->select(0);
+ mesh_tree->ensure_cursor_is_visible();
+ }
+ if (p_from != scene_tree) {
+ md.scene_node->uncollapse_tree();
+ md.scene_node->select(0);
+ scene_tree->ensure_cursor_is_visible();
+ }
+
+ mesh_preview->set_mesh(md.mesh);
+ mesh_preview->show();
+
+ material_tree->deselect_all();
+
+ scene_import_settings_data->settings = &md.settings;
+ scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH;
+ } else if (p_type == "Material") {
+ node_selected->hide();
+ if (Object::cast_to<Node3D>(scene)) {
+ Object::cast_to<Node3D>(scene)->hide();
+ }
+
+ mesh_preview->show();
+
+ MaterialData &md = material_map[p_id];
+
+ material_preview->set_material(md.material);
+ mesh_preview->set_mesh(material_preview);
+
+ if (p_from != mesh_tree) {
+ md.mesh_node->uncollapse_tree();
+ md.mesh_node->select(0);
+ mesh_tree->ensure_cursor_is_visible();
+ }
+ if (p_from != scene_tree) {
+ md.scene_node->uncollapse_tree();
+ md.scene_node->select(0);
+ scene_tree->ensure_cursor_is_visible();
+ }
+ if (p_from != material_tree) {
+ md.material_node->uncollapse_tree();
+ md.material_node->select(0);
+ material_tree->ensure_cursor_is_visible();
+ }
+
+ scene_import_settings_data->settings = &md.settings;
+ scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MATERIAL;
+ }
+
+ selected_type = p_type;
+ selected_id = p_id;
+
+ selecting = false;
+
+ _update_camera();
+
+ List<ResourceImporter::ImportOption> options;
+
+ if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) {
+ ResourceImporterScene::get_singleton()->get_import_options(&options);
+ } else {
+ ResourceImporterScene::get_singleton()->get_internal_import_options(scene_import_settings_data->category, &options);
+ }
+
+ scene_import_settings_data->defaults.clear();
+ scene_import_settings_data->current.clear();
+
+ for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
+ scene_import_settings_data->defaults[E->get().option.name] = E->get().default_value;
+ //needed for visibility toggling (fails if something is missing)
+ if (scene_import_settings_data->settings->has(E->get().option.name)) {
+ scene_import_settings_data->current[E->get().option.name] = (*scene_import_settings_data->settings)[E->get().option.name];
+ } else {
+ scene_import_settings_data->current[E->get().option.name] = E->get().default_value;
+ }
+ }
+ scene_import_settings_data->options = options;
+ inspector->edit(scene_import_settings_data);
+ scene_import_settings_data->notify_property_list_changed();
+}
+
+void SceneImportSettings::_material_tree_selected() {
+ if (selecting) {
+ return;
+ }
+ TreeItem *item = material_tree->get_selected();
+ String type = item->get_meta("type");
+ String import_id = item->get_meta("import_id");
+
+ _select(material_tree, type, import_id);
+}
+void SceneImportSettings::_mesh_tree_selected() {
+ if (selecting) {
+ return;
+ }
+
+ TreeItem *item = mesh_tree->get_selected();
+ String type = item->get_meta("type");
+ String import_id = item->get_meta("import_id");
+
+ _select(mesh_tree, type, import_id);
+}
+void SceneImportSettings::_scene_tree_selected() {
+ if (selecting) {
+ return;
+ }
+ TreeItem *item = scene_tree->get_selected();
+ String type = item->get_meta("type");
+ String import_id = item->get_meta("import_id");
+
+ _select(scene_tree, type, import_id);
+}
+
+void SceneImportSettings::_viewport_input(const Ref<InputEvent> &p_input) {
+ float *rot_x = &cam_rot_x;
+ float *rot_y = &cam_rot_y;
+ float *zoom = &cam_zoom;
+
+ if (selected_type == "Mesh" && mesh_map.has(selected_id)) {
+ MeshData &md = mesh_map[selected_id];
+ rot_x = &md.cam_rot_x;
+ rot_y = &md.cam_rot_y;
+ zoom = &md.cam_zoom;
+ } else if (selected_type == "Material" && material_map.has(selected_id)) {
+ MaterialData &md = material_map[selected_id];
+ rot_x = &md.cam_rot_x;
+ rot_y = &md.cam_rot_y;
+ zoom = &md.cam_zoom;
+ }
+ Ref<InputEventMouseMotion> mm = p_input;
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
+ (*rot_x) -= mm->get_relative().y * 0.01 * EDSCALE;
+ (*rot_y) -= mm->get_relative().x * 0.01 * EDSCALE;
+ (*rot_x) = CLAMP((*rot_x), -Math_PI / 2, Math_PI / 2);
+ _update_camera();
+ }
+ Ref<InputEventMouseButton> mb = p_input;
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
+ (*zoom) *= 1.1;
+ if ((*zoom) > 10.0) {
+ (*zoom) = 10.0;
+ }
+ _update_camera();
+ }
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
+ (*zoom) /= 1.1;
+ if ((*zoom) < 0.1) {
+ (*zoom) = 0.1;
+ }
+ _update_camera();
+ }
+}
+
+void SceneImportSettings::_re_import() {
+ Map<StringName, Variant> main_settings;
+
+ main_settings = defaults;
+ main_settings.erase("_subresources");
+ Dictionary nodes;
+ Dictionary materials;
+ Dictionary meshes;
+ Dictionary animations;
+
+ Dictionary subresources;
+
+ for (Map<String, NodeData>::Element *E = node_map.front(); E; E = E->next()) {
+ if (E->get().settings.size()) {
+ Dictionary d;
+ for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) {
+ d[String(F->key())] = F->get();
+ }
+ nodes[E->key()] = d;
+ }
+ }
+ if (nodes.size()) {
+ subresources["nodes"] = nodes;
+ }
+
+ for (Map<String, MaterialData>::Element *E = material_map.front(); E; E = E->next()) {
+ if (E->get().settings.size()) {
+ Dictionary d;
+ for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) {
+ d[String(F->key())] = F->get();
+ }
+ materials[E->key()] = d;
+ }
+ }
+ if (materials.size()) {
+ subresources["materials"] = materials;
+ }
+
+ for (Map<String, MeshData>::Element *E = mesh_map.front(); E; E = E->next()) {
+ if (E->get().settings.size()) {
+ Dictionary d;
+ for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) {
+ d[String(F->key())] = F->get();
+ }
+ meshes[E->key()] = d;
+ }
+ }
+ if (meshes.size()) {
+ subresources["meshes"] = meshes;
+ }
+
+ for (Map<String, AnimationData>::Element *E = animation_map.front(); E; E = E->next()) {
+ if (E->get().settings.size()) {
+ Dictionary d;
+ for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) {
+ d[String(F->key())] = F->get();
+ }
+ animations[E->key()] = d;
+ }
+ }
+ if (animations.size()) {
+ subresources["animations"] = animations;
+ }
+
+ if (subresources.size()) {
+ main_settings["_subresources"] = subresources;
+ }
+
+ EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(base_path, "scene", main_settings);
+}
+
+void SceneImportSettings::_notification(int p_what) {
+ if (p_what == NOTIFICATION_READY) {
+ connect("confirmed", callable_mp(this, &SceneImportSettings::_re_import));
+ }
+}
+
+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"));
+ 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"));
+ 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"));
+ external_extension_type->select(1);
+ } break;
+ }
+
+ save_path->set_current_dir(base_path.get_base_dir());
+ current_action = p_id;
+ save_path->popup_centered_ratio();
+}
+
+void SceneImportSettings::_save_path_changed(const String &p_path) {
+ save_path_item->set_text(1, p_path);
+
+ if (FileAccess::exists(p_path)) {
+ save_path_item->set_text(2, "Warning: File exists");
+ save_path_item->set_tooltip(2, TTR("Existing file with the same name will be replaced."));
+ save_path_item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons"));
+
+ } else {
+ save_path_item->set_text(2, "Will create new File");
+ save_path_item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons"));
+ }
+}
+
+void SceneImportSettings::_browse_save_callback(Object *p_item, int p_column, int p_id) {
+ TreeItem *item = Object::cast_to<TreeItem>(p_item);
+
+ String path = item->get_text(1);
+
+ item_save_path->set_current_file(path);
+ save_path_item = item;
+
+ item_save_path->popup_centered_ratio();
+}
+
+void SceneImportSettings::_save_dir_callback(const String &p_path) {
+ external_path_tree->clear();
+ TreeItem *root = external_path_tree->create_item();
+ save_path_items.clear();
+
+ switch (current_action) {
+ case ACTION_EXTRACT_MATERIALS: {
+ for (Map<String, MaterialData>::Element *E = material_map.front(); E; E = E->next()) {
+ MaterialData &md = material_map[E->key()];
+
+ TreeItem *item = external_path_tree->create_item(root);
+
+ String name = md.material_node->get_text(0);
+
+ item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ item->set_icon(0, get_theme_icon("StandardMaterial3D", "EditorIcons"));
+ item->set_text(0, name);
+
+ if (md.has_import_id) {
+ if (md.settings.has("use_external/enabled") && bool(md.settings["use_external/enabled"])) {
+ item->set_text(2, "Already External");
+ item->set_tooltip(2, TTR("This material already references an external file, no action will be taken.\nDisable the external property for it to be extracted again."));
+ } else {
+ item->set_metadata(0, E->key());
+ item->set_editable(0, true);
+ item->set_checked(0, true);
+ String path = p_path.plus_file(name);
+ if (external_extension_type->get_selected() == 0) {
+ path += ".tres";
+ } else {
+ path += ".res";
+ }
+
+ item->set_text(1, path);
+ if (FileAccess::exists(path)) {
+ item->set_text(2, "Warning: File exists");
+ item->set_tooltip(2, TTR("Existing file with the same name will be replaced."));
+ item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons"));
+
+ } else {
+ item->set_text(2, "Will create new File");
+ item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons"));
+ }
+
+ item->add_button(1, get_theme_icon("Folder", "EditorIcons"));
+ }
+
+ } else {
+ item->set_text(2, "No import ID");
+ item->set_tooltip(2, TTR("Material has no name nor any other way to identify on re-import.\nPlease name it or ensure it is exported with an unique ID."));
+ item->set_icon(2, get_theme_icon("StatusError", "EditorIcons"));
+ }
+
+ save_path_items.push_back(item);
+ }
+
+ external_paths->set_title(TTR("Extract Materials to Resource Files"));
+ external_paths->get_ok_button()->set_text(TTR("Extract"));
+ } break;
+ case ACTION_CHOOSE_MESH_SAVE_PATHS: {
+ for (Map<String, MeshData>::Element *E = mesh_map.front(); E; E = E->next()) {
+ MeshData &md = mesh_map[E->key()];
+
+ TreeItem *item = external_path_tree->create_item(root);
+
+ String name = md.mesh_node->get_text(0);
+
+ item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ item->set_icon(0, get_theme_icon("Mesh", "EditorIcons"));
+ item->set_text(0, name);
+
+ if (md.has_import_id) {
+ if (md.settings.has("save_to_file/enabled") && bool(md.settings["save_to_file/enabled"])) {
+ item->set_text(2, "Already Saving");
+ item->set_tooltip(2, TTR("This mesh already saves to an external resource, no action will be taken."));
+ } else {
+ item->set_metadata(0, E->key());
+ item->set_editable(0, true);
+ item->set_checked(0, true);
+ String path = p_path.plus_file(name);
+ if (external_extension_type->get_selected() == 0) {
+ path += ".tres";
+ } else {
+ path += ".res";
+ }
+
+ item->set_text(1, path);
+ if (FileAccess::exists(path)) {
+ item->set_text(2, "Warning: File exists");
+ item->set_tooltip(2, TTR("Existing file with the same name will be replaced on import."));
+ item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons"));
+
+ } else {
+ item->set_text(2, "Will save to new File");
+ item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons"));
+ }
+
+ item->add_button(1, get_theme_icon("Folder", "EditorIcons"));
+ }
+
+ } else {
+ item->set_text(2, "No import ID");
+ item->set_tooltip(2, TTR("Mesh has no name nor any other way to identify on re-import.\nPlease name it or ensure it is exported with an unique ID."));
+ item->set_icon(2, get_theme_icon("StatusError", "EditorIcons"));
+ }
+
+ save_path_items.push_back(item);
+ }
+
+ external_paths->set_title(TTR("Set paths to save meshes as resource files on Reimport"));
+ external_paths->get_ok_button()->set_text(TTR("Set Paths"));
+ } break;
+ case ACTION_CHOOSE_ANIMATION_SAVE_PATHS: {
+ for (Map<String, AnimationData>::Element *E = animation_map.front(); E; E = E->next()) {
+ AnimationData &ad = animation_map[E->key()];
+
+ TreeItem *item = external_path_tree->create_item(root);
+
+ String name = ad.scene_node->get_text(0);
+
+ item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ item->set_icon(0, get_theme_icon("Animation", "EditorIcons"));
+ item->set_text(0, name);
+
+ if (ad.settings.has("save_to_file/enabled") && bool(ad.settings["save_to_file/enabled"])) {
+ item->set_text(2, "Already Saving");
+ item->set_tooltip(2, TTR("This animation already saves to an external resource, no action will be taken."));
+ } else {
+ item->set_metadata(0, E->key());
+ item->set_editable(0, true);
+ item->set_checked(0, true);
+ String path = p_path.plus_file(name);
+ if (external_extension_type->get_selected() == 0) {
+ path += ".tres";
+ } else {
+ path += ".res";
+ }
+
+ item->set_text(1, path);
+ if (FileAccess::exists(path)) {
+ item->set_text(2, "Warning: File exists");
+ item->set_tooltip(2, TTR("Existing file with the same name will be replaced on import."));
+ item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons"));
+
+ } else {
+ item->set_text(2, "Will save to new File");
+ item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons"));
+ }
+
+ item->add_button(1, get_theme_icon("Folder", "EditorIcons"));
+ }
+
+ save_path_items.push_back(item);
+ }
+
+ external_paths->set_title(TTR("Set paths to save animations as resource files on Reimport"));
+ external_paths->get_ok_button()->set_text(TTR("Set Paths"));
+
+ } break;
+ }
+
+ external_paths->popup_centered_ratio();
+}
+
+void SceneImportSettings::_save_dir_confirm() {
+ for (int i = 0; i < save_path_items.size(); i++) {
+ TreeItem *item = save_path_items[i];
+ if (!item->is_checked(0)) {
+ continue; //ignore
+ }
+ String path = item->get_text(1);
+ if (!path.is_resource_file()) {
+ continue;
+ }
+
+ String id = item->get_metadata(0);
+
+ switch (current_action) {
+ case ACTION_EXTRACT_MATERIALS: {
+ ERR_CONTINUE(!material_map.has(id));
+ MaterialData &md = material_map[id];
+
+ Error err = ResourceSaver::save(path, md.material);
+ if (err != OK) {
+ EditorNode::get_singleton()->add_io_error(TTR("Can't make material external to file, write error:") + "\n\t" + path);
+ continue;
+ }
+
+ md.settings["use_external/enabled"] = true;
+ md.settings["use_external/path"] = path;
+
+ } break;
+ case ACTION_CHOOSE_MESH_SAVE_PATHS: {
+ ERR_CONTINUE(!mesh_map.has(id));
+ MeshData &md = mesh_map[id];
+
+ md.settings["save_to_file/enabled"] = true;
+ md.settings["save_to_file/path"] = path;
+ } break;
+ case ACTION_CHOOSE_ANIMATION_SAVE_PATHS: {
+ ERR_CONTINUE(!animation_map.has(id));
+ AnimationData &ad = animation_map[id];
+
+ ad.settings["save_to_file/enabled"] = true;
+ ad.settings["save_to_file/path"] = path;
+
+ } break;
+ }
+ }
+
+ if (current_action == ACTION_EXTRACT_MATERIALS) {
+ //as this happens right now, the scene needs to be saved and reimported.
+ _re_import();
+ open_settings(base_path);
+ } else {
+ scene_import_settings_data->notify_property_list_changed();
+ }
+}
+
+SceneImportSettings::SceneImportSettings() {
+ singleton = this;
+
+ VBoxContainer *main_vb = memnew(VBoxContainer);
+ add_child(main_vb);
+ HBoxContainer *menu_hb = memnew(HBoxContainer);
+ main_vb->add_child(menu_hb);
+
+ action_menu = memnew(MenuButton);
+ action_menu->set_text(TTR("Actions..."));
+ menu_hb->add_child(action_menu);
+
+ action_menu->get_popup()->add_item(TTR("Extract Materials"), ACTION_EXTRACT_MATERIALS);
+ action_menu->get_popup()->add_separator();
+ action_menu->get_popup()->add_item(TTR("Set Animation Save Paths"), ACTION_CHOOSE_ANIMATION_SAVE_PATHS);
+ action_menu->get_popup()->add_item(TTR("Set Mesh Save Paths"), ACTION_CHOOSE_MESH_SAVE_PATHS);
+
+ action_menu->get_popup()->connect("id_pressed", callable_mp(this, &SceneImportSettings::_menu_callback));
+
+ tree_split = memnew(HSplitContainer);
+ main_vb->add_child(tree_split);
+ tree_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+
+ data_mode = memnew(TabContainer);
+ tree_split->add_child(data_mode);
+ data_mode->set_custom_minimum_size(Size2(300 * EDSCALE, 0));
+
+ property_split = memnew(HSplitContainer);
+ tree_split->add_child(property_split);
+ property_split->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+ scene_tree = memnew(Tree);
+ scene_tree->set_name(TTR("Scene"));
+ data_mode->add_child(scene_tree);
+ scene_tree->connect("cell_selected", callable_mp(this, &SceneImportSettings::_scene_tree_selected));
+
+ mesh_tree = memnew(Tree);
+ mesh_tree->set_name(TTR("Meshes"));
+ data_mode->add_child(mesh_tree);
+ mesh_tree->set_hide_root(true);
+ mesh_tree->connect("cell_selected", callable_mp(this, &SceneImportSettings::_mesh_tree_selected));
+
+ material_tree = memnew(Tree);
+ material_tree->set_name(TTR("Materials"));
+ data_mode->add_child(material_tree);
+ material_tree->connect("cell_selected", callable_mp(this, &SceneImportSettings::_material_tree_selected));
+
+ material_tree->set_hide_root(true);
+
+ SubViewportContainer *vp_container = memnew(SubViewportContainer);
+ vp_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ vp_container->set_custom_minimum_size(Size2(10, 10));
+ vp_container->set_stretch(true);
+ vp_container->connect("gui_input", callable_mp(this, &SceneImportSettings::_viewport_input));
+ property_split->add_child(vp_container);
+
+ base_viewport = memnew(SubViewport);
+ vp_container->add_child(base_viewport);
+
+ base_viewport->set_use_own_world_3d(true);
+
+ camera = memnew(Camera3D);
+ base_viewport->add_child(camera);
+ camera->make_current();
+
+ light = memnew(DirectionalLight3D);
+ light->set_transform(Transform().looking_at(Vector3(-1, -2, -0.6), Vector3(0, 1, 0)));
+ base_viewport->add_child(light);
+ light->set_shadow(true);
+
+ {
+ Ref<StandardMaterial3D> selection_mat;
+ selection_mat.instance();
+ selection_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ selection_mat->set_albedo(Color(1, 0.8, 1.0));
+
+ Ref<SurfaceTool> st;
+ st.instance();
+ st->begin(Mesh::PRIMITIVE_LINES);
+
+ AABB base_aabb;
+ base_aabb.size = Vector3(1, 1, 1);
+
+ for (int i = 0; i < 12; i++) {
+ Vector3 a, b;
+ base_aabb.get_edge(i, a, b);
+
+ st->add_vertex(a);
+ st->add_vertex(a.lerp(b, 0.2));
+ st->add_vertex(b);
+ st->add_vertex(b.lerp(a, 0.2));
+ }
+
+ selection_mesh.instance();
+ st->commit(selection_mesh);
+ selection_mesh->surface_set_material(0, selection_mat);
+
+ node_selected = memnew(MeshInstance3D);
+ node_selected->set_mesh(selection_mesh);
+ base_viewport->add_child(node_selected);
+ node_selected->hide();
+ }
+
+ {
+ mesh_preview = memnew(MeshInstance3D);
+ base_viewport->add_child(mesh_preview);
+ mesh_preview->hide();
+
+ material_preview.instance();
+ }
+
+ inspector = memnew(EditorInspector);
+ inspector->set_custom_minimum_size(Size2(300 * EDSCALE, 0));
+
+ property_split->add_child(inspector);
+
+ scene_import_settings_data = memnew(SceneImportSettingsData);
+
+ get_ok_button()->set_text(TTR("Reimport"));
+ get_cancel_button()->set_text(TTR("Close"));
+
+ external_paths = memnew(ConfirmationDialog);
+ add_child(external_paths);
+ external_path_tree = memnew(Tree);
+ external_paths->add_child(external_path_tree);
+ external_path_tree->connect("button_pressed", callable_mp(this, &SceneImportSettings::_browse_save_callback));
+ external_paths->connect("confirmed", callable_mp(this, &SceneImportSettings::_save_dir_confirm));
+ external_path_tree->set_columns(3);
+ external_path_tree->set_column_titles_visible(true);
+ external_path_tree->set_column_expand(0, true);
+ external_path_tree->set_column_min_width(0, 100 * EDSCALE);
+ external_path_tree->set_column_title(0, TTR("Resource"));
+ external_path_tree->set_column_expand(1, true);
+ external_path_tree->set_column_min_width(1, 100 * EDSCALE);
+ external_path_tree->set_column_title(1, TTR("Path"));
+ external_path_tree->set_column_expand(2, false);
+ external_path_tree->set_column_min_width(2, 200 * EDSCALE);
+ external_path_tree->set_column_title(2, TTR("Status"));
+ save_path = memnew(EditorFileDialog);
+ save_path->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR);
+ HBoxContainer *extension_hb = memnew(HBoxContainer);
+ save_path->get_vbox()->add_child(extension_hb);
+ extension_hb->add_spacer();
+ extension_hb->add_child(memnew(Label(TTR("Save Extension: "))));
+ external_extension_type = memnew(OptionButton);
+ extension_hb->add_child(external_extension_type);
+ external_extension_type->add_item(TTR("Text: *.tres"));
+ external_extension_type->add_item(TTR("Binary: *.res"));
+ external_path_tree->set_hide_root(true);
+ add_child(save_path);
+
+ item_save_path = memnew(EditorFileDialog);
+ item_save_path->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
+ item_save_path->add_filter("*.tres;Text Resource");
+ item_save_path->add_filter("*.res;Binary Resource");
+ add_child(item_save_path);
+ item_save_path->connect("file_selected", callable_mp(this, &SceneImportSettings::_save_path_changed));
+
+ save_path->connect("dir_selected", callable_mp(this, &SceneImportSettings::_save_dir_callback));
+}
+
+SceneImportSettings::~SceneImportSettings() {
+ memdelete(scene_import_settings_data);
+}
diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h
new file mode 100644
index 0000000000..ddcf4a6d5d
--- /dev/null
+++ b/editor/import/scene_import_settings.h
@@ -0,0 +1,199 @@
+/*************************************************************************/
+/* scene_import_settings.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 SCENEIMPORTSETTINGS_H
+#define SCENEIMPORTSETTINGS_H
+
+#include "editor/editor_file_dialog.h"
+#include "editor/editor_inspector.h"
+#include "editor/import/resource_importer_scene.h"
+#include "scene/3d/camera_3d.h"
+#include "scene/3d/light_3d.h"
+#include "scene/3d/mesh_instance_3d.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/item_list.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/subviewport_container.h"
+#include "scene/gui/tab_container.h"
+#include "scene/gui/tree.h"
+#include "scene/resources/primitive_meshes.h"
+
+class SceneImportSettingsData;
+
+class SceneImportSettings : public ConfirmationDialog {
+ GDCLASS(SceneImportSettings, ConfirmationDialog)
+
+ static SceneImportSettings *singleton;
+
+ enum Actions {
+ ACTION_EXTRACT_MATERIALS,
+ ACTION_CHOOSE_MESH_SAVE_PATHS,
+ ACTION_CHOOSE_ANIMATION_SAVE_PATHS,
+ };
+
+ Node *scene = nullptr;
+
+ HSplitContainer *tree_split;
+ HSplitContainer *property_split;
+ TabContainer *data_mode;
+ Tree *scene_tree;
+ Tree *mesh_tree;
+ Tree *material_tree;
+
+ EditorInspector *inspector;
+
+ SubViewport *base_viewport;
+
+ Camera3D *camera;
+ bool first_aabb = false;
+ AABB contents_aabb;
+
+ DirectionalLight3D *light;
+ Ref<ArrayMesh> selection_mesh;
+ MeshInstance3D *node_selected;
+
+ MeshInstance3D *mesh_preview;
+ Ref<SphereMesh> material_preview;
+
+ float cam_rot_x;
+ float cam_rot_y;
+ float cam_zoom;
+
+ void _update_scene();
+
+ struct MaterialData {
+ bool has_import_id;
+ Ref<Material> material;
+ TreeItem *scene_node;
+ TreeItem *mesh_node;
+ TreeItem *material_node;
+
+ float cam_rot_x = -Math_PI / 4;
+ float cam_rot_y = -Math_PI / 4;
+ float cam_zoom = 1;
+
+ Map<StringName, Variant> settings;
+ };
+ Map<String, MaterialData> material_map;
+
+ struct MeshData {
+ bool has_import_id;
+ Ref<Mesh> mesh;
+ TreeItem *scene_node;
+ TreeItem *mesh_node;
+
+ float cam_rot_x = -Math_PI / 4;
+ float cam_rot_y = -Math_PI / 4;
+ float cam_zoom = 1;
+ Map<StringName, Variant> settings;
+ };
+ Map<String, MeshData> mesh_map;
+
+ struct AnimationData {
+ Ref<Animation> animation;
+ TreeItem *scene_node;
+ Map<StringName, Variant> settings;
+ };
+ Map<String, AnimationData> animation_map;
+
+ struct NodeData {
+ Node *node;
+ TreeItem *scene_node;
+ Map<StringName, Variant> settings;
+ };
+ Map<String, NodeData> node_map;
+
+ void _fill_material(Tree *p_tree, const Ref<Material> &p_material, TreeItem *p_parent);
+ void _fill_mesh(Tree *p_tree, const Ref<Mesh> &p_mesh, TreeItem *p_parent);
+ void _fill_animation(Tree *p_tree, const Ref<Animation> &p_anim, const String &p_name, TreeItem *p_parent);
+ void _fill_scene(Node *p_node, TreeItem *p_parent_item);
+
+ Set<Ref<Mesh>> mesh_set;
+ Set<Ref<Material>> material_set;
+
+ String selected_type;
+ String selected_id;
+
+ bool selecting = false;
+
+ void _update_camera();
+ void _select(Tree *p_from, String p_type, String p_id);
+ void _material_tree_selected();
+ void _mesh_tree_selected();
+ void _scene_tree_selected();
+
+ void _viewport_input(const Ref<InputEvent> &p_input);
+
+ Map<StringName, Variant> defaults;
+
+ SceneImportSettingsData *scene_import_settings_data;
+
+ void _re_import();
+
+ String base_path;
+
+ MenuButton *action_menu;
+
+ ConfirmationDialog *external_paths;
+ Tree *external_path_tree;
+ EditorFileDialog *save_path;
+ OptionButton *external_extension_type;
+
+ EditorFileDialog *item_save_path;
+
+ void _menu_callback(int p_id);
+ void _save_dir_callback(const String &p_path);
+
+ int current_action;
+
+ Vector<TreeItem *> save_path_items;
+
+ TreeItem *save_path_item = nullptr;
+ void _save_path_changed(const String &p_path);
+ void _browse_save_callback(Object *p_item, int p_column, int p_id);
+ void _save_dir_confirm();
+
+ Dictionary base_subresource_settings;
+
+ void _load_default_subresource_settings(Map<StringName, Variant> &settings, const String &p_type, const String &p_import_id, ResourceImporterScene::InternalImportCategory p_category);
+
+protected:
+ void _notification(int p_what);
+
+public:
+ void open_settings(const String &p_path);
+ static SceneImportSettings *get_singleton();
+ SceneImportSettings();
+ ~SceneImportSettings();
+};
+
+#endif // SCENEIMPORTSETTINGS_H
diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp
index 78a7cd84f1..28fdd4ddbd 100644
--- a/editor/import/scene_importer_mesh.cpp
+++ b/editor/import/scene_importer_mesh.cpp
@@ -136,6 +136,11 @@ Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const
return surfaces[p_surface].material;
}
+void EditorSceneImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_material) {
+ ERR_FAIL_INDEX(p_surface, surfaces.size());
+ surfaces.write[p_surface].material = p_material;
+}
+
void EditorSceneImporterMesh::generate_lods() {
if (!SurfaceTool::simplify_func) {
return;
@@ -219,11 +224,20 @@ bool EditorSceneImporterMesh::has_mesh() const {
return mesh.is_valid();
}
-Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh() {
+Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh(const Ref<Mesh> &p_base) {
ERR_FAIL_COND_V(surfaces.size() == 0, Ref<ArrayMesh>());
if (mesh.is_null()) {
- mesh.instance();
+ if (p_base.is_valid()) {
+ mesh = p_base;
+ }
+ if (mesh.is_null()) {
+ mesh.instance();
+ }
+ mesh->set_name(get_name());
+ if (has_meta("import_id")) {
+ mesh->set_meta("import_id", get_meta("import_id"));
+ }
for (int i = 0; i < blend_shapes.size(); i++) {
mesh->add_blend_shape(blend_shapes[i]);
}
@@ -251,6 +265,8 @@ Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh() {
}
}
+ mesh->set_lightmap_size_hint(lightmap_size_hint);
+
if (shadow_mesh.is_valid()) {
Ref<ArrayMesh> shadow = shadow_mesh->get_mesh();
mesh->set_shadow_mesh(shadow);
@@ -436,6 +452,338 @@ Dictionary EditorSceneImporterMesh::_get_data() const {
return data;
}
+Vector<Face3> EditorSceneImporterMesh::get_faces() const {
+ Vector<Face3> faces;
+ for (int i = 0; i < surfaces.size(); i++) {
+ if (surfaces[i].primitive == Mesh::PRIMITIVE_TRIANGLES) {
+ Vector<Vector3> vertices = surfaces[i].arrays[Mesh::ARRAY_VERTEX];
+ Vector<int> indices = surfaces[i].arrays[Mesh::ARRAY_INDEX];
+ if (indices.size()) {
+ for (int j = 0; j < indices.size(); j += 3) {
+ Face3 f;
+ f.vertex[0] = vertices[indices[j + 0]];
+ f.vertex[1] = vertices[indices[j + 1]];
+ f.vertex[2] = vertices[indices[j + 2]];
+ faces.push_back(f);
+ }
+ } else {
+ for (int j = 0; j < vertices.size(); j += 3) {
+ Face3 f;
+ f.vertex[0] = vertices[j + 0];
+ f.vertex[1] = vertices[j + 1];
+ f.vertex[2] = vertices[j + 2];
+ faces.push_back(f);
+ }
+ }
+ }
+ }
+
+ return faces;
+}
+
+Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose() const {
+ ERR_FAIL_COND_V(!Mesh::convex_composition_function, Vector<Ref<Shape3D>>());
+
+ const Vector<Face3> faces = get_faces();
+
+ Vector<Vector<Face3>> decomposed = Mesh::convex_composition_function(faces);
+
+ Vector<Ref<Shape3D>> ret;
+
+ for (int i = 0; i < decomposed.size(); i++) {
+ Set<Vector3> points;
+ for (int j = 0; j < decomposed[i].size(); j++) {
+ points.insert(decomposed[i][j].vertex[0]);
+ points.insert(decomposed[i][j].vertex[1]);
+ points.insert(decomposed[i][j].vertex[2]);
+ }
+
+ Vector<Vector3> convex_points;
+ convex_points.resize(points.size());
+ {
+ Vector3 *w = convex_points.ptrw();
+ int idx = 0;
+ for (Set<Vector3>::Element *E = points.front(); E; E = E->next()) {
+ w[idx++] = E->get();
+ }
+ }
+
+ Ref<ConvexPolygonShape3D> shape;
+ shape.instance();
+ shape->set_points(convex_points);
+ ret.push_back(shape);
+ }
+
+ return ret;
+}
+
+Ref<Shape3D> EditorSceneImporterMesh::create_trimesh_shape() const {
+ Vector<Face3> faces = get_faces();
+ if (faces.size() == 0) {
+ return Ref<Shape3D>();
+ }
+
+ Vector<Vector3> face_points;
+ face_points.resize(faces.size() * 3);
+
+ for (int i = 0; i < face_points.size(); i += 3) {
+ Face3 f = faces.get(i / 3);
+ face_points.set(i, f.vertex[0]);
+ face_points.set(i + 1, f.vertex[1]);
+ face_points.set(i + 2, f.vertex[2]);
+ }
+
+ Ref<ConcavePolygonShape3D> shape = memnew(ConcavePolygonShape3D);
+ shape->set_faces(face_points);
+ return shape;
+}
+
+Ref<NavigationMesh> EditorSceneImporterMesh::create_navigation_mesh() {
+ Vector<Face3> faces = get_faces();
+ if (faces.size() == 0) {
+ return Ref<NavigationMesh>();
+ }
+
+ Map<Vector3, int> unique_vertices;
+ LocalVector<int> face_indices;
+
+ for (int i = 0; i < faces.size(); i++) {
+ for (int j = 0; j < 3; j++) {
+ Vector3 v = faces[i].vertex[j];
+ int idx;
+ if (unique_vertices.has(v)) {
+ idx = unique_vertices[v];
+ } else {
+ idx = unique_vertices.size();
+ unique_vertices[v] = idx;
+ }
+ face_indices.push_back(idx);
+ }
+ }
+
+ Vector<Vector3> vertices;
+ vertices.resize(unique_vertices.size());
+ for (Map<Vector3, int>::Element *E = unique_vertices.front(); E; E = E->next()) {
+ vertices.write[E->get()] = E->key();
+ }
+
+ Ref<NavigationMesh> nm;
+ nm.instance();
+ nm->set_vertices(vertices);
+
+ Vector<int> v3;
+ v3.resize(3);
+ for (uint32_t i = 0; i < face_indices.size(); i += 3) {
+ v3.write[0] = face_indices[i + 0];
+ v3.write[1] = face_indices[i + 1];
+ v3.write[2] = face_indices[i + 2];
+ nm->add_polygon(v3);
+ }
+
+ return nm;
+}
+
+extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y, int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache);
+
+struct EditorSceneImporterMeshLightmapSurface {
+ Ref<Material> material;
+ LocalVector<SurfaceTool::Vertex> vertices;
+ Mesh::PrimitiveType primitive = Mesh::PrimitiveType::PRIMITIVE_MAX;
+ uint32_t format = 0;
+ String name;
+};
+
+Error EditorSceneImporterMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform, float p_texel_size) {
+ ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes.");
+
+ Vector<float> vertices;
+ Vector<float> normals;
+ Vector<int> indices;
+ Vector<float> uv;
+ Vector<Pair<int, int>> uv_indices;
+
+ Vector<EditorSceneImporterMeshLightmapSurface> lightmap_surfaces;
+
+ // Keep only the scale
+ Transform transform = p_base_transform;
+ transform.origin = Vector3();
+ transform.looking_at(Vector3(1, 0, 0), Vector3(0, 1, 0));
+
+ Basis normal_basis = transform.basis.inverse().transposed();
+
+ for (int i = 0; i < get_surface_count(); i++) {
+ EditorSceneImporterMeshLightmapSurface s;
+ s.primitive = get_surface_primitive_type(i);
+
+ ERR_FAIL_COND_V_MSG(s.primitive != Mesh::PRIMITIVE_TRIANGLES, ERR_UNAVAILABLE, "Only triangles are supported for lightmap unwrap.");
+ Array arrays = get_surface_arrays(i);
+ s.material = get_surface_material(i);
+ s.name = get_surface_name(i);
+
+ SurfaceTool::create_vertex_array_from_triangle_arrays(arrays, s.vertices, &s.format);
+
+ Vector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX];
+ int vc = rvertices.size();
+ const Vector3 *r = rvertices.ptr();
+
+ Vector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL];
+
+ ERR_FAIL_COND_V_MSG(rnormals.size() == 0, ERR_UNAVAILABLE, "Normals are required for lightmap unwrap.");
+
+ const Vector3 *rn = rnormals.ptr();
+
+ int vertex_ofs = vertices.size() / 3;
+
+ vertices.resize((vertex_ofs + vc) * 3);
+ normals.resize((vertex_ofs + vc) * 3);
+ uv_indices.resize(vertex_ofs + vc);
+
+ for (int j = 0; j < vc; j++) {
+ Vector3 v = transform.xform(r[j]);
+ Vector3 n = normal_basis.xform(rn[j]).normalized();
+
+ vertices.write[(j + vertex_ofs) * 3 + 0] = v.x;
+ vertices.write[(j + vertex_ofs) * 3 + 1] = v.y;
+ vertices.write[(j + vertex_ofs) * 3 + 2] = v.z;
+ normals.write[(j + vertex_ofs) * 3 + 0] = n.x;
+ normals.write[(j + vertex_ofs) * 3 + 1] = n.y;
+ normals.write[(j + vertex_ofs) * 3 + 2] = n.z;
+ uv_indices.write[j + vertex_ofs] = Pair<int, int>(i, j);
+ }
+
+ Vector<int> rindices = arrays[Mesh::ARRAY_INDEX];
+ int ic = rindices.size();
+
+ if (ic == 0) {
+ for (int j = 0; j < vc / 3; j++) {
+ if (Face3(r[j * 3 + 0], r[j * 3 + 1], r[j * 3 + 2]).is_degenerate()) {
+ continue;
+ }
+
+ indices.push_back(vertex_ofs + j * 3 + 0);
+ indices.push_back(vertex_ofs + j * 3 + 1);
+ indices.push_back(vertex_ofs + j * 3 + 2);
+ }
+
+ } else {
+ const int *ri = rindices.ptr();
+
+ for (int j = 0; j < ic / 3; j++) {
+ if (Face3(r[ri[j * 3 + 0]], r[ri[j * 3 + 1]], r[ri[j * 3 + 2]]).is_degenerate()) {
+ continue;
+ }
+ indices.push_back(vertex_ofs + ri[j * 3 + 0]);
+ indices.push_back(vertex_ofs + ri[j * 3 + 1]);
+ indices.push_back(vertex_ofs + ri[j * 3 + 2]);
+ }
+ }
+
+ lightmap_surfaces.push_back(s);
+ }
+
+ //unwrap
+
+ float *gen_uvs;
+ int *gen_vertices;
+ int *gen_indices;
+ int gen_vertex_count;
+ int gen_index_count;
+ int size_x;
+ int size_y;
+
+ bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y, r_cache_data, r_cache_size, r_used_cache);
+
+ if (!ok) {
+ return ERR_CANT_CREATE;
+ }
+
+ //remove surfaces
+ clear();
+
+ //create surfacetools for each surface..
+ Vector<Ref<SurfaceTool>> surfaces_tools;
+
+ for (int i = 0; i < lightmap_surfaces.size(); i++) {
+ Ref<SurfaceTool> st;
+ st.instance();
+ st->begin(Mesh::PRIMITIVE_TRIANGLES);
+ st->set_material(lightmap_surfaces[i].material);
+ st->set_meta("name", lightmap_surfaces[i].name);
+ surfaces_tools.push_back(st); //stay there
+ }
+
+ print_verbose("Mesh: Gen indices: " + itos(gen_index_count));
+ //go through all indices
+ for (int i = 0; i < gen_index_count; i += 3) {
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_indices.size(), ERR_BUG);
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_indices.size(), ERR_BUG);
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_indices.size(), ERR_BUG);
+
+ ERR_FAIL_COND_V(uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 1]]].first || uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG);
+
+ int surface = uv_indices[gen_vertices[gen_indices[i + 0]]].first;
+
+ for (int j = 0; j < 3; j++) {
+ SurfaceTool::Vertex v = lightmap_surfaces[surface].vertices[uv_indices[gen_vertices[gen_indices[i + j]]].second];
+
+ if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_COLOR) {
+ surfaces_tools.write[surface]->set_color(v.color);
+ }
+ if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_TEX_UV) {
+ surfaces_tools.write[surface]->set_uv(v.uv);
+ }
+ if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_NORMAL) {
+ surfaces_tools.write[surface]->set_normal(v.normal);
+ }
+ if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_TANGENT) {
+ Plane t;
+ t.normal = v.tangent;
+ t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1;
+ surfaces_tools.write[surface]->set_tangent(t);
+ }
+ if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_BONES) {
+ surfaces_tools.write[surface]->set_bones(v.bones);
+ }
+ if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_WEIGHTS) {
+ surfaces_tools.write[surface]->set_weights(v.weights);
+ }
+
+ Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]);
+ surfaces_tools.write[surface]->set_uv2(uv2);
+
+ surfaces_tools.write[surface]->add_vertex(v.vertex);
+ }
+ }
+
+ //generate surfaces
+
+ for (int i = 0; i < surfaces_tools.size(); i++) {
+ surfaces_tools.write[i]->index();
+ Array arrays = surfaces_tools.write[i]->commit_to_arrays();
+ add_surface(surfaces_tools.write[i]->get_primitive(), arrays, Array(), Dictionary(), surfaces_tools.write[i]->get_material(), surfaces_tools.write[i]->get_meta("name"));
+ }
+
+ set_lightmap_size_hint(Size2(size_x, size_y));
+
+ if (!r_used_cache) {
+ //free stuff
+ ::free(gen_vertices);
+ ::free(gen_indices);
+ ::free(gen_uvs);
+ }
+
+ return OK;
+}
+
+void EditorSceneImporterMesh::set_lightmap_size_hint(const Size2i &p_size) {
+ lightmap_size_hint = p_size;
+}
+
+Size2i EditorSceneImporterMesh::get_lightmap_size_hint() const {
+ return lightmap_size_hint;
+}
+
void EditorSceneImporterMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &EditorSceneImporterMesh::add_blend_shape);
ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &EditorSceneImporterMesh::get_blend_shape_count);
@@ -444,7 +792,7 @@ void EditorSceneImporterMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &EditorSceneImporterMesh::set_blend_shape_mode);
ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &EditorSceneImporterMesh::get_blend_shape_mode);
- ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()));
+ ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()));
ClassDB::bind_method(D_METHOD("get_surface_count"), &EditorSceneImporterMesh::get_surface_count);
ClassDB::bind_method(D_METHOD("get_surface_primitive_type", "surface_idx"), &EditorSceneImporterMesh::get_surface_primitive_type);
@@ -462,5 +810,8 @@ void EditorSceneImporterMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_data", "data"), &EditorSceneImporterMesh::_set_data);
ClassDB::bind_method(D_METHOD("_get_data"), &EditorSceneImporterMesh::_get_data);
+ ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &EditorSceneImporterMesh::set_lightmap_size_hint);
+ ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &EditorSceneImporterMesh::get_lightmap_size_hint);
+
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data");
}
diff --git a/editor/import/scene_importer_mesh.h b/editor/import/scene_importer_mesh.h
index 42507cbe8c..3326fab55d 100644
--- a/editor/import/scene_importer_mesh.h
+++ b/editor/import/scene_importer_mesh.h
@@ -32,7 +32,10 @@
#define EDITOR_SCENE_IMPORTER_MESH_H
#include "core/io/resource.h"
+#include "scene/resources/concave_polygon_shape_3d.h"
+#include "scene/resources/convex_polygon_shape_3d.h"
#include "scene/resources/mesh.h"
+#include "scene/resources/navigation_mesh.h"
// The following classes are used by importers instead of ArrayMesh and MeshInstance3D
// so the data is not registered (hence, quality loss), importing happens faster and
// its easier to modify before saving
@@ -63,6 +66,8 @@ class EditorSceneImporterMesh : public Resource {
Ref<EditorSceneImporterMesh> shadow_mesh;
+ Size2i lightmap_size_hint;
+
protected:
void _set_data(const Dictionary &p_data);
Dictionary _get_data() const;
@@ -89,13 +94,24 @@ public:
float get_surface_lod_size(int p_surface, int p_lod) const;
Ref<Material> get_surface_material(int p_surface) const;
+ void set_surface_material(int p_surface, const Ref<Material> &p_material);
+
void generate_lods();
void create_shadow_mesh();
Ref<EditorSceneImporterMesh> get_shadow_mesh() const;
+ Vector<Face3> get_faces() const;
+ Vector<Ref<Shape3D>> convex_decompose() const;
+ Ref<Shape3D> create_trimesh_shape() const;
+ Ref<NavigationMesh> create_navigation_mesh();
+ Error lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform, float p_texel_size);
+
+ void set_lightmap_size_hint(const Size2i &p_size);
+ Size2i get_lightmap_size_hint() const;
+
bool has_mesh() const;
- Ref<ArrayMesh> get_mesh();
+ Ref<ArrayMesh> get_mesh(const Ref<Mesh> &p_base = Ref<Mesh>());
void clear();
};
#endif // EDITOR_SCENE_IMPORTER_MESH_H
diff --git a/editor/import_defaults_editor.cpp b/editor/import_defaults_editor.cpp
new file mode 100644
index 0000000000..43b97eb910
--- /dev/null
+++ b/editor/import_defaults_editor.cpp
@@ -0,0 +1,216 @@
+/*************************************************************************/
+/* import_defaults_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "import_defaults_editor.h"
+
+class ImportDefaultsEditorSettings : public Object {
+ GDCLASS(ImportDefaultsEditorSettings, Object)
+ friend class ImportDefaultsEditor;
+ List<PropertyInfo> properties;
+ Map<StringName, Variant> values;
+ Map<StringName, Variant> default_values;
+
+ Ref<ResourceImporter> importer;
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value) {
+ if (values.has(p_name)) {
+ values[p_name] = p_value;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ bool _get(const StringName &p_name, Variant &r_ret) const {
+ if (values.has(p_name)) {
+ r_ret = values[p_name];
+ return true;
+ } else {
+ r_ret = Variant();
+ return false;
+ }
+ }
+ void _get_property_list(List<PropertyInfo> *p_list) const {
+ if (importer.is_null()) {
+ return;
+ }
+ for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
+ if (importer->get_option_visibility(E->get().name, values)) {
+ p_list->push_back(E->get());
+ }
+ }
+ }
+};
+
+void ImportDefaultsEditor::_notification(int p_what) {
+ if (p_what == NOTIFICATION_PREDELETE) {
+ inspector->edit(nullptr);
+ }
+}
+
+void ImportDefaultsEditor::_reset() {
+ if (settings->importer.is_valid()) {
+ settings->values = settings->default_values;
+ settings->notify_property_list_changed();
+ }
+}
+
+void ImportDefaultsEditor::_save() {
+ if (settings->importer.is_valid()) {
+ Dictionary modified;
+
+ for (Map<StringName, Variant>::Element *E = settings->values.front(); E; E = E->next()) {
+ if (E->get() != settings->default_values[E->key()]) {
+ modified[E->key()] = E->get();
+ }
+ }
+
+ if (modified.size()) {
+ ProjectSettings::get_singleton()->set("importer_defaults/" + settings->importer->get_importer_name(), modified);
+ } else {
+ ProjectSettings::get_singleton()->set("importer_defaults/" + settings->importer->get_importer_name(), Variant());
+ }
+
+ emit_signal("project_settings_changed");
+ }
+}
+
+void ImportDefaultsEditor::_update_importer() {
+ List<Ref<ResourceImporter>> importer_list;
+ ResourceFormatImporter::get_singleton()->get_importers(&importer_list);
+ Ref<ResourceImporter> importer;
+ for (List<Ref<ResourceImporter>>::Element *E = importer_list.front(); E; E = E->next()) {
+ if (E->get()->get_visible_name() == importers->get_item_text(importers->get_selected())) {
+ importer = E->get();
+ break;
+ }
+ }
+
+ settings->properties.clear();
+ settings->values.clear();
+ settings->importer = importer;
+
+ if (importer.is_valid()) {
+ List<ResourceImporter::ImportOption> options;
+ importer->get_import_options(&options);
+ Dictionary d;
+ if (ProjectSettings::get_singleton()->has_setting("importer_defaults/" + importer->get_importer_name())) {
+ d = ProjectSettings::get_singleton()->get("importer_defaults/" + importer->get_importer_name());
+ }
+
+ for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
+ settings->properties.push_back(E->get().option);
+ if (d.has(E->get().option.name)) {
+ settings->values[E->get().option.name] = d[E->get().option.name];
+ } else {
+ settings->values[E->get().option.name] = E->get().default_value;
+ }
+ settings->default_values[E->get().option.name] = E->get().default_value;
+ }
+
+ save_defaults->set_disabled(false);
+ reset_defaults->set_disabled(false);
+
+ } else {
+ save_defaults->set_disabled(true);
+ reset_defaults->set_disabled(true);
+ }
+
+ settings->notify_property_list_changed();
+
+ inspector->edit(settings);
+}
+
+void ImportDefaultsEditor::_importer_selected(int p_index) {
+ _update_importer();
+}
+
+void ImportDefaultsEditor::clear() {
+ String last_selected;
+ if (importers->get_selected() > 0) {
+ last_selected = importers->get_item_text(importers->get_selected());
+ }
+
+ importers->clear();
+
+ importers->add_item("<" + TTR("Select Importer") + ">");
+ importers->set_item_disabled(0, true);
+
+ List<Ref<ResourceImporter>> importer_list;
+ ResourceFormatImporter::get_singleton()->get_importers(&importer_list);
+ Vector<String> names;
+ for (List<Ref<ResourceImporter>>::Element *E = importer_list.front(); E; E = E->next()) {
+ String vn = E->get()->get_visible_name();
+ names.push_back(vn);
+ }
+ names.sort();
+
+ for (int i = 0; i < names.size(); i++) {
+ importers->add_item(names[i]);
+
+ if (names[i] == last_selected) {
+ importers->select(i + 1);
+ }
+ }
+}
+
+void ImportDefaultsEditor::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("project_settings_changed"));
+}
+
+ImportDefaultsEditor::ImportDefaultsEditor() {
+ HBoxContainer *hb = memnew(HBoxContainer);
+ hb->add_child(memnew(Label(TTR("Importer:"))));
+ importers = memnew(OptionButton);
+ hb->add_child(importers);
+ hb->add_spacer();
+ importers->connect("item_selected", callable_mp(this, &ImportDefaultsEditor::_importer_selected));
+ reset_defaults = memnew(Button);
+ reset_defaults->set_text(TTR("Reset to Defaults"));
+ reset_defaults->set_disabled(true);
+ reset_defaults->connect("pressed", callable_mp(this, &ImportDefaultsEditor::_reset));
+ hb->add_child(reset_defaults);
+ add_child(hb);
+ inspector = memnew(EditorInspector);
+ add_child(inspector);
+ inspector->set_v_size_flags(SIZE_EXPAND_FILL);
+ CenterContainer *cc = memnew(CenterContainer);
+ save_defaults = memnew(Button);
+ save_defaults->set_text(TTR("Save"));
+ save_defaults->connect("pressed", callable_mp(this, &ImportDefaultsEditor::_save));
+ cc->add_child(save_defaults);
+ add_child(cc);
+
+ settings = memnew(ImportDefaultsEditorSettings);
+}
+
+ImportDefaultsEditor::~ImportDefaultsEditor() {
+ memdelete(settings);
+}
diff --git a/editor/editor_sub_scene.h b/editor/import_defaults_editor.h
index 428bd5a40e..c1becac5e9 100644
--- a/editor/editor_sub_scene.h
+++ b/editor/import_defaults_editor.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* editor_sub_scene.h */
+/* import_defaults_editor.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,44 +28,48 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EDITOR_SUB_SCENE_H
-#define EDITOR_SUB_SCENE_H
+#ifndef IMPORT_DEFAULTS_EDITOR_H
+#define IMPORT_DEFAULTS_EDITOR_H
-#include "editor/editor_file_dialog.h"
-#include "scene/gui/dialogs.h"
-#include "scene/gui/tree.h"
+#include "core/object/undo_redo.h"
+#include "editor/action_map_editor.h"
+#include "editor/editor_data.h"
+#include "editor/editor_plugin_settings.h"
+#include "editor/editor_sectioned_inspector.h"
+#include "editor/localization_editor.h"
+#include "editor/shader_globals_editor.h"
+#include "editor_autoload_settings.h"
+#include "scene/gui/center_container.h"
+#include "scene/gui/option_button.h"
-class EditorSubScene : public ConfirmationDialog {
- GDCLASS(EditorSubScene, ConfirmationDialog);
+class ImportDefaultsEditorSettings;
- List<Node *> selection;
- LineEdit *path;
- Tree *tree;
- Node *scene;
- bool is_root;
+class ImportDefaultsEditor : public VBoxContainer {
+ GDCLASS(ImportDefaultsEditor, VBoxContainer)
- EditorFileDialog *file_dialog;
+ OptionButton *importers;
+ Button *save_defaults;
+ Button *reset_defaults;
- void _fill_tree(Node *p_node, TreeItem *p_parent);
- void _selected_changed();
- void _item_multi_selected(Object *p_object, int p_cell, bool p_selected);
- void _item_activated();
- void _remove_selection_child(Node *p_node);
- void _reown(Node *p_node, List<Node *> *p_to_reown);
+ EditorInspector *inspector;
- void ok_pressed() override;
+ ImportDefaultsEditorSettings *settings;
+
+ void _update_importer();
+ void _importer_selected(int p_index);
+
+ void _reset();
+ void _save();
protected:
void _notification(int p_what);
static void _bind_methods();
- void _path_browse();
- void _path_selected(const String &p_path);
- void _path_changed(const String &p_path);
public:
- void move(Node *p_new_parent, Node *p_new_owner);
void clear();
- EditorSubScene();
+
+ ImportDefaultsEditor();
+ ~ImportDefaultsEditor();
};
-#endif // EDITOR_SUB_SCENE_H
+#endif // IMPORT_DEFAULTS_EDITOR_H
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 103e5e81cb..ddc363113c 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -48,7 +48,7 @@ public:
values[p_name] = p_value;
if (checking) {
checked.insert(p_name);
- _change_notify();
+ notify_property_list_changed();
}
return true;
}
@@ -81,7 +81,7 @@ public:
}
void update() {
- _change_notify();
+ notify_property_list_changed();
}
ImportDockParameters() {
@@ -98,11 +98,9 @@ void ImportDock::set_edit_path(const String &p_path) {
return;
}
- params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(config->get_value("remap", "importer"));
- if (params->importer.is_null()) {
- clear();
- return;
- }
+ String importer_name = config->get_value("remap", "importer");
+
+ params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
params->paths.clear();
params->paths.push_back(p_path);
@@ -124,11 +122,18 @@ void ImportDock::set_edit_path(const String &p_path) {
for (List<Pair<String, String>>::Element *E = importer_names.front(); E; E = E->next()) {
import_as->add_item(E->get().first);
import_as->set_item_metadata(import_as->get_item_count() - 1, E->get().second);
- if (E->get().second == params->importer->get_importer_name()) {
+ if (E->get().second == importer_name) {
import_as->select(import_as->get_item_count() - 1);
}
}
+ import_as->add_separator();
+ import_as->add_item(TTR("Keep File (No Import)"));
+ import_as->set_item_metadata(import_as->get_item_count() - 1, "keep");
+ if (importer_name == "keep") {
+ import_as->select(import_as->get_item_count() - 1);
+ }
+
import->set_disabled(false);
import_as->set_disabled(false);
preset->set_disabled(false);
@@ -138,7 +143,10 @@ void ImportDock::set_edit_path(const String &p_path) {
void ImportDock::_update_options(const Ref<ConfigFile> &p_config) {
List<ResourceImporter::ImportOption> options;
- params->importer->get_import_options(&options);
+
+ if (params->importer.is_valid()) {
+ params->importer->get_import_options(&options);
+ }
params->properties.clear();
params->values.clear();
@@ -156,6 +164,14 @@ void ImportDock::_update_options(const Ref<ConfigFile> &p_config) {
params->update();
_update_preset_menu();
+
+ if (params->importer.is_valid() && params->paths.size() == 1 && params->importer->has_advanced_options()) {
+ advanced->show();
+ advanced_spacer->show();
+ } else {
+ advanced->hide();
+ advanced_spacer->hide();
+ }
}
void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
@@ -258,11 +274,26 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
preset->set_disabled(false);
imported->set_text(vformat(TTR("%d Files"), p_paths.size()));
+
+ if (params->paths.size() == 1 && params->importer->has_advanced_options()) {
+ advanced->show();
+ advanced_spacer->show();
+ } else {
+ advanced->hide();
+ advanced_spacer->hide();
+ }
}
void ImportDock::_update_preset_menu() {
preset->get_popup()->clear();
+ if (params->importer.is_null()) {
+ preset->get_popup()->add_item(TTR("Default"));
+ preset->hide();
+ return;
+ }
+ preset->show();
+
if (params->importer->get_preset_count() == 0) {
preset->get_popup()->add_item(TTR("Default"));
} else {
@@ -282,20 +313,25 @@ void ImportDock::_update_preset_menu() {
void ImportDock::_importer_selected(int i_idx) {
String name = import_as->get_selected_metadata();
- Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(name);
- ERR_FAIL_COND(importer.is_null());
+ if (name == "keep") {
+ params->importer.unref();
+ _update_options(Ref<ConfigFile>());
+ } else {
+ Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(name);
+ ERR_FAIL_COND(importer.is_null());
- params->importer = importer;
+ params->importer = importer;
- Ref<ConfigFile> config;
- if (params->paths.size()) {
- config.instance();
- Error err = config->load(params->paths[0] + ".import");
- if (err != OK) {
- config.unref();
+ Ref<ConfigFile> config;
+ if (params->paths.size()) {
+ config.instance();
+ Error err = config->load(params->paths[0] + ".import");
+ if (err != OK) {
+ config.unref();
+ }
}
+ _update_options(config);
}
- _update_options(config);
}
void ImportDock::_preset_selected(int p_idx) {
@@ -391,6 +427,13 @@ static bool _find_owners(EditorFileSystemDirectory *efsd, const String &p_path)
void ImportDock::_reimport_attempt() {
bool need_restart = false;
bool used_in_resources = false;
+
+ String importer_name;
+ if (params->importer.is_valid()) {
+ importer_name = params->importer->get_importer_name();
+ } else {
+ importer_name = "keep";
+ }
for (int i = 0; i < params->paths.size(); i++) {
Ref<ConfigFile> config;
config.instance();
@@ -398,7 +441,7 @@ void ImportDock::_reimport_attempt() {
ERR_CONTINUE(err != OK);
String imported_with = config->get_value("remap", "importer");
- if (imported_with != params->importer->get_importer_name()) {
+ if (imported_with != importer_name) {
need_restart = true;
if (_find_owners(EditorFileSystem::get_singleton()->get_filesystem(), params->paths[i])) {
used_in_resources = true;
@@ -422,6 +465,11 @@ void ImportDock::_reimport_and_restart() {
EditorNode::get_singleton()->restart_editor();
}
+void ImportDock::_advanced_options() {
+ if (params->paths.size() == 1 && params->importer.is_valid()) {
+ params->importer->show_advanced_options(params->paths[0]);
+ }
+}
void ImportDock::_reimport() {
for (int i = 0; i < params->paths.size(); i++) {
Ref<ConfigFile> config;
@@ -429,38 +477,45 @@ void ImportDock::_reimport() {
Error err = config->load(params->paths[i] + ".import");
ERR_CONTINUE(err != OK);
- String importer_name = params->importer->get_importer_name();
+ if (params->importer.is_valid()) {
+ String importer_name = params->importer->get_importer_name();
+
+ if (params->checking && config->get_value("remap", "importer") == params->importer->get_importer_name()) {
+ //update only what is edited (checkboxes) if the importer is the same
+ for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
+ if (params->checked.has(E->get().name)) {
+ config->set_value("params", E->get().name, params->values[E->get().name]);
+ }
+ }
+ } else {
+ //override entirely
+ config->set_value("remap", "importer", importer_name);
+ if (config->has_section("params")) {
+ config->erase_section("params");
+ }
- if (params->checking && config->get_value("remap", "importer") == params->importer->get_importer_name()) {
- //update only what is edited (checkboxes) if the importer is the same
- for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
- if (params->checked.has(E->get().name)) {
+ for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
config->set_value("params", E->get().name, params->values[E->get().name]);
}
}
- } else {
- //override entirely
- config->set_value("remap", "importer", importer_name);
- if (config->has_section("params")) {
- config->erase_section("params");
- }
- for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
- config->set_value("params", E->get().name, params->values[E->get().name]);
+ //handle group file
+ Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
+ ERR_CONTINUE(!importer.is_valid());
+ String group_file_property = importer->get_option_group_file();
+ if (group_file_property != String()) {
+ //can import from a group (as in, atlas)
+ ERR_CONTINUE(!params->values.has(group_file_property));
+ String group_file = params->values[group_file_property];
+ config->set_value("remap", "group_file", group_file);
+ } else {
+ config->set_value("remap", "group_file", Variant()); //clear group file if unused
}
- }
- //handle group file
- Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
- ERR_CONTINUE(!importer.is_valid());
- String group_file_property = importer->get_option_group_file();
- if (group_file_property != String()) {
- //can import from a group (as in, atlas)
- ERR_CONTINUE(!params->values.has(group_file_property));
- String group_file = params->values[group_file_property];
- config->set_value("remap", "group_file", group_file);
} else {
- config->set_value("remap", "group_file", Variant()); //clear group file if unused
+ //set to no import
+ config->clear();
+ config->set_value("remap", "importer", "keep");
}
config->save(params->paths[i] + ".import");
@@ -531,10 +586,27 @@ ImportDock::ImportDock() {
import->set_text(TTR("Reimport"));
import->set_disabled(true);
import->connect("pressed", callable_mp(this, &ImportDock::_reimport_attempt));
+ if (!DisplayServer::get_singleton()->get_swap_cancel_ok()) {
+ advanced_spacer = hb->add_spacer();
+ advanced = memnew(Button);
+ advanced->set_text(TTR("Advanced..."));
+ hb->add_child(advanced);
+ }
hb->add_spacer();
hb->add_child(import);
hb->add_spacer();
+ if (DisplayServer::get_singleton()->get_swap_cancel_ok()) {
+ advanced = memnew(Button);
+ advanced->set_text(TTR("Advanced..."));
+ hb->add_child(advanced);
+ advanced_spacer = hb->add_spacer();
+ }
+
+ advanced->hide();
+ advanced_spacer->hide();
+ advanced->connect("pressed", callable_mp(this, &ImportDock::_advanced_options));
+
reimport_confirm = memnew(ConfirmationDialog);
reimport_confirm->get_ok_button()->set_text(TTR("Save Scenes, Re-Import, and Restart"));
add_child(reimport_confirm);
diff --git a/editor/import_dock.h b/editor/import_dock.h
index 6c5779ddce..2be48dd505 100644
--- a/editor/import_dock.h
+++ b/editor/import_dock.h
@@ -57,6 +57,9 @@ class ImportDock : public VBoxContainer {
Label *label_warning;
Button *import;
+ Control *advanced_spacer;
+ Button *advanced;
+
ImportDockParameters *params;
void _preset_selected(int p_idx);
@@ -69,6 +72,7 @@ class ImportDock : public VBoxContainer {
void _reimport_and_restart();
void _reimport();
+ void _advanced_options();
enum {
ITEM_SET_AS_DEFAULT = 100,
ITEM_LOAD_DEFAULT,
diff --git a/editor/input_map_editor.cpp b/editor/input_map_editor.cpp
deleted file mode 100644
index 9a5e7d164c..0000000000
--- a/editor/input_map_editor.cpp
+++ /dev/null
@@ -1,1033 +0,0 @@
-/*************************************************************************/
-/* input_map_editor.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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 "input_map_editor.h"
-
-#include "core/input/input_map.h"
-#include "core/os/keyboard.h"
-#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
-
-void InputMapEditor::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- action_add_error->add_theme_color_override("font_color", input_editor->get_theme_color("error_color", "Editor"));
- popup_add->add_icon_item(input_editor->get_theme_icon("Keyboard", "EditorIcons"), TTR("Key"), INPUT_KEY);
- popup_add->add_icon_item(input_editor->get_theme_icon("KeyboardPhysical", "EditorIcons"), TTR("Physical Key"), INPUT_KEY_PHYSICAL);
- popup_add->add_icon_item(input_editor->get_theme_icon("JoyButton", "EditorIcons"), TTR("Joy Button"), INPUT_JOY_BUTTON);
- popup_add->add_icon_item(input_editor->get_theme_icon("JoyAxis", "EditorIcons"), TTR("Joy Axis"), INPUT_JOY_MOTION);
- popup_add->add_icon_item(input_editor->get_theme_icon("Mouse", "EditorIcons"), TTR("Mouse Button"), INPUT_MOUSE_BUTTON);
- _update_actions();
- } break;
- case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- action_add_error->add_theme_color_override("font_color", input_editor->get_theme_color("error_color", "Editor"));
- popup_add->set_item_icon(popup_add->get_item_index(INPUT_KEY), input_editor->get_theme_icon("Keyboard", "EditorIcons"));
- popup_add->set_item_icon(popup_add->get_item_index(INPUT_KEY_PHYSICAL), input_editor->get_theme_icon("KeyboardPhysical", "EditorIcons"));
- popup_add->set_item_icon(popup_add->get_item_index(INPUT_JOY_BUTTON), input_editor->get_theme_icon("JoyButton", "EditorIcons"));
- popup_add->set_item_icon(popup_add->get_item_index(INPUT_JOY_MOTION), input_editor->get_theme_icon("JoyAxis", "EditorIcons"));
- popup_add->set_item_icon(popup_add->get_item_index(INPUT_MOUSE_BUTTON), input_editor->get_theme_icon("Mouse", "EditorIcons"));
- _update_actions();
- } break;
- }
-}
-
-static bool _validate_action_name(const String &p_name) {
- const char32_t *cstr = p_name.get_data();
- for (int i = 0; cstr[i]; i++) {
- if (cstr[i] == '/' || cstr[i] == ':' || cstr[i] == '"' ||
- cstr[i] == '=' || cstr[i] == '\\' || cstr[i] < 32) {
- return false;
- }
- }
- return true;
-}
-
-void InputMapEditor::_action_selected() {
- TreeItem *ti = input_editor->get_selected();
- if (!ti || !ti->is_editable(0)) {
- return;
- }
-
- add_at = "input/" + ti->get_text(0);
- edit_idx = -1;
-}
-
-void InputMapEditor::_action_edited() {
- TreeItem *ti = input_editor->get_selected();
- if (!ti) {
- return;
- }
-
- if (input_editor->get_selected_column() == 0) {
- String new_name = ti->get_text(0);
- String old_name = add_at.substr(add_at.find("/") + 1, add_at.length());
-
- if (new_name == old_name) {
- return;
- }
-
- if (new_name == "" || !_validate_action_name(new_name)) {
- ti->set_text(0, old_name);
- add_at = "input/" + old_name;
-
- message->set_text(TTR("Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or '\"'"));
- message->popup_centered(Size2(300, 100) * EDSCALE);
- return;
- }
-
- String action_prop = "input/" + new_name;
-
- if (ProjectSettings::get_singleton()->has_setting(action_prop)) {
- ti->set_text(0, old_name);
- add_at = "input/" + old_name;
-
- message->set_text(vformat(TTR("An action with the name '%s' already exists."), new_name));
- message->popup_centered(Size2(300, 100) * EDSCALE);
- return;
- }
-
- int order = ProjectSettings::get_singleton()->get_order(add_at);
- Dictionary action = ProjectSettings::get_singleton()->get(add_at);
-
- setting = true;
- undo_redo->create_action(TTR("Rename Input Action Event"));
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", add_at);
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", action_prop, action);
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", action_prop, order);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", action_prop);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", add_at, action);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", add_at, order);
- undo_redo->add_do_method(this, "_update_actions");
- undo_redo->add_undo_method(this, "_update_actions");
- undo_redo->add_do_method(this, "emit_signal", inputmap_changed);
- undo_redo->add_undo_method(this, "emit_signal", inputmap_changed);
- undo_redo->commit_action();
- setting = false;
-
- add_at = action_prop;
- } else if (input_editor->get_selected_column() == 1) {
- String name = "input/" + ti->get_text(0);
- Dictionary old_action = ProjectSettings::get_singleton()->get(name);
- Dictionary new_action = old_action.duplicate();
- new_action["deadzone"] = ti->get_range(1);
-
- undo_redo->create_action(TTR("Change Action deadzone"));
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, new_action);
- undo_redo->add_do_method(this, "emit_signal", inputmap_changed);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_action);
- undo_redo->add_undo_method(this, "emit_signal", inputmap_changed);
- undo_redo->commit_action();
- }
-}
-
-void InputMapEditor::_device_input_add() {
- Ref<InputEvent> ie;
- String name = add_at;
- int idx = edit_idx;
- Dictionary old_val = ProjectSettings::get_singleton()->get(name);
- Dictionary action = old_val.duplicate();
- Array events = action["events"];
-
- switch (add_type) {
- case INPUT_MOUSE_BUTTON: {
- Ref<InputEventMouseButton> mb;
- mb.instance();
- mb->set_button_index(device_index->get_selected() + 1);
- mb->set_device(_get_current_device());
-
- for (int i = 0; i < events.size(); i++) {
- Ref<InputEventMouseButton> aie = events[i];
- if (aie.is_null()) {
- continue;
- }
- if (aie->get_device() == mb->get_device() && aie->get_button_index() == mb->get_button_index()) {
- return;
- }
- }
-
- ie = mb;
-
- } break;
- case INPUT_JOY_MOTION: {
- Ref<InputEventJoypadMotion> jm;
- jm.instance();
- jm->set_axis(device_index->get_selected() >> 1);
- jm->set_axis_value((device_index->get_selected() & 1) ? 1 : -1);
- jm->set_device(_get_current_device());
-
- for (int i = 0; i < events.size(); i++) {
- Ref<InputEventJoypadMotion> aie = events[i];
- if (aie.is_null()) {
- continue;
- }
-
- if (aie->get_device() == jm->get_device() && aie->get_axis() == jm->get_axis() && aie->get_axis_value() == jm->get_axis_value()) {
- return;
- }
- }
-
- ie = jm;
-
- } break;
- case INPUT_JOY_BUTTON: {
- Ref<InputEventJoypadButton> jb;
- jb.instance();
-
- jb->set_button_index(device_index->get_selected());
- jb->set_device(_get_current_device());
-
- for (int i = 0; i < events.size(); i++) {
- Ref<InputEventJoypadButton> aie = events[i];
- if (aie.is_null()) {
- continue;
- }
- if (aie->get_device() == jb->get_device() && aie->get_button_index() == jb->get_button_index()) {
- return;
- }
- }
- ie = jb;
-
- } break;
- default: {
- }
- }
-
- if (idx < 0 || idx >= events.size()) {
- events.push_back(ie);
- } else {
- events[idx] = ie;
- }
- action["events"] = events;
-
- undo_redo->create_action(TTR("Add Input Action Event"));
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
- undo_redo->add_do_method(this, "_update_actions");
- undo_redo->add_undo_method(this, "_update_actions");
- undo_redo->add_do_method(this, "emit_signal", inputmap_changed);
- undo_redo->add_undo_method(this, "emit_signal", inputmap_changed);
- undo_redo->commit_action();
-
- _show_last_added(ie, name);
-}
-
-void InputMapEditor::_set_current_device(int i_device) {
- device_id->select(i_device + 1);
-}
-
-int InputMapEditor::_get_current_device() {
- return device_id->get_selected() - 1;
-}
-
-String InputMapEditor::_get_device_string(int i_device) {
- if (i_device == InputMap::ALL_DEVICES) {
- return TTR("All Devices");
- }
- return TTR("Device") + " " + itos(i_device);
-}
-
-void InputMapEditor::_press_a_key_confirm() {
- if (last_wait_for_key.is_null()) {
- return;
- }
-
- Ref<InputEventKey> ie;
- ie.instance();
- if (press_a_key_physical) {
- ie->set_physical_keycode(last_wait_for_key->get_physical_keycode());
- ie->set_keycode(0);
- } else {
- ie->set_physical_keycode(0);
- ie->set_keycode(last_wait_for_key->get_keycode());
- }
- ie->set_shift(last_wait_for_key->get_shift());
- ie->set_alt(last_wait_for_key->get_alt());
- ie->set_control(last_wait_for_key->get_control());
- ie->set_metakey(last_wait_for_key->get_metakey());
-
- String name = add_at;
- int idx = edit_idx;
-
- Dictionary old_val = ProjectSettings::get_singleton()->get(name);
- Dictionary action = old_val.duplicate();
- Array events = action["events"];
-
- for (int i = 0; i < events.size(); i++) {
- Ref<InputEventKey> aie = events[i];
- if (aie.is_null()) {
- continue;
- }
- if (!press_a_key_physical) {
- if (aie->get_keycode_with_modifiers() == ie->get_keycode_with_modifiers()) {
- return;
- }
- } else {
- if (aie->get_physical_keycode_with_modifiers() == ie->get_physical_keycode_with_modifiers()) {
- return;
- }
- }
- }
-
- if (idx < 0 || idx >= events.size()) {
- events.push_back(ie);
- } else {
- events[idx] = ie;
- }
- action["events"] = events;
-
- undo_redo->create_action(TTR("Add Input Action Event"));
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
- undo_redo->add_do_method(this, "_update_actions");
- undo_redo->add_undo_method(this, "_update_actions");
- undo_redo->add_do_method(this, "emit_signal", inputmap_changed);
- undo_redo->add_undo_method(this, "emit_signal", inputmap_changed);
- undo_redo->commit_action();
-
- _show_last_added(ie, name);
-}
-
-void InputMapEditor::_show_last_added(const Ref<InputEvent> &p_event, const String &p_name) {
- TreeItem *r = input_editor->get_root();
-
- String name = p_name;
- name.erase(0, 6);
- if (!r) {
- return;
- }
- r = r->get_children();
- if (!r) {
- return;
- }
- bool found = false;
- while (r) {
- if (r->get_text(0) != name) {
- r = r->get_next();
- continue;
- }
- TreeItem *child = r->get_children();
- while (child) {
- Variant input = child->get_meta("__input");
- if (p_event == input) {
- r->set_collapsed(false);
- child->select(0);
- found = true;
- break;
- }
- child = child->get_next();
- }
- if (found) {
- break;
- }
- r = r->get_next();
- }
-
- if (found) {
- input_editor->ensure_cursor_is_visible();
- }
-}
-
-// Maps to 2*axis if value is neg, or + 1 if value is pos.
-static const char *_joy_axis_descriptions[JOY_AXIS_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"),
-};
-
-// Separate from `InputEvent::as_text()` since the descriptions need to be different for the input map editor. See #43660.
-String InputMapEditor::_get_joypad_motion_event_text(const Ref<InputEventJoypadMotion> &p_event) {
- ERR_FAIL_COND_V_MSG(p_event.is_null(), String(), "Provided event is not a valid instance of InputEventJoypadMotion");
-
- String desc = TTR("Unknown Joypad Axis");
- if (p_event->get_axis() < JOY_AXIS_MAX) {
- desc = RTR(_joy_axis_descriptions[2 * p_event->get_axis() + (p_event->get_axis_value() < 0 ? 0 : 1)]);
- }
-
- return vformat("Joypad Axis %s %s (%s)", itos(p_event->get_axis()), p_event->get_axis_value() < 0 ? "-" : "+", desc);
-}
-
-void InputMapEditor::_wait_for_key(const Ref<InputEvent> &p_event) {
- Ref<InputEventKey> k = p_event;
-
- if (k.is_valid() && k->is_pressed() && k->get_keycode() != 0) {
- last_wait_for_key = p_event;
- const String str = (press_a_key_physical) ? keycode_get_string(k->get_physical_keycode_with_modifiers()) + TTR(" (Physical)") : keycode_get_string(k->get_keycode_with_modifiers());
-
- press_a_key_label->set_text(str);
- press_a_key->get_ok_button()->set_disabled(false);
- press_a_key->set_input_as_handled();
- }
-}
-
-void InputMapEditor::_edit_item(Ref<InputEvent> p_exiting_event) {
- InputType ie_type;
-
- if ((Ref<InputEventKey>(p_exiting_event)).is_valid()) {
- if ((Ref<InputEventKey>(p_exiting_event))->get_keycode() != 0) {
- ie_type = INPUT_KEY;
- } else {
- ie_type = INPUT_KEY_PHYSICAL;
- }
- } else if ((Ref<InputEventJoypadButton>(p_exiting_event)).is_valid()) {
- ie_type = INPUT_JOY_BUTTON;
- } else if ((Ref<InputEventMouseButton>(p_exiting_event)).is_valid()) {
- ie_type = INPUT_MOUSE_BUTTON;
- } else if ((Ref<InputEventJoypadMotion>(p_exiting_event)).is_valid()) {
- ie_type = INPUT_JOY_MOTION;
- } else {
- return;
- }
-
- _add_item(ie_type, p_exiting_event);
-}
-
-void InputMapEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_event) {
- add_type = InputType(p_item);
-
- switch (add_type) {
- case INPUT_KEY: {
- press_a_key_physical = false;
- press_a_key_label->set_text(TTR("Press a Key..."));
- press_a_key->get_ok_button()->set_disabled(true);
- last_wait_for_key = Ref<InputEvent>();
- press_a_key->popup_centered(Size2(250, 80) * EDSCALE);
- //press_a_key->grab_focus();
-
- } break;
- case INPUT_KEY_PHYSICAL: {
- press_a_key_physical = true;
- press_a_key_label->set_text(TTR("Press a Key..."));
-
- last_wait_for_key = Ref<InputEvent>();
- press_a_key->popup_centered(Size2(250, 80) * EDSCALE);
- press_a_key->grab_focus();
-
- } break;
- case INPUT_MOUSE_BUTTON: {
- device_index_label->set_text(TTR("Mouse Button Index:"));
- device_index->clear();
- device_index->add_item(TTR("Left Button"));
- device_index->add_item(TTR("Right Button"));
- device_index->add_item(TTR("Middle Button"));
- device_index->add_item(TTR("Wheel Up Button"));
- device_index->add_item(TTR("Wheel Down Button"));
- device_index->add_item(TTR("Wheel Left Button"));
- device_index->add_item(TTR("Wheel Right Button"));
- device_index->add_item(TTR("X Button 1"));
- device_index->add_item(TTR("X Button 2"));
- device_input->popup_centered(Size2(350, 95) * EDSCALE);
-
- Ref<InputEventMouseButton> mb = p_exiting_event;
- if (mb.is_valid()) {
- device_index->select(mb->get_button_index() - 1);
- _set_current_device(mb->get_device());
- device_input->get_ok_button()->set_text(TTR("Change"));
- } else {
- _set_current_device(0);
- device_input->get_ok_button()->set_text(TTR("Add"));
- }
-
- } break;
- case INPUT_JOY_MOTION: {
- device_index_label->set_text(TTR("Joypad Axis Index:"));
- device_index->clear();
- for (int i = 0; i < JOY_AXIS_MAX * 2; i++) {
- Ref<InputEventJoypadMotion> jm;
- jm.instance();
- jm->set_axis(i / 2);
- jm->set_axis_value((i & 1) ? 1 : -1);
- device_index->add_item(_get_joypad_motion_event_text(jm));
- }
- device_input->popup_centered(Size2(350, 95) * EDSCALE);
-
- Ref<InputEventJoypadMotion> jm = p_exiting_event;
- if (jm.is_valid()) {
- device_index->select(jm->get_axis() * 2 + (jm->get_axis_value() > 0 ? 1 : 0));
- _set_current_device(jm->get_device());
- device_input->get_ok_button()->set_text(TTR("Change"));
- } else {
- _set_current_device(0);
- device_input->get_ok_button()->set_text(TTR("Add"));
- }
-
- } break;
- case INPUT_JOY_BUTTON: {
- device_index_label->set_text(TTR("Joypad Button Index:"));
- device_index->clear();
- for (int i = 0; i < JOY_BUTTON_MAX; i++) {
- Ref<InputEventJoypadButton> jb;
- jb.instance();
- jb->set_button_index(i);
- device_index->add_item(jb->as_text());
- }
- device_input->popup_centered(Size2(350, 95) * EDSCALE);
-
- Ref<InputEventJoypadButton> jb = p_exiting_event;
- if (jb.is_valid()) {
- device_index->select(jb->get_button_index());
- _set_current_device(jb->get_device());
- device_input->get_ok_button()->set_text(TTR("Change"));
- } else {
- _set_current_device(0);
- device_input->get_ok_button()->set_text(TTR("Add"));
- }
-
- } break;
- default: {
- }
- }
-}
-
-void InputMapEditor::_action_activated() {
- TreeItem *ti = input_editor->get_selected();
-
- if (!ti || ti->get_parent() == input_editor->get_root()) {
- return;
- }
-
- String name = "input/" + ti->get_parent()->get_text(0);
- Dictionary action = ProjectSettings::get_singleton()->get(name);
- Array events = action["events"];
- int idx = ti->get_metadata(0);
-
- ERR_FAIL_INDEX(idx, events.size());
- Ref<InputEvent> event = events[idx];
- if (event.is_null()) {
- return;
- }
-
- add_at = name;
- edit_idx = idx;
- _edit_item(event);
-}
-
-void InputMapEditor::_action_button_pressed(Object *p_obj, int p_column, int p_id) {
- TreeItem *ti = Object::cast_to<TreeItem>(p_obj);
-
- ERR_FAIL_COND(!ti);
-
- if (p_id == 1) {
- // Add action event
- Point2 ofs = input_editor->get_global_position();
- Rect2 ir = input_editor->get_item_rect(ti);
- ir.position.y -= input_editor->get_scroll().y;
- ofs += ir.position + ir.size;
- ofs.x -= 100;
- popup_add->set_position(ofs);
- popup_add->popup();
- add_at = "input/" + ti->get_text(0);
- edit_idx = -1;
-
- } else if (p_id == 2) {
- // Remove
-
- if (ti->get_parent() == input_editor->get_root()) {
- // Remove action
- String name = "input/" + ti->get_text(0);
- Dictionary old_val = ProjectSettings::get_singleton()->get(name);
- int order = ProjectSettings::get_singleton()->get_order(name);
-
- undo_redo->create_action(TTR("Erase Input Action"));
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", name);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", name, order);
- undo_redo->add_do_method(this, "_update_actions");
- undo_redo->add_undo_method(this, "_update_actions");
- undo_redo->add_do_method(this, "emit_signal", inputmap_changed);
- undo_redo->add_undo_method(this, "emit_signal", inputmap_changed);
- undo_redo->commit_action();
-
- } else {
- // Remove action event
- String name = "input/" + ti->get_parent()->get_text(0);
- Dictionary old_val = ProjectSettings::get_singleton()->get(name);
- Dictionary action = old_val.duplicate();
- int idx = ti->get_metadata(0);
-
- Array events = action["events"];
- ERR_FAIL_INDEX(idx, events.size());
- events.remove(idx);
- action["events"] = events;
-
- undo_redo->create_action(TTR("Erase Input Action Event"));
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
- undo_redo->add_do_method(this, "_update_actions");
- undo_redo->add_undo_method(this, "_update_actions");
- undo_redo->add_do_method(this, "emit_signal", inputmap_changed);
- undo_redo->add_undo_method(this, "emit_signal", inputmap_changed);
- undo_redo->commit_action();
- }
- } else if (p_id == 3) {
- // Edit
-
- if (ti->get_parent() == input_editor->get_root()) {
- // Edit action name
- ti->set_as_cursor(0);
- input_editor->edit_selected();
-
- } else {
- // Edit action event
- String name = "input/" + ti->get_parent()->get_text(0);
- int idx = ti->get_metadata(0);
- Dictionary action = ProjectSettings::get_singleton()->get(name);
-
- Array events = action["events"];
- ERR_FAIL_INDEX(idx, events.size());
-
- Ref<InputEvent> event = events[idx];
-
- if (event.is_null()) {
- return;
- }
-
- ti->set_as_cursor(0);
- add_at = name;
- edit_idx = idx;
- _edit_item(event);
- }
- }
-}
-
-void InputMapEditor::_update_actions() {
- if (setting) {
- return;
- }
-
- Map<String, bool> collapsed;
-
- if (input_editor->get_root() && input_editor->get_root()->get_children()) {
- for (TreeItem *item = input_editor->get_root()->get_children(); item; item = item->get_next()) {
- collapsed[item->get_text(0)] = item->is_collapsed();
- }
- }
-
- input_editor->clear();
- TreeItem *root = input_editor->create_item();
- input_editor->set_hide_root(true);
-
- List<PropertyInfo> props;
- ProjectSettings::get_singleton()->get_property_list(&props);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- const String property_name = E->get().name;
-
- if (!property_name.begins_with("input/")) {
- continue;
- }
-
- const String name = property_name.get_slice("/", 1);
-
- TreeItem *item = input_editor->create_item(root);
- item->set_text(0, name);
- item->set_custom_bg_color(0, input_editor->get_theme_color("prop_subsection", "Editor"));
- if (collapsed.has(name)) {
- item->set_collapsed(collapsed[name]);
- }
-
- item->set_editable(1, true);
- item->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
- item->set_range_config(1, 0.0, 1.0, 0.01);
-
- item->set_custom_bg_color(1, input_editor->get_theme_color("prop_subsection", "Editor"));
-
- const bool is_builtin_input = ProjectSettings::get_singleton()->get_input_presets().find(property_name) != nullptr;
- const String tooltip_remove = is_builtin_input ? TTR("Built-in actions can't be removed as they're used for UI navigation.") : TTR("Remove");
- item->add_button(2, input_editor->get_theme_icon("Add", "EditorIcons"), 1, false, TTR("Add Event"));
- item->add_button(2, input_editor->get_theme_icon("Remove", "EditorIcons"), 2, false, tooltip_remove);
-
- if (is_builtin_input) {
- item->set_button_disabled(2, 1, true);
- } else {
- item->set_editable(0, true);
- }
-
- Dictionary action = ProjectSettings::get_singleton()->get(property_name);
- Array events = action["events"];
- item->set_range(1, action["deadzone"]);
-
- for (int i = 0; i < events.size(); i++) {
- Ref<InputEvent> event = events[i];
- if (event.is_null()) {
- continue;
- }
-
- TreeItem *action2 = input_editor->create_item(item);
-
- Ref<InputEventKey> k = event;
- if (k.is_valid()) {
- if (k->get_keycode() != 0) {
- action2->set_text(0, keycode_get_string(k->get_keycode_with_modifiers()));
- action2->set_icon(0, input_editor->get_theme_icon("Keyboard", "EditorIcons"));
- } else {
- action2->set_text(0, keycode_get_string(k->get_physical_keycode_with_modifiers()) + TTR(" (Physical)"));
- action2->set_icon(0, input_editor->get_theme_icon("KeyboardPhysical", "EditorIcons"));
- }
- }
-
- Ref<InputEventJoypadButton> jb = event;
- if (jb.is_valid()) {
- action2->set_text(0, jb->as_text());
- action2->set_icon(0, input_editor->get_theme_icon("JoyButton", "EditorIcons"));
- }
-
- Ref<InputEventMouseButton> mb = event;
- if (mb.is_valid()) {
- String str = _get_device_string(mb->get_device()) + ", ";
- switch (mb->get_button_index()) {
- case BUTTON_LEFT:
- str += TTR("Left Button");
- break;
- case BUTTON_RIGHT:
- str += TTR("Right Button");
- break;
- case BUTTON_MIDDLE:
- str += TTR("Middle Button");
- break;
- case BUTTON_WHEEL_UP:
- str += TTR("Wheel Up");
- break;
- case BUTTON_WHEEL_DOWN:
- str += TTR("Wheel Down");
- break;
- default:
- str += vformat(TTR("%d Button"), mb->get_button_index());
- }
-
- action2->set_text(0, str);
- action2->set_icon(0, input_editor->get_theme_icon("Mouse", "EditorIcons"));
- }
-
- Ref<InputEventJoypadMotion> jm = event;
- if (jm.is_valid()) {
- device_index->add_item(_get_joypad_motion_event_text(jm));
- action2->set_text(0, jm->as_text());
- action2->set_icon(0, input_editor->get_theme_icon("JoyAxis", "EditorIcons"));
- }
- action2->set_metadata(0, i);
- action2->set_meta("__input", event);
-
- action2->add_button(2, input_editor->get_theme_icon("Edit", "EditorIcons"), 3, false, TTR("Edit"));
- action2->add_button(2, input_editor->get_theme_icon("Remove", "EditorIcons"), 2, false, TTR("Remove"));
- // Fade out the individual event buttons slightly to make the
- // Add/Remove buttons stand out more.
- action2->set_button_color(2, 0, Color(1, 1, 1, 0.75));
- action2->set_button_color(2, 1, Color(1, 1, 1, 0.75));
- }
- }
-
- _action_check(action_name->get_text());
-}
-
-void InputMapEditor::_action_check(String p_action) {
- if (p_action == "") {
- action_add->set_disabled(true);
- } else {
- if (!_validate_action_name(p_action)) {
- action_add_error->set_text(TTR("Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or '\"'."));
- action_add_error->show();
- action_add->set_disabled(true);
- return;
- }
- if (ProjectSettings::get_singleton()->has_setting("input/" + p_action)) {
- action_add_error->set_text(vformat(TTR("An action with the name '%s' already exists."), p_action));
- action_add_error->show();
- action_add->set_disabled(true);
- return;
- }
-
- action_add->set_disabled(false);
- }
-
- action_add_error->hide();
-}
-
-void InputMapEditor::_action_adds(String) {
- if (!action_add->is_disabled()) {
- _action_add();
- }
-}
-
-void InputMapEditor::_action_add() {
- Dictionary action;
- action["events"] = Array();
- action["deadzone"] = 0.5f;
- String name = "input/" + action_name->get_text();
- undo_redo->create_action(TTR("Add Input Action"));
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name);
- undo_redo->add_do_method(this, "_update_actions");
- undo_redo->add_undo_method(this, "_update_actions");
- undo_redo->add_do_method(this, "emit_signal", inputmap_changed);
- undo_redo->add_undo_method(this, "emit_signal", inputmap_changed);
- undo_redo->commit_action();
-
- TreeItem *r = input_editor->get_root();
-
- if (!r) {
- return;
- }
- r = r->get_children();
- if (!r) {
- return;
- }
- while (r->get_next()) {
- r = r->get_next();
- }
-
- r->select(0);
- input_editor->ensure_cursor_is_visible();
- action_add_error->hide();
- action_name->clear();
-}
-
-Variant InputMapEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
- TreeItem *selected = input_editor->get_selected();
- if (!selected || selected->get_parent() != input_editor->get_root()) {
- return Variant();
- }
-
- String name = selected->get_text(0);
- VBoxContainer *vb = memnew(VBoxContainer);
- HBoxContainer *hb = memnew(HBoxContainer);
- Label *label = memnew(Label(name));
- hb->set_modulate(Color(1, 1, 1, 1.0f));
- hb->add_child(label);
- vb->add_child(hb);
- input_editor->set_drag_preview(vb);
-
- Dictionary drag_data;
- drag_data["type"] = "nodes";
-
- input_editor->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
-
- return drag_data;
-}
-
-bool InputMapEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
- Dictionary d = p_data;
- if (!d.has("type") || d["type"] != "nodes") {
- return false;
- }
-
- TreeItem *selected = input_editor->get_selected();
- TreeItem *item = input_editor->get_item_at_position(p_point);
- if (!selected || !item || item == selected || item->get_parent() == selected) {
- return false;
- }
-
- return true;
-}
-
-void InputMapEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
- if (!can_drop_data_fw(p_point, p_data, p_from)) {
- return;
- }
-
- TreeItem *selected = input_editor->get_selected();
- TreeItem *item = input_editor->get_item_at_position(p_point);
- if (!item) {
- return;
- }
- TreeItem *target = item->get_parent() == input_editor->get_root() ? item : item->get_parent();
-
- String selected_name = "input/" + selected->get_text(0);
- int old_order = ProjectSettings::get_singleton()->get_order(selected_name);
- String target_name = "input/" + target->get_text(0);
- int target_order = ProjectSettings::get_singleton()->get_order(target_name);
-
- int order = old_order;
- bool is_below = target_order > old_order;
- TreeItem *iterator = is_below ? selected->get_next() : selected->get_prev();
-
- undo_redo->create_action(TTR("Moved Input Action Event"));
- while (iterator != target) {
- String iterator_name = "input/" + iterator->get_text(0);
- int iterator_order = ProjectSettings::get_singleton()->get_order(iterator_name);
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", iterator_name, order);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", iterator_name, iterator_order);
- order = iterator_order;
- iterator = is_below ? iterator->get_next() : iterator->get_prev();
- }
-
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", target_name, order);
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", selected_name, target_order);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", target_name, target_order);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", selected_name, old_order);
-
- undo_redo->add_do_method(this, "_update_actions");
- undo_redo->add_undo_method(this, "_update_actions");
- undo_redo->add_do_method(this, "emit_signal", inputmap_changed);
- undo_redo->add_undo_method(this, "emit_signal", inputmap_changed);
- undo_redo->commit_action();
-}
-
-void InputMapEditor::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_update_actions"), &InputMapEditor::_update_actions);
-
- ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &InputMapEditor::get_drag_data_fw);
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &InputMapEditor::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &InputMapEditor::drop_data_fw);
-
- ADD_SIGNAL(MethodInfo("inputmap_changed"));
-}
-
-InputMapEditor::InputMapEditor() {
- undo_redo = EditorNode::get_undo_redo();
- press_a_key_physical = false;
- inputmap_changed = "inputmap_changed";
-
- VBoxContainer *vbc = memnew(VBoxContainer);
- vbc->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_BEGIN, 0);
- vbc->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, 0);
- vbc->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 0);
- vbc->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, 0);
- add_child(vbc);
-
- HBoxContainer *hbc = memnew(HBoxContainer);
- vbc->add_child(hbc);
-
- Label *l = memnew(Label);
- l->set_text(TTR("Action:"));
- hbc->add_child(l);
-
- action_name = memnew(LineEdit);
- action_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- action_name->connect("text_entered", callable_mp(this, &InputMapEditor::_action_adds));
- action_name->connect("text_changed", callable_mp(this, &InputMapEditor::_action_check));
- hbc->add_child(action_name);
-
- action_add_error = memnew(Label);
- action_add_error->hide();
- hbc->add_child(action_add_error);
-
- Button *add = memnew(Button);
- add->set_text(TTR("Add"));
- add->set_disabled(true);
- add->connect("pressed", callable_mp(this, &InputMapEditor::_action_add));
- hbc->add_child(add);
- action_add = add;
-
- input_editor = memnew(Tree);
- input_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- input_editor->set_columns(3);
- input_editor->set_column_titles_visible(true);
- input_editor->set_column_title(0, TTR("Action"));
- input_editor->set_column_title(1, TTR("Deadzone"));
- input_editor->set_column_expand(1, false);
- input_editor->set_column_min_width(1, 80 * EDSCALE);
- input_editor->set_column_expand(2, false);
- input_editor->set_column_min_width(2, 50 * EDSCALE);
- input_editor->connect("item_edited", callable_mp(this, &InputMapEditor::_action_edited));
- input_editor->connect("item_activated", callable_mp(this, &InputMapEditor::_action_activated));
- input_editor->connect("cell_selected", callable_mp(this, &InputMapEditor::_action_selected));
- input_editor->connect("button_pressed", callable_mp(this, &InputMapEditor::_action_button_pressed));
-#ifndef _MSC_VER
-#warning need to make drag data forwarding to non controls happen
-#endif
- //input_editor->set_drag_forwarding(this);
- vbc->add_child(input_editor);
-
- // Popups
-
- popup_add = memnew(PopupMenu);
- popup_add->connect("id_pressed", callable_mp(this, &InputMapEditor::_add_item), make_binds(Ref<InputEvent>()));
- add_child(popup_add);
-
- press_a_key = memnew(ConfirmationDialog);
- press_a_key->get_ok_button()->set_disabled(true);
- //press_a_key->set_focus_mode(Control::FOCUS_ALL);
- press_a_key->connect("window_input", callable_mp(this, &InputMapEditor::_wait_for_key));
- press_a_key->connect("confirmed", callable_mp(this, &InputMapEditor::_press_a_key_confirm));
- add_child(press_a_key);
-
- l = memnew(Label);
- l->set_text(TTR("Press a Key..."));
- l->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
- l->set_align(Label::ALIGN_CENTER);
- l->set_offset(SIDE_TOP, 20);
- l->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_BEGIN, 30);
- press_a_key->add_child(l);
- press_a_key_label = l;
-
- device_input = memnew(ConfirmationDialog);
- device_input->get_ok_button()->set_text(TTR("Add"));
- device_input->connect("confirmed", callable_mp(this, &InputMapEditor::_device_input_add));
- add_child(device_input);
-
- hbc = memnew(HBoxContainer);
- device_input->add_child(hbc);
-
- VBoxContainer *vbc_left = memnew(VBoxContainer);
- hbc->add_child(vbc_left);
-
- l = memnew(Label);
- l->set_text(TTR("Device:"));
- vbc_left->add_child(l);
-
- device_id = memnew(OptionButton);
- for (int i = -1; i < 8; i++) {
- device_id->add_item(_get_device_string(i));
- }
- _set_current_device(0);
- vbc_left->add_child(device_id);
-
- VBoxContainer *vbc_right = memnew(VBoxContainer);
- vbc_right->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- hbc->add_child(vbc_right);
-
- l = memnew(Label);
- l->set_text(TTR("Index:"));
- vbc_right->add_child(l);
-
- device_index_label = l;
- device_index = memnew(OptionButton);
- device_index->set_clip_text(true);
- vbc_right->add_child(device_index);
-
- message = memnew(AcceptDialog);
- add_child(message);
-}
diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp
index 60553143d5..0e68af06f0 100644
--- a/editor/localization_editor.cpp
+++ b/editor/localization_editor.cpp
@@ -84,7 +84,7 @@ void LocalizationEditor::add_translation(const String &p_translation) {
}
void LocalizationEditor::_translation_add(const PackedStringArray &p_paths) {
- PackedStringArray translations = ProjectSettings::get_singleton()->get("locale/translations");
+ PackedStringArray translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
for (int i = 0; i < p_paths.size(); i++) {
if (!translations.has(p_paths[i])) {
// Don't add duplicate translation paths.
@@ -93,8 +93,8 @@ void LocalizationEditor::_translation_add(const PackedStringArray &p_paths) {
}
undo_redo->create_action(vformat(TTR("Add %d Translations"), p_paths.size()));
- undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translations", translations);
- undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translations", ProjectSettings::get_singleton()->get("locale/translations"));
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translations", translations);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translations", ProjectSettings::get_singleton()->get("internationalization/locale/translations"));
undo_redo->add_do_method(this, "update_translations");
undo_redo->add_undo_method(this, "update_translations");
undo_redo->add_do_method(this, "emit_signal", localization_changed);
@@ -112,15 +112,15 @@ void LocalizationEditor::_translation_delete(Object *p_item, int p_column, int p
int idx = ti->get_metadata(0);
- PackedStringArray translations = ProjectSettings::get_singleton()->get("locale/translations");
+ PackedStringArray translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
ERR_FAIL_INDEX(idx, translations.size());
translations.remove(idx);
undo_redo->create_action(TTR("Remove Translation"));
- undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translations", translations);
- undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translations", ProjectSettings::get_singleton()->get("locale/translations"));
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translations", translations);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translations", ProjectSettings::get_singleton()->get("internationalization/locale/translations"));
undo_redo->add_do_method(this, "update_translations");
undo_redo->add_undo_method(this, "update_translations");
undo_redo->add_do_method(this, "emit_signal", localization_changed);
@@ -136,8 +136,8 @@ void LocalizationEditor::_translation_res_add(const PackedStringArray &p_paths)
Variant prev;
Dictionary remaps;
- if (ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) {
- remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
+ if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) {
+ remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps");
prev = remaps;
}
@@ -149,8 +149,8 @@ void LocalizationEditor::_translation_res_add(const PackedStringArray &p_paths)
}
undo_redo->create_action(vformat(TTR("Translation Resource Remap: Add %d Path(s)"), p_paths.size()));
- undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translation_remaps", remaps);
- undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translation_remaps", prev);
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", remaps);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", prev);
undo_redo->add_do_method(this, "update_translations");
undo_redo->add_undo_method(this, "update_translations");
undo_redo->add_do_method(this, "emit_signal", localization_changed);
@@ -163,9 +163,9 @@ void LocalizationEditor::_translation_res_option_file_open() {
}
void LocalizationEditor::_translation_res_option_add(const PackedStringArray &p_paths) {
- ERR_FAIL_COND(!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps"));
+ ERR_FAIL_COND(!ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps"));
- Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
+ Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps");
TreeItem *k = translation_remap->get_selected();
ERR_FAIL_COND(!k);
@@ -180,8 +180,8 @@ void LocalizationEditor::_translation_res_option_add(const PackedStringArray &p_
remaps[key] = r;
undo_redo->create_action(vformat(TTR("Translation Resource Remap: Add %d Remap(s)"), p_paths.size()));
- undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translation_remaps", remaps);
- undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translation_remaps", ProjectSettings::get_singleton()->get("locale/translation_remaps"));
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", remaps);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps"));
undo_redo->add_do_method(this, "update_translations");
undo_redo->add_undo_method(this, "update_translations");
undo_redo->add_do_method(this, "emit_signal", localization_changed);
@@ -202,11 +202,11 @@ void LocalizationEditor::_translation_res_option_changed() {
return;
}
- if (!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) {
+ if (!ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) {
return;
}
- Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
+ Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps");
TreeItem *k = translation_remap->get_selected();
ERR_FAIL_COND(!k);
@@ -234,8 +234,8 @@ void LocalizationEditor::_translation_res_option_changed() {
updating_translations = true;
undo_redo->create_action(TTR("Change Resource Remap Language"));
- undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translation_remaps", remaps);
- undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translation_remaps", ProjectSettings::get_singleton()->get("locale/translation_remaps"));
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", remaps);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps"));
undo_redo->add_do_method(this, "update_translations");
undo_redo->add_undo_method(this, "update_translations");
undo_redo->add_do_method(this, "emit_signal", localization_changed);
@@ -249,11 +249,11 @@ void LocalizationEditor::_translation_res_delete(Object *p_item, int p_column, i
return;
}
- if (!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) {
+ if (!ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) {
return;
}
- Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
+ Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps");
TreeItem *k = Object::cast_to<TreeItem>(p_item);
@@ -263,8 +263,8 @@ void LocalizationEditor::_translation_res_delete(Object *p_item, int p_column, i
remaps.erase(key);
undo_redo->create_action(TTR("Remove Resource Remap"));
- undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translation_remaps", remaps);
- undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translation_remaps", ProjectSettings::get_singleton()->get("locale/translation_remaps"));
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", remaps);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps"));
undo_redo->add_do_method(this, "update_translations");
undo_redo->add_undo_method(this, "update_translations");
undo_redo->add_do_method(this, "emit_signal", localization_changed);
@@ -277,11 +277,11 @@ void LocalizationEditor::_translation_res_option_delete(Object *p_item, int p_co
return;
}
- if (!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) {
+ if (!ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) {
return;
}
- Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
+ Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps");
TreeItem *k = translation_remap->get_selected();
ERR_FAIL_COND(!k);
@@ -298,8 +298,8 @@ void LocalizationEditor::_translation_res_option_delete(Object *p_item, int p_co
remaps[key] = r;
undo_redo->create_action(TTR("Remove Resource Remap Option"));
- undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translation_remaps", remaps);
- undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translation_remaps", ProjectSettings::get_singleton()->get("locale/translation_remaps"));
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", remaps);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps"));
undo_redo->add_do_method(this, "update_translations");
undo_redo->add_undo_method(this, "update_translations");
undo_redo->add_do_method(this, "emit_signal", localization_changed);
@@ -316,8 +316,8 @@ void LocalizationEditor::_translation_filter_option_changed() {
Variant prev;
Array f_locales_all;
- if (ProjectSettings::get_singleton()->has_setting("locale/locale_filter")) {
- f_locales_all = ProjectSettings::get_singleton()->get("locale/locale_filter");
+ if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter")) {
+ f_locales_all = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter");
prev = f_locales_all;
if (f_locales_all.size() != 2) {
@@ -346,8 +346,8 @@ void LocalizationEditor::_translation_filter_option_changed() {
f_locales.sort();
undo_redo->create_action(TTR("Changed Locale Filter"));
- undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/locale_filter", f_locales_all);
- undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/locale_filter", prev);
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", f_locales_all);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", prev);
undo_redo->add_do_method(this, "update_translations");
undo_redo->add_undo_method(this, "update_translations");
undo_redo->add_do_method(this, "emit_signal", localization_changed);
@@ -361,8 +361,8 @@ void LocalizationEditor::_translation_filter_mode_changed(int p_mode) {
Variant prev;
Array f_locales_all;
- if (ProjectSettings::get_singleton()->has_setting("locale/locale_filter")) {
- f_locales_all = ProjectSettings::get_singleton()->get("locale/locale_filter");
+ if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter")) {
+ f_locales_all = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter");
prev = f_locales_all;
if (f_locales_all.size() != 2) {
@@ -378,8 +378,8 @@ void LocalizationEditor::_translation_filter_mode_changed(int p_mode) {
}
undo_redo->create_action(TTR("Changed Locale Filter Mode"));
- undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/locale_filter", f_locales_all);
- undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/locale_filter", prev);
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", f_locales_all);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", prev);
undo_redo->add_do_method(this, "update_translations");
undo_redo->add_undo_method(this, "update_translations");
undo_redo->add_do_method(this, "emit_signal", localization_changed);
@@ -388,7 +388,7 @@ void LocalizationEditor::_translation_filter_mode_changed(int p_mode) {
}
void LocalizationEditor::_pot_add(const PackedStringArray &p_paths) {
- PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("locale/translations_pot_files");
+ PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations_pot_files");
for (int i = 0; i < p_paths.size(); i++) {
for (int j = 0; j < pot_translations.size(); j++) {
@@ -401,8 +401,8 @@ void LocalizationEditor::_pot_add(const PackedStringArray &p_paths) {
}
undo_redo->create_action(vformat(TTR("Add %d file(s) for POT generation"), p_paths.size()));
- undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", pot_translations);
- undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", ProjectSettings::get_singleton()->get("locale/translations_pot_files"));
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translations_pot_files", pot_translations);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translations_pot_files", ProjectSettings::get_singleton()->get("internationalization/locale/translations_pot_files"));
undo_redo->add_do_method(this, "update_translations");
undo_redo->add_undo_method(this, "update_translations");
undo_redo->add_do_method(this, "emit_signal", localization_changed);
@@ -416,15 +416,15 @@ void LocalizationEditor::_pot_delete(Object *p_item, int p_column, int p_button)
int idx = ti->get_metadata(0);
- PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("locale/translations_pot_files");
+ PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations_pot_files");
ERR_FAIL_INDEX(idx, pot_translations.size());
pot_translations.remove(idx);
undo_redo->create_action(TTR("Remove file from POT generation"));
- undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", pot_translations);
- undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", ProjectSettings::get_singleton()->get("locale/translations_pot_files"));
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translations_pot_files", pot_translations);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translations_pot_files", ProjectSettings::get_singleton()->get("internationalization/locale/translations_pot_files"));
undo_redo->add_do_method(this, "update_translations");
undo_redo->add_undo_method(this, "update_translations");
undo_redo->add_do_method(this, "emit_signal", localization_changed);
@@ -463,8 +463,8 @@ void LocalizationEditor::update_translations() {
translation_list->clear();
TreeItem *root = translation_list->create_item(nullptr);
translation_list->set_hide_root(true);
- if (ProjectSettings::get_singleton()->has_setting("locale/translations")) {
- PackedStringArray translations = ProjectSettings::get_singleton()->get("locale/translations");
+ if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translations")) {
+ PackedStringArray translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
for (int i = 0; i < translations.size(); i++) {
TreeItem *t = translation_list->create_item(root);
t->set_editable(0, false);
@@ -482,8 +482,8 @@ void LocalizationEditor::update_translations() {
Array l_filter_all;
bool is_arr_empty = true;
- if (ProjectSettings::get_singleton()->has_setting("locale/locale_filter")) {
- l_filter_all = ProjectSettings::get_singleton()->get("locale/locale_filter");
+ if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter")) {
+ l_filter_all = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter");
if (l_filter_all.size() == 2) {
translation_locale_filter_mode->select(l_filter_all[0]);
@@ -573,8 +573,8 @@ void LocalizationEditor::update_translations() {
}
}
- if (ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) {
- Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
+ if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) {
+ Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps");
List<Variant> rk;
remaps.get_key_list(&rk);
Vector<String> keys;
@@ -631,8 +631,8 @@ void LocalizationEditor::update_translations() {
translation_pot_list->clear();
root = translation_pot_list->create_item(nullptr);
translation_pot_list->set_hide_root(true);
- if (ProjectSettings::get_singleton()->has_setting("locale/translations_pot_files")) {
- PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("locale/translations_pot_files");
+ if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translations_pot_files")) {
+ PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations_pot_files");
for (int i = 0; i < pot_translations.size(); i++) {
TreeItem *t = translation_pot_list->create_item(root);
t->set_editable(0, false);
diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp
index bd825d0802..7dcabafece 100644
--- a/editor/node_3d_editor_gizmos.cpp
+++ b/editor/node_3d_editor_gizmos.cpp
@@ -198,7 +198,11 @@ void EditorNode3DGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard,
}
void EditorNode3DGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard, const Color &p_modulate) {
- if (p_lines.is_empty()) {
+ add_vertices(p_lines, p_material, Mesh::PRIMITIVE_LINES, p_billboard, p_modulate);
+}
+
+void EditorNode3DGizmo::add_vertices(const Vector<Vector3> &p_vertices, const Ref<Material> &p_material, Mesh::PrimitiveType p_primitive_type, bool p_billboard, const Color &p_modulate) {
+ if (p_vertices.is_empty()) {
return;
}
@@ -209,13 +213,13 @@ void EditorNode3DGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Mate
Array a;
a.resize(Mesh::ARRAY_MAX);
- a[Mesh::ARRAY_VERTEX] = p_lines;
+ a[Mesh::ARRAY_VERTEX] = p_vertices;
Vector<Color> color;
- color.resize(p_lines.size());
+ color.resize(p_vertices.size());
{
Color *w = color.ptrw();
- for (int i = 0; i < p_lines.size(); i++) {
+ for (int i = 0; i < p_vertices.size(); i++) {
if (is_selected()) {
w[i] = Color(1, 1, 1, 0.8) * p_modulate;
} else {
@@ -226,13 +230,13 @@ void EditorNode3DGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Mate
a[Mesh::ARRAY_COLOR] = color;
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a);
+ mesh->add_surface_from_arrays(p_primitive_type, a);
mesh->surface_set_material(0, p_material);
if (p_billboard) {
float md = 0;
- for (int i = 0; i < p_lines.size(); i++) {
- md = MAX(0, p_lines[i].length());
+ for (int i = 0; i < p_vertices.size(); i++) {
+ md = MAX(0, p_vertices[i].length());
}
if (md) {
mesh->set_custom_aabb(AABB(Vector3(-md, -md, -md), Vector3(md, md, md) * 2.0));
@@ -557,7 +561,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
Transform t = spatial_node->get_global_transform();
Vector3 camera_position = p_camera->get_camera_transform().origin;
if (camera_position.distance_squared_to(t.origin) > 0.01) {
- t.set_look_at(t.origin, camera_position, Vector3(0, 1, 0));
+ t.set_look_at(t.origin, camera_position);
}
float scale = t.origin.distance_to(p_camera->get_camera_transform().origin);
@@ -574,7 +578,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
if (orig_camera_transform.origin.distance_squared_to(t.origin) > 0.01 &&
ABS(orig_camera_transform.basis.get_axis(Vector3::AXIS_Z).dot(Vector3(0, 1, 0))) < 0.99) {
- p_camera->look_at(t.origin, Vector3(0, 1, 0));
+ p_camera->look_at(t.origin);
}
Vector3 c0 = t.xform(Vector3(selectable_icon_size, selectable_icon_size, 0) * scale);
@@ -1906,16 +1910,15 @@ void RayCast3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
p_gizmo->clear();
- Vector<Vector3> lines;
+ const Ref<StandardMaterial3D> material = raycast->is_enabled() ? raycast->get_debug_material() : get_material("shape_material_disabled");
- lines.push_back(Vector3());
- lines.push_back(raycast->get_target_position());
+ p_gizmo->add_lines(raycast->get_debug_line_vertices(), material);
- const Ref<StandardMaterial3D> material =
- get_material(raycast->is_enabled() ? "shape_material" : "shape_material_disabled", p_gizmo);
+ if (raycast->get_debug_shape_thickness() > 1) {
+ p_gizmo->add_vertices(raycast->get_debug_shape_vertices(), material, Mesh::PRIMITIVE_TRIANGLE_STRIP);
+ }
- p_gizmo->add_lines(lines, material);
- p_gizmo->add_collision_segments(lines);
+ p_gizmo->add_collision_segments(raycast->get_debug_line_vertices());
}
/////
@@ -2070,7 +2073,13 @@ void SoftBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Ref<TriangleMesh> tm = soft_body->get_mesh()->generate_triangle_mesh();
Vector<Vector3> points;
- soft_body->get_mesh()->generate_debug_mesh_indices(points);
+ for (int i = 0; i < soft_body->get_mesh()->get_surface_count(); i++) {
+ Array arrays = soft_body->get_mesh()->surface_get_arrays(i);
+ ERR_CONTINUE(arrays.is_empty());
+
+ const Vector<Vector3> &vertices = arrays[Mesh::ARRAY_VERTEX];
+ points.append_array(vertices);
+ }
Ref<Material> material = get_material("shape_material", p_gizmo);
@@ -3505,6 +3514,57 @@ void LightmapProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
////
+CollisionObject3DGizmoPlugin::CollisionObject3DGizmoPlugin() {
+ const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
+ create_material("shape_material", gizmo_color);
+ const float gizmo_value = gizmo_color.get_v();
+ const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65);
+ create_material("shape_material_disabled", gizmo_color_disabled);
+}
+
+bool CollisionObject3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
+ return Object::cast_to<CollisionObject3D>(p_spatial) != nullptr;
+}
+
+String CollisionObject3DGizmoPlugin::get_gizmo_name() const {
+ return "CollisionObject3D";
+}
+
+int CollisionObject3DGizmoPlugin::get_priority() const {
+ return -2;
+}
+
+void CollisionObject3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
+ CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_gizmo->get_spatial_node());
+
+ p_gizmo->clear();
+
+ List<uint32_t> owners;
+ co->get_shape_owners(&owners);
+ for (List<uint32_t>::Element *E = owners.front(); E; E = E->next()) {
+ uint32_t owner_id = E->get();
+ Transform xform = co->shape_owner_get_transform(owner_id);
+ Object *owner = co->shape_owner_get_owner(owner_id);
+ // Exclude CollisionShape3D and CollisionPolygon3D as they have their gizmo.
+ if (!Object::cast_to<CollisionShape3D>(owner) && !Object::cast_to<CollisionPolygon3D>(owner)) {
+ Ref<Material> material = get_material(!co->is_shape_owner_disabled(owner_id) ? "shape_material" : "shape_material_disabled", p_gizmo);
+ for (int shape_id = 0; shape_id < co->shape_owner_get_shape_count(owner_id); shape_id++) {
+ Ref<Shape3D> s = co->shape_owner_get_shape(owner_id, shape_id);
+ if (s.is_null()) {
+ continue;
+ }
+ SurfaceTool st;
+ st.append_from(s->get_debug_mesh(), 0, xform);
+
+ p_gizmo->add_mesh(st.commit(), false, Ref<SkinReference>(), material);
+ p_gizmo->add_collision_segments(s->get_debug_mesh_lines());
+ }
+ }
+ }
+}
+
+////
+
CollisionShape3DGizmoPlugin::CollisionShape3DGizmoPlugin() {
const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
create_material("shape_material", gizmo_color);
diff --git a/editor/node_3d_editor_gizmos.h b/editor/node_3d_editor_gizmos.h
index df4ed15a8e..6f98d3a08c 100644
--- a/editor/node_3d_editor_gizmos.h
+++ b/editor/node_3d_editor_gizmos.h
@@ -355,6 +355,18 @@ public:
LightmapProbeGizmoPlugin();
};
+class CollisionObject3DGizmoPlugin : public EditorNode3DGizmoPlugin {
+ GDCLASS(CollisionObject3DGizmoPlugin, EditorNode3DGizmoPlugin);
+
+public:
+ bool has_gizmo(Node3D *p_spatial) override;
+ String get_gizmo_name() const override;
+ int get_priority() const override;
+ void redraw(EditorNode3DGizmo *p_gizmo) override;
+
+ CollisionObject3DGizmoPlugin();
+};
+
class CollisionShape3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(CollisionShape3DGizmoPlugin, EditorNode3DGizmoPlugin);
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index 19c9662162..f496811e0a 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -86,7 +86,7 @@ void PluginConfigDialog::_on_confirmed() {
// Hard-coded GDScript template to keep usability until we use script templates.
Ref<Script> gdscript = memnew(GDScript);
gdscript->set_source_code(
- "tool\n"
+ "@tool\n"
"extends EditorPlugin\n"
"\n"
"\n"
@@ -112,7 +112,7 @@ void PluginConfigDialog::_on_confirmed() {
}
#endif
- emit_signal("plugin_ready", script.operator->(), active_edit->is_pressed() ? subfolder_edit->get_text() : "");
+ emit_signal("plugin_ready", script.operator->(), active_edit->is_pressed() ? _to_absolute_plugin_path(subfolder_edit->get_text()) : "");
} else {
EditorNode::get_singleton()->get_project_settings()->update_plugins();
}
@@ -129,6 +129,10 @@ void PluginConfigDialog::_on_required_text_changed(const String &) {
get_ok_button()->set_disabled(script_edit->get_text().get_basename().is_empty() || script_edit->get_text().get_extension() != ext || name_edit->get_text().is_empty());
}
+String PluginConfigDialog::_to_absolute_plugin_path(const String &p_plugin_name) {
+ return "res://addons/" + p_plugin_name + "/plugin.cfg";
+}
+
void PluginConfigDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
diff --git a/editor/plugin_config_dialog.h b/editor/plugin_config_dialog.h
index 50ca417d81..f49f14c881 100644
--- a/editor/plugin_config_dialog.h
+++ b/editor/plugin_config_dialog.h
@@ -56,6 +56,8 @@ class PluginConfigDialog : public ConfirmationDialog {
void _on_cancelled();
void _on_required_text_changed(const String &p_text);
+ static String _to_absolute_plugin_path(const String &p_plugin_name);
+
protected:
virtual void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index 876b67fa77..80d0a7db60 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -264,7 +264,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position())));
if (mode == MODE_EDIT || (_is_line() && mode == MODE_CREATE)) {
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
if (mb->get_control() || mb->get_shift() || mb->get_alt()) {
return false;
@@ -326,7 +326,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
return true;
}
}
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && !edited_point.valid()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && !edited_point.valid()) {
const PosVertex closest = closest_point(gpoint);
if (closest.valid()) {
@@ -335,7 +335,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
}
}
} else if (mode == MODE_DELETE) {
- if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) {
const PosVertex closest = closest_point(gpoint);
if (closest.valid()) {
@@ -346,7 +346,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
}
if (mode == MODE_CREATE) {
- if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) {
if (_is_line()) {
// for lines, we don't have a wip mode, and we can undo each single add point.
Vector<Vector2> vertices = _get_polygon(0);
@@ -384,7 +384,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
return true;
}
}
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && wip_active) {
_wip_cancel();
}
}
@@ -395,7 +395,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
if (mm.is_valid()) {
Vector2 gpoint = mm->get_position();
- if (edited_point.valid() && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) {
+ if (edited_point.valid() && (wip_active || (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT))) {
Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)));
//Move the point in a single axis. Should only work when editing a polygon and while holding shift.
@@ -585,11 +585,11 @@ void AbstractPolygon2DEditor::edit(Node *p_polygon) {
edited_point = PosVertex();
hover_point = Vertex();
selected_point = Vertex();
-
- canvas_item_editor->update_viewport();
} else {
_set_node(nullptr);
}
+
+ canvas_item_editor->update_viewport();
}
void AbstractPolygon2DEditor::_bind_methods() {
diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp
index d69913cc46..025fcaf818 100644
--- a/editor/plugins/animation_blend_space_1d_editor.cpp
+++ b/editor/plugins/animation_blend_space_1d_editor.cpp
@@ -51,7 +51,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) || (mb->get_button_index() == BUTTON_LEFT && tool_create->is_pressed()))) {
+ if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && tool_create->is_pressed()))) {
menu->clear();
animations_menu->clear();
animations_to_add.clear();
@@ -110,7 +110,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
}
}
- if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
blend_space_draw->update(); // why not
// try to see if a point can be selected
@@ -132,7 +132,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
}
}
- if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (dragging_selected) {
// move
float point = blend_space->get_blend_point_position(selected_point);
@@ -161,7 +161,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
}
// *set* the blend
- if (mb.is_valid() && !mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && !mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
float blend_pos = mb->get_position().x / blend_space_draw->get_size().x;
blend_pos *= blend_space->get_max_space() - blend_space->get_min_space();
blend_pos += blend_space->get_min_space();
@@ -184,7 +184,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
_update_edited_point_pos();
}
- if (mm.is_valid() && tool_blend->is_pressed() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mm.is_valid() && tool_blend->is_pressed() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
float blend_pos = mm->get_position().x / blend_space_draw->get_size().x;
blend_pos *= blend_space->get_max_space() - blend_space->get_min_space();
blend_pos += blend_space->get_min_space();
diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp
index 6a57463dbc..af9c391174 100644
--- a/editor/plugins/animation_blend_space_2d_editor.cpp
+++ b/editor/plugins/animation_blend_space_2d_editor.cpp
@@ -79,7 +79,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) || (mb->get_button_index() == BUTTON_LEFT && tool_create->is_pressed()))) {
+ if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && tool_create->is_pressed()))) {
menu->clear();
animations_menu->clear();
animations_to_add.clear();
@@ -134,7 +134,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
}
}
- if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
blend_space_draw->update(); //update anyway
//try to see if a point can be selected
selected_point = -1;
@@ -174,7 +174,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
}
}
- if (mb.is_valid() && mb->is_pressed() && tool_triangle->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && tool_triangle->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
blend_space_draw->update(); //update anyway
//try to see if a point can be selected
selected_point = -1;
@@ -209,7 +209,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
}
}
- if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (dragging_selected) {
//move
Vector2 point = blend_space->get_blend_point_position(selected_point);
@@ -236,7 +236,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
blend_space_draw->update();
}
- if (mb.is_valid() && mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
Vector2 blend_pos = (mb->get_position() / blend_space_draw->get_size());
blend_pos.y = 1.0 - blend_pos.y;
blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
@@ -270,7 +270,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
blend_space_draw->update();
}
- if (mm.is_valid() && tool_blend->is_pressed() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mm.is_valid() && tool_blend->is_pressed() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
Vector2 blend_pos = (mm->get_position() / blend_space_draw->get_size());
blend_pos.y = 1.0 - blend_pos.y;
blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index e7e069e8b6..fdbbe5184b 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -139,7 +139,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
name->set_expand_to_text_length(true);
node->add_child(name);
node->set_slot(0, false, 0, Color(), true, 0, get_theme_color("font_color", "Label"));
- name->connect("text_entered", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed), varray(agnode));
+ name->connect("text_entered", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed), varray(agnode), CONNECT_DEFERRED);
name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out), varray(name, agnode), CONNECT_DEFERRED);
base = 1;
node->set_show_close_button(true);
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 56d82acd2f..7c623505b5 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -78,7 +78,6 @@ void AnimationPlayerEditor::_notification(int p_what) {
}
frame->set_value(player->get_current_animation_position());
track_editor->set_anim_pos(player->get_current_animation_position());
- EditorNode::get_singleton()->get_inspector()->refresh();
} else if (!player->is_valid()) {
// Reset timeline when the player has been stopped externally
@@ -1072,8 +1071,6 @@ void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_drag)
frame->set_value(Math::snapped(p_pos, _get_editor_step()));
updating = false;
_seek_value_changed(p_pos, !p_drag);
-
- EditorNode::get_singleton()->get_inspector()->refresh();
}
void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
@@ -1400,7 +1397,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() {
// Render every past/future step with the capture shader.
RS::get_singleton()->canvas_item_set_material(onion.capture.canvas_item, onion.capture.material->get_rid());
- onion.capture.material->set_shader_param("bkg_color", GLOBAL_GET("rendering/environment/default_clear_color"));
+ onion.capture.material->set_shader_param("bkg_color", GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
onion.capture.material->set_shader_param("differences_only", onion.differences_only);
onion.capture.material->set_shader_param("present", onion.differences_only ? RS::get_singleton()->viewport_get_texture(present_rid) : RID());
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index c6d2faf849..a9709bbb16 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -76,7 +76,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
Ref<InputEventMouseButton> mb = p_event;
//Add new node
- if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) || (tool_create->is_pressed() && mb->get_button_index() == BUTTON_LEFT))) {
+ if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) || (tool_create->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT))) {
menu->clear();
animations_menu->clear();
animations_to_add.clear();
@@ -124,7 +124,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
}
// select node or push a field inside
- if (mb.is_valid() && !mb->get_shift() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && !mb->get_shift() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
selected_transition_from = StringName();
selected_transition_to = StringName();
selected_node = StringName();
@@ -216,7 +216,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
}
//end moving node
- if (mb.is_valid() && dragging_selected_attempt && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) {
+ if (mb.is_valid() && dragging_selected_attempt && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) {
if (dragging_selected) {
Ref<AnimationNode> an = state_machine->get_node(selected_node);
updating = true;
@@ -237,7 +237,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
}
//connect nodes
- if (mb.is_valid() && ((tool_select->is_pressed() && mb->get_shift()) || tool_connect->is_pressed()) && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
+ if (mb.is_valid() && ((tool_select->is_pressed() && mb->get_shift()) || tool_connect->is_pressed()) && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) {
for (int i = node_rects.size() - 1; i >= 0; i--) { //inverse to draw order
if (node_rects[i].node.has_point(mb->get_position())) { //select node since nothing else was selected
connecting = true;
@@ -250,7 +250,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
}
//end connecting nodes
- if (mb.is_valid() && connecting && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) {
+ if (mb.is_valid() && connecting && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) {
if (connecting_to_node != StringName()) {
if (state_machine->has_transition(connecting_from, connecting_to_node)) {
EditorNode::get_singleton()->show_warning(TTR("Transition exists!"));
@@ -284,7 +284,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
Ref<InputEventMouseMotion> mm = p_event;
//pan window
- if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_MIDDLE) {
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) {
h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x);
v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y);
}
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index d726cd031e..b7484aa748 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -350,7 +350,7 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int
if (sha256 != download_sha256) {
error_text = TTR("Bad download hash, assuming file has been tampered with.") + "\n";
error_text += TTR("Expected:") + " " + sha256 + "\n" + TTR("Got:") + " " + download_sha256;
- status->set_text(TTR("Failed sha256 hash check"));
+ status->set_text(TTR("Failed SHA-256 hash check"));
}
}
} break;
@@ -359,6 +359,8 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int
if (error_text != String()) {
download_error->set_text(TTR("Asset Download Error:") + "\n" + error_text);
download_error->popup_centered();
+ // Let the user retry the download.
+ retry->show();
return;
}
@@ -459,6 +461,9 @@ void EditorAssetLibraryItemDownload::_install() {
}
void EditorAssetLibraryItemDownload::_make_request() {
+ // Hide the Retry button if we've just pressed it.
+ retry->hide();
+
download->cancel_request();
download->set_download_file(EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_asset_" + itos(asset_id)) + ".zip");
@@ -516,6 +521,8 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() {
retry = memnew(Button);
retry->set_text(TTR("Retry"));
retry->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDownload::_make_request));
+ // Only show the Retry button in case of a failure.
+ retry->hide();
hb2->add_child(retry);
hb2->add_child(install);
@@ -577,6 +584,24 @@ void EditorAssetLibrary::_notification(int p_what) {
filter->set_right_icon(get_theme_icon("Search", "EditorIcons"));
filter->set_clear_button_enabled(true);
} break;
+
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+ _update_repository_options();
+ } break;
+ }
+}
+
+void EditorAssetLibrary::_update_repository_options() {
+ Dictionary default_urls;
+ default_urls["godotengine.org"] = "https://godotengine.org/asset-library/api";
+ default_urls["localhost"] = "http://127.0.0.1/asset-library/api";
+ Dictionary available_urls = _EDITOR_DEF("asset_library/available_urls", default_urls, true);
+ repository->clear();
+ Array keys = available_urls.keys();
+ for (int i = 0; i < available_urls.size(); i++) {
+ String key = keys[i];
+ repository->add_item(key);
+ repository->set_item_metadata(i, available_urls[key]);
}
}
@@ -962,14 +987,16 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int
for (int i = from; i < to; i++) {
if (i == p_page) {
Button *current = memnew(Button);
- current->set_text(itos(i + 1));
+ // Keep the extended padding for the currently active page (see below).
+ current->set_text(vformat(" %d ", i + 1));
current->set_disabled(true);
current->set_focus_mode(Control::FOCUS_NONE);
hbc->add_child(current);
} else {
Button *current = memnew(Button);
- current->set_text(itos(i + 1));
+ // Add padding to make page number buttons easier to click.
+ current->set_text(vformat(" %d ", i + 1));
current->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(i));
hbc->add_child(current);
@@ -1364,18 +1391,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
search_hb2->add_child(memnew(Label(TTR("Site:") + " ")));
repository = memnew(OptionButton);
- {
- Dictionary default_urls;
- default_urls["godotengine.org"] = "https://godotengine.org/asset-library/api";
- default_urls["localhost"] = "http://127.0.0.1/asset-library/api";
- Dictionary available_urls = _EDITOR_DEF("asset_library/available_urls", default_urls, true);
- Array keys = available_urls.keys();
- for (int i = 0; i < available_urls.size(); i++) {
- String key = keys[i];
- repository->add_item(key);
- repository->set_item_metadata(i, available_urls[key]);
- }
- }
+ _update_repository_options();
repository->connect("item_selected", callable_mp(this, &EditorAssetLibrary::_repository_changed));
@@ -1387,6 +1403,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
support = memnew(MenuButton);
search_hb2->add_child(support);
support->set_text(TTR("Support"));
+ support->get_popup()->set_hide_on_checkable_item_selection(false);
support->get_popup()->add_check_item(TTR("Official"), SUPPORT_OFFICIAL);
support->get_popup()->add_check_item(TTR("Community"), SUPPORT_COMMUNITY);
support->get_popup()->add_check_item(TTR("Testing"), SUPPORT_TESTING);
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index 0509145673..11eae9e041 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -176,6 +176,7 @@ class EditorAssetLibrary : public PanelContainer {
void _asset_open();
void _asset_file_selected(const String &p_file);
+ void _update_repository_options();
PanelContainer *library_scroll_bg;
ScrollContainer *library_scroll;
diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp
index 1765c99572..3553450672 100644
--- a/editor/plugins/audio_stream_editor_plugin.cpp
+++ b/editor/plugins/audio_stream_editor_plugin.cpp
@@ -96,7 +96,7 @@ void AudioStreamEditor::_preview_changed(ObjectID p_which) {
}
}
-void AudioStreamEditor::_changed_callback(Object *p_changed, const char *p_prop) {
+void AudioStreamEditor::_audio_changed() {
if (!is_visible()) {
return;
}
@@ -105,6 +105,8 @@ void AudioStreamEditor::_changed_callback(Object *p_changed, const char *p_prop)
void AudioStreamEditor::_play() {
if (_player->is_playing()) {
+ // '_pausing' variable indicates that we want to pause the audio player, not stop it. See '_on_finished()'.
+ _pausing = true;
_player->stop();
_play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons"));
set_process(false);
@@ -125,10 +127,13 @@ void AudioStreamEditor::_stop() {
void AudioStreamEditor::_on_finished() {
_play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons"));
- if (_current == _player->get_stream()->get_length()) {
+ if (!_pausing) {
_current = 0;
_indicator->update();
+ } else {
+ _pausing = false;
}
+ set_process(false);
}
void AudioStreamEditor::_draw_indicator() {
@@ -172,7 +177,7 @@ void AudioStreamEditor::_seek_to(real_t p_x) {
void AudioStreamEditor::edit(Ref<AudioStream> p_stream) {
if (!stream.is_null()) {
- stream->remove_change_receptor(this);
+ stream->disconnect("changed", callable_mp(this, &AudioStreamEditor::_audio_changed));
}
stream = p_stream;
@@ -182,7 +187,7 @@ void AudioStreamEditor::edit(Ref<AudioStream> p_stream) {
_duration_label->set_text(text);
if (!stream.is_null()) {
- stream->add_change_receptor(this);
+ stream->connect("changed", callable_mp(this, &AudioStreamEditor::_audio_changed));
update();
} else {
hide();
@@ -194,8 +199,6 @@ void AudioStreamEditor::_bind_methods() {
AudioStreamEditor::AudioStreamEditor() {
set_custom_minimum_size(Size2(1, 100) * EDSCALE);
- _current = 0;
- _dragging = false;
_player = memnew(AudioStreamPlayer);
_player->connect("finished", callable_mp(this, &AudioStreamEditor::_on_finished));
diff --git a/editor/plugins/audio_stream_editor_plugin.h b/editor/plugins/audio_stream_editor_plugin.h
index f27add7229..14e829d025 100644
--- a/editor/plugins/audio_stream_editor_plugin.h
+++ b/editor/plugins/audio_stream_editor_plugin.h
@@ -41,17 +41,20 @@ class AudioStreamEditor : public ColorRect {
GDCLASS(AudioStreamEditor, ColorRect);
Ref<AudioStream> stream;
- AudioStreamPlayer *_player;
- ColorRect *_preview;
- Control *_indicator;
- Label *_current_label;
- Label *_duration_label;
+ AudioStreamPlayer *_player = nullptr;
+ ColorRect *_preview = nullptr;
+ Control *_indicator = nullptr;
+ Label *_current_label = nullptr;
+ Label *_duration_label = nullptr;
- Button *_play_button;
- Button *_stop_button;
+ Button *_play_button = nullptr;
+ Button *_stop_button = nullptr;
- float _current;
- bool _dragging;
+ float _current = 0;
+ bool _dragging = false;
+ bool _pausing = false;
+
+ void _audio_changed();
protected:
void _notification(int p_what);
@@ -63,7 +66,6 @@ protected:
void _draw_indicator();
void _on_input_indicator(Ref<InputEvent> p_event);
void _seek_to(real_t p_x);
- void _changed_callback(Object *p_changed, const char *p_prop) override;
static void _bind_methods();
public:
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index d92837b68d..d4e06aa9ca 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -629,9 +629,9 @@ void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_Sel
Node *node = r_items[i].item;
// Make sure the selected node is in the current scene, or editable
- while (node && node != get_tree()->get_edited_scene_root() && node->get_owner() != scene && !scene->is_editable_instance(node->get_owner())) {
- node = node->get_parent();
- };
+ if (node && node != get_tree()->get_edited_scene_root()) {
+ node = scene->get_deepest_editable_node(node);
+ }
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(node);
if (!p_allow_locked) {
@@ -762,7 +762,7 @@ void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_n
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
Node *scene = editor->get_edited_scene();
- bool editable = p_node == scene || p_node->get_owner() == scene || scene->is_editable_instance(p_node->get_owner());
+ bool editable = p_node == scene || p_node->get_owner() == scene || p_node == scene->get_deepest_editable_node(p_node);
bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_");
bool locked = _is_node_locked(p_node);
@@ -955,9 +955,11 @@ void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_it
for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- canvas_item->_edit_set_state(se->undo_state);
- if (restore_bones) {
- _restore_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_undo_state));
+ if (se) {
+ canvas_item->_edit_set_state(se->undo_state);
+ if (restore_bones) {
+ _restore_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_undo_state));
+ }
}
}
}
@@ -982,13 +984,15 @@ void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_ite
for (List<CanvasItem *>::Element *E = modified_canvas_items.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
- undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state);
- if (commit_bones) {
- for (List<Dictionary>::Element *F = se->pre_drag_bones_undo_state.front(); F; F = F->next()) {
- canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
- undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
- undo_redo->add_undo_method(canvas_item, "_edit_set_state", F->get());
+ if (se) {
+ undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
+ undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state);
+ if (commit_bones) {
+ for (List<Dictionary>::Element *F = se->pre_drag_bones_undo_state.front(); F; F = F->next()) {
+ canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
+ undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
+ undo_redo->add_undo_method(canvas_item, "_edit_set_state", F->get());
+ }
}
}
}
@@ -1021,6 +1025,32 @@ void CanvasItemEditor::_selection_menu_hide() {
selection_menu->set_size(Vector2(0, 0));
}
+void CanvasItemEditor::_add_node_pressed(int p_result) {
+ if (p_result == AddNodeOption::ADD_NODE) {
+ editor->get_scene_tree_dock()->open_add_child_dialog();
+ } else if (p_result == AddNodeOption::ADD_INSTANCE) {
+ editor->get_scene_tree_dock()->open_instance_child_dialog();
+ }
+}
+
+void CanvasItemEditor::_node_created(Node *p_node) {
+ if (node_create_position == Point2()) {
+ return;
+ }
+
+ CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
+ if (c) {
+ Transform2D xform = c->get_global_transform_with_canvas().affine_inverse() * c->get_transform();
+ c->_edit_set_position(xform.xform(node_create_position));
+ }
+
+ call_deferred("_reset_create_position"); // Defer the call in case more than one node is added.
+}
+
+void CanvasItemEditor::_reset_create_position() {
+ node_create_position = Point2();
+}
+
bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> b = p_event;
Ref<InputEventMouseMotion> m = p_event;
@@ -1065,7 +1095,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve
}
// Start dragging a guide
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) {
// Press button
if (b->get_position().x < RULER_WIDTH && b->get_position().y < RULER_WIDTH) {
// Drag a new double guide
@@ -1124,7 +1154,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve
}
// Release confirms the guide move
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) {
if (show_guides && EditorNode::get_singleton()->get_edited_scene()) {
Transform2D xform = viewport_scrollable->get_transform() * transform;
@@ -1238,7 +1268,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
if (pan_on_scroll) {
// Perform horizontal scrolling first so we can check for Shift being held.
if (b->is_pressed() &&
- (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_UP))) {
+ (b->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT || (b->get_shift() && b->get_button_index() == MOUSE_BUTTON_WHEEL_UP))) {
// Pan left
view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
update_viewport();
@@ -1246,7 +1276,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
}
if (b->is_pressed() &&
- (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_DOWN))) {
+ (b->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT || (b->get_shift() && b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN))) {
// Pan right
view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
update_viewport();
@@ -1254,7 +1284,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
}
}
- if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_DOWN) {
+ if (b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
// Scroll or pan down
if (pan_on_scroll) {
view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
@@ -1269,7 +1299,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
return true;
}
- if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_UP) {
+ if (b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
// Scroll or pan up
if (pan_on_scroll) {
view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
@@ -1286,17 +1316,17 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
if (!panning) {
if (b->is_pressed() &&
- (b->get_button_index() == BUTTON_MIDDLE ||
- b->get_button_index() == BUTTON_RIGHT ||
- (b->get_button_index() == BUTTON_LEFT && tool == TOOL_PAN) ||
- (b->get_button_index() == BUTTON_LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_panning") && pan_pressed))) {
+ (b->get_button_index() == MOUSE_BUTTON_MIDDLE ||
+ b->get_button_index() == MOUSE_BUTTON_RIGHT ||
+ (b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_PAN) ||
+ (b->get_button_index() == MOUSE_BUTTON_LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_panning") && pan_pressed))) {
// Pan the viewport
panning = true;
}
}
if (panning) {
- if (!b->is_pressed() && (pan_on_scroll || (b->get_button_index() != BUTTON_WHEEL_DOWN && b->get_button_index() != BUTTON_WHEEL_UP))) {
+ if (!b->is_pressed() && (pan_on_scroll || (b->get_button_index() != MOUSE_BUTTON_WHEEL_DOWN && b->get_button_index() != MOUSE_BUTTON_WHEEL_UP))) {
// Stop panning the viewport (for any mouse button press except zooming)
panning = false;
}
@@ -1382,7 +1412,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
// Drag the pivot (in pivot mode / with V key)
if (drag_type == DRAG_NONE) {
- if ((b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
+ if ((b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
(k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_V)) {
List<CanvasItem *> selection = _get_edited_canvas_items();
@@ -1436,7 +1466,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
// Confirm the pivot move
if (drag_selection.size() >= 1 &&
- ((b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
+ ((b.is_valid() && !b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
(k.is_valid() && !k->is_pressed() && k->get_keycode() == KEY_V))) {
_commit_canvas_item_state(
drag_selection,
@@ -1450,7 +1480,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
}
// Cancel a drag
- if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) {
_restore_canvas_item_state(drag_selection);
drag_type = DRAG_NONE;
viewport->update();
@@ -1536,7 +1566,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
// Start rotation
if (drag_type == DRAG_NONE) {
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) {
if ((b->get_command() && !b->get_alt() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
List<CanvasItem *> selection = _get_edited_canvas_items();
@@ -1580,7 +1610,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
}
// Confirms the node rotation
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) {
if (drag_selection.size() != 1) {
_commit_canvas_item_state(
drag_selection,
@@ -1604,7 +1634,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
}
// Cancel a drag
- if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) {
_restore_canvas_item_state(drag_selection);
drag_type = DRAG_NONE;
viewport->update();
@@ -1618,7 +1648,7 @@ bool CanvasItemEditor::_gui_input_open_scene_on_double_click(const Ref<InputEven
Ref<InputEventMouseButton> b = p_event;
// Open a sub-scene on double-click
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && b->is_doubleclick() && tool == TOOL_SELECT) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && b->is_doubleclick() && tool == TOOL_SELECT) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (selection.size() == 1) {
CanvasItem *canvas_item = selection[0];
@@ -1637,7 +1667,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
// Starts anchor dragging if needed
if (drag_type == DRAG_NONE) {
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (selection.size() == 1) {
Control *control = Object::cast_to<Control>(selection[0]);
@@ -1757,7 +1787,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
}
// Confirms new anchor position
- if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
+ if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) {
_commit_canvas_item_state(
drag_selection,
vformat(TTR("Move CanvasItem \"%s\" Anchor"), drag_selection[0]->get_name()));
@@ -1766,7 +1796,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
}
// Cancel a drag
- if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) {
_restore_canvas_item_state(drag_selection);
drag_type = DRAG_NONE;
viewport->update();
@@ -1782,7 +1812,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
// Drag resize handles
if (drag_type == DRAG_NONE) {
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (selection.size() == 1) {
CanvasItem *canvas_item = selection[0];
@@ -1936,7 +1966,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
}
// Confirm resize
- if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
+ if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) {
const Node2D *node2d = Object::cast_to<Node2D>(drag_selection[0]);
if (node2d) {
// Extends from Node2D.
@@ -1973,7 +2003,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
}
// Cancel a drag
- if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) {
_restore_canvas_item_state(drag_selection);
snap_target[0] = SNAP_TARGET_NONE;
snap_target[1] = SNAP_TARGET_NONE;
@@ -1991,7 +2021,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
// Drag resize handles
if (drag_type == DRAG_NONE) {
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && ((b->get_alt() && b->get_control()) || tool == TOOL_SCALE)) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && ((b->get_alt() && b->get_control()) || tool == TOOL_SCALE)) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (selection.size() == 1) {
CanvasItem *canvas_item = selection[0];
@@ -2087,7 +2117,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
}
// Confirm resize
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) {
if (drag_selection.size() != 1) {
_commit_canvas_item_state(
drag_selection,
@@ -2112,7 +2142,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
}
// Cancel a drag
- if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) {
_restore_canvas_item_state(drag_selection);
drag_type = DRAG_NONE;
viewport->update();
@@ -2129,7 +2159,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
if (drag_type == DRAG_NONE) {
//Start moving the nodes
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) {
if ((b->get_alt() && !b->get_control()) || tool == TOOL_MOVE) {
List<CanvasItem *> selection = _get_edited_canvas_items();
@@ -2212,17 +2242,19 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
-
- Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
- if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) {
- real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
- _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
- real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
- node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
- _solve_IK(node2d, new_pos);
- } else {
- canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
+ if (se) {
+ Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
+
+ Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
+ if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) {
+ real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
+ _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
+ real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
+ node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
+ _solve_IK(node2d, new_pos);
+ } else {
+ canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
+ }
}
index++;
}
@@ -2230,7 +2262,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
}
// Confirm the move (only if it was moved)
- if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) {
+ if (b.is_valid() && !b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT) {
if (transform.affine_inverse().xform(b->get_position()) != drag_from) {
if (drag_selection.size() != 1) {
_commit_canvas_item_state(
@@ -2263,7 +2295,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
}
// Cancel a drag
- if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) {
_restore_canvas_item_state(drag_selection, true);
snap_target[0] = SNAP_TARGET_NONE;
snap_target[1] = SNAP_TARGET_NONE;
@@ -2346,17 +2378,19 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
-
- Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
- if (node2d && se->pre_drag_bones_undo_state.size() > 0) {
- real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
- _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
- real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
- node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
- _solve_IK(node2d, new_pos);
- } else {
- canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
+ if (se) {
+ Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
+
+ Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
+ if (node2d && se->pre_drag_bones_undo_state.size() > 0) {
+ real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
+ _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
+ real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
+ node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
+ _solve_IK(node2d, new_pos);
+ } else {
+ canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
+ }
}
index++;
}
@@ -2401,8 +2435,8 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
if (drag_type == DRAG_NONE) {
if (b.is_valid() &&
- ((b->get_button_index() == BUTTON_RIGHT && b->get_alt() && tool == TOOL_SELECT) ||
- (b->get_button_index() == BUTTON_LEFT && tool == TOOL_LIST_SELECT))) {
+ ((b->get_button_index() == MOUSE_BUTTON_RIGHT && b->get_alt() && tool == TOOL_SELECT) ||
+ (b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_LIST_SELECT))) {
// Popup the selection menu list
Point2 click = transform.affine_inverse().xform(b->get_position());
@@ -2463,7 +2497,15 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
}
}
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
+ if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->get_control()) {
+ add_node_menu->set_position(get_global_transform().xform(get_local_mouse_position()));
+ add_node_menu->set_size(Vector2(1, 1));
+ add_node_menu->popup();
+ node_create_position = transform.affine_inverse().xform((get_local_mouse_position()));
+ return true;
+ }
+
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
// Single item selection
Point2 click = transform.affine_inverse().xform(b->get_position());
@@ -2529,7 +2571,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
}
if (drag_type == DRAG_BOX_SELECTION) {
- if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) {
+ if (b.is_valid() && !b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT) {
// Confirms box selection
Node *scene = editor->get_edited_scene();
if (scene) {
@@ -2555,7 +2597,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
return true;
}
- if (b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_RIGHT) {
+ if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT) {
// Cancel box selection
drag_type = DRAG_NONE;
viewport->update();
@@ -2580,6 +2622,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
bool CanvasItemEditor::_gui_input_ruler_tool(const Ref<InputEvent> &p_event) {
if (tool != TOOL_RULER) {
+ ruler_tool_active = false;
return false;
}
@@ -2591,7 +2634,7 @@ bool CanvasItemEditor::_gui_input_ruler_tool(const Ref<InputEvent> &p_event) {
ruler_tool_origin = snap_point(viewport->get_local_mouse_position() / zoom + view_offset);
}
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT) {
+ if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT) {
if (b->is_pressed()) {
ruler_tool_active = true;
} else {
@@ -2868,21 +2911,22 @@ void CanvasItemEditor::_draw_guides() {
// Dragged guide
Color text_color = get_theme_color("font_color", "Editor");
- text_color.a = 0.5;
+ Color outline_color = text_color.inverted();
+ const float outline_size = 2;
if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE) {
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x)));
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font("bold", "EditorFonts");
+ int font_size = get_theme_font_size("bold_size", "EditorFonts");
Size2 text_size = font->get_string_size(str, font_size);
- viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HALIGN_LEFT, -1, font_size, text_color);
+ viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HALIGN_LEFT, -1, font_size, text_color, outline_size, outline_color);
viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color, Math::round(EDSCALE));
}
if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) {
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y)));
- Ref<Font> font = get_theme_font("font", "Label");
- int font_size = get_theme_font_size("font_size", "Label");
+ Ref<Font> font = get_theme_font("bold", "EditorFonts");
+ int font_size = get_theme_font_size("bold_size", "EditorFonts");
Size2 text_size = font->get_string_size(str, font_size);
- viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HALIGN_LEFT, -1, font_size, text_color);
+ viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HALIGN_LEFT, -1, font_size, text_color, outline_size, outline_color);
viewport->draw_line(Point2(0, dragged_guide_pos.y), Point2(viewport->get_size().x, dragged_guide_pos.y), guide_color, Math::round(EDSCALE));
}
}
@@ -3867,7 +3911,7 @@ bool CanvasItemEditor::_build_bones_list(Node *p_node) {
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
Node *scene = editor->get_edited_scene();
- if (!canvas_item || !canvas_item->is_visible() || (canvas_item != scene && canvas_item->get_owner() != scene && !scene->is_editable_instance(canvas_item->get_owner()))) {
+ if (!canvas_item || !canvas_item->is_visible() || (canvas_item != scene && canvas_item->get_owner() != scene && canvas_item != scene->get_deepest_editable_node(canvas_item))) {
return false;
}
@@ -5363,6 +5407,7 @@ void CanvasItemEditor::_bind_methods() {
ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input);
ClassDB::bind_method("_queue_update_bone_list", &CanvasItemEditor::_update_bone_list);
ClassDB::bind_method("_update_bone_list", &CanvasItemEditor::_update_bone_list);
+ ClassDB::bind_method("_reset_create_position", &CanvasItemEditor::_reset_create_position);
ClassDB::bind_method(D_METHOD("set_state"), &CanvasItemEditor::set_state);
ClassDB::bind_method(D_METHOD("update_viewport"), &CanvasItemEditor::update_viewport);
@@ -5684,6 +5729,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
editor_selection->connect("selection_changed", callable_mp((CanvasItem *)this, &CanvasItem::update));
editor_selection->connect("selection_changed", callable_mp(this, &CanvasItemEditor::_selection_changed));
+ editor->get_scene_tree_dock()->connect("node_created", callable_mp(this, &CanvasItemEditor::_node_created));
+ editor->get_scene_tree_dock()->connect("add_node_used", callable_mp(this, &CanvasItemEditor::_reset_create_position));
+
editor->call_deferred("connect", "play_pressed", Callable(this, "_update_override_camera_button"), make_binds(true));
editor->call_deferred("connect", "stop_pressed", Callable(this, "_update_override_camera_button"), make_binds(false));
@@ -6105,6 +6153,12 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
selection_menu->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_selection_result_pressed));
selection_menu->connect("popup_hide", callable_mp(this, &CanvasItemEditor::_selection_menu_hide));
+ add_node_menu = memnew(PopupMenu);
+ add_child(add_node_menu);
+ add_node_menu->add_icon_item(editor->get_scene_tree_dock()->get_theme_icon("Add", "EditorIcons"), TTR("Add Node Here"));
+ add_node_menu->add_icon_item(editor->get_scene_tree_dock()->get_theme_icon("Instance", "EditorIcons"), TTR("Instance Scene Here"));
+ add_node_menu->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_add_node_pressed));
+
multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY);
divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE);
pan_view_shortcut = ED_SHORTCUT("canvas_item_editor/pan_view", TTR("Pan View"), KEY_SPACE);
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 24149a57b0..62a9b1e162 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -79,6 +79,11 @@ public:
TOOL_MAX
};
+ enum AddNodeOption {
+ ADD_NODE,
+ ADD_INSTANCE,
+ };
+
private:
EditorNode *editor;
@@ -284,6 +289,7 @@ private:
bool ruler_tool_active;
Point2 ruler_tool_origin;
+ Point2 node_create_position;
MenuOption last_option;
@@ -376,6 +382,7 @@ private:
Button *key_auto_insert_button;
PopupMenu *selection_menu;
+ PopupMenu *add_node_menu;
Control *top_ruler;
Control *left_ruler;
@@ -436,6 +443,9 @@ private:
void _snap_changed();
void _selection_result_pressed(int);
void _selection_menu_hide();
+ void _add_node_pressed(int p_result);
+ void _node_created(Node *p_node);
+ void _reset_create_position();
UndoRedo *undo_redo;
bool _build_bones_list(Node *p_node);
diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.cpp b/editor/plugins/collision_polygon_3d_editor_plugin.cpp
index 0c18975258..b50a497ccf 100644
--- a/editor/plugins/collision_polygon_3d_editor_plugin.cpp
+++ b/editor/plugins/collision_polygon_3d_editor_plugin.cpp
@@ -142,7 +142,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con
switch (mode) {
case MODE_CREATE: {
- if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) {
if (!wip_active) {
wip.clear();
wip.push_back(cpoint);
@@ -166,14 +166,14 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con
return true;
}
}
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && wip_active) {
_wip_close();
}
} break;
case MODE_EDIT: {
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
if (mb->get_control()) {
if (poly.size() < 3) {
@@ -267,7 +267,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con
}
}
}
- if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
+ if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
int closest_idx = -1;
Vector2 closest_pos;
real_t closest_dist = 1e10;
@@ -301,7 +301,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
- if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) {
+ if (edited_point != -1 && (wip_active || mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT)) {
Vector2 gpoint = mm->get_position();
Vector3 ray_from = p_camera->project_ray_origin(gpoint);
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp
index a1e7d3d6e0..c38458c37f 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp
@@ -207,7 +207,7 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) {
} break;
}
- node->get_shape()->_change_notify();
+ node->get_shape()->notify_property_list_changed();
}
void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
@@ -325,7 +325,7 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e
if (mb.is_valid()) {
Vector2 gpoint = mb->get_position();
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
for (int i = 0; i < handles.size(); i++) {
if (xform.xform(handles[i]).distance_to(gpoint) < 8) {
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index bff5cb8d2a..db999f50ab 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -115,22 +115,22 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) {
}
switch (mb.get_button_index()) {
- case BUTTON_RIGHT:
+ case MOUSE_BUTTON_RIGHT:
_context_click_pos = mpos;
open_context_menu(get_global_transform().xform(mpos));
break;
- case BUTTON_MIDDLE:
+ case MOUSE_BUTTON_MIDDLE:
remove_point(_hover_point);
break;
- case BUTTON_LEFT:
+ case MOUSE_BUTTON_LEFT:
_dragging = true;
break;
}
}
- if (!mb.is_pressed() && _dragging && mb.get_button_index() == BUTTON_LEFT) {
+ if (!mb.is_pressed() && _dragging && mb.get_button_index() == MOUSE_BUTTON_LEFT) {
_dragging = false;
if (_has_undo_data) {
UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo();
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index 63bb785c5e..eb3c06fba1 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -301,7 +301,7 @@ EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() {
//////////////////////////////////////////////////////////////////
void EditorMaterialPreviewPlugin::_preview_done(const Variant &p_udata) {
- preview_done = true;
+ preview_done.set();
}
void EditorMaterialPreviewPlugin::_bind_methods() {
@@ -325,10 +325,10 @@ Ref<Texture2D> EditorMaterialPreviewPlugin::generate(const RES &p_from, const Si
RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture
- preview_done = false;
+ preview_done.clear();
RS::get_singleton()->request_frame_drawn_callback(const_cast<EditorMaterialPreviewPlugin *>(this), "_preview_done", Variant());
- while (!preview_done) {
+ while (!preview_done.is_set()) {
OS::get_singleton()->delay_usec(10);
}
@@ -677,7 +677,7 @@ EditorAudioStreamPreviewPlugin::EditorAudioStreamPreviewPlugin() {
///////////////////////////////////////////////////////////////////////////
void EditorMeshPreviewPlugin::_preview_done(const Variant &p_udata) {
- preview_done = true;
+ preview_done.set();
}
void EditorMeshPreviewPlugin::_bind_methods() {
@@ -714,10 +714,10 @@ Ref<Texture2D> EditorMeshPreviewPlugin::generate(const RES &p_from, const Size2
RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture
- preview_done = false;
+ preview_done.clear();
RS::get_singleton()->request_frame_drawn_callback(const_cast<EditorMeshPreviewPlugin *>(this), "_preview_done", Variant());
- while (!preview_done) {
+ while (!preview_done.is_set()) {
OS::get_singleton()->delay_usec(10);
}
@@ -792,7 +792,7 @@ EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() {
///////////////////////////////////////////////////////////////////////////
void EditorFontPreviewPlugin::_preview_done(const Variant &p_udata) {
- preview_done = true;
+ preview_done.set();
}
void EditorFontPreviewPlugin::_bind_methods() {
@@ -883,11 +883,11 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path,
font->draw_string(canvas_item, pos, sample, HALIGN_LEFT, -1.f, 50, Color(1, 1, 1));
- preview_done = false;
+ preview_done.clear();
RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture
RS::get_singleton()->request_frame_drawn_callback(const_cast<EditorFontPreviewPlugin *>(this), "_preview_done", Variant());
- while (!preview_done) {
+ while (!preview_done.is_set()) {
OS::get_singleton()->delay_usec(10);
}
diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h
index 57e2911c89..6e8b9a34cf 100644
--- a/editor/plugins/editor_preview_plugins.h
+++ b/editor/plugins/editor_preview_plugins.h
@@ -33,6 +33,8 @@
#include "editor/editor_resource_preview.h"
+#include "core/templates/safe_refcount.h"
+
void post_process_preview(Ref<Image> p_image);
class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator {
@@ -90,7 +92,7 @@ class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator {
RID light2;
RID light_instance2;
RID camera;
- mutable volatile bool preview_done = false;
+ mutable SafeFlag preview_done;
void _preview_done(const Variant &p_udata);
@@ -134,7 +136,7 @@ class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator {
RID light2;
RID light_instance2;
RID camera;
- mutable volatile bool preview_done = false;
+ mutable SafeFlag preview_done;
void _preview_done(const Variant &p_udata);
@@ -156,7 +158,7 @@ class EditorFontPreviewPlugin : public EditorResourcePreviewGenerator {
RID viewport_texture;
RID canvas;
RID canvas_item;
- mutable volatile bool preview_done = false;
+ mutable SafeFlag preview_done;
void _preview_done(const Variant &p_udata);
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index 1aaa98d02e..b447304a3f 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
@@ -81,7 +81,7 @@ void GPUParticles2DEditorPlugin::_menu_callback(int p_idx) {
cpu_particles->set_name(particles->get_name());
cpu_particles->set_transform(particles->get_transform());
cpu_particles->set_visible(particles->is_visible());
- cpu_particles->set_pause_mode(particles->get_pause_mode());
+ cpu_particles->set_process_mode(particles->get_process_mode());
cpu_particles->set_z_index(particles->get_z_index());
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index 5b840ddbcf..433a5ae51c 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -263,7 +263,7 @@ void GPUParticles3DEditor::_menu_option(int p_option) {
cpu_particles->set_name(node->get_name());
cpu_particles->set_transform(node->get_transform());
cpu_particles->set_visible(node->is_visible());
- cpu_particles->set_pause_mode(node->get_pause_mode());
+ cpu_particles->set_process_mode(node->get_process_mode());
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Convert to CPUParticles3D"));
diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp
index c0f690bb6a..1ea6630622 100644
--- a/editor/plugins/item_list_editor_plugin.cpp
+++ b/editor/plugins/item_list_editor_plugin.cpp
@@ -145,7 +145,7 @@ int ItemListOptionButtonPlugin::get_flags() const {
void ItemListOptionButtonPlugin::add_item() {
ob->add_item(vformat(TTR("Item %d"), ob->get_item_count()));
- _change_notify();
+ notify_property_list_changed();
}
int ItemListOptionButtonPlugin::get_item_count() const {
@@ -154,7 +154,7 @@ int ItemListOptionButtonPlugin::get_item_count() const {
void ItemListOptionButtonPlugin::erase(int p_idx) {
ob->remove_item(p_idx);
- _change_notify();
+ notify_property_list_changed();
}
ItemListOptionButtonPlugin::ItemListOptionButtonPlugin() {
@@ -181,7 +181,7 @@ int ItemListPopupMenuPlugin::get_flags() const {
void ItemListPopupMenuPlugin::add_item() {
pp->add_item(vformat(TTR("Item %d"), pp->get_item_count()));
- _change_notify();
+ notify_property_list_changed();
}
int ItemListPopupMenuPlugin::get_item_count() const {
@@ -190,7 +190,7 @@ int ItemListPopupMenuPlugin::get_item_count() const {
void ItemListPopupMenuPlugin::erase(int p_idx) {
pp->remove_item(p_idx);
- _change_notify();
+ notify_property_list_changed();
}
ItemListPopupMenuPlugin::ItemListPopupMenuPlugin() {
@@ -213,7 +213,7 @@ int ItemListItemListPlugin::get_flags() const {
void ItemListItemListPlugin::add_item() {
pp->add_item(vformat(TTR("Item %d"), pp->get_item_count()));
- _change_notify();
+ notify_property_list_changed();
}
int ItemListItemListPlugin::get_item_count() const {
@@ -222,7 +222,7 @@ int ItemListItemListPlugin::get_item_count() const {
void ItemListItemListPlugin::erase(int p_idx) {
pp->remove_item(p_idx);
- _change_notify();
+ notify_property_list_changed();
}
ItemListItemListPlugin::ItemListItemListPlugin() {
diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp
index 1e4553a967..77719104b1 100644
--- a/editor/plugins/mesh_editor_plugin.cpp
+++ b/editor/plugins/mesh_editor_plugin.cpp
@@ -34,7 +34,7 @@
void MeshEditor::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
rot_x -= mm->get_relative().y * 0.01;
rot_y -= mm->get_relative().x * 0.01;
if (rot_x < -Math_PI / 2) {
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index a3009731f9..fccc042a02 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -48,6 +48,7 @@
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/3d/visual_instance_3d.h"
+#include "scene/gui/center_container.h"
#include "scene/gui/subviewport_container.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/surface_tool.h"
@@ -185,7 +186,7 @@ void ViewportRotationControl::_get_sorted_axis(Vector<Axis2D> &r_axis) {
void ViewportRotationControl::_gui_input(Ref<InputEvent> p_event) {
const Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
Vector2 pos = mb->get_position();
if (mb->is_pressed()) {
if (pos.distance_to(get_size() / 2.0) < get_size().x / 2.0) {
@@ -535,8 +536,8 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b
if (dist < closest_dist) {
item = Object::cast_to<Node>(spat);
- while (item->get_owner() && item->get_owner() != edited_scene && !edited_scene->is_editable_instance(item->get_owner())) {
- item = item->get_owner();
+ if (item != edited_scene) {
+ item = edited_scene->get_deepest_editable_node(item);
}
closest = item->get_instance_id();
@@ -697,8 +698,8 @@ void Node3DEditorViewport::_select_region() {
}
Node *item = Object::cast_to<Node>(sp);
- while (item->get_owner() && item->get_owner() != edited_scene && !edited_scene->is_editable_instance(item->get_owner())) {
- item = item->get_owner();
+ if (item != edited_scene) {
+ item = edited_scene->get_deepest_editable_node(item);
}
// Replace the node by the group if grouped
@@ -1027,7 +1028,7 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
for (int i = 0; i < selection_results.size(); i++) {
Node3D *item = selection_results[i].item;
- if (item != scene && item->get_owner() != scene && !scene->is_editable_instance(item->get_owner())) {
+ if (item != scene && item->get_owner() != scene && item != scene->get_deepest_editable_node(item)) {
//invalid result
selection_results.remove(i);
i--;
@@ -1122,23 +1123,21 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
float zoom_factor = 1 + (ZOOM_FREELOOK_MULTIPLIER - 1) * b->get_factor();
switch (b->get_button_index()) {
- case BUTTON_WHEEL_UP: {
+ case MOUSE_BUTTON_WHEEL_UP: {
if (is_freelook_active()) {
scale_freelook_speed(zoom_factor);
} else {
scale_cursor_distance(1.0 / zoom_factor);
}
} break;
-
- case BUTTON_WHEEL_DOWN: {
+ case MOUSE_BUTTON_WHEEL_DOWN: {
if (is_freelook_active()) {
scale_freelook_speed(1.0 / zoom_factor);
} else {
scale_cursor_distance(zoom_factor);
}
} break;
-
- case BUTTON_RIGHT: {
+ case MOUSE_BUTTON_RIGHT: {
NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
if (b->is_pressed() && _edit.gizmo.is_valid()) {
@@ -1199,7 +1198,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
} break;
- case BUTTON_MIDDLE: {
+ case MOUSE_BUTTON_MIDDLE: {
if (b->is_pressed() && _edit.mode != TRANSFORM_NONE) {
switch (_edit.plane) {
case TRANSFORM_VIEW: {
@@ -1230,7 +1229,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
}
} break;
- case BUTTON_LEFT: {
+ case MOUSE_BUTTON_LEFT: {
if (b->is_pressed()) {
NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
if ((nav_scheme == NAVIGATION_MAYA || nav_scheme == NAVIGATION_MODO) && b->get_alt()) {
@@ -1439,7 +1438,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
String n = _edit.gizmo->get_handle_name(_edit.gizmo_handle);
set_message(n + ": " + String(v));
- } else if (m->get_button_mask() & BUTTON_MASK_LEFT) {
+ } else if (m->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
if (nav_scheme == NAVIGATION_MAYA && m->get_alt()) {
nav_mode = NAVIGATION_ORBIT;
} else if (nav_scheme == NAVIGATION_MODO && m->get_alt() && m->get_shift()) {
@@ -1829,8 +1828,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
}
}
-
- } else if ((m->get_button_mask() & BUTTON_MASK_RIGHT) || freelook_active) {
+ } else if ((m->get_button_mask() & MOUSE_BUTTON_MASK_RIGHT) || freelook_active) {
if (nav_scheme == NAVIGATION_MAYA && m->get_alt()) {
nav_mode = NAVIGATION_ZOOM;
} else if (freelook_active) {
@@ -1839,10 +1837,9 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
nav_mode = NAVIGATION_PAN;
}
- } else if (m->get_button_mask() & BUTTON_MASK_MIDDLE) {
+ } else if (m->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) {
+ const int mod = _get_key_modifier(m);
if (nav_scheme == NAVIGATION_GODOT) {
- const int mod = _get_key_modifier(m);
-
if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) {
nav_mode = NAVIGATION_PAN;
} else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) {
@@ -1851,13 +1848,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
// Always allow Alt as a modifier to better support graphic tablets.
nav_mode = NAVIGATION_ORBIT;
}
-
} else if (nav_scheme == NAVIGATION_MAYA) {
- if (m->get_alt()) {
+ if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) {
nav_mode = NAVIGATION_PAN;
}
}
-
} else if (EditorSettings::get_singleton()->get("editors/3d/navigation/emulate_3_button_mouse")) {
// Handle trackpad (no external mouse) use case
const int mod = _get_key_modifier(m);
@@ -2335,7 +2330,43 @@ void Node3DEditorPlugin::edited_scene_changed() {
}
}
+void Node3DEditorViewport::_project_settings_changed() {
+ //update shadow atlas if changed
+ int shadowmap_size = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/size");
+ bool shadowmap_16_bits = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/16_bits");
+ int atlas_q0 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_0_subdiv");
+ int atlas_q1 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_1_subdiv");
+ int atlas_q2 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_2_subdiv");
+ int atlas_q3 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_3_subdiv");
+
+ viewport->set_shadow_atlas_size(shadowmap_size);
+ viewport->set_shadow_atlas_16_bits(shadowmap_16_bits);
+ viewport->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0));
+ viewport->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1));
+ viewport->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2));
+ viewport->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3));
+
+ bool shrink = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_HALF_RESOLUTION));
+
+ if (shrink != (subviewport_container->get_stretch_shrink() > 1)) {
+ subviewport_container->set_stretch_shrink(shrink ? 2 : 1);
+ }
+
+ // Update MSAA, screen-space AA and debanding if changed
+
+ const int msaa_mode = ProjectSettings::get_singleton()->get("rendering/anti_aliasing/quality/msaa");
+ viewport->set_msaa(Viewport::MSAA(msaa_mode));
+ const int ssaa_mode = GLOBAL_GET("rendering/anti_aliasing/quality/screen_space_aa");
+ viewport->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
+ const bool use_debanding = GLOBAL_GET("rendering/anti_aliasing/quality/use_debanding");
+ viewport->set_use_debanding(use_debanding);
+}
+
void Node3DEditorViewport::_notification(int p_what) {
+ if (p_what == NOTIFICATION_READY) {
+ EditorNode::get_singleton()->connect("project_settings_changed", callable_mp(this, &Node3DEditorViewport::_project_settings_changed));
+ }
+
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
bool visible = is_visible_in_tree();
@@ -2442,37 +2473,6 @@ void Node3DEditorViewport::_notification(int p_what) {
}
}
- //update shadow atlas if changed
-
- int shadowmap_size = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/size");
- bool shadowmap_16_bits = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/16_bits");
- int atlas_q0 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_0_subdiv");
- int atlas_q1 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_1_subdiv");
- int atlas_q2 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_2_subdiv");
- int atlas_q3 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_3_subdiv");
-
- viewport->set_shadow_atlas_size(shadowmap_size);
- viewport->set_shadow_atlas_16_bits(shadowmap_16_bits);
- viewport->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0));
- viewport->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1));
- viewport->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2));
- viewport->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3));
-
- bool shrink = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_HALF_RESOLUTION));
-
- if (shrink != (subviewport_container->get_stretch_shrink() > 1)) {
- subviewport_container->set_stretch_shrink(shrink ? 2 : 1);
- }
-
- // Update MSAA, screen-space AA and debanding if changed
-
- const int msaa_mode = ProjectSettings::get_singleton()->get("rendering/quality/screen_filters/msaa");
- viewport->set_msaa(Viewport::MSAA(msaa_mode));
- const int ssaa_mode = GLOBAL_GET("rendering/quality/screen_filters/screen_space_aa");
- viewport->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
- const bool use_debanding = GLOBAL_GET("rendering/quality/screen_filters/use_debanding");
- viewport->set_use_debanding(use_debanding);
-
bool show_info = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION));
if (show_info != info_label->is_visible()) {
info_label->set_visible(show_info);
@@ -4194,7 +4194,7 @@ Node3DEditorViewport::~Node3DEditorViewport() {
void Node3DEditorViewportContainer::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
Vector2 size = get_size();
@@ -4707,11 +4707,33 @@ Dictionary Node3DEditor::get_state() const {
continue;
}
int state = gizmos_menu->get_item_state(gizmos_menu->get_item_index(i));
- String name = gizmo_plugins_by_name[i]->get_name();
+ String name = gizmo_plugins_by_name[i]->get_gizmo_name();
gizmos_status[name] = state;
}
d["gizmos_status"] = gizmos_status;
+ {
+ Dictionary pd;
+
+ pd["sun_rotation"] = sun_rotation;
+
+ pd["environ_sky_color"] = environ_sky_color->get_pick_color();
+ pd["environ_ground_color"] = environ_ground_color->get_pick_color();
+ pd["environ_energy"] = environ_energy->get_value();
+ pd["environ_glow_enabled"] = environ_glow_button->is_pressed();
+ pd["environ_tonemap_enabled"] = environ_tonemap_button->is_pressed();
+ pd["environ_ao_enabled"] = environ_ao_button->is_pressed();
+ pd["environ_gi_enabled"] = environ_gi_button->is_pressed();
+ pd["sun_max_distance"] = sun_max_distance->get_value();
+
+ pd["sun_color"] = sun_color->get_pick_color();
+ pd["sun_energy"] = sun_energy->get_value();
+
+ pd["sun_disabled"] = sun_button->is_pressed();
+ pd["environ_disabled"] = environ_button->is_pressed();
+
+ d["preview_sun_env"] = pd;
+ }
return d;
}
@@ -4811,7 +4833,7 @@ void Node3DEditor::set_state(const Dictionary &p_state) {
}
int state = EditorNode3DGizmoPlugin::VISIBLE;
for (int i = 0; i < keys.size(); i++) {
- if (gizmo_plugins_by_name.write[j]->get_name() == String(keys[i])) {
+ if (gizmo_plugins_by_name.write[j]->get_gizmo_name() == String(keys[i])) {
state = gizmos_status[keys[i]];
break;
}
@@ -4821,6 +4843,38 @@ void Node3DEditor::set_state(const Dictionary &p_state) {
}
_update_gizmos_menu();
}
+
+ if (d.has("preview_sun_env")) {
+ sun_environ_updating = true;
+ Dictionary pd = d["preview_sun_env"];
+ sun_rotation = pd["sun_rotation"];
+
+ environ_sky_color->set_pick_color(pd["environ_sky_color"]);
+ environ_ground_color->set_pick_color(pd["environ_ground_color"]);
+ environ_energy->set_value(pd["environ_energy"]);
+ environ_glow_button->set_pressed(pd["environ_glow_enabled"]);
+ environ_tonemap_button->set_pressed(pd["environ_tonemap_enabled"]);
+ environ_ao_button->set_pressed(pd["environ_ao_enabled"]);
+ environ_gi_button->set_pressed(pd["environ_gi_enabled"]);
+ sun_max_distance->set_value(pd["sun_max_distance"]);
+
+ sun_color->set_pick_color(pd["sun_color"]);
+ sun_energy->set_value(pd["sun_energy"]);
+
+ sun_button->set_pressed(pd["sun_disabled"]);
+ environ_button->set_pressed(pd["environ_disabled"]);
+
+ sun_environ_updating = false;
+
+ _preview_settings_changed();
+ _update_preview_environment();
+ } else {
+ _load_default_preview_settings();
+ sun_button->set_pressed(false);
+ environ_button->set_pressed(false);
+ _preview_settings_changed();
+ _update_preview_environment();
+ }
}
void Node3DEditor::edit(Node3D *p_spatial) {
@@ -5690,7 +5744,7 @@ void Node3DEditor::_update_gizmos_menu() {
if (!gizmo_plugins_by_name[i]->can_be_hidden()) {
continue;
}
- String plugin_name = gizmo_plugins_by_name[i]->get_name();
+ String plugin_name = gizmo_plugins_by_name[i]->get_gizmo_name();
const int plugin_state = gizmo_plugins_by_name[i]->get_state();
gizmos_menu->add_multistate_item(plugin_name, 3, plugin_state, i);
const int idx = gizmos_menu->get_item_index(i);
@@ -5761,7 +5815,7 @@ void Node3DEditor::_init_grid() {
// Offsets division_level for bigger or smaller grids.
// Default value is -0.2. -1.0 gives Blender-like behavior, 0.5 gives huge grids.
real_t division_level_bias = EditorSettings::get_singleton()->get("editors/3d/grid_division_level_bias");
- // Default largest grid size is 100m, 10^2 (default value is 2).
+ // Default largest grid size is 8^2 when primary_grid_steps is 8 (64m apart, so primary grid lines are 512m apart).
int division_level_max = EditorSettings::get_singleton()->get("editors/3d/grid_division_level_max");
// Default smallest grid size is 1cm, 10^-2 (default value is -2).
int division_level_min = EditorSettings::get_singleton()->get("editors/3d/grid_division_level_min");
@@ -6107,6 +6161,51 @@ void Node3DEditor::_unhandled_key_input(Ref<InputEvent> p_event) {
snap_key_enabled = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
}
+void Node3DEditor::_sun_environ_settings_pressed() {
+ Vector2 pos = sun_environ_settings->get_screen_position() + sun_environ_settings->get_size();
+ sun_environ_popup->set_position(pos - Vector2(sun_environ_popup->get_contents_minimum_size().width / 2, 0));
+ sun_environ_popup->popup();
+}
+
+void Node3DEditor::_add_sun_to_scene() {
+ sun_environ_popup->hide();
+
+ Node *base = get_tree()->get_edited_scene_root();
+ if (!base) {
+ EditorNode::get_singleton()->show_warning(TTR("A root node is needed for this operation"));
+ return;
+ }
+ ERR_FAIL_COND(!base);
+ Node *new_sun = preview_sun->duplicate();
+
+ undo_redo->create_action("Add Preview Sun to Scene");
+ undo_redo->add_do_method(base, "add_child", new_sun);
+ undo_redo->add_do_method(new_sun, "set_owner", base);
+ undo_redo->add_undo_method(base, "remove_child", new_sun);
+ undo_redo->add_do_reference(new_sun);
+ undo_redo->commit_action();
+}
+void Node3DEditor::_add_environment_to_scene() {
+ sun_environ_popup->hide();
+
+ Node *base = get_tree()->get_edited_scene_root();
+ if (!base) {
+ EditorNode::get_singleton()->show_warning(TTR("A root node is needed for this operation"));
+ return;
+ }
+ ERR_FAIL_COND(!base);
+
+ WorldEnvironment *new_env = memnew(WorldEnvironment);
+ new_env->set_environment(preview_environment->get_environment()->duplicate(true));
+
+ undo_redo->create_action("Add Preview Environment to Scene");
+ undo_redo->add_do_method(base, "add_child", new_env);
+ undo_redo->add_do_method(new_env, "set_owner", base);
+ undo_redo->add_undo_method(base, "remove_child", new_env);
+ undo_redo->add_do_reference(new_env);
+ undo_redo->commit_action();
+}
+
void Node3DEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_READY) {
tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
@@ -6135,17 +6234,31 @@ void Node3DEditor::_notification(int p_what) {
_refresh_menu_icons();
get_tree()->connect("node_removed", callable_mp(this, &Node3DEditor::_node_removed));
+ get_tree()->connect("node_added", callable_mp(this, &Node3DEditor::_node_added));
EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons));
editor_selection->connect("selection_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons));
editor->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(false));
editor->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(true));
+
+ sun_button->set_icon(get_theme_icon("DirectionalLight3D", "EditorIcons"));
+ environ_button->set_icon(get_theme_icon("WorldEnvironment", "EditorIcons"));
+ sun_environ_settings->set_icon(get_theme_icon("GuiTabMenuHl", "EditorIcons"));
+
+ _update_preview_environment();
+ sun_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
+ environ_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
+
+ sun_state->set_custom_minimum_size(sun_vb->get_combined_minimum_size());
+ environ_state->set_custom_minimum_size(environ_vb->get_combined_minimum_size());
} else if (p_what == NOTIFICATION_ENTER_TREE) {
_register_all_gizmos();
_update_gizmos_menu();
_init_indicators();
} else if (p_what == NOTIFICATION_THEME_CHANGED) {
_update_gizmos_menu_theme();
+ sun_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
+ environ_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
} else if (p_what == NOTIFICATION_EXIT_TREE) {
_finish_indicators();
} else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
@@ -6282,7 +6395,37 @@ void Node3DEditor::_toggle_maximize_view(Object *p_viewport) {
}
}
+void Node3DEditor::_node_added(Node *p_node) {
+ if (EditorNode::get_singleton()->get_scene_root()->is_a_parent_of(p_node)) {
+ if (Object::cast_to<WorldEnvironment>(p_node)) {
+ world_env_count++;
+ if (world_env_count == 1) {
+ _update_preview_environment();
+ }
+ } else if (Object::cast_to<DirectionalLight3D>(p_node)) {
+ directional_light_count++;
+ if (directional_light_count == 1) {
+ _update_preview_environment();
+ }
+ }
+ }
+}
+
void Node3DEditor::_node_removed(Node *p_node) {
+ if (EditorNode::get_singleton()->get_scene_root()->is_a_parent_of(p_node)) {
+ if (Object::cast_to<WorldEnvironment>(p_node)) {
+ world_env_count--;
+ if (world_env_count == 0) {
+ _update_preview_environment();
+ }
+ } else if (Object::cast_to<DirectionalLight3D>(p_node)) {
+ directional_light_count--;
+ if (directional_light_count == 0) {
+ _update_preview_environment();
+ }
+ }
+ }
+
if (p_node == selected) {
selected = nullptr;
}
@@ -6309,6 +6452,7 @@ void Node3DEditor::_register_all_gizmos() {
add_gizmo_plugin(Ref<GIProbeGizmoPlugin>(memnew(GIProbeGizmoPlugin)));
add_gizmo_plugin(Ref<BakedLightmapGizmoPlugin>(memnew(BakedLightmapGizmoPlugin)));
add_gizmo_plugin(Ref<LightmapProbeGizmoPlugin>(memnew(LightmapProbeGizmoPlugin)));
+ add_gizmo_plugin(Ref<CollisionObject3DGizmoPlugin>(memnew(CollisionObject3DGizmoPlugin)));
add_gizmo_plugin(Ref<CollisionShape3DGizmoPlugin>(memnew(CollisionShape3DGizmoPlugin)));
add_gizmo_plugin(Ref<CollisionPolygon3DGizmoPlugin>(memnew(CollisionPolygon3DGizmoPlugin)));
add_gizmo_plugin(Ref<NavigationRegion3DGizmoPlugin>(memnew(NavigationRegion3DGizmoPlugin)));
@@ -6352,6 +6496,128 @@ void Node3DEditor::clear() {
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true);
}
+void Node3DEditor::_sun_direction_draw() {
+ sun_direction->draw_rect(Rect2(Vector2(), sun_direction->get_size()), Color(1, 1, 1, 1));
+ sun_direction_material->set_shader_param("sun_direction", -preview_sun->get_transform().basis.get_axis(Vector3::AXIS_Z));
+ float nrg = sun_energy->get_value();
+ sun_direction_material->set_shader_param("sun_color", Vector3(sun_color->get_pick_color().r * nrg, sun_color->get_pick_color().g * nrg, sun_color->get_pick_color().b * nrg));
+}
+
+void Node3DEditor::_preview_settings_changed() {
+ if (sun_environ_updating) {
+ return;
+ }
+
+ { // preview sun
+ Transform t;
+ t.basis = sun_rotation;
+ preview_sun->set_transform(t);
+ sun_direction->update();
+ preview_sun->set_param(Light3D::PARAM_ENERGY, sun_energy->get_value());
+ preview_sun->set_param(Light3D::PARAM_SHADOW_MAX_DISTANCE, sun_max_distance->get_value());
+ preview_sun->set_color(sun_color->get_pick_color());
+ }
+
+ { //preview env
+ sky_material->set_sky_energy(environ_energy->get_value());
+ Color hz_color = environ_sky_color->get_pick_color().lerp(environ_ground_color->get_pick_color(), 0.5).lerp(Color(1, 1, 1), 0.5);
+ sky_material->set_sky_top_color(environ_sky_color->get_pick_color());
+ sky_material->set_sky_horizon_color(hz_color);
+ sky_material->set_ground_bottom_color(environ_ground_color->get_pick_color());
+ sky_material->set_ground_horizon_color(hz_color);
+
+ environment->set_ssao_enabled(environ_ao_button->is_pressed());
+ environment->set_glow_enabled(environ_glow_button->is_pressed());
+ environment->set_sdfgi_enabled(environ_gi_button->is_pressed());
+ environment->set_tonemapper(environ_tonemap_button->is_pressed() ? Environment::TONE_MAPPER_FILMIC : Environment::TONE_MAPPER_LINEAR);
+ }
+}
+void Node3DEditor::_load_default_preview_settings() {
+ sun_environ_updating = true;
+
+ sun_rotation = Basis(Vector3(0, 1, 0), Math_PI * 3.0 / 4) * Basis(Vector3(1, 0, 0), -Math_PI / 4);
+
+ sun_direction->update();
+ environ_sky_color->set_pick_color(Color::hex(0x91b2ceff));
+ environ_ground_color->set_pick_color(Color::hex(0x1f1f21ff));
+ environ_energy->set_value(1.0);
+ environ_glow_button->set_pressed(true);
+ environ_tonemap_button->set_pressed(true);
+ environ_ao_button->set_pressed(false);
+ environ_gi_button->set_pressed(false);
+ sun_max_distance->set_value(250);
+
+ sun_color->set_pick_color(Color(1, 1, 1));
+ sun_energy->set_value(1.0);
+
+ sun_environ_updating = false;
+}
+
+void Node3DEditor::_update_preview_environment() {
+ bool disable_light = directional_light_count > 0 || sun_button->is_pressed();
+
+ sun_button->set_disabled(directional_light_count > 0);
+
+ if (disable_light) {
+ if (preview_sun->get_parent()) {
+ preview_sun->get_parent()->remove_child(preview_sun);
+ sun_state->show();
+ sun_vb->hide();
+ }
+
+ if (directional_light_count > 0) {
+ sun_state->set_text(TTR("Scene contains\nDirectionalLight3D.\nPreview disabled."));
+ } else {
+ sun_state->set_text(TTR("Preview disabled."));
+ }
+
+ } else {
+ if (!preview_sun->get_parent()) {
+ add_child(preview_sun);
+ sun_state->hide();
+ sun_vb->show();
+ }
+ }
+
+ bool disable_env = world_env_count > 0 || environ_button->is_pressed();
+
+ environ_button->set_disabled(world_env_count > 0);
+
+ if (disable_env) {
+ if (preview_environment->get_parent()) {
+ preview_environment->get_parent()->remove_child(preview_environment);
+ environ_state->show();
+ environ_vb->hide();
+ }
+ if (world_env_count > 0) {
+ environ_state->set_text(TTR("Scene contains\nWorldEnvironment.\nPreview disabled."));
+ } else {
+ environ_state->set_text(TTR("Preview disabled."));
+ }
+
+ } else {
+ if (!preview_environment->get_parent()) {
+ add_child(preview_environment);
+ environ_state->hide();
+ environ_vb->show();
+ }
+ }
+}
+
+void Node3DEditor::_sun_direction_input(const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
+ float x = -mm->get_relative().y * 0.02 * EDSCALE;
+ float y = mm->get_relative().x * 0.02 * EDSCALE;
+
+ Basis rot = Basis(Vector3(0, 1, 0), y) * Basis(Vector3(1, 0, 0), x);
+
+ sun_rotation = rot * sun_rotation;
+ sun_rotation.orthonormalize();
+ _preview_settings_changed();
+ }
+}
+
Node3DEditor::Node3DEditor(EditorNode *p_editor) {
gizmo.visible = true;
gizmo.scale = 1.0;
@@ -6489,6 +6755,32 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
_update_camera_override_button(false);
hbc_menu->add_child(memnew(VSeparator));
+ sun_button = memnew(Button);
+ sun_button->set_tooltip(TTR("Toggle preview sunlight.\nIf a DirectionalLight3D node is added to the scene, preview sunlight is disabled."));
+ sun_button->set_toggle_mode(true);
+ sun_button->set_flat(true);
+ sun_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), varray(), CONNECT_DEFERRED);
+ sun_button->set_disabled(true);
+
+ hbc_menu->add_child(sun_button);
+
+ environ_button = memnew(Button);
+ environ_button->set_tooltip(TTR("Toggle preview environment.\nIf a WorldEnvironment node is added to the scene, preview environment is disabled."));
+ environ_button->set_toggle_mode(true);
+ environ_button->set_flat(true);
+ environ_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), varray(), CONNECT_DEFERRED);
+ environ_button->set_disabled(true);
+
+ hbc_menu->add_child(environ_button);
+
+ sun_environ_settings = memnew(Button);
+ sun_environ_settings->set_tooltip(TTR("Edit Sun and Environment settings."));
+ sun_environ_settings->set_flat(true);
+ sun_environ_settings->connect("pressed", callable_mp(this, &Node3DEditor::_sun_environ_settings_pressed));
+
+ hbc_menu->add_child(sun_environ_settings);
+
+ hbc_menu->add_child(memnew(VSeparator));
// Drag and drop support;
preview_node = memnew(Node3D);
@@ -6718,6 +7010,152 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
EDITOR_DEF("editors/3d/navigation/show_viewport_rotation_gizmo", true);
over_gizmo_handle = -1;
+ {
+ //sun popup
+
+ sun_environ_popup = memnew(PopupPanel);
+ add_child(sun_environ_popup);
+
+ HBoxContainer *sun_environ_hb = memnew(HBoxContainer);
+
+ sun_environ_popup->add_child(sun_environ_hb);
+
+ sun_vb = memnew(VBoxContainer);
+ sun_environ_hb->add_child(sun_vb);
+ sun_vb->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
+ sun_vb->hide();
+
+ sun_title = memnew(Label);
+ sun_vb->add_child(sun_title);
+ sun_title->set_text(TTR("Preview Sun"));
+ sun_title->set_align(Label::ALIGN_CENTER);
+
+ CenterContainer *sun_direction_center = memnew(CenterContainer);
+ sun_direction = memnew(Control);
+ sun_direction->set_custom_minimum_size(Size2i(128, 128) * EDSCALE);
+ sun_direction_center->add_child(sun_direction);
+ sun_vb->add_margin_child(TTR("Sun Direction"), sun_direction_center);
+ sun_direction->connect("gui_input", callable_mp(this, &Node3DEditor::_sun_direction_input));
+ sun_direction->connect("draw", callable_mp(this, &Node3DEditor::_sun_direction_draw));
+ sun_direction->set_default_cursor_shape(CURSOR_MOVE);
+
+ String sun_dir_shader_code = "shader_type canvas_item; uniform vec3 sun_direction; uniform vec3 sun_color; void fragment() { vec3 n; n.xy = UV * 2.0 - 1.0; n.z = sqrt(max(0.0, 1.0 - dot(n.xy, n.xy))); COLOR.rgb = dot(n,sun_direction) * sun_color; COLOR.a = 1.0 - smoothstep(0.99,1.0,length(n.xy)); }";
+ sun_direction_shader.instance();
+ sun_direction_shader->set_code(sun_dir_shader_code);
+ sun_direction_material.instance();
+ sun_direction_material->set_shader(sun_direction_shader);
+ sun_direction_material->set_shader_param("sun_direction", Vector3(0, 0, 1));
+ sun_direction_material->set_shader_param("sun_color", Vector3(1, 1, 1));
+ sun_direction->set_material(sun_direction_material);
+
+ sun_color = memnew(ColorPickerButton);
+ sun_color->set_edit_alpha(false);
+ sun_vb->add_margin_child(TTR("Sun Color"), sun_color);
+ sun_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+
+ sun_energy = memnew(EditorSpinSlider);
+ sun_vb->add_margin_child(TTR("Sun Energy"), sun_energy);
+ sun_energy->connect("value_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ sun_energy->set_max(64.0);
+
+ sun_max_distance = memnew(EditorSpinSlider);
+ sun_vb->add_margin_child(TTR("Shadow Max Distance"), sun_max_distance);
+ sun_max_distance->connect("value_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ sun_max_distance->set_min(1);
+ sun_max_distance->set_max(4096);
+
+ sun_add_to_scene = memnew(Button);
+ sun_add_to_scene->set_text(TTR("Add Sun to Scene"));
+ sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene));
+ sun_vb->add_spacer();
+ sun_vb->add_child(sun_add_to_scene);
+
+ sun_state = memnew(Label);
+ sun_environ_hb->add_child(sun_state);
+ sun_state->set_align(Label::ALIGN_CENTER);
+ sun_state->set_valign(Label::VALIGN_CENTER);
+ sun_state->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ VSeparator *sc = memnew(VSeparator);
+ sc->set_custom_minimum_size(Size2(50 * EDSCALE, 0));
+ sc->set_v_size_flags(SIZE_EXPAND_FILL);
+ sun_environ_hb->add_child(sc);
+
+ environ_vb = memnew(VBoxContainer);
+ sun_environ_hb->add_child(environ_vb);
+ environ_vb->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
+ environ_vb->hide();
+
+ environ_title = memnew(Label);
+ environ_vb->add_child(environ_title);
+ environ_title->set_text(TTR("Preview Environment"));
+ environ_title->set_align(Label::ALIGN_CENTER);
+
+ environ_sky_color = memnew(ColorPickerButton);
+ environ_sky_color->set_edit_alpha(false);
+ environ_sky_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ environ_vb->add_margin_child(TTR("Sky Color"), environ_sky_color);
+ environ_ground_color = memnew(ColorPickerButton);
+ environ_ground_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ environ_ground_color->set_edit_alpha(false);
+ environ_vb->add_margin_child(TTR("Ground Color"), environ_ground_color);
+ environ_energy = memnew(EditorSpinSlider);
+ environ_energy->connect("value_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ environ_energy->set_max(8.0);
+ environ_vb->add_margin_child(TTR("Sky Energy"), environ_energy);
+ HBoxContainer *fx_vb = memnew(HBoxContainer);
+ fx_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ environ_ao_button = memnew(Button);
+ environ_ao_button->set_text(TTR("AO"));
+ environ_ao_button->set_toggle_mode(true);
+ environ_ao_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ fx_vb->add_child(environ_ao_button);
+ environ_glow_button = memnew(Button);
+ environ_glow_button->set_text(TTR("Glow"));
+ environ_glow_button->set_toggle_mode(true);
+ environ_glow_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ fx_vb->add_child(environ_glow_button);
+ environ_tonemap_button = memnew(Button);
+ environ_tonemap_button->set_text(TTR("Tonemap"));
+ environ_tonemap_button->set_toggle_mode(true);
+ environ_tonemap_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ fx_vb->add_child(environ_tonemap_button);
+ environ_gi_button = memnew(Button);
+ environ_gi_button->set_text(TTR("GI"));
+ environ_gi_button->set_toggle_mode(true);
+ environ_gi_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ fx_vb->add_child(environ_gi_button);
+ environ_vb->add_margin_child(TTR("Post Process"), fx_vb);
+
+ environ_add_to_scene = memnew(Button);
+ environ_add_to_scene->set_text(TTR("Add Environment to Scene"));
+ environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene));
+ environ_vb->add_spacer();
+ environ_vb->add_child(environ_add_to_scene);
+
+ environ_state = memnew(Label);
+ sun_environ_hb->add_child(environ_state);
+ environ_state->set_align(Label::ALIGN_CENTER);
+ environ_state->set_valign(Label::VALIGN_CENTER);
+ environ_state->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ preview_sun = memnew(DirectionalLight3D);
+ preview_sun->set_shadow(true);
+ preview_sun->set_shadow_mode(DirectionalLight3D::SHADOW_PARALLEL_4_SPLITS);
+ preview_environment = memnew(WorldEnvironment);
+ environment.instance();
+ preview_environment->set_environment(environment);
+ Ref<Sky> sky;
+ sky.instance();
+ sky_material.instance();
+ sky->set_material(sky_material);
+ environment->set_sky(sky);
+ environment->set_background(Environment::BG_SKY);
+
+ _load_default_preview_settings();
+ _preview_settings_changed();
+ }
}
Node3DEditor::~Node3DEditor() {
@@ -6808,7 +7246,7 @@ void Node3DEditorPlugin::snap_cursor_to_plane(const Plane &p_plane) {
struct _GizmoPluginPriorityComparator {
bool operator()(const Ref<EditorNode3DGizmoPlugin> &p_a, const Ref<EditorNode3DGizmoPlugin> &p_b) const {
if (p_a->get_priority() == p_b->get_priority()) {
- return p_a->get_name() < p_b->get_name();
+ return p_a->get_gizmo_name() < p_b->get_gizmo_name();
}
return p_a->get_priority() > p_b->get_priority();
}
@@ -6816,7 +7254,7 @@ struct _GizmoPluginPriorityComparator {
struct _GizmoPluginNameComparator {
bool operator()(const Ref<EditorNode3DGizmoPlugin> &p_a, const Ref<EditorNode3DGizmoPlugin> &p_b) const {
- return p_a->get_name() < p_b->get_name();
+ return p_a->get_gizmo_name() < p_b->get_gizmo_name();
}
};
@@ -7027,7 +7465,7 @@ void EditorNode3DGizmoPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorNode3DGizmoPlugin::get_material, DEFVAL(Ref<EditorNode3DGizmo>()));
- BIND_VMETHOD(MethodInfo(Variant::STRING, "get_name"));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "get_gizmo_name"));
BIND_VMETHOD(MethodInfo(Variant::INT, "get_priority"));
BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_be_hidden"));
BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_selectable_when_hidden"));
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 9fb7488a0f..ff4a941b06 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -37,7 +37,10 @@
#include "scene/3d/immediate_geometry_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/visual_instance_3d.h"
+#include "scene/3d/world_environment.h"
#include "scene/gui/panel_container.h"
+#include "scene/resources/environment.h"
+#include "scene/resources/sky_material.h"
class Camera3D;
class Node3DEditor;
@@ -96,6 +99,7 @@ protected:
public:
void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
+ void add_vertices(const Vector<Vector3> &p_vertices, const Ref<Material> &p_material, Mesh::PrimitiveType p_primitive_type, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const Ref<SkinReference> &p_skin_reference = Ref<SkinReference>(), const Ref<Material> &p_material = Ref<Material>());
void add_collision_segments(const Vector<Vector3> &p_lines);
void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh);
@@ -463,6 +467,8 @@ 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 _project_settings_changed();
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -730,6 +736,7 @@ private:
static Node3DEditor *singleton;
+ void _node_added(Node *p_node);
void _node_removed(Node *p_node);
Vector<Ref<EditorNode3DGizmoPlugin>> gizmo_plugins_by_priority;
Vector<Ref<EditorNode3DGizmoPlugin>> gizmo_plugins_by_name;
@@ -742,6 +749,61 @@ private:
void _refresh_menu_icons();
+ // Preview Sun and Environment
+
+ uint32_t world_env_count = 0;
+ uint32_t directional_light_count = 0;
+
+ Button *sun_button;
+ Label *sun_state;
+ Label *sun_title;
+ VBoxContainer *sun_vb;
+ Popup *sun_environ_popup;
+ Control *sun_direction;
+ ColorPickerButton *sun_color;
+ EditorSpinSlider *sun_energy;
+ EditorSpinSlider *sun_max_distance;
+ Button *sun_add_to_scene;
+
+ void _sun_direction_draw();
+ void _sun_direction_input(const Ref<InputEvent> &p_event);
+
+ Basis sun_rotation;
+
+ Ref<Shader> sun_direction_shader;
+ Ref<ShaderMaterial> sun_direction_material;
+
+ Button *environ_button;
+ Label *environ_state;
+ Label *environ_title;
+ VBoxContainer *environ_vb;
+ ColorPickerButton *environ_sky_color;
+ ColorPickerButton *environ_ground_color;
+ EditorSpinSlider *environ_energy;
+ Button *environ_ao_button;
+ Button *environ_glow_button;
+ Button *environ_tonemap_button;
+ Button *environ_gi_button;
+ Button *environ_add_to_scene;
+
+ Button *sun_environ_settings;
+
+ DirectionalLight3D *preview_sun;
+ WorldEnvironment *preview_environment;
+ Ref<Environment> environment;
+ Ref<ProceduralSkyMaterial> sky_material;
+
+ bool sun_environ_updating = false;
+
+ void _load_default_preview_settings();
+ void _update_preview_environment();
+
+ void _preview_settings_changed();
+ void _sun_environ_settings_pressed();
+
+ void _add_sun_to_scene();
+ void _add_environment_to_scene();
+
protected:
void _notification(int p_what);
//void _gui_input(InputEvent p_event);
diff --git a/editor/plugins/packed_scene_translation_parser_plugin.cpp b/editor/plugins/packed_scene_translation_parser_plugin.cpp
index 1f20a87565..0a949c8610 100644
--- a/editor/plugins/packed_scene_translation_parser_plugin.cpp
+++ b/editor/plugins/packed_scene_translation_parser_plugin.cpp
@@ -42,7 +42,7 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path,
// These properties are translated with the tr() function in the C++ code when being set or updated.
Error err;
- RES loaded_res = ResourceLoader::load(p_path, "PackedScene", false, &err);
+ RES loaded_res = ResourceLoader::load(p_path, "PackedScene", ResourceFormatLoader::CACHE_MODE_REUSE, &err);
if (err) {
ERR_PRINT("Failed to load " + p_path);
return err;
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index 908235f89f..84b4516452 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -88,7 +88,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
real_t dist_to_p_in = gpoint.distance_to(xform.xform(curve->get_point_position(i) + curve->get_point_in(i)));
// Check for point movement start (for point + in/out controls).
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mode == MODE_EDIT && !mb->get_shift() && dist_to_p < grab_threshold) {
// Points can only be moved in edit mode.
@@ -118,7 +118,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
}
// Check for point deletion.
- if ((mb->get_button_index() == BUTTON_RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == BUTTON_LEFT && mode == MODE_DELETE)) {
+ if ((mb->get_button_index() == MOUSE_BUTTON_RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && mode == MODE_DELETE)) {
if (dist_to_p < grab_threshold) {
undo_redo->create_action(TTR("Remove Point from Curve"));
undo_redo->add_do_method(curve.ptr(), "remove_point", i);
@@ -149,7 +149,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
}
// Check for point creation.
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && ((mb->get_command() && mode == MODE_EDIT) || mode == MODE_CREATE)) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && ((mb->get_command() && mode == MODE_EDIT) || mode == MODE_CREATE)) {
Ref<Curve2D> curve = node->get_curve();
undo_redo->create_action(TTR("Add Point to Curve"));
@@ -170,7 +170,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
}
// Check for segment split.
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && mode == MODE_EDIT && on_edge) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mode == MODE_EDIT && on_edge) {
Vector2 gpoint2 = mb->get_position();
Ref<Curve2D> curve = node->get_curve();
@@ -207,7 +207,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
}
// Check for point movement completion.
- if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && action != ACTION_NONE) {
+ if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && action != ACTION_NONE) {
Ref<Curve2D> curve = node->get_curve();
Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from);
diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp
index 3783af8fc6..47bd1114d2 100644
--- a/editor/plugins/path_3d_editor_plugin.cpp
+++ b/editor/plugins/path_3d_editor_plugin.cpp
@@ -316,7 +316,7 @@ bool Path3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref
set_handle_clicked(false);
}
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->get_control()))) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->get_control()))) {
//click into curve, break it down
Vector<Vector3> v3a = c->tessellate();
int idx = 0;
@@ -411,7 +411,7 @@ bool Path3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref
//add new at pos
}
- } else if (mb->is_pressed() && ((mb->get_button_index() == BUTTON_LEFT && curve_del->is_pressed()) || (mb->get_button_index() == BUTTON_RIGHT && curve_edit->is_pressed()))) {
+ } else if (mb->is_pressed() && ((mb->get_button_index() == MOUSE_BUTTON_LEFT && curve_del->is_pressed()) || (mb->get_button_index() == MOUSE_BUTTON_RIGHT && curve_edit->is_pressed()))) {
for (int i = 0; i < c->get_point_count(); i++) {
real_t dist_to_p = p_camera->unproject_position(gt.xform(c->get_point_position(i))).distance_to(mbpos);
real_t dist_to_p_out = p_camera->unproject_position(gt.xform(c->get_point_position(i) + c->get_point_out(i))).distance_to(mbpos);
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 3d7b01c149..470d897dcc 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -447,7 +447,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
Ref<InputEventMouseButton> mb = p_input;
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
uv_drag_from = snap_point(Vector2(mb->get_position().x, mb->get_position().y));
uv_drag = true;
@@ -759,7 +759,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
bone_painting = false;
}
}
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) {
_cancel_editing();
if (bone_painting) {
@@ -768,9 +768,9 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
uv_edit_draw->update();
- } else if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) {
uv_zoom->set_value(uv_zoom->get_value() / (1 - (0.1 * mb->get_factor())));
- } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) {
uv_zoom->set_value(uv_zoom->get_value() * (1 - (0.1 * mb->get_factor())));
}
}
@@ -778,7 +778,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
Ref<InputEventMouseMotion> mm = p_input;
if (mm.is_valid()) {
- if ((mm->get_button_mask() & BUTTON_MASK_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
+ if ((mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
Vector2 drag(mm->get_relative().x, mm->get_relative().y);
uv_hscroll->set_value(uv_hscroll->get_value() - drag.x);
uv_vscroll->set_value(uv_vscroll->get_value() - drag.y);
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 216c0c3bef..b298474406 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -755,8 +755,8 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) {
_save_layout();
}
-void ScriptEditor::_close_current_tab() {
- _close_tab(tab_container->get_current_tab());
+void ScriptEditor::_close_current_tab(bool p_save) {
+ _close_tab(tab_container->get_current_tab(), p_save);
}
void ScriptEditor::_close_discard_current_tab(const String &p_str) {
@@ -802,7 +802,7 @@ void ScriptEditor::_close_other_tabs() {
}
}
- _close_current_tab();
+ _close_current_tab(false);
}
}
@@ -820,7 +820,7 @@ void ScriptEditor::_close_all_tabs() {
}
}
- _close_current_tab();
+ _close_current_tab(false);
}
}
@@ -894,7 +894,7 @@ void ScriptEditor::_reload_scripts() {
Ref<Script> script = edited_res;
if (script != nullptr) {
- Ref<Script> rel_script = ResourceLoader::load(script->get_path(), script->get_class(), true);
+ Ref<Script> rel_script = ResourceLoader::load(script->get_path(), script->get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE);
ERR_CONTINUE(!rel_script.is_valid());
script->set_source_code(rel_script->get_source_code());
script->set_last_modified_time(rel_script->get_last_modified_time());
@@ -1372,7 +1372,7 @@ void ScriptEditor::_menu_option(int p_option) {
if (current->is_unsaved()) {
_ask_close_current_unsaved_tab(current);
} else {
- _close_current_tab();
+ _close_current_tab(false);
}
} break;
case FILE_COPY_PATH: {
@@ -2737,7 +2737,7 @@ void ScriptEditor::_script_list_gui_input(const Ref<InputEvent> &ev) {
Ref<InputEventMouseButton> mb = ev;
if (mb.is_valid() && mb->is_pressed()) {
switch (mb->get_button_index()) {
- case BUTTON_MIDDLE: {
+ case MOUSE_BUTTON_MIDDLE: {
// Right-click selects automatically; middle-click does not.
int idx = script_list->get_item_at_position(mb->get_position(), true);
if (idx >= 0) {
@@ -2747,7 +2747,7 @@ void ScriptEditor::_script_list_gui_input(const Ref<InputEvent> &ev) {
}
} break;
- case BUTTON_RIGHT: {
+ case MOUSE_BUTTON_RIGHT: {
_make_script_list_context_menu();
} break;
}
@@ -3497,7 +3497,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
erase_tab_confirm = memnew(ConfirmationDialog);
erase_tab_confirm->get_ok_button()->set_text(TTR("Save"));
erase_tab_confirm->add_button(TTR("Discard"), DisplayServer::get_singleton()->get_swap_cancel_ok(), "discard");
- erase_tab_confirm->connect("confirmed", callable_mp(this, &ScriptEditor::_close_current_tab));
+ erase_tab_confirm->connect("confirmed", callable_mp(this, &ScriptEditor::_close_current_tab), varray(true));
erase_tab_confirm->connect("custom_action", callable_mp(this, &ScriptEditor::_close_discard_current_tab));
add_child(erase_tab_confirm);
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 09ed3854ea..b2172e7f10 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -325,7 +325,7 @@ class ScriptEditor : public PanelContainer {
void _close_tab(int p_idx, bool p_save = true, bool p_history_back = true);
- void _close_current_tab();
+ void _close_current_tab(bool p_save = true);
void _close_discard_current_tab(const String &p_str);
void _close_docs_tab();
void _close_other_tabs();
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index f57c8fbd6b..ec931caac3 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -688,7 +688,7 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo
uint64_t date = FileAccess::get_modified_time(script->get_path());
if (last_date != date) {
- Ref<Script> rel_script = ResourceLoader::load(script->get_path(), script->get_class(), true);
+ Ref<Script> rel_script = ResourceLoader::load(script->get_path(), script->get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE);
ERR_CONTINUE(!rel_script.is_valid());
script->set_source_code(rel_script->get_source_code());
script->set_last_modified_time(rel_script->get_last_modified_time());
@@ -1066,7 +1066,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
return;
}
- tx->indent_left();
+ tx->indent_selected_lines_left();
} break;
case EDIT_INDENT_RIGHT: {
Ref<Script> scr = script;
@@ -1074,7 +1074,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
return;
}
- tx->indent_right();
+ tx->indent_selected_lines_right();
} break;
case EDIT_DELETE_LINE: {
code_editor->delete_lines();
@@ -1517,7 +1517,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
bool create_menu = false;
CodeEdit *tx = code_editor->get_text_editor();
- if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) {
local_pos = mb->get_global_position() - tx->get_global_position();
create_menu = true;
} else if (k.is_valid() && k->get_keycode() == KEY_MENU) {
@@ -1632,16 +1632,16 @@ void ScriptTextEditor::_color_changed(const Color &p_color) {
void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos) {
context_menu->clear();
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO);
context_menu->add_separator();
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_cut"), EDIT_CUT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_copy"), EDIT_COPY);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_paste"), EDIT_PASTE);
context_menu->add_separator();
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_text_select_all"), EDIT_SELECT_ALL);
context_menu->add_separator();
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left"), EDIT_INDENT_LEFT);
@@ -1743,14 +1743,14 @@ void ScriptTextEditor::_enable_code_editor() {
search_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
edit_hb->add_child(edit_menu);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_cut"), EDIT_CUT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_copy"), EDIT_COPY);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_paste"), EDIT_PASTE);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_select_all"), EDIT_SELECT_ALL);
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_up"), EDIT_MOVE_LINE_UP);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_down"), EDIT_MOVE_LINE_DOWN);
@@ -1763,7 +1763,7 @@ void ScriptTextEditor::_enable_code_editor() {
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_all_lines"), EDIT_UNFOLD_ALL_LINES);
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/complete_symbol"), EDIT_COMPLETE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_completion_query"), EDIT_COMPLETE);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/evaluate_selection"), EDIT_EVALUATE);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/trim_trailing_whitespace"), EDIT_TRIM_TRAILING_WHITESAPCE);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/convert_indent_to_spaces"), EDIT_CONVERT_INDENT_TO_SPACES);
@@ -1915,12 +1915,6 @@ static ScriptEditorBase *create_editor(const RES &p_resource) {
}
void ScriptTextEditor::register_editor() {
- ED_SHORTCUT("script_text_editor/undo", TTR("Undo"), KEY_MASK_CMD | KEY_Z);
- ED_SHORTCUT("script_text_editor/redo", TTR("Redo"), KEY_MASK_CMD | KEY_Y);
- ED_SHORTCUT("script_text_editor/cut", TTR("Cut"), KEY_MASK_CMD | KEY_X);
- ED_SHORTCUT("script_text_editor/copy", TTR("Copy"), KEY_MASK_CMD | KEY_C);
- ED_SHORTCUT("script_text_editor/paste", TTR("Paste"), KEY_MASK_CMD | KEY_V);
- ED_SHORTCUT("script_text_editor/select_all", TTR("Select All"), KEY_MASK_CMD | KEY_A);
ED_SHORTCUT("script_text_editor/move_up", TTR("Move Up"), KEY_MASK_ALT | KEY_UP);
ED_SHORTCUT("script_text_editor/move_down", TTR("Move Down"), KEY_MASK_ALT | KEY_DOWN);
ED_SHORTCUT("script_text_editor/delete_line", TTR("Delete Line"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_K);
@@ -1936,10 +1930,8 @@ void ScriptTextEditor::register_editor() {
ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), 0);
#ifdef OSX_ENABLED
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C);
- ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CTRL | KEY_SPACE);
#else
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD | KEY_D);
- ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CMD | KEY_SPACE);
#endif
ED_SHORTCUT("script_text_editor/evaluate_selection", TTR("Evaluate Selection"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_E);
ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_T);
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 05a1561f7d..8f8a4b3054 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -282,7 +282,7 @@ void ShaderEditor::_menu_option(int p_option) {
}
CodeEdit *tx = shader_editor->get_text_editor();
- tx->indent_left();
+ tx->indent_selected_lines_left();
} break;
case EDIT_INDENT_RIGHT: {
@@ -291,7 +291,7 @@ void ShaderEditor::_menu_option(int p_option) {
}
CodeEdit *tx = shader_editor->get_text_editor();
- tx->indent_right();
+ tx->indent_selected_lines_right();
} break;
case EDIT_DELETE_LINE: {
@@ -405,7 +405,7 @@ void ShaderEditor::_check_for_external_edit() {
}
void ShaderEditor::_reload_shader_from_disk() {
- Ref<Shader> rel_shader = ResourceLoader::load(shader->get_path(), shader->get_class(), true);
+ Ref<Shader> rel_shader = ResourceLoader::load(shader->get_path(), shader->get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE);
ERR_FAIL_COND(!rel_shader.is_valid());
shader->set_code(rel_shader->get_code());
@@ -460,7 +460,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
Ref<InputEventMouseButton> mb = ev;
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) {
int col, row;
CodeEdit *tx = shader_editor->get_text_editor();
tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
@@ -533,15 +533,15 @@ void ShaderEditor::_bookmark_item_pressed(int p_idx) {
void ShaderEditor::_make_context_menu(bool p_selection, Vector2 p_position) {
context_menu->clear();
if (p_selection) {
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_cut"), EDIT_CUT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_copy"), EDIT_COPY);
}
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_paste"), EDIT_PASTE);
context_menu->add_separator();
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_text_select_all"), EDIT_SELECT_ALL);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO);
context_menu->add_separator();
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left"), EDIT_INDENT_LEFT);
@@ -585,14 +585,14 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
edit_menu->set_text(TTR("Edit"));
edit_menu->set_switch_on_hover(true);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_cut"), EDIT_CUT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_copy"), EDIT_COPY);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_paste"), EDIT_PASTE);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_select_all"), EDIT_SELECT_ALL);
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_up"), EDIT_MOVE_LINE_UP);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_down"), EDIT_MOVE_LINE_DOWN);
@@ -602,7 +602,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/complete_symbol"), EDIT_COMPLETE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_completion_query"), EDIT_COMPLETE);
edit_menu->get_popup()->connect("id_pressed", callable_mp(this, &ShaderEditor::_menu_option));
search_menu = memnew(MenuButton);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index e160e6ca0d..121ccfa417 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -388,7 +388,7 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi
bone_shape->set_transform(capsule_transform);
Transform body_transform;
- body_transform.set_look_at(Vector3(0, 0, 0), child_rest.origin, Vector3(0, 1, 0));
+ body_transform.set_look_at(Vector3(0, 0, 0), child_rest.origin);
body_transform.origin = body_transform.basis.xform(Vector3(0, 0, -half_height));
Transform joint_transform;
diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp
index 03ddaa2c74..4acacf3058 100644
--- a/editor/plugins/sprite_2d_editor_plugin.cpp
+++ b/editor/plugins/sprite_2d_editor_plugin.cpp
@@ -173,8 +173,13 @@ void Sprite2DEditor::_update_mesh_data() {
Ref<Image> image = texture->get_data();
ERR_FAIL_COND(image.is_null());
+
+ if (image->is_compressed()) {
+ image->decompress();
+ }
+
Rect2 rect;
- if (node->is_region()) {
+ if (node->is_region_enabled()) {
rect = node->get_region_rect();
} else {
rect.size = Size2(image->get_width(), image->get_height());
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 0547f99079..bd6dac7490 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -105,7 +105,7 @@ void SpriteFramesEditor::_sheet_preview_draw() {
void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
Size2i size = split_sheet_preview->get_size();
int h = split_sheet_h->get_value();
int v = split_sheet_v->get_value();
@@ -150,11 +150,11 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) {
// Zoom in/out using Ctrl + mouse wheel. This is done on the ScrollContainer
// to allow performing this action anywhere, even if the cursor isn't
// hovering the texture in the workspace.
- if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
_sheet_zoom_in();
// Don't scroll up after zooming in.
accept_event();
- } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
_sheet_zoom_out();
// Don't scroll down after zooming out.
accept_event();
@@ -219,7 +219,8 @@ void SpriteFramesEditor::_sheet_zoom_out() {
}
void SpriteFramesEditor::_sheet_zoom_reset() {
- sheet_zoom = 1.f;
+ // Default the zoom to match the editor scale, but don't dezoom on editor scales below 100% to prevent pixel art from looking bad.
+ sheet_zoom = MAX(1.0, EDSCALE);
Size2 texture_size = split_sheet_preview->get_texture()->get_size();
split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom);
}
@@ -693,11 +694,11 @@ void SpriteFramesEditor::_tree_input(const Ref<InputEvent> &p_event) {
const Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
_zoom_in();
// Don't scroll up after zooming in.
accept_event();
- } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
_zoom_out();
// Don't scroll down after zooming out.
accept_event();
@@ -732,7 +733,7 @@ void SpriteFramesEditor::_zoom_out() {
}
void SpriteFramesEditor::_zoom_reset() {
- thumbnail_zoom = 1.0f;
+ thumbnail_zoom = MAX(1.0, EDSCALE);
tree->set_fixed_column_width(thumbnail_default_size * 3 / 2);
tree->set_fixed_icon_size(Size2(thumbnail_default_size, thumbnail_default_size));
}
@@ -1229,13 +1230,14 @@ SpriteFramesEditor::SpriteFramesEditor() {
// Config scale.
scale_ratio = 1.2f;
- thumbnail_default_size = 96;
- thumbnail_zoom = 1.0f;
- max_thumbnail_zoom = 8.0f;
- min_thumbnail_zoom = 0.1f;
- sheet_zoom = 1.0f;
- max_sheet_zoom = 16.0f;
- min_sheet_zoom = 0.01f;
+ thumbnail_default_size = 96 * MAX(1.0, EDSCALE);
+ thumbnail_zoom = MAX(1.0, EDSCALE);
+ max_thumbnail_zoom = 8.0f * MAX(1.0, EDSCALE);
+ min_thumbnail_zoom = 0.1f * MAX(1.0, EDSCALE);
+ // Default the zoom to match the editor scale, but don't dezoom on editor scales below 100% to prevent pixel art from looking bad.
+ sheet_zoom = MAX(1.0, EDSCALE);
+ max_sheet_zoom = 16.0f * MAX(1.0, EDSCALE);
+ min_sheet_zoom = 0.01f * MAX(1.0, EDSCALE);
_zoom_reset();
}
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index d45011c8aa..2b8bfe067d 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -363,10 +363,10 @@ void TextEditor::_edit_option(int p_op) {
code_editor->move_lines_down();
} break;
case EDIT_INDENT_LEFT: {
- tx->indent_left();
+ tx->indent_selected_lines_left();
} break;
case EDIT_INDENT_RIGHT: {
- tx->indent_right();
+ tx->indent_selected_lines_right();
} break;
case EDIT_DELETE_LINE: {
code_editor->delete_lines();
@@ -469,7 +469,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
Ref<InputEventMouseButton> mb = ev;
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_RIGHT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
int col, row;
CodeEdit *tx = code_editor->get_text_editor();
tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
@@ -514,15 +514,15 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position) {
context_menu->clear();
if (p_selection) {
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_cut"), EDIT_CUT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_copy"), EDIT_COPY);
}
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_paste"), EDIT_PASTE);
context_menu->add_separator();
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_text_select_all"), EDIT_SELECT_ALL);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO);
context_menu->add_separator();
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left"), EDIT_INDENT_LEFT);
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
@@ -584,14 +584,14 @@ TextEditor::TextEditor() {
edit_menu->set_switch_on_hover(true);
edit_menu->get_popup()->connect("id_pressed", callable_mp(this, &TextEditor::_edit_option));
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("un_redo"), EDIT_REDO);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_cut"), EDIT_CUT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_copy"), EDIT_COPY);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_paste"), EDIT_PASTE);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_select_all"), EDIT_SELECT_ALL);
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_up"), EDIT_MOVE_LINE_UP);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_down"), EDIT_MOVE_LINE_DOWN);
diff --git a/editor/plugins/texture_3d_editor_plugin.cpp b/editor/plugins/texture_3d_editor_plugin.cpp
index 04e6aa6fa8..36297c8a4a 100644
--- a/editor/plugins/texture_3d_editor_plugin.cpp
+++ b/editor/plugins/texture_3d_editor_plugin.cpp
@@ -57,7 +57,7 @@ void Texture3DEditor::_notification(int p_what) {
}
}
-void Texture3DEditor::_changed_callback(Object *p_changed, const char *p_prop) {
+void Texture3DEditor::_texture_changed() {
if (!is_visible()) {
return;
}
@@ -118,7 +118,7 @@ void Texture3DEditor::_texture_rect_update_area() {
void Texture3DEditor::edit(Ref<Texture3D> p_texture) {
if (!texture.is_null()) {
- texture->remove_change_receptor(this);
+ texture->disconnect("changed", callable_mp(this, &Texture3DEditor::_texture_changed));
}
texture = p_texture;
@@ -128,7 +128,7 @@ void Texture3DEditor::edit(Ref<Texture3D> p_texture) {
_make_shaders();
}
- texture->add_change_receptor(this);
+ texture->connect("changed", callable_mp(this, &Texture3DEditor::_texture_changed));
update();
texture_rect->set_material(material);
setting = true;
@@ -184,7 +184,7 @@ Texture3DEditor::Texture3DEditor() {
Texture3DEditor::~Texture3DEditor() {
if (!texture.is_null()) {
- texture->remove_change_receptor(this);
+ texture->disconnect("changed", callable_mp(this, &Texture3DEditor::_texture_changed));
}
}
diff --git a/editor/plugins/texture_3d_editor_plugin.h b/editor/plugins/texture_3d_editor_plugin.h
index 944abf16d9..9d90d3653f 100644
--- a/editor/plugins/texture_3d_editor_plugin.h
+++ b/editor/plugins/texture_3d_editor_plugin.h
@@ -61,10 +61,12 @@ class Texture3DEditor : public Control {
void _texture_rect_update_area();
void _texture_rect_draw();
+ void _texture_changed();
+
protected:
void _notification(int p_what);
void _gui_input(Ref<InputEvent> p_event);
- void _changed_callback(Object *p_changed, const char *p_prop) override;
+
static void _bind_methods();
public:
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index 1d3fd668c6..253f8878d2 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -104,7 +104,7 @@ void TextureEditor::_notification(int p_what) {
}
}
-void TextureEditor::_changed_callback(Object *p_changed, const char *p_prop) {
+void TextureEditor::_texture_changed() {
if (!is_visible()) {
return;
}
@@ -113,13 +113,13 @@ void TextureEditor::_changed_callback(Object *p_changed, const char *p_prop) {
void TextureEditor::edit(Ref<Texture2D> p_texture) {
if (!texture.is_null()) {
- texture->remove_change_receptor(this);
+ texture->disconnect("changed", callable_mp(this, &TextureEditor::_texture_changed));
}
texture = p_texture;
if (!texture.is_null()) {
- texture->add_change_receptor(this);
+ texture->connect("changed", callable_mp(this, &TextureEditor::_texture_changed));
update();
} else {
hide();
@@ -137,7 +137,7 @@ TextureEditor::TextureEditor() {
TextureEditor::~TextureEditor() {
if (!texture.is_null()) {
- texture->remove_change_receptor(this);
+ texture->disconnect("changed", callable_mp(this, &TextureEditor::_texture_changed));
}
}
diff --git a/editor/plugins/texture_editor_plugin.h b/editor/plugins/texture_editor_plugin.h
index 621d737028..ebe8882194 100644
--- a/editor/plugins/texture_editor_plugin.h
+++ b/editor/plugins/texture_editor_plugin.h
@@ -43,7 +43,7 @@ class TextureEditor : public Control {
protected:
void _notification(int p_what);
void _gui_input(Ref<InputEvent> p_event);
- void _changed_callback(Object *p_changed, const char *p_prop) override;
+ void _texture_changed();
static void _bind_methods();
public:
diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp
index 2be300ad66..265d4ccc1e 100644
--- a/editor/plugins/texture_layered_editor_plugin.cpp
+++ b/editor/plugins/texture_layered_editor_plugin.cpp
@@ -36,7 +36,7 @@
void TextureLayeredEditor::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
y_rot += -mm->get_relative().x * 0.01;
x_rot += mm->get_relative().y * 0.01;
_update_material();
@@ -63,7 +63,7 @@ void TextureLayeredEditor::_notification(int p_what) {
}
}
-void TextureLayeredEditor::_changed_callback(Object *p_changed, const char *p_prop) {
+void TextureLayeredEditor::_texture_changed() {
if (!is_visible()) {
return;
}
@@ -173,7 +173,7 @@ void TextureLayeredEditor::_texture_rect_update_area() {
void TextureLayeredEditor::edit(Ref<TextureLayered> p_texture) {
if (!texture.is_null()) {
- texture->remove_change_receptor(this);
+ texture->disconnect("changed", callable_mp(this, &TextureLayeredEditor::_texture_changed));
}
texture = p_texture;
@@ -183,7 +183,7 @@ void TextureLayeredEditor::edit(Ref<TextureLayered> p_texture) {
_make_shaders();
}
- texture->add_change_receptor(this);
+ texture->connect("changed", callable_mp(this, &TextureLayeredEditor::_texture_changed));
update();
texture_rect->set_material(materials[texture->get_layered_type()]);
setting = true;
@@ -248,9 +248,6 @@ TextureLayeredEditor::TextureLayeredEditor() {
}
TextureLayeredEditor::~TextureLayeredEditor() {
- if (!texture.is_null()) {
- texture->remove_change_receptor(this);
- }
}
//
diff --git a/editor/plugins/texture_layered_editor_plugin.h b/editor/plugins/texture_layered_editor_plugin.h
index 4bcc8fa1f1..c4ced62fb9 100644
--- a/editor/plugins/texture_layered_editor_plugin.h
+++ b/editor/plugins/texture_layered_editor_plugin.h
@@ -63,10 +63,11 @@ class TextureLayeredEditor : public Control {
void _texture_rect_update_area();
void _texture_rect_draw();
+ void _texture_changed();
+
protected:
void _notification(int p_what);
void _gui_input(Ref<InputEvent> p_event);
- void _changed_callback(Object *p_changed, const char *p_prop) override;
static void _bind_methods();
public:
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 61e0cc281d..7b927ad98b 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -285,7 +285,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
Ref<InputEventMouseButton> mb = p_input;
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
if (node_ninepatch || obj_styleBox.is_valid()) {
edited_margin = -1;
@@ -447,7 +447,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
creating = false;
}
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) {
if (drag) {
drag = false;
if (edited_margin >= 0) {
@@ -466,9 +466,9 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
drag_index = -1;
}
}
- } else if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) {
_zoom_on_position(draw_zoom * ((0.95 + (0.05 * mb->get_factor())) / 0.95), mb->get_position());
- } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) {
_zoom_on_position(draw_zoom * (1 - (0.05 * mb->get_factor())), mb->get_position());
}
}
@@ -476,24 +476,45 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
Ref<InputEventMouseMotion> mm = p_input;
if (mm.is_valid()) {
- if (mm->get_button_mask() & BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
+ if (mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
Vector2 dragged(mm->get_relative().x / draw_zoom, mm->get_relative().y / draw_zoom);
hscroll->set_value(hscroll->get_value() - dragged.x);
vscroll->set_value(vscroll->get_value() - dragged.y);
-
} else if (drag) {
if (edited_margin >= 0) {
float new_margin = 0;
- if (edited_margin == 0) {
- new_margin = prev_margin + (mm->get_position().y - drag_from.y) / draw_zoom;
- } else if (edited_margin == 1) {
- new_margin = prev_margin - (mm->get_position().y - drag_from.y) / draw_zoom;
- } else if (edited_margin == 2) {
- new_margin = prev_margin + (mm->get_position().x - drag_from.x) / draw_zoom;
- } else if (edited_margin == 3) {
- new_margin = prev_margin - (mm->get_position().x - drag_from.x) / draw_zoom;
+
+ if (snap_mode != SNAP_GRID) {
+ if (edited_margin == 0) {
+ new_margin = prev_margin + (mm->get_position().y - drag_from.y) / draw_zoom;
+ } else if (edited_margin == 1) {
+ new_margin = prev_margin - (mm->get_position().y - drag_from.y) / draw_zoom;
+ } else if (edited_margin == 2) {
+ new_margin = prev_margin + (mm->get_position().x - drag_from.x) / draw_zoom;
+ } else if (edited_margin == 3) {
+ new_margin = prev_margin - (mm->get_position().x - drag_from.x) / draw_zoom;
+ } else {
+ ERR_PRINT("Unexpected edited_margin");
+ }
+
+ if (snap_mode == SNAP_PIXEL) {
+ new_margin = Math::round(new_margin);
+ }
} else {
- ERR_PRINT("Unexpected edited_margin");
+ Vector2 pos_snapped = snap_point(mtx.affine_inverse().xform(mm->get_position()));
+ Rect2 rect_rounded = Rect2(rect.position.round(), rect.size.round());
+
+ if (edited_margin == 0) {
+ new_margin = pos_snapped.y - rect_rounded.position.y;
+ } else if (edited_margin == 1) {
+ new_margin = rect_rounded.size.y + rect_rounded.position.y - pos_snapped.y;
+ } else if (edited_margin == 2) {
+ new_margin = pos_snapped.x - rect_rounded.position.x;
+ } else if (edited_margin == 3) {
+ new_margin = rect_rounded.size.x + rect_rounded.position.x - pos_snapped.x;
+ } else {
+ ERR_PRINT("Unexpected edited_margin");
+ }
}
if (new_margin < 0) {
@@ -842,19 +863,19 @@ Sprite2D *TextureRegionEditor::get_sprite() {
void TextureRegionEditor::edit(Object *p_obj) {
if (node_sprite) {
- node_sprite->remove_change_receptor(this);
+ node_sprite->disconnect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
}
if (node_sprite_3d) {
- node_sprite_3d->remove_change_receptor(this);
+ node_sprite_3d->disconnect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
}
if (node_ninepatch) {
- node_ninepatch->remove_change_receptor(this);
+ node_ninepatch->disconnect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
}
if (obj_styleBox.is_valid()) {
- obj_styleBox->remove_change_receptor(this);
+ obj_styleBox->disconnect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
}
if (atlas_tex.is_valid()) {
- atlas_tex->remove_change_receptor(this);
+ atlas_tex->disconnect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
}
if (p_obj) {
node_sprite = Object::cast_to<Sprite2D>(p_obj);
@@ -866,7 +887,7 @@ void TextureRegionEditor::edit(Object *p_obj) {
if (Object::cast_to<AtlasTexture>(p_obj)) {
atlas_tex = Ref<AtlasTexture>(Object::cast_to<AtlasTexture>(p_obj));
}
- p_obj->add_change_receptor(this);
+ p_obj->connect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed));
_edit_region();
} else {
node_sprite = nullptr;
@@ -876,7 +897,7 @@ void TextureRegionEditor::edit(Object *p_obj) {
atlas_tex = Ref<AtlasTexture>(nullptr);
}
edit_draw->update();
- if ((node_sprite && !node_sprite->is_region()) || (node_sprite_3d && !node_sprite_3d->is_region())) {
+ if ((node_sprite && !node_sprite->is_region_enabled()) || (node_sprite_3d && !node_sprite_3d->is_region_enabled())) {
set_process(true);
}
if (!p_obj) {
@@ -884,14 +905,11 @@ void TextureRegionEditor::edit(Object *p_obj) {
}
}
-void TextureRegionEditor::_changed_callback(Object *p_changed, const char *p_prop) {
+void TextureRegionEditor::_texture_changed() {
if (!is_visible()) {
return;
}
- String prop = p_prop;
- if (prop == "atlas" || prop == "texture" || prop == "region") {
- _edit_region();
- }
+ _edit_region();
}
void TextureRegionEditor::_edit_region() {
@@ -1097,7 +1115,7 @@ void TextureRegionEditorPlugin::_editor_visiblity_changed() {
void TextureRegionEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
texture_region_button->show();
- bool is_node_configured = region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch() || (region_editor->get_sprite() && region_editor->get_sprite()->is_region()) || (region_editor->get_sprite_3d() && region_editor->get_sprite_3d()->is_region());
+ bool is_node_configured = region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch() || (region_editor->get_sprite() && region_editor->get_sprite()->is_region_enabled()) || (region_editor->get_sprite_3d() && region_editor->get_sprite_3d()->is_region_enabled());
if ((is_node_configured && !manually_hidden) || texture_region_button->is_pressed()) {
editor->make_bottom_panel_item_visible(region_editor);
}
diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h
index 56ccefb025..d3db0a08a9 100644
--- a/editor/plugins/texture_region_editor_plugin.h
+++ b/editor/plugins/texture_region_editor_plugin.h
@@ -117,6 +117,8 @@ class TextureRegionEditor : public VBoxContainer {
void _update_rect();
void _update_autoslice();
+ void _texture_changed();
+
protected:
void _notification(int p_what);
void _node_removed(Object *p_obj);
@@ -124,8 +126,6 @@ protected:
Vector2 snap_point(Vector2 p_target) const;
- virtual void _changed_callback(Object *p_changed, const char *p_prop) override;
-
public:
void _edit_region();
void _region_draw();
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 6a16aa28a9..bd721244ea 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -40,9 +40,12 @@
void TileMapEditor::_node_removed(Node *p_node) {
if (p_node == node && node) {
- // Fixes #44824, which describes a situation where you can reselect a TileMap node without first de-selecting it when switching scenes.
- node->disconnect("settings_changed", callable_mp(this, &TileMapEditor::_tileset_settings_changed));
+ Callable callable_tileset_settings_changed = callable_mp(this, &TileMapEditor::_tileset_settings_changed);
+ if (node->is_connected("settings_changed", callable_tileset_settings_changed)) {
+ // Fixes #44824, which describes a situation where you can reselect a TileMap node without first de-selecting it when switching scenes.
+ node->disconnect("settings_changed", callable_tileset_settings_changed);
+ }
node = nullptr;
}
}
@@ -230,11 +233,11 @@ void TileMapEditor::_palette_input(const Ref<InputEvent> &p_event) {
// Zoom in/out using Ctrl + mouse wheel.
if (mb.is_valid() && mb->is_pressed() && mb->get_command()) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
size_slider->set_value(size_slider->get_value() + 0.2);
}
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
size_slider->set_value(size_slider->get_value() - 0.2);
}
}
@@ -963,9 +966,9 @@ void TileMapEditor::_update_copydata() {
tcd.flip_v = node->is_cell_y_flipped(j, i);
tcd.transpose = node->is_cell_transposed(j, i);
tcd.autotile_coord = node->get_cell_autotile_coord(j, i);
- }
- copydata.push_back(tcd);
+ copydata.push_back(tcd);
+ }
}
}
}
@@ -1024,7 +1027,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
if (Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
return false; // Drag.
@@ -1174,7 +1177,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return true;
}
}
- } else if (mb->get_button_index() == BUTTON_RIGHT) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
if (mb->is_pressed()) {
if (tool == TOOL_SELECTING || selection_active) {
tool = TOOL_NONE;
@@ -1459,7 +1462,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return true;
}
- if (tool == TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+ if (tool == TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) {
_pick_tile(over_tile);
return true;
@@ -1870,7 +1873,11 @@ void TileMapEditor::edit(Node *p_tile_map) {
}
if (node) {
- node->disconnect("settings_changed", callable_mp(this, &TileMapEditor::_tileset_settings_changed));
+ Callable callable_tileset_settings_changed = callable_mp(this, &TileMapEditor::_tileset_settings_changed);
+
+ if (node->is_connected("settings_changed", callable_tileset_settings_changed)) {
+ node->disconnect("settings_changed", callable_tileset_settings_changed);
+ }
}
if (p_tile_map) {
node = Object::cast_to<TileMap>(p_tile_map);
@@ -1897,7 +1904,11 @@ void TileMapEditor::edit(Node *p_tile_map) {
}
if (node) {
- node->connect("settings_changed", callable_mp(this, &TileMapEditor::_tileset_settings_changed));
+ Callable callable_tileset_settings_changed = callable_mp(this, &TileMapEditor::_tileset_settings_changed);
+
+ if (!node->is_connected("settings_changed", callable_tileset_settings_changed)) {
+ node->connect("settings_changed", callable_tileset_settings_changed);
+ }
}
_clear_bucket_cache();
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index deeab2fbc7..cca4f594e9 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -39,7 +39,6 @@
void TileSetEditor::edit(const Ref<TileSet> &p_tileset) {
tileset = p_tileset;
- tileset->add_change_receptor(this);
texture_list->clear();
texture_map.clear();
@@ -81,7 +80,7 @@ void TileSetEditor::_import_node(Node *p_node, Ref<TileSet> p_library) {
Vector2 phys_offset;
Size2 s;
- if (mi->is_region()) {
+ if (mi->is_region_enabled()) {
s = mi->get_region_rect().size;
p_library->tile_set_region(id, mi->get_region_rect());
} else {
@@ -1247,12 +1246,12 @@ void TileSetEditor::_on_scroll_container_input(const Ref<InputEvent> &p_event) {
// Zoom in/out using Ctrl + mouse wheel. This is done on the ScrollContainer
// to allow performing this action anywhere, even if the cursor isn't
// hovering the texture in the workspace.
- if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
print_line("zooming in");
_zoom_in();
// Don't scroll up after zooming in.
accept_event();
- } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
print_line("zooming out");
_zoom_out();
// Don't scroll down after zooming out.
@@ -1281,7 +1280,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
const Ref<InputEventMouseMotion> mm = p_ie;
if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && !creating_shape) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !creating_shape) {
if (!current_tile_region.has_point(mb->get_position())) {
List<int> *tiles = new List<int>();
tileset->get_tile_list(tiles);
@@ -1305,7 +1304,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
}
// Drag Middle Mouse
if (mm.is_valid()) {
- if (mm->get_button_mask() & BUTTON_MASK_MIDDLE) {
+ if (mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) {
Vector2 dragged(mm->get_relative().x, mm->get_relative().y);
scroll->set_h_scroll(scroll->get_h_scroll() - dragged.x * workspace->get_scale().x);
scroll->set_v_scroll(scroll->get_v_scroll() - dragged.y * workspace->get_scale().x);
@@ -1314,7 +1313,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
if (edit_mode == EDITMODE_REGION) {
if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (get_current_tile() >= 0 || workspace_mode != WORKSPACE_EDIT) {
dragging = true;
region_from = mb->get_position();
@@ -1323,13 +1322,13 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
workspace_overlay->update();
return;
}
- } else if (dragging && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ } else if (dragging && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
dragging = false;
edited_region = Rect2();
workspace->update();
workspace_overlay->update();
return;
- } else if (dragging && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ } else if (dragging && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
dragging = false;
update_edited_region(mb->get_position());
edited_region.position -= WORKSPACE_MARGIN;
@@ -1429,7 +1428,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
switch (edit_mode) {
case EDITMODE_ICON: {
if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && current_tile_region.has_point(mb->get_position())) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && current_tile_region.has_point(mb->get_position())) {
Vector2 coord((int)((mb->get_position().x - current_tile_region.position.x) / (spacing + size.x)), (int)((mb->get_position().y - current_tile_region.position.y) / (spacing + size.y)));
undo_redo->create_action(TTR("Set Tile Icon"));
undo_redo->add_do_method(tileset.ptr(), "autotile_set_icon_coordinate", get_current_tile(), coord);
@@ -1446,9 +1445,9 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
if (dragging) {
return;
}
- if ((mb->get_button_index() == BUTTON_RIGHT || mb->get_button_index() == BUTTON_LEFT) && current_tile_region.has_point(mb->get_position())) {
+ if ((mb->get_button_index() == MOUSE_BUTTON_RIGHT || mb->get_button_index() == MOUSE_BUTTON_LEFT) && current_tile_region.has_point(mb->get_position())) {
dragging = true;
- erasing = (mb->get_button_index() == BUTTON_RIGHT);
+ erasing = (mb->get_button_index() == MOUSE_BUTTON_RIGHT);
alternative = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
Vector2 coord((int)((mb->get_position().x - current_tile_region.position.x) / (spacing + size.x)), (int)((mb->get_position().y - current_tile_region.position.y) / (spacing + size.y)));
Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y));
@@ -1519,7 +1518,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
}
}
} else {
- if ((erasing && mb->get_button_index() == BUTTON_RIGHT) || (!erasing && mb->get_button_index() == BUTTON_LEFT)) {
+ if ((erasing && mb->get_button_index() == MOUSE_BUTTON_RIGHT) || (!erasing && mb->get_button_index() == MOUSE_BUTTON_LEFT)) {
dragging = false;
erasing = false;
alternative = false;
@@ -1613,7 +1612,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
shape_anchor += current_tile_region.position;
if (tools[TOOL_SELECT]->is_pressed()) {
if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (edit_mode != EDITMODE_PRIORITY && current_shape.size() > 0) {
int grabbed_point = get_grabbed_point(mb->get_position(), grab_threshold);
@@ -1631,7 +1630,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
}
}
workspace->update();
- } else if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ } else if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (edit_mode == EDITMODE_COLLISION) {
if (dragging_point >= 0) {
dragging_point = -1;
@@ -1706,7 +1705,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
}
} else if (tools[SHAPE_NEW_POLYGON]->is_pressed()) {
if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
Vector2 pos = mb->get_position();
pos = snap_point(pos);
if (creating_shape) {
@@ -1726,7 +1725,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
current_shape.push_back(snap_point(pos));
workspace->update();
}
- } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ } else if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
if (creating_shape) {
creating_shape = false;
_select_edited_shape_coord();
@@ -1740,7 +1739,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
}
} else if (tools[SHAPE_NEW_RECTANGLE]->is_pressed()) {
if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
_set_edited_collision_shape(Ref<ConvexPolygonShape2D>());
current_shape.resize(0);
Vector2 pos = mb->get_position();
@@ -1752,13 +1751,13 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
creating_shape = true;
workspace->update();
return;
- } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ } else if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
if (creating_shape) {
creating_shape = false;
_select_edited_shape_coord();
workspace->update();
}
- } else if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ } else if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (creating_shape) {
// if the first two corners are within grabbing distance of one another, expand the rect to fill the tile
if (is_within_grabbing_distance_of_first_point(current_shape[1], grab_threshold)) {
@@ -1859,7 +1858,7 @@ void TileSetEditor::_on_tool_clicked(int p_tool) {
_update_toggle_shape_button();
workspace->update();
workspace_container->update();
- helper->_change_notify("");
+ helper->notify_property_list_changed();
}
} else if (p_tool == SELECT_NEXT) {
_select_next_shape();
@@ -2173,7 +2172,7 @@ Array TileSetEditor::_get_tiles_in_current_texture(bool sorted) {
}
}
if (sorted) {
- a.sort_custom(this, "_sort_tiles");
+ a.sort_custom(callable_mp(this, &TileSetEditor::_sort_tiles));
}
return a;
}
@@ -2287,7 +2286,7 @@ void TileSetEditor::_select_next_shape() {
}
workspace->update();
workspace_container->update();
- helper->_change_notify("");
+ helper->notify_property_list_changed();
}
}
@@ -2349,7 +2348,7 @@ void TileSetEditor::_select_previous_shape() {
}
workspace->update();
workspace_container->update();
- helper->_change_notify("");
+ helper->notify_property_list_changed();
}
}
@@ -3012,7 +3011,7 @@ void TileSetEditor::close_shape(const Vector2 &shape_anchor) {
undo_redo->add_undo_method(this, "_select_edited_shape_coord");
undo_redo->commit_action();
}
- tileset->_change_notify("");
+ tileset->notify_property_list_changed();
}
void TileSetEditor::select_coord(const Vector2 &coord) {
@@ -3115,7 +3114,7 @@ void TileSetEditor::select_coord(const Vector2 &coord) {
}
workspace->update();
workspace_container->update();
- helper->_change_notify("");
+ helper->notify_property_list_changed();
}
Vector2 TileSetEditor::snap_point(const Vector2 &point) {
@@ -3225,7 +3224,7 @@ void TileSetEditor::update_texture_list() {
workspace_overlay->update();
}
update_texture_list_icon();
- helper->_change_notify("");
+ helper->notify_property_list_changed();
}
void TileSetEditor::update_texture_list_icon() {
@@ -3389,7 +3388,7 @@ int TileSetEditor::get_current_tile() const {
void TileSetEditor::set_current_tile(int p_id) {
if (current_tile != p_id) {
current_tile = p_id;
- helper->_change_notify("");
+ helper->notify_property_list_changed();
select_coord(Vector2(0, 0));
update_workspace_tile_mode();
if (p_id == -1) {
@@ -3414,7 +3413,7 @@ void TilesetEditorContext::set_tileset(const Ref<TileSet> &p_tileset) {
void TilesetEditorContext::set_snap_options_visible(bool p_visible) {
snap_options_visible = p_visible;
- _change_notify("");
+ notify_property_list_changed();
}
bool TilesetEditorContext::_set(const StringName &p_name, const Variant &p_value) {
@@ -3450,7 +3449,7 @@ bool TilesetEditorContext::_set(const StringName &p_name, const Variant &p_value
tileset->set(String::num(tileset_editor->get_current_tile(), 0) + "/" + name2, p_value, &v);
}
if (v) {
- tileset->_change_notify("");
+ tileset->notify_property_list_changed();
tileset_editor->workspace->update();
tileset_editor->workspace_overlay->update();
}
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 5061067ded..69bdc05b3a 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -1023,7 +1023,7 @@ void VisualShaderEditor::_update_options_menu() {
Color unsupported_color = get_theme_color("error_color", "Editor");
Color supported_color = get_theme_color("warning_color", "Editor");
- static bool low_driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name") == "GLES2";
+ static bool low_driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name") == "GLES2";
Map<String, TreeItem *> folders;
@@ -2504,7 +2504,7 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
VisualShader::Type type = get_current_shader_type();
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
selected_constants.clear();
selected_uniforms.clear();
diff --git a/editor/pot_generator.cpp b/editor/pot_generator.cpp
index 2d65c00a89..497cc0cbdc 100644
--- a/editor/pot_generator.cpp
+++ b/editor/pot_generator.cpp
@@ -55,7 +55,7 @@ void POTGenerator::_print_all_translation_strings() {
#endif
void POTGenerator::generate_pot(const String &p_file) {
- if (!ProjectSettings::get_singleton()->has_setting("locale/translations_pot_files")) {
+ if (!ProjectSettings::get_singleton()->has_setting("internationalization/locale/translations_pot_files")) {
WARN_PRINT("No files selected for POT generation.");
return;
}
@@ -63,7 +63,7 @@ void POTGenerator::generate_pot(const String &p_file) {
// Clear all_translation_strings of the previous round.
all_translation_strings.clear();
- Vector<String> files = ProjectSettings::get_singleton()->get("locale/translations_pot_files");
+ Vector<String> files = ProjectSettings::get_singleton()->get("internationalization/locale/translations_pot_files");
// Collect all translatable strings according to files order in "POT Generation" setting.
for (int i = 0; i < files.size(); i++) {
@@ -100,7 +100,7 @@ void POTGenerator::_write_to_pot(const String &p_file) {
}
String project_name = ProjectSettings::get_singleton()->get("application/config/name");
- Vector<String> files = ProjectSettings::get_singleton()->get("locale/translations_pot_files");
+ Vector<String> files = ProjectSettings::get_singleton()->get("internationalization/locale/translations_pot_files");
String extracted_files = "";
for (int i = 0; i < files.size(); i++) {
extracted_files += "# " + files[i] + "\n";
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 4bcb616fbd..b7dd1013f3 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -37,7 +37,7 @@
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
-#include "core/string/compressed_translation.h"
+#include "core/string/optimized_translation.h"
#include "editor_data.h"
#include "editor_node.h"
#include "editor_scale.h"
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 5951373af9..914806039f 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -474,20 +474,20 @@ private:
}
ProjectSettings::CustomMap initial_settings;
if (rasterizer_button_group->get_pressed_button()->get_meta("driver_name") == "Vulkan") {
- initial_settings["rendering/quality/driver/driver_name"] = "Vulkan";
+ initial_settings["rendering/driver/driver_name"] = "Vulkan";
} else {
- initial_settings["rendering/quality/driver/driver_name"] = "GLES2";
- initial_settings["rendering/vram_compression/import_etc2"] = false;
- initial_settings["rendering/vram_compression/import_etc"] = true;
+ initial_settings["rendering/driver/driver_name"] = "GLES2";
+ initial_settings["rendering/textures/vram_compression/import_etc2"] = false;
+ initial_settings["rendering/textures/vram_compression/import_etc"] = true;
}
initial_settings["application/config/name"] = project_name->get_text();
initial_settings["application/config/icon"] = "res://icon.png";
- initial_settings["rendering/environment/default_environment"] = "res://default_env.tres";
+ initial_settings["rendering/environment/defaults/default_environment"] = "res://default_env.tres";
if (ProjectSettings::get_singleton()->save_custom(dir.plus_file("project.godot"), initial_settings, Vector<String>(), false) != OK) {
set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR);
} else {
- ResourceSaver::save(dir.plus_file("icon.png"), msg->get_theme_icon("DefaultProjectIcon", "EditorIcons"));
+ ResourceSaver::save(dir.plus_file("icon.png"), create_unscaled_default_project_icon());
FileAccess *f = FileAccess::open(dir.plus_file("default_env.tres"), FileAccess::WRITE);
if (!f) {
@@ -1741,7 +1741,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) {
int clicked_index = p_hb->get_index();
const Item &clicked_project = _projects[clicked_index];
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->get_shift() && _selected_project_keys.size() > 0 && _last_clicked != "" && clicked_project.project_key != _last_clicked) {
int anchor_index = -1;
for (int i = 0; i < _projects.size(); ++i) {
@@ -2015,6 +2015,10 @@ void ProjectManager::_confirm_update_settings() {
}
void ProjectManager::_open_selected_projects() {
+ // Show loading text to tell the user that the project manager is busy loading.
+ // This is especially important for the HTML5 project manager.
+ loading_label->set_modulate(Color(1, 1, 1));
+
const Set<String> &selected_list = _project_list->get_selected_project_keys();
for (const Set<String>::Element *E = selected_list.front(); E; E = E->next()) {
@@ -2268,11 +2272,6 @@ void ProjectManager::_restart_confirm() {
get_tree()->quit();
}
-void ProjectManager::_exit_dialog() {
- _dim_window();
- get_tree()->quit();
-}
-
void ProjectManager::_install_project(const String &p_zip_path, const String &p_title) {
npdialog->set_mode(ProjectDialog::MODE_INSTALL);
npdialog->set_zip_path(p_zip_path);
@@ -2281,6 +2280,11 @@ void ProjectManager::_install_project(const String &p_zip_path, const String &p_
}
void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) {
+ if (p_files.size() == 1 && p_files[0].ends_with(".zip")) {
+ const String file = p_files[0].get_file();
+ _install_project(p_files[0], file.substr(0, file.length() - 4).capitalize());
+ return;
+ }
Set<String> folders_set;
DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < p_files.size(); i++) {
@@ -2346,7 +2350,6 @@ void ProjectManager::_on_search_term_changed(const String &p_term) {
}
void ProjectManager::_bind_methods() {
- ClassDB::bind_method("_exit_dialog", &ProjectManager::_exit_dialog);
ClassDB::bind_method("_unhandled_key_input", &ProjectManager::_unhandled_key_input);
ClassDB::bind_method("_update_project_buttons", &ProjectManager::_update_project_buttons);
}
@@ -2380,6 +2383,10 @@ ProjectManager::ProjectManager() {
if (DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).y >= 1400) {
// hiDPI display.
scale = 2.0;
+ } else if (DisplayServer::get_singleton()->screen_get_size(screen).y >= 1700) {
+ // Likely a hiDPI display, but we aren't certain due to the returned DPI.
+ // Use an intermediate scale to handle this situation.
+ scale = 1.5;
} else if (DisplayServer::get_singleton()->screen_get_size(screen).y <= 800) {
// Small loDPI display. Use a smaller display scale so that editor elements fit more easily.
// Icons won't look great, but this is better than having editor elements overflow from its window.
@@ -2476,7 +2483,12 @@ ProjectManager::ProjectManager() {
search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
hb->add_child(search_box);
- hb->add_spacer();
+ loading_label = memnew(Label(TTR("Loading, please wait...")));
+ loading_label->add_theme_font_override("font", get_theme_font("bold", "EditorFonts"));
+ loading_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hb->add_child(loading_label);
+ // Hide the label but make it still take up space. This prevents reflows when showing the label.
+ loading_label->set_modulate(Color(0, 0, 0, 0));
Label *sort_label = memnew(Label);
sort_label->set_text(TTR("Sort:"));
diff --git a/editor/project_manager.h b/editor/project_manager.h
index db8cb8410c..6dc0e67cba 100644
--- a/editor/project_manager.h
+++ b/editor/project_manager.h
@@ -54,6 +54,7 @@ class ProjectManager : public Control {
ProjectList *_project_list;
LineEdit *search_box;
+ Label *loading_label;
OptionButton *filter_option;
Button *run_btn;
@@ -98,7 +99,6 @@ class ProjectManager : public Control {
void _update_project_buttons();
void _language_selected(int p_id);
void _restart_confirm();
- void _exit_dialog();
void _confirm_update_settings();
void _nonempty_confirmation_ok_pressed();
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 4516180fa5..de7996eaa2 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -52,9 +52,11 @@ void ProjectSettingsEditor::popup_project_settings() {
localization_editor->update_translations();
autoload_settings->update_autoload();
plugin_settings->update_plugins();
+ import_defaults_editor->clear();
}
void ProjectSettingsEditor::queue_save() {
+ EditorNode::get_singleton()->notify_settings_changed();
timer->start();
}
@@ -74,8 +76,12 @@ void ProjectSettingsEditor::_advanced_pressed() {
if (advanced->is_pressed()) {
_update_advanced_bar();
advanced_bar->show();
+ EditorSettings::get_singleton()->set_project_metadata("project_settings", "advanced_mode", true);
+ inspector->set_restrict_to_basic_settings(false);
} else {
advanced_bar->hide();
+ EditorSettings::get_singleton()->set_project_metadata("project_settings", "advanced_mode", false);
+ inspector->set_restrict_to_basic_settings(true);
}
}
@@ -190,9 +196,6 @@ void ProjectSettingsEditor::_update_advanced_bar() {
add_button->set_disabled(disable_add);
del_button->set_disabled(disable_del);
-
- error_label->set_text(error_msg);
- error_label->set_visible(error_msg != "");
}
String ProjectSettingsEditor::_get_setting_name() const {
@@ -255,6 +258,7 @@ void ProjectSettingsEditor::_add_feature_overrides() {
}
void ProjectSettingsEditor::_editor_restart() {
+ ProjectSettings::get_singleton()->save();
EditorNode::get_singleton()->save_all_scenes();
EditorNode::get_singleton()->restart_editor();
}
@@ -267,21 +271,216 @@ void ProjectSettingsEditor::_editor_restart_close() {
restart_container->hide();
}
+void ProjectSettingsEditor::_action_added(const String &p_name) {
+ String name = "input/" + p_name;
+
+ if (ProjectSettings::get_singleton()->has_setting(name)) {
+ action_map->show_message(vformat(TTR("An action with the name '%s' already exists."), name));
+ return;
+ }
+
+ Dictionary action;
+ action["events"] = Array();
+ action["deadzone"] = 0.5f;
+
+ undo_redo->create_action(TTR("Add Input Action"));
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name);
+
+ undo_redo->add_do_method(this, "_update_action_map_editor");
+ undo_redo->add_undo_method(this, "_update_action_map_editor");
+ undo_redo->add_do_method(this, "queue_save");
+ undo_redo->add_undo_method(this, "queue_save");
+ undo_redo->commit_action();
+}
+
+void ProjectSettingsEditor::_action_edited(const String &p_name, const Dictionary &p_action) {
+ const String property_name = "input/" + p_name;
+ Dictionary old_val = ProjectSettings::get_singleton()->get(property_name);
+
+ if (old_val["deadzone"] != p_action["deadzone"]) {
+ // Deadzone Changed
+ undo_redo->create_action(TTR("Change Action deadzone"));
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", property_name, p_action);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", property_name, old_val);
+
+ } else {
+ // Events changed
+ int event_count = ((Array)p_action["events"]).size();
+ int old_event_count = ((Array)old_val["events"]).size();
+
+ if (event_count == old_event_count) {
+ undo_redo->create_action(TTR("Edit Input Action Event"));
+ } else if (event_count > old_event_count) {
+ undo_redo->create_action(TTR("Add Input Action Event"));
+ } else if (event_count < old_event_count) {
+ undo_redo->create_action(TTR("Remove Input Action Event"));
+ }
+
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", property_name, p_action);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", property_name, old_val);
+ }
+
+ undo_redo->add_do_method(this, "_update_action_map_editor");
+ undo_redo->add_undo_method(this, "_update_action_map_editor");
+ undo_redo->add_do_method(this, "queue_save");
+ undo_redo->add_undo_method(this, "queue_save");
+ undo_redo->commit_action();
+}
+
+void ProjectSettingsEditor::_action_removed(const String &p_name) {
+ const String property_name = "input/" + p_name;
+
+ Dictionary old_val = ProjectSettings::get_singleton()->get(property_name);
+ int order = ProjectSettings::get_singleton()->get_order(property_name);
+
+ undo_redo->create_action(TTR("Erase Input Action"));
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", property_name);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", property_name, old_val);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", property_name, order);
+
+ undo_redo->add_do_method(this, "_update_action_map_editor");
+ undo_redo->add_undo_method(this, "_update_action_map_editor");
+ undo_redo->add_do_method(this, "queue_save");
+ undo_redo->add_undo_method(this, "queue_save");
+ undo_redo->commit_action();
+}
+
+void ProjectSettingsEditor::_action_renamed(const String &p_old_name, const String &p_new_name) {
+ const String old_property_name = "input/" + p_old_name;
+ const String new_property_name = "input/" + p_new_name;
+
+ if (ProjectSettings::get_singleton()->has_setting(new_property_name)) {
+ action_map->show_message(vformat(TTR("An action with the name '%s' already exists."), new_property_name));
+ return;
+ }
+
+ int order = ProjectSettings::get_singleton()->get_order(old_property_name);
+ Dictionary action = ProjectSettings::get_singleton()->get(old_property_name);
+
+ undo_redo->create_action(TTR("Rename Input Action Event"));
+ // Do: clear old, set new
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", old_property_name);
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", new_property_name, action);
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", new_property_name, order);
+ // Undo: clear new, set old
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", new_property_name);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", old_property_name, action);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", old_property_name, order);
+
+ undo_redo->add_do_method(this, "_update_action_map_editor");
+ undo_redo->add_undo_method(this, "_update_action_map_editor");
+ undo_redo->add_do_method(this, "queue_save");
+ undo_redo->add_undo_method(this, "queue_save");
+ undo_redo->commit_action();
+}
+
+void ProjectSettingsEditor::_action_reordered(const String &p_action_name, const String &p_relative_to, bool p_before) {
+ const String action_name = "input/" + p_action_name;
+ const String target_name = "input/" + p_relative_to;
+
+ // It is much easier to rebuild the custom "input" properties rather than messing around with the "order" values of them.
+ Variant action_value = ps->get(action_name);
+ Variant target_value = ps->get(target_name);
+
+ List<PropertyInfo> props;
+ OrderedHashMap<String, Variant> action_values;
+ ProjectSettings::get_singleton()->get_property_list(&props);
+
+ undo_redo->create_action(TTR("Update Input Action Order"));
+
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+ PropertyInfo prop = E->get();
+ // Skip builtins and non-inputs
+ if (ProjectSettings::get_singleton()->is_builtin_setting(prop.name) || !prop.name.begins_with("input/")) {
+ continue;
+ }
+
+ action_values.insert(prop.name, ps->get(prop.name));
+
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", prop.name);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", prop.name);
+ }
+
+ for (OrderedHashMap<String, Variant>::Element E = action_values.front(); E; E = E.next()) {
+ String name = E.key();
+ Variant value = E.get();
+
+ if (name == target_name) {
+ if (p_before) {
+ // Insert before target
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", action_name, action_value);
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", target_name, target_value);
+
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", target_name, target_value);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", action_name, action_value);
+ } else {
+ // Insert after target
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", target_name, target_value);
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", action_name, action_value);
+
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", action_name, action_value);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", target_name, target_value);
+ }
+
+ } else if (name != action_name) {
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, value);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, value);
+ }
+ }
+
+ undo_redo->add_do_method(this, "_update_action_map_editor");
+ undo_redo->add_undo_method(this, "_update_action_map_editor");
+ undo_redo->add_do_method(this, "queue_save");
+ undo_redo->add_undo_method(this, "queue_save");
+ undo_redo->commit_action();
+}
+
+void ProjectSettingsEditor::_update_action_map_editor() {
+ Vector<ActionMapEditor::ActionInfo> actions;
+
+ List<PropertyInfo> props;
+ ProjectSettings::get_singleton()->get_property_list(&props);
+
+ const Ref<Texture2D> builtin_icon = get_theme_icon("PinPressed", "EditorIcons");
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+ const String property_name = E->get().name;
+
+ if (!property_name.begins_with("input/")) {
+ continue;
+ }
+
+ // Strip the "input/" from the left.
+ String display_name = property_name.substr(String("input/").size() - 1);
+ Dictionary action = ProjectSettings::get_singleton()->get(property_name);
+
+ ActionMapEditor::ActionInfo action_info;
+ action_info.action = action;
+ action_info.editable = true;
+ action_info.name = display_name;
+
+ const bool is_builtin_input = ProjectSettings::get_singleton()->get_input_presets().find(property_name) != nullptr;
+ if (is_builtin_input) {
+ action_info.editable = false;
+ action_info.icon = builtin_icon;
+ }
+
+ actions.push_back(action_info);
+ }
+
+ action_map->update_action_list(actions);
+}
+
void ProjectSettingsEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
if (!is_visible()) {
EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "project_settings", Rect2(get_position(), get_size()));
- if (advanced->is_pressed()) {
- advanced->set_pressed(false);
- advanced_bar->hide();
- }
}
} break;
case NOTIFICATION_ENTER_TREE: {
inspector->edit(ps);
- error_label->add_theme_color_override("font_color", error_label->get_theme_color("error_color", "Editor"));
add_button->set_icon(get_theme_icon("Add", "EditorIcons"));
del_button->set_icon(get_theme_icon("Remove", "EditorIcons"));
@@ -292,6 +491,8 @@ void ProjectSettingsEditor::_notification(int p_what) {
restart_container->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
restart_icon->set_texture(get_theme_icon("StatusWarning", "EditorIcons"));
restart_label->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"));
+
+ _update_action_map_editor();
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
search_box->set_right_icon(get_theme_icon("Search", "EditorIcons"));
@@ -302,6 +503,8 @@ void ProjectSettingsEditor::_notification(int p_what) {
void ProjectSettingsEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("queue_save"), &ProjectSettingsEditor::queue_save);
+
+ ClassDB::bind_method(D_METHOD("_update_action_map_editor"), &ProjectSettingsEditor::_update_action_map_editor);
}
ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
@@ -339,23 +542,19 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
search_bar->add_child(search_box);
advanced = memnew(CheckButton);
- advanced->set_text(TTR("Advanced"));
+ advanced->set_text(TTR("Advanced Settings"));
advanced->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_advanced_pressed));
search_bar->add_child(advanced);
}
{
// Advanced bar.
- advanced_bar = memnew(VBoxContainer);
- advanced_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ advanced_bar = memnew(HBoxContainer);
advanced_bar->hide();
header->add_child(advanced_bar);
- advanced_bar->add_child(memnew(HSeparator));
-
- HBoxContainer *hbc = memnew(HBoxContainer);
+ HBoxContainer *hbc = advanced_bar;
hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- advanced_bar->add_margin_child(TTR("Add or Remove Custom Project Settings:"), hbc, true);
category_box = memnew(LineEdit);
category_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -364,7 +563,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
hbc->add_child(category_box);
Label *l = memnew(Label);
- l->set_text("/");
+ l->set_text(" / ");
hbc->add_child(l);
property_box = memnew(LineEdit);
@@ -407,9 +606,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
del_button->set_flat(true);
del_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_delete_setting), varray(false));
hbc->add_child(del_button);
-
- error_label = memnew(Label);
- advanced_bar->add_child(error_label);
}
inspector = memnew(SectionedInspector);
@@ -447,10 +643,16 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
restart_close_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_editor_restart_close));
restart_hb->add_child(restart_close_button);
- inputmap_editor = memnew(InputMapEditor);
- inputmap_editor->set_name(TTR("Input Map"));
- inputmap_editor->connect("inputmap_changed", callable_mp(this, &ProjectSettingsEditor::queue_save));
- tab_container->add_child(inputmap_editor);
+ action_map = memnew(ActionMapEditor);
+ action_map->set_name(TTR("Input Map"));
+ action_map->connect("action_added", callable_mp(this, &ProjectSettingsEditor::_action_added));
+ action_map->connect("action_edited", callable_mp(this, &ProjectSettingsEditor::_action_edited));
+ action_map->connect("action_removed", callable_mp(this, &ProjectSettingsEditor::_action_removed));
+ action_map->connect("action_renamed", callable_mp(this, &ProjectSettingsEditor::_action_renamed));
+ action_map->connect("action_reordered", callable_mp(this, &ProjectSettingsEditor::_action_reordered));
+ action_map->set_toggle_editable_label(TTR("Show Built-in Actions"));
+ action_map->set_show_uneditable(false);
+ tab_container->add_child(action_map);
localization_editor = memnew(LocalizationEditor);
localization_editor->set_name(TTR("Localization"));
@@ -483,4 +685,18 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
get_ok_button()->set_text(TTR("Close"));
set_hide_on_ok(true);
+
+ bool use_advanced = EditorSettings::get_singleton()->get_project_metadata("project_settings", "advanced_mode", false);
+
+ if (use_advanced) {
+ advanced->set_pressed(true);
+ advanced_bar->show();
+ }
+
+ inspector->set_restrict_to_basic_settings(!use_advanced);
+
+ import_defaults_editor = memnew(ImportDefaultsEditor);
+ import_defaults_editor->set_name(TTR("Import Defaults"));
+ tab_container->add_child(import_defaults_editor);
+ import_defaults_editor->connect("project_settings_changed", callable_mp(this, &ProjectSettingsEditor::queue_save));
}
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index 88c96540ff..cde46ac4c4 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -32,10 +32,11 @@
#define PROJECT_SETTINGS_EDITOR_H
#include "core/object/undo_redo.h"
+#include "editor/action_map_editor.h"
#include "editor/editor_data.h"
#include "editor/editor_plugin_settings.h"
#include "editor/editor_sectioned_inspector.h"
-#include "editor/input_map_editor.h"
+#include "editor/import_defaults_editor.h"
#include "editor/localization_editor.h"
#include "editor/shader_globals_editor.h"
#include "editor_autoload_settings.h"
@@ -44,38 +45,29 @@
class ProjectSettingsEditor : public AcceptDialog {
GDCLASS(ProjectSettingsEditor, AcceptDialog);
- enum InputType {
- INPUT_KEY,
- INPUT_KEY_PHYSICAL,
- INPUT_JOY_BUTTON,
- INPUT_JOY_MOTION,
- INPUT_MOUSE_BUTTON
- };
-
static ProjectSettingsEditor *singleton;
ProjectSettings *ps;
Timer *timer;
TabContainer *tab_container;
SectionedInspector *inspector;
- InputMapEditor *inputmap_editor;
LocalizationEditor *localization_editor;
EditorAutoloadSettings *autoload_settings;
ShaderGlobalsEditor *shaders_global_variables_editor;
EditorPluginSettings *plugin_settings;
+ ActionMapEditor *action_map;
HBoxContainer *search_bar;
LineEdit *search_box;
CheckButton *advanced;
- VBoxContainer *advanced_bar;
+ HBoxContainer *advanced_bar;
LineEdit *category_box;
LineEdit *property_box;
Button *add_button;
Button *del_button;
OptionButton *type;
OptionButton *feature_override;
- Label *error_label;
ConfirmationDialog *del_confirmation;
@@ -84,6 +76,7 @@ class ProjectSettingsEditor : public AcceptDialog {
PanelContainer *restart_container;
Button *restart_close_button;
+ ImportDefaultsEditor *import_defaults_editor;
EditorData *data;
UndoRedo *undo_redo;
@@ -103,6 +96,14 @@ class ProjectSettingsEditor : public AcceptDialog {
void _editor_restart_close();
void _add_feature_overrides();
+
+ void _action_added(const String &p_name);
+ void _action_edited(const String &p_name, const Dictionary &p_action);
+ void _action_removed(const String &p_name);
+ void _action_renamed(const String &p_old_name, const String &p_new_name);
+ void _action_reordered(const String &p_action_name, const String &p_relative_to, bool p_before);
+ void _update_action_map_editor();
+
ProjectSettingsEditor();
protected:
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 07312e42b4..0a4f432e4a 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -417,7 +417,12 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
updating = false;
return false;
- } else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || hint == PROPERTY_HINT_LAYERS_2D_RENDER || hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || hint == PROPERTY_HINT_LAYERS_3D_RENDER) {
+ } else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS ||
+ hint == PROPERTY_HINT_LAYERS_2D_RENDER ||
+ hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION ||
+ hint == PROPERTY_HINT_LAYERS_3D_PHYSICS ||
+ hint == PROPERTY_HINT_LAYERS_3D_RENDER ||
+ hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) {
String basename;
switch (hint) {
case PROPERTY_HINT_LAYERS_2D_RENDER:
@@ -426,12 +431,18 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
case PROPERTY_HINT_LAYERS_2D_PHYSICS:
basename = "layer_names/2d_physics";
break;
+ case PROPERTY_HINT_LAYERS_2D_NAVIGATION:
+ basename = "layer_names/2d_navigation";
+ break;
case PROPERTY_HINT_LAYERS_3D_RENDER:
basename = "layer_names/3d_render";
break;
case PROPERTY_HINT_LAYERS_3D_PHYSICS:
basename = "layer_names/3d_physics";
break;
+ case PROPERTY_HINT_LAYERS_3D_NAVIGATION:
+ basename = "layer_names/3d_navigation";
+ break;
}
checks20gc->show();
@@ -1153,7 +1164,12 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
emit_signal("variant_changed");
} break;
case Variant::INT: {
- if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || hint == PROPERTY_HINT_LAYERS_2D_RENDER || hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || hint == PROPERTY_HINT_LAYERS_3D_RENDER) {
+ if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS ||
+ hint == PROPERTY_HINT_LAYERS_2D_RENDER ||
+ hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION ||
+ hint == PROPERTY_HINT_LAYERS_3D_PHYSICS ||
+ hint == PROPERTY_HINT_LAYERS_3D_RENDER ||
+ hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) {
uint32_t f = v;
if (checks20[p_which]->is_pressed()) {
f |= (1 << p_which);
@@ -1337,7 +1353,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
void CustomPropertyEditor::_drag_easing(const Ref<InputEvent> &p_ev) {
Ref<InputEventMouseMotion> mm = p_ev;
- if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
float rel = mm->get_relative().x;
if (rel == 0) {
return;
diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp
index 48aa0471c9..b51524b299 100644
--- a/editor/rename_dialog.cpp
+++ b/editor/rename_dialog.cpp
@@ -434,7 +434,10 @@ String RenameDialog::_substitute(const String &subject, const Node *node, int co
}
int current = EditorNode::get_singleton()->get_editor_data().get_edited_scene();
- result = result.replace("${SCENE}", EditorNode::get_singleton()->get_editor_data().get_scene_title(current));
+ // Always request the scene title with the extension stripped.
+ // Otherwise, the result could vary depending on whether a scene with the same name
+ // (but different extension) is currently open.
+ result = result.replace("${SCENE}", EditorNode::get_singleton()->get_editor_data().get_scene_title(current, true));
Node *root_node = SceneTree::get_singleton()->get_edited_scene_root();
if (root_node) {
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index ac1beb1c37..023019b2aa 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -63,7 +63,7 @@ void SceneTreeDock::_quick_open() {
void SceneTreeDock::_input(Ref<InputEvent> p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
restore_script_editor_on_drag = false; //lost chance
}
}
@@ -87,6 +87,12 @@ void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) {
_tool_selected(TOOL_INSTANCE);
} else if (ED_IS_SHORTCUT("scene_tree/expand_collapse_all", p_event)) {
_tool_selected(TOOL_EXPAND_COLLAPSE);
+ } else if (ED_IS_SHORTCUT("scene_tree/cut_node", p_event)) {
+ _tool_selected(TOOL_CUT);
+ } else if (ED_IS_SHORTCUT("scene_tree/copy_node", p_event)) {
+ _tool_selected(TOOL_COPY);
+ } else if (ED_IS_SHORTCUT("scene_tree/paste_node", p_event)) {
+ _tool_selected(TOOL_PASTE);
} else if (ED_IS_SHORTCUT("scene_tree/change_node_type", p_event)) {
_tool_selected(TOOL_REPLACE);
} else if (ED_IS_SHORTCUT("scene_tree/duplicate", p_event)) {
@@ -101,8 +107,6 @@ void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) {
_tool_selected(TOOL_MOVE_DOWN);
} else if (ED_IS_SHORTCUT("scene_tree/reparent", p_event)) {
_tool_selected(TOOL_REPARENT);
- } else if (ED_IS_SHORTCUT("scene_tree/merge_from_scene", p_event)) {
- _tool_selected(TOOL_MERGE_FROM_SCENE);
} else if (ED_IS_SHORTCUT("scene_tree/save_branch_as_scene", p_event)) {
_tool_selected(TOOL_NEW_SCENE_FROM);
} else if (ED_IS_SHORTCUT("scene_tree/delete_no_confirm", p_event)) {
@@ -215,6 +219,9 @@ void SceneTreeDock::_perform_instance_scenes(const Vector<String> &p_files, Node
editor_data->get_undo_redo().commit_action();
editor->push_item(instances[instances.size() - 1]);
+ for (int i = 0; i < instances.size(); i++) {
+ emit_signal("node_created", instances[i]);
+ }
}
void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) {
@@ -343,6 +350,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
break;
}
+ if (reset_create_dialog) {
+ create_dialog->set_base_type("Node");
+ reset_create_dialog = false;
+ }
+
// Prefer nodes that inherit from the current scene root.
Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene();
if (current_edited_scene_root) {
@@ -363,6 +375,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
create_dialog->popup_create(true);
+ if (!p_confirm_override) {
+ emit_signal("add_node_used");
+ }
} break;
case TOOL_INSTANCE: {
if (!profile_allow_editing) {
@@ -377,7 +392,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
quick_open->popup_dialog("PackedScene", true);
quick_open->set_title(TTR("Instance Child Scene"));
-
+ if (!p_confirm_override) {
+ emit_signal("add_node_used");
+ }
} break;
case TOOL_EXPAND_COLLAPSE: {
if (!scene_tree->get_selected()) {
@@ -397,11 +414,127 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
tree->ensure_cursor_is_visible();
} break;
+ case TOOL_CUT:
+ case TOOL_COPY: {
+ if (!edited_scene || !_validate_no_foreign()) {
+ break;
+ }
+
+ List<Node *> selection = editor_selection->get_selected_node_list();
+ if (selection.size() == 0) {
+ break;
+ }
+
+ if (!node_clipboard.is_empty()) {
+ _clear_clipboard();
+ }
+ clipboard_source_scene = editor->get_edited_scene()->get_filename();
+
+ selection.sort_custom<Node::Comparator>();
+
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ Node *node = E->get();
+ Map<const Node *, Node *> duplimap;
+ Node *dup = node->duplicate_from_editor(duplimap);
+
+ ERR_CONTINUE(!dup);
+
+ node_clipboard.push_back(dup);
+ }
+
+ if (p_tool == TOOL_CUT) {
+ _delete_confirm(true);
+ }
+ } break;
+ case TOOL_PASTE: {
+ if (node_clipboard.is_empty() || !edited_scene) {
+ break;
+ }
+
+ bool has_cycle = false;
+ if (edited_scene->get_filename() != String()) {
+ for (List<Node *>::Element *E = node_clipboard.front(); E; E = E->next()) {
+ if (edited_scene->get_filename() == E->get()->get_filename()) {
+ has_cycle = true;
+ break;
+ }
+ }
+ }
+
+ if (has_cycle) {
+ current_option = -1;
+ accept->set_text(TTR("Can't paste root node into the same scene."));
+ accept->popup_centered();
+ break;
+ }
+
+ Node *paste_parent = edited_scene;
+ List<Node *> selection = editor_selection->get_selected_node_list();
+ if (selection.size() > 0) {
+ paste_parent = selection.back()->get();
+ }
+
+ Node *owner = paste_parent->get_owner();
+ if (!owner) {
+ owner = paste_parent;
+ }
+
+ editor_data->get_undo_redo().create_action(TTR("Paste Node(s)"));
+ editor_data->get_undo_redo().add_do_method(editor_selection, "clear");
+
+ Map<RES, RES> resource_remap;
+ String target_scene = editor->get_edited_scene()->get_filename();
+ if (target_scene != clipboard_source_scene) {
+ if (!clipboard_resource_remap.has(target_scene)) {
+ Map<RES, RES> remap;
+ for (List<Node *>::Element *E = node_clipboard.front(); E; E = E->next()) {
+ _create_remap_for_node(E->get(), remap);
+ }
+ clipboard_resource_remap[target_scene] = remap;
+ }
+ resource_remap = clipboard_resource_remap[target_scene];
+ }
+
+ for (List<Node *>::Element *E = node_clipboard.front(); E; E = E->next()) {
+ Node *node = E->get();
+ Map<const Node *, Node *> duplimap;
+
+ Node *dup = node->duplicate_from_editor(duplimap, resource_remap);
+
+ ERR_CONTINUE(!dup);
+
+ editor_data->get_undo_redo().add_do_method(paste_parent, "add_child", dup);
+
+ for (Map<const Node *, Node *>::Element *E2 = duplimap.front(); E2; E2 = E2->next()) {
+ Node *d = E2->value();
+ editor_data->get_undo_redo().add_do_method(d, "set_owner", owner);
+ }
+
+ editor_data->get_undo_redo().add_do_method(dup, "set_owner", owner);
+ editor_data->get_undo_redo().add_do_method(editor_selection, "add_node", dup);
+ editor_data->get_undo_redo().add_undo_method(paste_parent, "remove_child", dup);
+ editor_data->get_undo_redo().add_do_reference(dup);
+
+ if (node_clipboard.size() == 1) {
+ editor_data->get_undo_redo().add_do_method(editor, "push_item", dup);
+ }
+ }
+
+ editor_data->get_undo_redo().commit_action();
+ } break;
case TOOL_REPLACE: {
if (!profile_allow_editing) {
break;
}
+ if (!_validate_no_foreign()) {
+ break;
+ }
+
+ if (!_validate_no_instance()) {
+ break;
+ }
+
Node *selected = scene_tree->get_selected();
if (!selected && !editor_selection->get_selected_node_list().is_empty()) {
selected = editor_selection->get_selected_node_list().front()->get();
@@ -552,7 +685,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
editor_data->get_undo_redo().add_do_method(editor_selection, "clear");
Node *dupsingle = nullptr;
- List<Node *> editable_children;
selection.sort_custom<Node::Comparator>();
@@ -568,10 +700,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
Map<const Node *, Node *> duplimap;
Node *dup = node->duplicate_from_editor(duplimap);
- if (EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node)) {
- editable_children.push_back(dup);
- }
-
ERR_CONTINUE(!dup);
if (selection.size() == 1) {
@@ -606,11 +734,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
if (dupsingle) {
editor->push_item(dupsingle);
}
-
- for (List<Node *>::Element *E = editable_children.back(); E; E = E->prev()) {
- _toggle_editable_children(E->get());
- }
-
} break;
case TOOL_REPARENT: {
if (!profile_allow_editing) {
@@ -766,13 +889,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
} break;
- case TOOL_MERGE_FROM_SCENE: {
- if (!profile_allow_editing) {
- break;
- }
-
- EditorNode::get_singleton()->merge_from_scene();
- } break;
case TOOL_NEW_SCENE_FROM: {
if (!profile_allow_editing) {
break;
@@ -781,7 +897,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
Node *scene = editor_data->get_edited_scene_root();
if (!scene) {
- accept->set_text(TTR("This operation can't be done without a scene."));
+ accept->set_text(TTR("Saving the branch as a scene requires having a scene open in the editor."));
accept->popup_centered();
break;
}
@@ -789,7 +905,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
List<Node *> selection = editor_selection->get_selected_node_list();
if (selection.size() != 1) {
- accept->set_text(TTR("This operation requires a single selected node."));
+ accept->set_text(vformat(TTR("Saving the branch as a scene requires selecting only one node, but you have selected %d nodes."), selection.size()));
accept->popup_centered();
break;
}
@@ -797,13 +913,13 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
Node *tocopy = selection.front()->get();
if (tocopy == scene) {
- accept->set_text(TTR("Can not perform with the root node."));
+ accept->set_text(TTR("Can't save the root node branch as an instanced scene.\nTo create an editable copy of the current scene, duplicate it using the FileSystem dock context menu\nor create an inherited scene using Scene > New Inherited Scene... instead."));
accept->popup_centered();
break;
}
if (tocopy != editor_data->get_edited_scene_root() && tocopy->get_filename() != "") {
- accept->set_text(TTR("This operation can't be done on instanced scenes."));
+ accept->set_text(TTR("Can't save the branch of an already instanced scene.\nTo create a variation of a scene, you can make an inherited scene based on the instanced scene using Scene > New Inherited Scene... instead."));
accept->popup_centered();
break;
}
@@ -1510,6 +1626,20 @@ bool SceneTreeDock::_validate_no_foreign() {
return true;
}
+bool SceneTreeDock::_validate_no_instance() {
+ List<Node *> selection = editor_selection->get_selected_node_list();
+
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ if (E->get() != edited_scene && E->get()->get_filename() != "") {
+ accept->set_text(TTR("This operation can't be done on instanced scenes."));
+ accept->popup_centered();
+ return false;
+ }
+ }
+
+ return true;
+}
+
void SceneTreeDock::_node_reparent(NodePath p_path, bool p_keep_global_xform) {
Node *new_parent = scene_root->get_node(p_path);
ERR_FAIL_COND(!new_parent);
@@ -1795,7 +1925,7 @@ void SceneTreeDock::_toggle_editable_children(Node *p_node) {
}
}
-void SceneTreeDock::_delete_confirm() {
+void SceneTreeDock::_delete_confirm(bool p_cut) {
List<Node *> remove_list = editor_selection->get_selected_node_list();
if (remove_list.is_empty()) {
@@ -1804,7 +1934,11 @@ void SceneTreeDock::_delete_confirm() {
editor->get_editor_plugins_over()->make_visible(false);
- editor_data->get_undo_redo().create_action(TTR("Remove Node(s)"));
+ if (p_cut) {
+ editor_data->get_undo_redo().create_action(TTR("Cut Node(s)"));
+ } else {
+ editor_data->get_undo_redo().create_action(TTR("Remove Node(s)"));
+ }
bool entire_scene = false;
@@ -1970,6 +2104,8 @@ void SceneTreeDock::_do_create(Node *p_parent) {
}
ct->set_size(ms);
}
+
+ emit_signal("node_created", c);
}
void SceneTreeDock::_create() {
@@ -2173,21 +2309,6 @@ void SceneTreeDock::set_selected(Node *p_node, bool p_emit_selected) {
scene_tree->set_selected(p_node, p_emit_selected);
}
-void SceneTreeDock::import_subscene() {
- import_subscene_dialog->popup_centered_clamped(Size2(500, 800) * EDSCALE, 0.8);
-}
-
-void SceneTreeDock::_import_subscene() {
- Node *parent = scene_tree->get_selected();
- if (!parent) {
- parent = editor_data->get_edited_scene_root();
- ERR_FAIL_COND(!parent);
- }
-
- import_subscene_dialog->move(parent, edited_scene);
- editor_data->get_undo_redo().clear_history(); //no undo for now..
-}
-
void SceneTreeDock::_new_scene_from(String p_file) {
List<Node *> selection = editor_selection->get_selected_node_list();
@@ -2205,10 +2326,14 @@ void SceneTreeDock::_new_scene_from(String p_file) {
Node *base = selection.front()->get();
- Map<Node *, Node *> reown;
- reown[editor_data->get_edited_scene_root()] = base;
- Node *copy = base->duplicate_and_reown(reown);
+ Map<const Node *, Node *> duplimap;
+ Node *copy = base->duplicate_from_editor(duplimap);
+
if (copy) {
+ for (int i = 0; i < copy->get_child_count(); i++) {
+ _set_node_owner_recursive(copy->get_child(i), copy);
+ }
+
Ref<PackedScene> sdata = memnew(PackedScene);
Error err = sdata->pack(copy);
memdelete(copy);
@@ -2238,6 +2363,16 @@ void SceneTreeDock::_new_scene_from(String p_file) {
}
}
+void SceneTreeDock::_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(); i++) {
+ _set_node_owner_recursive(p_node->get_child(i), p_owner);
+ }
+}
+
static bool _is_node_visible(Node *p_node) {
if (!p_node->get_owner()) {
return false;
@@ -2444,6 +2579,13 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
}
if (profile_allow_script_editing) {
+ menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/cut_node"), TOOL_CUT);
+ menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/copy_node"), TOOL_COPY);
+ if (selection.size() == 1 && !node_clipboard.is_empty()) {
+ menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/paste_node"), TOOL_PASTE);
+ }
+ menu->add_separator();
+
bool add_separator = false;
if (full_selection.size() == 1) {
@@ -2480,7 +2622,18 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
if (full_selection.size() == 1) {
menu->add_icon_shortcut(get_theme_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME);
}
- menu->add_icon_shortcut(get_theme_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);
+
+ bool can_replace = true;
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ if (E->get() != edited_scene && (E->get()->get_owner() != edited_scene || E->get()->get_filename() != "")) {
+ can_replace = false;
+ break;
+ }
+ }
+
+ if (can_replace) {
+ menu->add_icon_shortcut(get_theme_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);
+ }
if (scene_tree->get_selected() != edited_scene) {
menu->add_separator();
@@ -2497,7 +2650,6 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
if (selection.size() == 1) {
if (profile_allow_editing) {
menu->add_separator();
- menu->add_icon_shortcut(get_theme_icon("Blend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/merge_from_scene"), TOOL_MERGE_FROM_SCENE);
menu->add_icon_shortcut(get_theme_icon("CreateNewSceneFrom", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
}
if (full_selection.size() == 1) {
@@ -2643,6 +2795,16 @@ void SceneTreeDock::open_script_dialog(Node *p_for_node, bool p_extend) {
}
}
+void SceneTreeDock::open_add_child_dialog() {
+ create_dialog->set_base_type("CanvasItem");
+ _tool_selected(TOOL_NEW, true);
+ reset_create_dialog = true;
+}
+
+void SceneTreeDock::open_instance_child_dialog() {
+ _tool_selected(TOOL_INSTANCE, true);
+}
+
void SceneTreeDock::add_remote_tree_editor(Control *p_remote) {
ERR_FAIL_COND(remote_tree != nullptr);
add_child(p_remote);
@@ -2775,6 +2937,62 @@ void SceneTreeDock::_feature_profile_changed() {
_update_script_button();
}
+void SceneTreeDock::_clear_clipboard() {
+ for (List<Node *>::Element *E = node_clipboard.front(); E; E = E->next()) {
+ memdelete(E->get());
+ }
+ node_clipboard.clear();
+ clipboard_resource_remap.clear();
+}
+
+void SceneTreeDock::_create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap) {
+ List<PropertyInfo> props;
+ p_node->get_property_list(&props);
+
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ continue;
+ }
+
+ Variant v = p_node->get(E->get().name);
+ if (v.is_ref()) {
+ RES res = v;
+ if (res.is_valid()) {
+ if ((res->get_path() == "" || res->get_path().find("::") > -1) && !r_remap.has(res)) {
+ _create_remap_for_resource(res, r_remap);
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _create_remap_for_node(p_node->get_child(i), r_remap);
+ }
+}
+
+void SceneTreeDock::_create_remap_for_resource(RES p_resource, Map<RES, RES> &r_remap) {
+ r_remap[p_resource] = p_resource->duplicate();
+
+ List<PropertyInfo> props;
+ p_resource->get_property_list(&props);
+
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ continue;
+ }
+
+ Variant v = p_resource->get(E->get().name);
+ if (v.is_ref()) {
+ RES res = v;
+ if (res.is_valid()) {
+ if ((res->get_path() == "" || res->get_path().find("::") > -1) && !r_remap.has(res)) {
+ _create_remap_for_resource(res, r_remap);
+ }
+ }
+ }
+ }
+}
+
void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_owners"), &SceneTreeDock::_set_owners);
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &SceneTreeDock::_unhandled_key_input);
@@ -2786,6 +3004,8 @@ void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("replace_node"), &SceneTreeDock::replace_node);
ADD_SIGNAL(MethodInfo("remote_tree_selected"));
+ ADD_SIGNAL(MethodInfo("add_node_used"));
+ ADD_SIGNAL(MethodInfo("node_created", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
}
SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data) {
@@ -2806,6 +3026,9 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node"), KEY_MASK_CMD | KEY_A);
ED_SHORTCUT("scene_tree/instance_scene", TTR("Instance Child Scene"));
ED_SHORTCUT("scene_tree/expand_collapse_all", TTR("Expand/Collapse All"));
+ ED_SHORTCUT("scene_tree/cut_node", TTR("Cut"), KEY_MASK_CMD | KEY_X);
+ ED_SHORTCUT("scene_tree/copy_node", TTR("Copy"), KEY_MASK_CMD | KEY_C);
+ ED_SHORTCUT("scene_tree/paste_node", TTR("Paste"), KEY_MASK_CMD | KEY_V);
ED_SHORTCUT("scene_tree/change_node_type", TTR("Change Type"));
ED_SHORTCUT("scene_tree/attach_script", TTR("Attach Script"));
ED_SHORTCUT("scene_tree/extend_script", TTR("Extend Script"));
@@ -2816,9 +3039,8 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
ED_SHORTCUT("scene_tree/reparent", TTR("Reparent"));
ED_SHORTCUT("scene_tree/reparent_to_new_node", TTR("Reparent to New Node"));
ED_SHORTCUT("scene_tree/make_root", TTR("Make Scene Root"));
- ED_SHORTCUT("scene_tree/merge_from_scene", TTR("Merge From Scene"));
ED_SHORTCUT("scene_tree/save_branch_as_scene", TTR("Save Branch as Scene"));
- ED_SHORTCUT("scene_tree/copy_node_path", TTR("Copy Node Path"), KEY_MASK_CMD | KEY_C);
+ ED_SHORTCUT("scene_tree/copy_node_path", TTR("Copy Node Path"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_C);
ED_SHORTCUT("scene_tree/delete_no_confirm", TTR("Delete (No Confirm)"), KEY_MASK_SHIFT | KEY_DELETE);
ED_SHORTCUT("scene_tree/delete", TTR("Delete"), KEY_DELETE);
@@ -2841,7 +3063,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
filter->set_h_size_flags(SIZE_EXPAND_FILL);
filter->set_placeholder(TTR("Filter nodes"));
filter_hbc->add_child(filter);
- filter->add_theme_constant_override("minimum_spaces", 0);
+ filter->add_theme_constant_override("minimum_character_width", 0);
filter->connect("text_changed", callable_mp(this, &SceneTreeDock::_filter_changed));
button_create_script = memnew(Button);
@@ -2936,7 +3158,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
delete_dialog = memnew(ConfirmationDialog);
add_child(delete_dialog);
- delete_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_delete_confirm));
+ delete_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_delete_confirm), varray(false));
editable_instance_remove_dialog = memnew(ConfirmationDialog);
add_child(editable_instance_remove_dialog);
@@ -2946,10 +3168,6 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
add_child(placeholder_editable_instance_remove_dialog);
placeholder_editable_instance_remove_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_toggle_placeholder_from_selection));
- import_subscene_dialog = memnew(EditorSubScene);
- add_child(import_subscene_dialog);
- import_subscene_dialog->connect("subscene_selected", callable_mp(this, &SceneTreeDock::_import_subscene));
-
new_scene_from_dialog = memnew(EditorFileDialog);
new_scene_from_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
add_child(new_scene_from_dialog);
@@ -2981,3 +3199,9 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
EDITOR_DEF("interface/editors/derive_script_globals_by_name", true);
EDITOR_DEF("_use_favorites_root_selection", false);
}
+
+SceneTreeDock::~SceneTreeDock() {
+ if (!node_clipboard.is_empty()) {
+ _clear_clipboard();
+ }
+}
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index 4f8d85f07c..aa62c93cb5 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -34,7 +34,6 @@
#include "editor/connections_dialog.h"
#include "editor/create_dialog.h"
#include "editor/editor_data.h"
-#include "editor/editor_sub_scene.h"
#include "editor/groups_editor.h"
#include "editor/quick_open.h"
#include "editor/rename_dialog.h"
@@ -58,6 +57,9 @@ class SceneTreeDock : public VBoxContainer {
TOOL_NEW,
TOOL_INSTANCE,
TOOL_EXPAND_COLLAPSE,
+ TOOL_CUT,
+ TOOL_COPY,
+ TOOL_PASTE,
TOOL_RENAME,
TOOL_BATCH_RENAME,
TOOL_REPLACE,
@@ -71,7 +73,6 @@ class SceneTreeDock : public VBoxContainer {
TOOL_REPARENT_TO_NEW_NODE,
TOOL_MAKE_ROOT,
TOOL_NEW_SCENE_FROM,
- TOOL_MERGE_FROM_SCENE,
TOOL_MULTI_EDIT,
TOOL_ERASE,
TOOL_COPY_NODE_PATH,
@@ -99,6 +100,7 @@ class SceneTreeDock : public VBoxContainer {
Vector<ObjectID> subresources;
bool restore_script_editor_on_drag;
+ bool reset_create_dialog = false;
int current_option;
CreateDialog *create_dialog;
@@ -126,6 +128,10 @@ class SceneTreeDock : public VBoxContainer {
EditorData *editor_data;
EditorSelection *editor_selection;
+ List<Node *> node_clipboard;
+ String clipboard_source_scene;
+ HashMap<String, Map<RES, RES>> clipboard_resource_remap;
+
ScriptCreateDialog *script_create_dialog;
AcceptDialog *accept;
ConfirmationDialog *delete_dialog;
@@ -134,7 +140,6 @@ class SceneTreeDock : public VBoxContainer {
ReparentDialog *reparent_dialog;
EditorQuickOpen *quick_open;
- EditorSubScene *import_subscene_dialog;
EditorFileDialog *new_scene_from_dialog;
LineEdit *filter;
@@ -183,7 +188,7 @@ class SceneTreeDock : public VBoxContainer {
void _script_created(Ref<Script> p_script);
void _script_creation_closed();
- void _delete_confirm();
+ void _delete_confirm(bool p_cut = false);
void _toggle_editable_children_from_selection();
void _toggle_editable_children(Node *p_node);
@@ -199,8 +204,10 @@ class SceneTreeDock : public VBoxContainer {
void _import_subscene();
void _new_scene_from(String p_file);
+ void _set_node_owner_recursive(Node *p_node, Node *p_owner);
bool _validate_no_foreign();
+ bool _validate_no_instance();
void _selection_changed();
void _update_script_button();
@@ -230,6 +237,10 @@ class SceneTreeDock : public VBoxContainer {
void _feature_profile_changed();
+ void _clear_clipboard();
+ void _create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap);
+ void _create_remap_for_resource(RES p_resource, Map<RES, RES> &r_remap);
+
bool profile_allow_editing;
bool profile_allow_script_editing;
@@ -264,9 +275,13 @@ public:
void attach_script_to_selected(bool p_extend);
void open_script_dialog(Node *p_for_node, bool p_extend);
+ void open_add_child_dialog();
+ void open_instance_child_dialog();
+
ScriptCreateDialog *get_script_create_dialog() { return script_create_dialog; }
SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data);
+ ~SceneTreeDock();
};
#endif // SCENE_TREE_DOCK_H
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index b8475656ee..b5e9aec854 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -156,7 +156,7 @@ void SceneTreeEditor::_toggle_visible(Node *p_node) {
}
}
-bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
+bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll_to_selected) {
if (!p_node) {
return false;
}
@@ -236,6 +236,8 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
item->set_text(0, node_name);
item->set_selectable(0, marked_selectable);
item->set_custom_color(0, get_theme_color("accent_color", "Editor"));
+ } else if (!p_node->can_process()) {
+ item->set_custom_color(0, get_theme_color("disabled_font_color", "Editor"));
} else if (!marked_selectable && !marked_children_selectable) {
Node *node = p_node;
while (node) {
@@ -391,15 +393,19 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
}
}
+ bool scroll = false;
+
if (editor_selection) {
if (editor_selection->is_selected(p_node)) {
item->select(0);
+ scroll = p_scroll_to_selected;
}
}
if (selected == p_node) {
if (!editor_selection) {
item->select(0);
+ scroll = p_scroll_to_selected;
}
item->set_as_cursor(0);
}
@@ -407,7 +413,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
bool keep = (filter.is_subsequence_ofi(String(p_node->get_name())));
for (int i = 0; i < p_node->get_child_count(); i++) {
- bool child_keep = _add_nodes(p_node->get_child(i), item);
+ bool child_keep = _add_nodes(p_node->get_child(i), item, p_scroll_to_selected);
keep = keep || child_keep;
}
@@ -438,6 +444,9 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
memdelete(item);
return false;
} else {
+ if (scroll) {
+ tree->scroll_to_item(item);
+ }
return true;
}
}
@@ -525,7 +534,7 @@ void SceneTreeEditor::_node_renamed(Node *p_node) {
}
}
-void SceneTreeEditor::_update_tree() {
+void SceneTreeEditor::_update_tree(bool p_scroll_to_selected) {
if (!is_inside_tree()) {
tree_dirty = false;
return;
@@ -534,7 +543,7 @@ void SceneTreeEditor::_update_tree() {
updating_tree = true;
tree->clear();
if (get_scene_node()) {
- _add_nodes(get_scene_node(), nullptr);
+ _add_nodes(get_scene_node(), nullptr, p_scroll_to_selected);
last_hash = hash_djb2_one_64(0);
_compute_hash(get_scene_node(), last_hash);
}
@@ -578,6 +587,11 @@ void SceneTreeEditor::_test_update_tree() {
tree_dirty = true;
}
+void SceneTreeEditor::_tree_process_mode_changed() {
+ MessageQueue::get_singleton()->push_call(this, "_update_tree");
+ tree_dirty = true;
+}
+
void SceneTreeEditor::_tree_changed() {
if (EditorNode::get_singleton()->is_exiting()) {
return; //speed up exit
@@ -612,7 +626,7 @@ void SceneTreeEditor::_selected_changed() {
}
void SceneTreeEditor::_deselect_items() {
- // Clear currently elected items in scene tree dock.
+ // Clear currently selected items in scene tree dock.
if (editor_selection) {
editor_selection->clear();
emit_signal("node_changed");
@@ -648,6 +662,7 @@ void SceneTreeEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
get_tree()->connect("tree_changed", callable_mp(this, &SceneTreeEditor::_tree_changed));
+ get_tree()->connect("tree_process_mode_changed", callable_mp(this, &SceneTreeEditor::_tree_process_mode_changed));
get_tree()->connect("node_removed", callable_mp(this, &SceneTreeEditor::_node_removed));
get_tree()->connect("node_renamed", callable_mp(this, &SceneTreeEditor::_node_renamed));
get_tree()->connect("node_configuration_warning_changed", callable_mp(this, &SceneTreeEditor::_warning_changed));
@@ -658,6 +673,7 @@ void SceneTreeEditor::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
get_tree()->disconnect("tree_changed", callable_mp(this, &SceneTreeEditor::_tree_changed));
+ get_tree()->disconnect("tree_process_mode_changed", callable_mp(this, &SceneTreeEditor::_tree_process_mode_changed));
get_tree()->disconnect("node_removed", callable_mp(this, &SceneTreeEditor::_node_removed));
get_tree()->disconnect("node_renamed", callable_mp(this, &SceneTreeEditor::_node_renamed));
tree->disconnect("item_collapsed", callable_mp(this, &SceneTreeEditor::_cell_collapsed));
@@ -760,9 +776,11 @@ void SceneTreeEditor::_renamed() {
return;
}
- String new_name = which->get_text(0);
- if (!Node::_validate_node_name(new_name)) {
- error->set_text(TTR("Invalid node name, the following characters are not allowed:") + "\n" + Node::invalid_character);
+ String raw_new_name = which->get_text(0);
+ String new_name = raw_new_name.validate_node_name();
+
+ if (new_name != raw_new_name) {
+ error->set_text(TTR("Invalid node name, the following characters are not allowed:") + "\n" + String::invalid_node_name_characters);
error->popup_centered();
if (new_name.is_empty()) {
@@ -817,7 +835,7 @@ void SceneTreeEditor::set_marked(Node *p_marked, bool p_selectable, bool p_child
void SceneTreeEditor::set_filter(const String &p_filter) {
filter = p_filter;
- _update_tree();
+ _update_tree(true);
}
String SceneTreeEditor::get_filter() const {
@@ -976,9 +994,6 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_d
if (!can_rename) {
return false; //not editable tree
}
- if (filter != String()) {
- return false; //can't rearrange tree with filter turned on
- }
Dictionary d = p_data;
if (!d.has("type")) {
@@ -1031,7 +1046,7 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_d
}
}
- return String(d["type"]) == "nodes";
+ return String(d["type"]) == "nodes" && filter == String();
}
void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
@@ -1103,7 +1118,7 @@ void SceneTreeEditor::set_connecting_signal(bool p_enable) {
}
void SceneTreeEditor::_bind_methods() {
- ClassDB::bind_method("_update_tree", &SceneTreeEditor::_update_tree); // Still used by some connect_compat.
+ ClassDB::bind_method(D_METHOD("_update_tree", "scroll_to_selected"), &SceneTreeEditor::_update_tree, DEFVAL(false)); // Still used by some connect_compat.
ClassDB::bind_method("_rename_node", &SceneTreeEditor::_rename_node);
ClassDB::bind_method("_test_update_tree", &SceneTreeEditor::_test_update_tree);
@@ -1154,6 +1169,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
tree->set_anchor(SIDE_BOTTOM, ANCHOR_END);
tree->set_begin(Point2(0, p_label ? 18 : 0));
tree->set_end(Point2(0, 0));
+ tree->set_allow_reselect(true);
tree->add_theme_constant_override("button_margin", 0);
add_child(tree);
@@ -1187,7 +1203,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
blocked = 0;
update_timer = memnew(Timer);
- update_timer->connect("timeout", callable_mp(this, &SceneTreeEditor::_update_tree));
+ update_timer->connect("timeout", callable_mp(this, &SceneTreeEditor::_update_tree), varray(false));
update_timer->set_one_shot(true);
update_timer->set_wait_time(0.5);
add_child(update_timer);
@@ -1253,7 +1269,7 @@ SceneTreeDialog::SceneTreeDialog() {
filter = memnew(LineEdit);
filter->set_h_size_flags(Control::SIZE_EXPAND_FILL);
filter->set_placeholder(TTR("Filter nodes"));
- filter->add_theme_constant_override("minimum_spaces", 0);
+ filter->add_theme_constant_override("minimum_character_width", 0);
filter->connect("text_changed", callable_mp(this, &SceneTreeDialog::_filter_changed));
vbc->add_child(filter);
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index 831723a27c..fd5157f04f 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -71,10 +71,11 @@ class SceneTreeEditor : public Control {
void _compute_hash(Node *p_node, uint64_t &hash);
- bool _add_nodes(Node *p_node, TreeItem *p_parent);
+ bool _add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll_to_selected = false);
void _test_update_tree();
- void _update_tree();
+ void _update_tree(bool p_scroll_to_selected = false);
void _tree_changed();
+ void _tree_process_mode_changed();
void _node_removed(Node *p_node);
void _node_renamed(Node *p_node);
@@ -180,6 +181,7 @@ protected:
public:
void popup_scenetree_dialog();
SceneTreeEditor *get_scene_tree() { return tree; }
+ LineEdit *get_filter_line_edit() { return filter; }
SceneTreeDialog();
~SceneTreeDialog();
};
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index 1dad3c091d..3852c389c7 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -31,6 +31,7 @@
#include "settings_config_dialog.h"
#include "core/config/project_settings.h"
+#include "core/input/input_map.h"
#include "core/os/keyboard.h"
#include "editor/debugger/editor_debugger_node.h"
#include "editor_file_system.h"
@@ -143,7 +144,7 @@ void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
if (k.is_valid() && k->is_pressed()) {
bool handled = false;
- if (ED_IS_SHORTCUT("editor/undo", p_event)) {
+ if (ED_IS_SHORTCUT("ui_undo", p_event)) {
String action = undo_redo->get_current_action_name();
if (action != "") {
EditorNode::get_log()->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR);
@@ -152,7 +153,7 @@ void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
handled = true;
}
- if (ED_IS_SHORTCUT("editor/redo", p_event)) {
+ if (ED_IS_SHORTCUT("ui_redo", p_event)) {
undo_redo->redo();
String action = undo_redo->get_current_action_name();
if (action != "") {
@@ -184,7 +185,52 @@ void EditorSettingsDialog::_update_icons() {
restart_label->add_theme_color_override("font_color", shortcuts->get_theme_color("warning_color", "Editor"));
}
+void EditorSettingsDialog::_event_config_confirmed() {
+ Ref<InputEventKey> k = shortcut_editor->get_event();
+ if (k.is_null()) {
+ return;
+ }
+
+ if (editing_action) {
+ if (current_action_event_index == -1) {
+ // Add new event
+ current_action_events.push_back(k);
+ } else {
+ // Edit existing event
+ current_action_events[current_action_event_index] = k;
+ }
+
+ _update_builtin_action(current_action, current_action_events);
+ } else {
+ k = k->duplicate();
+ Ref<Shortcut> current_sc = EditorSettings::get_singleton()->get_shortcut(shortcut_being_edited);
+
+ undo_redo->create_action(TTR("Change Shortcut") + " '" + shortcut_being_edited + "'");
+ undo_redo->add_do_method(current_sc.ptr(), "set_shortcut", k);
+ undo_redo->add_undo_method(current_sc.ptr(), "set_shortcut", current_sc->get_shortcut());
+ undo_redo->add_do_method(this, "_update_shortcuts");
+ undo_redo->add_undo_method(this, "_update_shortcuts");
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+ undo_redo->commit_action();
+ }
+}
+
+void EditorSettingsDialog::_update_builtin_action(const String &p_name, const Array &p_events) {
+ Array old_input_array = EditorSettings::get_singleton()->get_builtin_action_overrides(current_action);
+
+ undo_redo->create_action(TTR("Edit Built-in Action"));
+ undo_redo->add_do_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, p_events);
+ undo_redo->add_undo_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, old_input_array);
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+ undo_redo->commit_action();
+
+ _update_shortcuts();
+}
+
void EditorSettingsDialog::_update_shortcuts() {
+ // Before clearing the tree, take note of which categories are collapsed so that this state can be maintained when the tree is repopulated.
Map<String, bool> collapsed;
if (shortcuts->get_root() && shortcuts->get_root()->get_children()) {
@@ -192,15 +238,93 @@ void EditorSettingsDialog::_update_shortcuts() {
collapsed[item->get_text(0)] = item->is_collapsed();
}
}
-
shortcuts->clear();
- List<String> slist;
- EditorSettings::get_singleton()->get_shortcut_list(&slist);
TreeItem *root = shortcuts->create_item();
-
Map<String, TreeItem *> sections;
+ // Set up section for Common/Built-in actions
+ TreeItem *common_section = shortcuts->create_item(root);
+
+ sections["Common"] = common_section;
+ common_section->set_text(0, TTR("Common"));
+ if (collapsed.has("Common")) {
+ common_section->set_collapsed(collapsed["Common"]);
+ }
+ common_section->set_custom_bg_color(0, shortcuts->get_theme_color("prop_subsection", "Editor"));
+ common_section->set_custom_bg_color(1, shortcuts->get_theme_color("prop_subsection", "Editor"));
+
+ // Get the action map for the editor, and add each item to the "Common" section.
+ OrderedHashMap<StringName, InputMap::Action> action_map = InputMap::get_singleton()->get_action_map();
+ for (OrderedHashMap<StringName, InputMap::Action>::Element E = action_map.front(); E; E = E.next()) {
+ String action_name = E.key();
+
+ if (!shortcut_filter.is_subsequence_ofi(action_name)) {
+ continue;
+ }
+
+ InputMap::Action action = E.get();
+
+ Array events; // Need to get the list of events into an array so it can be set as metadata on the item.
+ Vector<String> event_strings;
+
+ List<Ref<InputEvent>> defaults = InputMap::get_singleton()->get_builtins().find(action_name).value();
+ // Remove all non-key events from the defaults.
+ for (List<Ref<InputEvent>>::Element *I = defaults.front(); I; I = I->next()) {
+ Ref<InputEventKey> k = I->get();
+ if (k.is_null()) {
+ I->erase();
+ }
+ }
+
+ bool same_as_defaults = defaults.size() == action.inputs.size(); // Initially this is set to just whether the arrays are equal. Later we check the events if needed.
+
+ int count = 0;
+ for (List<Ref<InputEvent>>::Element *I = action.inputs.front(); I; I = I->next()) {
+ // Add event and event text to respective arrays.
+ events.push_back(I->get());
+ event_strings.push_back(I->get()->as_text());
+
+ // Only check if the events have been the same so far - once one fails, we don't need to check any more.
+ if (same_as_defaults) {
+ Ref<InputEventKey> k = defaults[count];
+ // Only check keys, since we are in the editor.
+ if (k.is_valid() && !defaults[count]->shortcut_match(I->get())) {
+ same_as_defaults = false;
+ }
+ }
+ count++;
+ }
+
+ // Join the text of the events with a delimiter so they can all be displayed in one cell.
+ String events_display_string = event_strings.is_empty() ? "None" : String("; ").join(event_strings);
+
+ TreeItem *item = shortcuts->create_item(common_section);
+ item->set_text(0, action_name);
+ item->set_text(1, events_display_string);
+
+ if (!same_as_defaults) {
+ item->add_button(1, shortcuts->get_theme_icon("Reload", "EditorIcons"), 2);
+ }
+
+ if (events_display_string == "None") {
+ // Fade out unassigned shortcut labels for easier visual grepping.
+ item->set_custom_color(1, shortcuts->get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.5));
+ }
+
+ item->add_button(1, shortcuts->get_theme_icon("Edit", "EditorIcons"), 0);
+ item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), 1);
+ item->set_tooltip(0, action_name);
+ item->set_tooltip(1, events_display_string);
+ item->set_metadata(0, "Common");
+ item->set_metadata(1, events);
+ }
+
+ // Editor Shortcuts
+
+ List<String> slist;
+ EditorSettings::get_singleton()->get_shortcut_list(&slist);
+
for (List<String>::Element *E = slist.front(); E; E = E->next()) {
Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(E->get());
if (!sc->has_meta("original")) {
@@ -267,84 +391,119 @@ void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column
TreeItem *ti = Object::cast_to<TreeItem>(p_item);
ERR_FAIL_COND(!ti);
- String item = ti->get_metadata(0);
- Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(item);
-
- if (p_idx == 0) {
- press_a_key_label->set_text(TTR("Press a Key..."));
- last_wait_for_key = Ref<InputEventKey>();
- press_a_key->popup_centered(Size2(250, 80) * EDSCALE);
- //press_a_key->grab_focus();
- press_a_key->get_ok_button()->set_focus_mode(Control::FOCUS_NONE);
- press_a_key->get_cancel_button()->set_focus_mode(Control::FOCUS_NONE);
- shortcut_configured = item;
-
- } else if (p_idx == 1) { //erase
- if (!sc.is_valid()) {
- return; //pointless, there is nothing
+ if (ti->get_metadata(0) == "Common") {
+ // Editing a Built-in action, which can have multiple bindings.
+ button_idx = p_idx;
+ editing_action = true;
+ current_action = ti->get_text(0);
+
+ switch (button_idx) {
+ case SHORTCUT_REVERT: {
+ Array events;
+ List<Ref<InputEvent>> defaults = InputMap::get_singleton()->get_builtins()[current_action];
+
+ // Convert the list to an array, and only keep key events as this is for the editor.
+ for (List<Ref<InputEvent>>::Element *E = defaults.front(); E; E = E->next()) {
+ Ref<InputEventKey> k = E->get();
+ if (k.is_valid()) {
+ events.append(E->get());
+ }
+ }
+
+ _update_builtin_action(current_action, events);
+ } break;
+ case SHORTCUT_EDIT:
+ case SHORTCUT_ERASE: {
+ // For Edit end Delete, we will show a popup which displays each event so the user can select which one to edit/delete.
+ current_action_events = ti->get_metadata(1);
+ action_popup->clear();
+
+ for (int i = 0; i < current_action_events.size(); i++) {
+ Ref<InputEvent> ie = current_action_events[i];
+ action_popup->add_item(ie->as_text());
+ action_popup->set_item_metadata(i, ie);
+ }
+
+ if (button_idx == SHORTCUT_EDIT) {
+ // If editing, add a button which can be used to add an additional event.
+ action_popup->add_icon_item(get_theme_icon("Add", "EditorIcons"), TTR("Add"));
+ }
+
+ action_popup->set_position(get_position() + get_mouse_position());
+ action_popup->take_mouse_focus();
+ action_popup->popup();
+ action_popup->set_as_minsize();
+ } break;
+ default:
+ break;
}
-
- undo_redo->create_action(TTR("Erase Shortcut"));
- undo_redo->add_do_method(sc.ptr(), "set_shortcut", Ref<InputEvent>());
- undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut());
- undo_redo->add_do_method(this, "_update_shortcuts");
- undo_redo->add_undo_method(this, "_update_shortcuts");
- undo_redo->add_do_method(this, "_settings_changed");
- undo_redo->add_undo_method(this, "_settings_changed");
- undo_redo->commit_action();
- } else if (p_idx == 2) { //revert to original
- if (!sc.is_valid()) {
- return; //pointless, there is nothing
+ } else {
+ // Editing an Editor Shortcut, which can only have 1 binding.
+ String item = ti->get_metadata(0);
+ Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(item);
+ editing_action = false;
+
+ switch (button_idx) {
+ case EditorSettingsDialog::SHORTCUT_EDIT:
+ shortcut_editor->popup_and_configure(sc->get_shortcut());
+ shortcut_being_edited = item;
+ break;
+ case EditorSettingsDialog::SHORTCUT_ERASE: {
+ if (!sc.is_valid()) {
+ return; //pointless, there is nothing
+ }
+
+ undo_redo->create_action(TTR("Erase Shortcut"));
+ undo_redo->add_do_method(sc.ptr(), "set_shortcut", Ref<InputEvent>());
+ undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut());
+ undo_redo->add_do_method(this, "_update_shortcuts");
+ undo_redo->add_undo_method(this, "_update_shortcuts");
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+ undo_redo->commit_action();
+ } break;
+ case EditorSettingsDialog::SHORTCUT_REVERT: {
+ if (!sc.is_valid()) {
+ return; //pointless, there is nothing
+ }
+
+ Ref<InputEvent> original = sc->get_meta("original");
+
+ undo_redo->create_action(TTR("Restore Shortcut"));
+ undo_redo->add_do_method(sc.ptr(), "set_shortcut", original);
+ undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut());
+ undo_redo->add_do_method(this, "_update_shortcuts");
+ undo_redo->add_undo_method(this, "_update_shortcuts");
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+ undo_redo->commit_action();
+ } break;
+ default:
+ break;
}
-
- Ref<InputEvent> original = sc->get_meta("original");
-
- undo_redo->create_action(TTR("Restore Shortcut"));
- undo_redo->add_do_method(sc.ptr(), "set_shortcut", original);
- undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut());
- undo_redo->add_do_method(this, "_update_shortcuts");
- undo_redo->add_undo_method(this, "_update_shortcuts");
- undo_redo->add_do_method(this, "_settings_changed");
- undo_redo->add_undo_method(this, "_settings_changed");
- undo_redo->commit_action();
}
}
-void EditorSettingsDialog::_wait_for_key(const Ref<InputEvent> &p_event) {
- Ref<InputEventKey> k = p_event;
-
- if (k.is_valid() && k->is_pressed() && k->get_keycode() != 0) {
- last_wait_for_key = k;
- const String str = keycode_get_string(k->get_keycode_with_modifiers());
-
- press_a_key_label->set_text(str);
- press_a_key->set_input_as_handled();
- }
-}
-
-void EditorSettingsDialog::_press_a_key_confirm() {
- if (last_wait_for_key.is_null()) {
- return;
+void EditorSettingsDialog::_builtin_action_popup_index_pressed(int p_index) {
+ switch (button_idx) {
+ case SHORTCUT_EDIT: {
+ if (p_index == action_popup->get_item_count() - 1) {
+ // Selected last item in list (Add button), therefore add new
+ current_action_event_index = -1;
+ shortcut_editor->popup_and_configure();
+ } else {
+ // Configure existing
+ current_action_event_index = p_index;
+ shortcut_editor->popup_and_configure(action_popup->get_item_metadata(p_index));
+ }
+ } break;
+ case SHORTCUT_ERASE: {
+ current_action_events.remove(p_index);
+ _update_builtin_action(current_action, current_action_events);
+ } break;
+ default:
+ break;
}
-
- Ref<InputEventKey> ie;
- ie.instance();
- ie->set_keycode(last_wait_for_key->get_keycode());
- ie->set_shift(last_wait_for_key->get_shift());
- ie->set_control(last_wait_for_key->get_control());
- ie->set_alt(last_wait_for_key->get_alt());
- ie->set_metakey(last_wait_for_key->get_metakey());
-
- Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(shortcut_configured);
-
- undo_redo->create_action(TTR("Change Shortcut") + " '" + shortcut_configured + "'");
- undo_redo->add_do_method(sc.ptr(), "set_shortcut", ie);
- undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut());
- undo_redo->add_do_method(this, "_update_shortcuts");
- undo_redo->add_undo_method(this, "_update_shortcuts");
- undo_redo->add_do_method(this, "_settings_changed");
- undo_redo->add_undo_method(this, "_settings_changed");
- undo_redo->commit_action();
}
void EditorSettingsDialog::_tabs_tab_changed(int p_tab) {
@@ -382,9 +541,14 @@ void EditorSettingsDialog::_editor_restart_close() {
void EditorSettingsDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_unhandled_input"), &EditorSettingsDialog::_unhandled_input);
ClassDB::bind_method(D_METHOD("_update_shortcuts"), &EditorSettingsDialog::_update_shortcuts);
+ ClassDB::bind_method(D_METHOD("_settings_changed"), &EditorSettingsDialog::_settings_changed);
}
EditorSettingsDialog::EditorSettingsDialog() {
+ action_popup = memnew(PopupMenu);
+ action_popup->connect("index_pressed", callable_mp(this, &EditorSettingsDialog::_builtin_action_popup_index_pressed));
+ add_child(action_popup);
+
set_title(TTR("Editor Settings"));
undo_redo = memnew(UndoRedo);
@@ -442,21 +606,17 @@ EditorSettingsDialog::EditorSettingsDialog() {
// Shortcuts Tab
tab_shortcuts = memnew(VBoxContainer);
+
tabs->add_child(tab_shortcuts);
tab_shortcuts->set_name(TTR("Shortcuts"));
- hbc = memnew(HBoxContainer);
- hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- tab_shortcuts->add_child(hbc);
-
shortcut_search_box = memnew(LineEdit);
shortcut_search_box->set_placeholder(TTR("Search"));
shortcut_search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- hbc->add_child(shortcut_search_box);
+ tab_shortcuts->add_child(shortcut_search_box);
shortcut_search_box->connect("text_changed", callable_mp(this, &EditorSettingsDialog::_filter_shortcuts));
shortcuts = memnew(Tree);
- tab_shortcuts->add_child(shortcuts, true);
shortcuts->set_v_size_flags(Control::SIZE_EXPAND_FILL);
shortcuts->set_columns(2);
shortcuts->set_hide_root(true);
@@ -464,21 +624,13 @@ EditorSettingsDialog::EditorSettingsDialog() {
shortcuts->set_column_title(0, TTR("Name"));
shortcuts->set_column_title(1, TTR("Binding"));
shortcuts->connect("button_pressed", callable_mp(this, &EditorSettingsDialog::_shortcut_button_pressed));
+ tab_shortcuts->add_child(shortcuts);
- press_a_key = memnew(ConfirmationDialog);
- //press_a_key->set_focus_mode(Control::FOCUS_ALL);
- add_child(press_a_key);
-
- Label *l = memnew(Label);
- l->set_text(TTR("Press a Key..."));
- l->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
- l->set_align(Label::ALIGN_CENTER);
- l->set_offset(SIDE_TOP, 20);
- l->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_BEGIN, 30);
- press_a_key_label = l;
- press_a_key->add_child(l);
- press_a_key->connect("window_input", callable_mp(this, &EditorSettingsDialog::_wait_for_key));
- press_a_key->connect("confirmed", callable_mp(this, &EditorSettingsDialog::_press_a_key_confirm));
+ // Adding event dialog
+ shortcut_editor = memnew(InputEventConfigurationDialog);
+ shortcut_editor->connect("confirmed", callable_mp(this, &EditorSettingsDialog::_event_config_confirmed));
+ shortcut_editor->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_KEY);
+ add_child(shortcut_editor);
set_hide_on_ok(true);
diff --git a/editor/settings_config_dialog.h b/editor/settings_config_dialog.h
index b1ee58ae8f..c38fceedf1 100644
--- a/editor/settings_config_dialog.h
+++ b/editor/settings_config_dialog.h
@@ -31,6 +31,7 @@
#ifndef SETTINGS_CONFIG_DIALOG_H
#define SETTINGS_CONFIG_DIALOG_H
+#include "editor/action_map_editor.h"
#include "editor/editor_sectioned_inspector.h"
#include "editor_inspector.h"
#include "scene/gui/dialogs.h"
@@ -52,16 +53,28 @@ class EditorSettingsDialog : public AcceptDialog {
LineEdit *shortcut_search_box;
SectionedInspector *inspector;
+ enum ShortcutButton {
+ SHORTCUT_EDIT,
+ SHORTCUT_ERASE,
+ SHORTCUT_REVERT
+ };
+
+ int button_idx;
+ int current_action_event_index = -1;
+ bool editing_action = false;
+ String current_action;
+ Array current_action_events;
+ PopupMenu *action_popup;
+
Timer *timer;
UndoRedo *undo_redo;
- Tree *shortcuts;
- ConfirmationDialog *press_a_key;
- Label *press_a_key_label;
- Ref<InputEventKey> last_wait_for_key;
- String shortcut_configured;
+ // Shortcuts
String shortcut_filter;
+ Tree *shortcuts;
+ InputEventConfigurationDialog *shortcut_editor;
+ String shortcut_being_edited;
virtual void cancel_pressed() override;
virtual void ok_pressed() override;
@@ -74,20 +87,20 @@ class EditorSettingsDialog : public AcceptDialog {
void _notification(int p_what);
void _update_icons();
- void _press_a_key_confirm();
- void _wait_for_key(const Ref<InputEvent> &p_event);
+ void _event_config_confirmed();
+
+ void _update_builtin_action(const String &p_name, const Array &p_events);
void _tabs_tab_changed(int p_tab);
void _focus_current_search_box();
- void _clear_shortcut_search_box();
- void _clear_search_box();
-
void _filter_shortcuts(const String &p_filter);
void _update_shortcuts();
void _shortcut_button_pressed(Object *p_item, int p_column, int p_idx);
+ void _builtin_action_popup_index_pressed(int p_index);
+
static void _undo_redo_callback(void *p_self, const String &p_name);
Label *restart_label;
diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp
index 14d305e34f..ebef5be9ed 100644
--- a/editor/shader_globals_editor.cpp
+++ b/editor/shader_globals_editor.cpp
@@ -427,7 +427,7 @@ void ShaderGlobalsEditor::_variable_deleted(const String &p_variable) {
void ShaderGlobalsEditor::_changed() {
emit_signal("globals_changed");
if (!interface->block_update) {
- interface->_change_notify();
+ interface->notify_property_list_changed();
}
}
@@ -483,8 +483,5 @@ ShaderGlobalsEditor::ShaderGlobalsEditor() {
}
ShaderGlobalsEditor::~ShaderGlobalsEditor() {
- if (is_visible_in_tree()) {
- inspector->edit(nullptr);
- }
memdelete(interface);
}
diff --git a/editor/translations/af.po b/editor/translations/af.po
index 5caef149fa..bda0eed750 100644
--- a/editor/translations/af.po
+++ b/editor/translations/af.po
@@ -659,7 +659,7 @@ msgstr "Stel Oorgange na:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1913,8 +1913,8 @@ msgid "Open a File or Directory"
msgstr "Open 'n Lêer of Gids"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Stoor"
@@ -2581,7 +2581,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2981,14 +2981,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Soek"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -3143,6 +3135,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3349,7 +3357,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -4071,6 +4079,21 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Skep Vouer"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Ek sien..."
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Laai Verstek"
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -5069,7 +5092,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5178,7 +5201,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -7006,6 +7028,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Soek"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -7058,16 +7088,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7167,8 +7187,8 @@ msgstr "Skep"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7402,6 +7422,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -10017,6 +10041,11 @@ msgid "Projects"
msgstr "Projek Stigters"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Laai"
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10382,6 +10411,11 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Laai Verstek"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10632,6 +10666,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Anim Dupliseer Sleutels"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Deursoek Hulp"
@@ -10758,6 +10801,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Anim Dupliseer Sleutels"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12396,6 +12444,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12651,11 +12707,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/ar.po b/editor/translations/ar.po
index 2cfe1ac76c..5c03984e01 100644
--- a/editor/translations/ar.po
+++ b/editor/translations/ar.po
@@ -46,12 +46,13 @@
# Musab Alasaifer <mousablasefer@gmail.com>, 2020.
# Yassine Oudjana <y.oudjana@protonmail.com>, 2020.
# bruvzg <bruvzg13@gmail.com>, 2020.
-# StarlkYT <mrsstarlkps4@gmail.com>, 2020.
+# StarlkYT <mrsstarlkps4@gmail.com>, 2020, 2021.
+# Games Toon <xxtvgoodxx@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-12-29 15:03+0000\n"
+"PO-Revision-Date: 2021-03-07 06:04+0000\n"
"Last-Translator: StarlkYT <mrsstarlkps4@gmail.com>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/"
"godot/ar/>\n"
@@ -61,7 +62,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.4.1-dev\n"
+"X-Generator: Weblate 4.5.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -684,7 +685,7 @@ msgstr "إختر المقاطع المراد نسخها"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "نسخ"
@@ -1701,9 +1702,8 @@ msgid "Node Dock"
msgstr "رصيف العُقد"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "FileSystem Dock"
-msgstr "نظام الملفات"
+msgstr "قوائم نظام الملفات"
#: editor/editor_feature_profile.cpp
msgid "Import Dock"
@@ -1885,8 +1885,8 @@ msgid "Open a File or Directory"
msgstr "إفتح ملف أو وجهة"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "حفظ"
@@ -2342,6 +2342,9 @@ msgid ""
"To restore the Default layout to its base settings, use the Delete Layout "
"option and delete the Default layout."
msgstr ""
+"تم تجاوز اعدادات المحرر الاساسيه.\n"
+"لإستعادة اعدادات المحرر, اذهب إلى خيار 'Delete Layout' من ثم إحفظ الاعدادات "
+"الاساسيه."
#: editor/editor_node.cpp
msgid "Layout name not found!"
@@ -2406,7 +2409,7 @@ msgstr "ليس هناك مشهد محدد ليتم تشغيله."
#: editor/editor_node.cpp
msgid "Save scene before running..."
-msgstr ""
+msgstr "احفظ المشهد قبل التشغيل..."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -2551,7 +2554,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr "غير قادر علي تفعيل إضافة البرنامج المُساعد في: '%s' تحميل الظبط فشل."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"غير قادر علي إيجاد منطقة النص البرمجي من أجل إضافة البرنامج في: 'res://"
"addons/%s'."
@@ -2983,14 +2987,6 @@ msgid "Help"
msgstr "مساعدة"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "بحث"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "مستندات الإنترنت"
@@ -3154,6 +3150,24 @@ msgid "Open & Run a Script"
msgstr "فتح و تشغيل كود"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"الملفات التالية أحدث على القرص.\n"
+"ما الإجراء الذي ينبغي اتخاذه؟"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "إعادة تحميل"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "إعادة حفظ"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "موروث جديد"
@@ -3363,7 +3377,7 @@ msgstr "إجعلة مميزاً"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "لصق"
@@ -4062,6 +4076,21 @@ msgstr "هل قمت بإرجاع كائن مشتق من العقدة في دال
msgid "Saving..."
msgstr "جاري الحفظ..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "تحديد الوضع"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "إستيراد"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "تحميل الإفتراضي"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d ملفات"
@@ -5028,7 +5057,8 @@ msgid "Got:"
msgstr "ما تم الحصول عليه:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "فشل التاكد من ترميز sha256"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5132,7 +5162,6 @@ msgid "Sort:"
msgstr "ترتيب:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "الفئة:"
@@ -6955,6 +6984,14 @@ msgstr "إغلاق المستندات"
msgid "Run"
msgstr "تشغيل"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "بحث"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "اخط خطوة ضمن"
@@ -7008,16 +7045,6 @@ msgstr ""
"الملفات التالية أحدث على القرص.\n"
"ما الإجراء الذي ينبغي اتخاذه؟:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "إعادة تحميل"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "إعادة حفظ"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "مُنقح الأخطاء"
@@ -7111,8 +7138,8 @@ msgstr "نقاط التكسّر"
msgid "Go To"
msgstr "التوجه إلى"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "قص"
@@ -7335,6 +7362,10 @@ msgid "Yaw"
msgstr "الإنحراف Yaw"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "الحجم"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "كائنات مرسومة"
@@ -10023,6 +10054,11 @@ msgid "Projects"
msgstr "المشاريع"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "يستقبل المرايا، من فضلك إنتظر..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "آخر ما تم تعديله"
@@ -10392,6 +10428,11 @@ msgstr "تحميل تلقائي"
msgid "Plugins"
msgstr "إضافات"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "تحميل الإفتراضي"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "إعداد مُسبق..."
@@ -10453,9 +10494,8 @@ msgid "Batch Rename"
msgstr "إعادة تسمية الدفعة"
#: editor/rename_dialog.cpp
-#, fuzzy
msgid "Replace:"
-msgstr "إستبدال: "
+msgstr "إستبدال:"
#: editor/rename_dialog.cpp
#, fuzzy
@@ -10644,6 +10684,16 @@ msgid "Instance Child Scene"
msgstr "نمذجة المشهد الابن"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Can't paste root node into the same scene."
+msgstr "لا يمكن تنفيذ الإجراء على عُقدة من مشهد أجنبي!"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "لصق العُقد"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "فصل النص البرمجي"
@@ -10771,6 +10821,11 @@ msgid "Attach Script"
msgstr "إلحاق نص برمجي"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "قص العُقد"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "إزالة عُقدة (عُقد)"
@@ -12427,6 +12482,14 @@ msgstr ""
"مُضلع تصادم ثنائي الأبعاد (CollisionPolygon2D) الفارغ ليس له أي تأثير على "
"التصادم."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12763,11 +12826,6 @@ msgstr ""
"GIProbes لا يدعم برنامج تشغيل الفيديو GLES2.\n"
"استخدم BakedLightmap بدلاً من ذلك."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "بقعة الضوء بزاوية أكبر من 90 درجة لا يمكنها إلقاء الظلال."
diff --git a/editor/translations/bg.po b/editor/translations/bg.po
index fd7a8f4332..848574a1f1 100644
--- a/editor/translations/bg.po
+++ b/editor/translations/bg.po
@@ -17,7 +17,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-22 10:21+0000\n"
+"PO-Revision-Date: 2021-03-10 22:14+0000\n"
"Last-Translator: Любомир Василев <lyubomirv@gmx.com>\n"
"Language-Team: Bulgarian <https://hosted.weblate.org/projects/godot-engine/"
"godot/bg/>\n"
@@ -26,7 +26,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.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -640,7 +640,7 @@ msgstr "Изберете пътечки за копиране"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Копиране"
@@ -1811,8 +1811,8 @@ msgid "Open a File or Directory"
msgstr "Отваряне на файл или папка"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Запазване"
@@ -2232,11 +2232,11 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Can't load MeshLibrary for merging!"
-msgstr ""
+msgstr "Не може да се зареди библиотеката с полигонни мрежи за сливане!"
#: editor/editor_node.cpp
msgid "Error saving MeshLibrary!"
-msgstr ""
+msgstr "Грешка при запазването на библиотеката с полигонни мрежи!"
#: editor/editor_node.cpp
msgid "Can't load TileSet for merging!"
@@ -2359,7 +2359,7 @@ msgstr "Операцията не може да се извърши без сц
#: editor/editor_node.cpp
msgid "Export Mesh Library"
-msgstr ""
+msgstr "Изнасяне на библиотека с полигонни мрежи"
#: editor/editor_node.cpp
msgid "This operation can't be done without a root node."
@@ -2446,39 +2446,50 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr ""
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "Не може да бъде намерено полето за скрипт за добавката: „%s“."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
-msgstr "Не може да се зареди скриптът на добавка от: „%s“."
+msgstr "Не може да се зареди добавката-скрипт от: „%s“."
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s' There seems to be an error in "
"the code, please check the syntax."
msgstr ""
+"Не може да се зареди добавката-скрипт от: „%s“. Изглежда има грешка в кода. "
+"Моля, проверете синтаксиса."
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
+"Не може да се зареди добавката-скрипт от: „%s“. Базовият тип не е "
+"„EditorPlugin“."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
+"Не може да се зареди добавката-скрипт от: „%s“. Скриптът не е в режим на "
+"„инструмент“."
#: editor/editor_node.cpp
msgid ""
"Scene '%s' was automatically imported, so it can't be modified.\n"
"To make changes to it, a new inherited scene can be created."
msgstr ""
+"Сцената „%s“ е била внесена автоматично и затова не може да се променя.\n"
+"Ако искате да правите промени в нея, може да създадете нова сцена-наследник."
#: editor/editor_node.cpp
msgid ""
"Error loading scene, it must be inside the project path. Use 'Import' to "
"open the scene, then save it inside the project path."
msgstr ""
+"Грешка при зареждането на сцената. Тя трябва да се намира в папката на "
+"проекта. Използвайте „Внасяне“, за да отворите сцената, и след това я "
+"запазете някъде в папката на проекта."
#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
@@ -2494,6 +2505,9 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
+"Няма определена главна сцена. Искате ли да изберете такава сега?\n"
+"Можете да промените това по всяко време в „Настройките на проекта“, в "
+"категорията „Приложение“."
#: editor/editor_node.cpp
msgid ""
@@ -2501,6 +2515,9 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
+"Избраната сцена „%s“ не съществува. Искате ли да изберете друга?\n"
+"Можете да промените това по всяко време в „Настройките на проекта“, в "
+"категорията „Приложение“."
#: editor/editor_node.cpp
msgid ""
@@ -2508,6 +2525,10 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
+"Избраната сцена „%s“ не е файл съдържащ сцена. Искате ли да изберете "
+"подходящ файл?\n"
+"Можете да промените това по всяко време в „Настройките на проекта“, в "
+"категорията „Приложение“."
#: editor/editor_node.cpp
msgid "Save Layout"
@@ -2641,7 +2662,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "MeshLibrary..."
-msgstr ""
+msgstr "Библиотека с полигонни мрежи…"
#: editor/editor_node.cpp
msgid "TileSet..."
@@ -2758,6 +2779,8 @@ msgid ""
"When this option is enabled, navigation meshes and polygons will be visible "
"in the running project."
msgstr ""
+"Ако тази настройка е включено, навигационните полигони и мрежи ще бъдат "
+"видими в изпълняващия се проект."
#: editor/editor_node.cpp
msgid "Synchronize Scene Changes"
@@ -2836,14 +2859,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Търсене"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2997,6 +3012,24 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Следните файлове са по-нови на диска.\n"
+"Кое действие трябва да се предприеме?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Презареждане"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Презаписване"
+
+#: editor/editor_node.cpp
#, fuzzy
msgid "New Inherited"
msgstr "Нов скрипт"
@@ -3200,7 +3233,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Поставяне"
@@ -3855,7 +3888,7 @@ msgstr ""
#: editor/import/resource_importer_scene.cpp
msgid "Generating for Mesh: "
-msgstr ""
+msgstr "Създаване за полигонна мрежа: "
#: editor/import/resource_importer_scene.cpp
msgid "Running Custom Script..."
@@ -3881,9 +3914,21 @@ msgstr ""
msgid "Saving..."
msgstr "Запазване..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "Изберете метод на внасяне"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "Метод на внасяне:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Връщане на стандартните настройки"
+
#: editor/import_dock.cpp
msgid "%d Files"
-msgstr "%d Файлове"
+msgstr "%d файла"
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
@@ -4339,7 +4384,7 @@ msgstr "Ново име на анимацията:"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "New Anim"
-msgstr ""
+msgstr "Нова анимация"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Change Animation Name:"
@@ -4353,20 +4398,20 @@ msgstr "Изтриване на анимацията?"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Remove Animation"
-msgstr ""
+msgstr "Премахване на анимацията"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Invalid animation name!"
-msgstr ""
+msgstr "Неправилно име на анимацията!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation name already exists!"
-msgstr ""
+msgstr "Вече съществува анимация с това име!"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Rename Animation"
-msgstr ""
+msgstr "Преименуване на анимацията"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Blend Next Changed"
@@ -4374,19 +4419,19 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Change Blend Time"
-msgstr ""
+msgstr "Промяна на времето на смесване"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Load Animation"
-msgstr ""
+msgstr "Зареждане на анимация"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Duplicate Animation"
-msgstr ""
+msgstr "Дублиране на анимацията"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "No animation to copy!"
-msgstr ""
+msgstr "Няма анимация за копиране!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "No animation resource on clipboard!"
@@ -4394,11 +4439,11 @@ msgstr "Няма ресурс–анимация в буфера за обмен
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Pasted Animation"
-msgstr ""
+msgstr "Поставена анимация"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Paste Animation"
-msgstr ""
+msgstr "Поставяне на анимация"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "No animation to edit!"
@@ -4407,30 +4452,32 @@ msgstr "Няма анимация за редактиране!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation backwards from current pos. (A)"
msgstr ""
+"Възпроизвеждане на избраната анимация наобратно от текущата позиция. (A)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation backwards from end. (Shift+A)"
-msgstr ""
+msgstr "Възпроизвеждане на избраната анимация наобратно от края. (Shift+A)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Stop animation playback. (S)"
-msgstr ""
+msgstr "Спиране на възпроизвеждането на анимацията. (S)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation from start. (Shift+D)"
-msgstr ""
+msgstr "Възпроизвеждане на избраната анимация от началото. (Shift+D)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation from current pos. (D)"
-msgstr ""
+msgstr "Възпроизвеждане на избраната анимация от текущата позиция. (D)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation position (in seconds)."
-msgstr ""
+msgstr "Позиция в анимацията (в секунди)."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Scale animation playback globally for the node."
msgstr ""
+"Скалиране на скоростта на възпроизвеждане на анимацията глобално за възела."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation Tools"
@@ -4438,7 +4485,7 @@ msgstr "Инструменти за анимациите"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation"
-msgstr ""
+msgstr "Анимация"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Edit Transitions..."
@@ -4446,7 +4493,7 @@ msgstr "Редактиране на преходите..."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Open in Inspector"
-msgstr ""
+msgstr "Отваряне в инспектора"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Display list of animations in player."
@@ -4454,15 +4501,15 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Autoplay on Load"
-msgstr ""
+msgstr "Авт. възпроизвеждане при зареждане"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Enable Onion Skinning"
-msgstr ""
+msgstr "Показване на избледняващи кадри"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Onion Skinning Options"
-msgstr ""
+msgstr "Настройки на режима с избледняващи кадри"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Directions"
@@ -4510,11 +4557,11 @@ msgstr "Закачане на AnimationPlayer"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Create New Animation"
-msgstr ""
+msgstr "Създаване на нова анимация"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation Name:"
-msgstr ""
+msgstr "Име на анимацията:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
@@ -4525,15 +4572,15 @@ msgstr "Грешка!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Blend Times:"
-msgstr ""
+msgstr "Времена на смесване:"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Next (Auto Queue):"
-msgstr ""
+msgstr "Следваща (авт. опашка):"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Cross-Animation Blend Times"
-msgstr ""
+msgstr "Времена на смесване между анимациите"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Move Node"
@@ -4550,23 +4597,23 @@ msgstr "Добавяне на преход"
#: editor/plugins/animation_state_machine_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "Add Node"
-msgstr ""
+msgstr "Добавяне на възел"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "End"
-msgstr ""
+msgstr "Край"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Immediate"
-msgstr ""
+msgstr "Незабавно"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Sync"
-msgstr ""
+msgstr "Синхронизиране"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "At End"
-msgstr ""
+msgstr "На края"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Travel"
@@ -4837,7 +4884,8 @@ msgid "Got:"
msgstr "Получено:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "Неуспешна проверка на хеш от вид „sha256“"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4941,7 +4989,6 @@ msgid "Sort:"
msgstr "Сортиране:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Категория:"
@@ -5461,7 +5508,7 @@ msgstr "Преглед"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Always Show Grid"
-msgstr ""
+msgstr "Винаги да се показва решетката"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Show Helpers"
@@ -5469,7 +5516,7 @@ msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Show Rulers"
-msgstr ""
+msgstr "Показване на линиите"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Show Guides"
@@ -5668,12 +5715,12 @@ msgstr ""
#: editor/plugins/cpu_particles_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
msgid "Create Emission Points From Mesh"
-msgstr ""
+msgstr "Създаване на излъчващи точки от полигонната мрежа"
#: editor/plugins/cpu_particles_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
msgid "Create Emission Points From Node"
-msgstr ""
+msgstr "Създаване на излъчващи точки от възела"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Flat 0"
@@ -5770,7 +5817,7 @@ msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Mesh is empty!"
-msgstr ""
+msgstr "Полигонната мрежа е празна!"
#: editor/plugins/mesh_instance_editor_plugin.cpp
#, fuzzy
@@ -5815,19 +5862,21 @@ msgstr "Създаване на няколко изпъкнали форми"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Navigation Mesh"
-msgstr ""
+msgstr "Създаване на навигационна полигонна мрежа"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Contained Mesh is not of type ArrayMesh."
-msgstr ""
+msgstr "Съдържащата се полигонна мрежа не е от тип ArrayMesh."
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Unwrap failed, mesh may not be manifold?"
msgstr ""
+"Разгъването на UV беше неуспешно. Възможно ли е полигонната мрежа да се "
+"състои от повече от една форма?"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "No mesh to debug."
-msgstr ""
+msgstr "Няма полигонна мрежа за дебъгване."
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Model has no UV in this layer"
@@ -5835,15 +5884,15 @@ msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "MeshInstance lacks a Mesh!"
-msgstr ""
+msgstr "В MeshInstance няма полигонна мрежа!"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Mesh has not surface to create outlines from!"
-msgstr ""
+msgstr "Полигонната мрежа няма повърхност, от която да се създадат контури!"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Mesh primitive type is not PRIMITIVE_TRIANGLES!"
-msgstr ""
+msgstr "Примитивният тип на полигонната мрежа не е PRIMITIVE_TRIANGLES!"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Could not create outline!"
@@ -5855,7 +5904,7 @@ msgstr "Създаване на контур"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Mesh"
-msgstr ""
+msgstr "Полигонна мрежа"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
@@ -5902,7 +5951,7 @@ msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Outline Mesh..."
-msgstr ""
+msgstr "Създаване на контурна полигонна мрежа…"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid ""
@@ -5911,6 +5960,10 @@ msgid ""
"This can be used instead of the SpatialMaterial Grow property when using "
"that property isn't possible."
msgstr ""
+"Създава статична полигонна мрежа за контура. Нормалите на контурната "
+"полигонна мрежа ще бъдат автоматично обърнати.\n"
+"Това може да се използва вместо свойството Grow на SpatialMaterial, когато "
+"това свойство не може да се променя."
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "View UV1"
@@ -5926,7 +5979,7 @@ msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Outline Mesh"
-msgstr ""
+msgstr "Създаване на контурна полигонна мрежа"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Outline Size:"
@@ -5950,7 +6003,7 @@ msgstr ""
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
-msgstr "Библиотека от полигонни мрежи"
+msgstr "Библиотека с полигонни мрежи"
#: editor/plugins/mesh_library_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp
@@ -5972,22 +6025,27 @@ msgstr "Обновяване от сцена"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "No mesh source specified (and no MultiMesh set in node)."
msgstr ""
+"Няма посочен източник за полигонна мрежа (и във възела няма MultiMesh)."
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "No mesh source specified (and MultiMesh contains no Mesh)."
msgstr ""
+"Няма посочен източник за полигонна мрежа (и MultiMesh не съдържа полигонна "
+"мрежа)."
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Mesh source is invalid (invalid path)."
-msgstr ""
+msgstr "Източникът за полигонна мрежа е неправилен (грешен път)."
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Mesh source is invalid (not a MeshInstance)."
-msgstr ""
+msgstr "Източникът за полигонна мрежа е неправилен (не е MeshInstance)."
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Mesh source is invalid (contains no Mesh resource)."
msgstr ""
+"Източникът за полигонна мрежа е неправилен (не съдържа ресурс, който е "
+"полигонна мрежа)."
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "No surface source specified."
@@ -6007,7 +6065,7 @@ msgstr ""
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Select a Source Mesh:"
-msgstr ""
+msgstr "Изберете източник за полигонна мрежа:"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Select a Target Surface:"
@@ -6027,7 +6085,7 @@ msgstr ""
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Source Mesh:"
-msgstr ""
+msgstr "Източник за полигонна мрежа:"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "X-Axis"
@@ -6043,7 +6101,7 @@ msgstr ""
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Mesh Up Axis:"
-msgstr ""
+msgstr "Ос сочеща нагоре за полигонната мрежа:"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Random Rotation:"
@@ -6118,15 +6176,15 @@ msgstr ""
#: editor/plugins/particles_editor_plugin.cpp
msgid "Emission Points:"
-msgstr ""
+msgstr "Излъчващи точки:"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Surface Points"
-msgstr ""
+msgstr "Точки на повърхността"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Surface Points+Normal (Directed)"
-msgstr ""
+msgstr "Точки на повърхността + нормали (насочени)"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Volume"
@@ -6134,7 +6192,7 @@ msgstr "Обем"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Emission Source: "
-msgstr ""
+msgstr "Източник на излъчването: "
#: editor/plugins/particles_editor_plugin.cpp
msgid "A processor material of type 'ParticlesMaterial' is required."
@@ -6729,6 +6787,14 @@ msgstr "Затваряне на документацията"
msgid "Run"
msgstr "Пускане"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Търсене"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6782,16 +6848,6 @@ msgstr ""
"Следните файлове са по-нови на диска.\n"
"Кое действие трябва да се предприеме?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Презареждане"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Презаписване"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Дебъгер"
@@ -6884,8 +6940,8 @@ msgstr "Точки на прекъсване"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Изрязване"
@@ -7108,6 +7164,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -7533,15 +7593,15 @@ msgstr ""
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't replace by mesh."
-msgstr ""
+msgstr "Неправилна геометрия. Не може да се замени с полигонна мрежа."
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Convert to Mesh2D"
-msgstr ""
+msgstr "Преобразуване в Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create polygon."
-msgstr ""
+msgstr "Неправилна геометрия, не може да се създаде полигон."
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Convert to Polygon2D"
@@ -7549,7 +7609,7 @@ msgstr "Превръщане в Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create collision polygon."
-msgstr ""
+msgstr "Неправилна геометрия, не може да се създаде полигон за колизии."
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D Sibling"
@@ -7561,7 +7621,7 @@ msgstr ""
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D Sibling"
-msgstr ""
+msgstr "Създаване на съседен LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite"
@@ -7569,15 +7629,15 @@ msgstr ""
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Simplification: "
-msgstr ""
+msgstr "Опростяване: "
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Shrink (Pixels): "
-msgstr ""
+msgstr "Смаляване (пиксели): "
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Grow (Pixels): "
-msgstr ""
+msgstr "Уголемяване (пиксели): "
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Update Preview"
@@ -7593,11 +7653,11 @@ msgstr "Няма избрани кадри"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Add %d Frame(s)"
-msgstr ""
+msgstr "Добавяне на %d кадър/кадри"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Add Frame"
-msgstr ""
+msgstr "Добавяне на кадър"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Unable to load images"
@@ -7605,27 +7665,27 @@ msgstr "Изображенията не могат да бъдат зареде
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
-msgstr ""
+msgstr "ГРЕШКА: Не може да се зареди ресурсът с кадъра!"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Resource clipboard is empty or not a texture!"
-msgstr ""
+msgstr "Буферът за обмен на ресурси е празен или не съдържа текстура!"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Paste Frame"
-msgstr ""
+msgstr "Поставяне на кадър"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Add Empty"
-msgstr ""
+msgstr "Добавяне на празен"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Change Animation FPS"
-msgstr ""
+msgstr "Промяна на скоростта (кадри/сек) на анимацията"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "(empty)"
-msgstr ""
+msgstr "(празно)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Move Frame"
@@ -7645,7 +7705,7 @@ msgstr "Скорост:"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Loop"
-msgstr ""
+msgstr "Повтаряне"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames:"
@@ -7661,11 +7721,11 @@ msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Insert Empty (Before)"
-msgstr ""
+msgstr "Вмъкване на празен (преди)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Insert Empty (After)"
-msgstr ""
+msgstr "Вмъкване на празен (след)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Move (Before)"
@@ -7673,7 +7733,7 @@ msgstr "Преместване (преди)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Move (After)"
-msgstr ""
+msgstr "Преместване (след)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Select Frames"
@@ -7681,11 +7741,11 @@ msgstr "Избиране на кадри"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Horizontal:"
-msgstr ""
+msgstr "Хоризонтала:"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Vertical:"
-msgstr ""
+msgstr "Вертикала:"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Select/Clear All Frames"
@@ -7705,40 +7765,40 @@ msgstr ""
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Set Margin"
-msgstr ""
+msgstr "Задаване на отстъп"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Snap Mode:"
-msgstr ""
+msgstr "Режим на прилепване:"
#: editor/plugins/texture_region_editor_plugin.cpp
#: scene/resources/visual_shader.cpp
msgid "None"
-msgstr ""
+msgstr "Няма"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Pixel Snap"
-msgstr ""
+msgstr "Прилепване към пикселите"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Grid Snap"
-msgstr ""
+msgstr "Прилепване към решетката"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Auto Slice"
-msgstr ""
+msgstr "Автоматично отрязване"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Offset:"
-msgstr ""
+msgstr "Отместване:"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Step:"
-msgstr ""
+msgstr "Стъпка:"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Sep.:"
-msgstr ""
+msgstr "Разделител:"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "TextureRegion"
@@ -7746,15 +7806,15 @@ msgstr "Текстурна област"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add All Items"
-msgstr ""
+msgstr "Добавяне на всички елементи"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add All"
-msgstr ""
+msgstr "Добавяне на всичко"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Remove All Items"
-msgstr ""
+msgstr "Премахване на всички елементи"
#: editor/plugins/theme_editor_plugin.cpp editor/project_manager.cpp
msgid "Remove All"
@@ -7766,7 +7826,7 @@ msgstr "Редактиране на темата"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Theme editing menu."
-msgstr ""
+msgstr "Меню за редактиране на темата."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -7798,7 +7858,7 @@ msgstr "Заключен бутон"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Item"
-msgstr ""
+msgstr "Елемент"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Disabled Item"
@@ -7806,11 +7866,11 @@ msgstr "Заключен елемент"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Check Item"
-msgstr ""
+msgstr "Елемент за отметка"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Checked Item"
-msgstr ""
+msgstr "Отметнат елемент"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Radio Item"
@@ -7822,27 +7882,27 @@ msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Named Sep."
-msgstr ""
+msgstr "Именуван разд."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Submenu"
-msgstr ""
+msgstr "Подменю"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Subitem 1"
-msgstr ""
+msgstr "Поделемент 1"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Subitem 2"
-msgstr ""
+msgstr "Поделемент 2"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Has"
-msgstr ""
+msgstr "Има"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Many"
-msgstr ""
+msgstr "Много"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Disabled LineEdit"
@@ -7850,15 +7910,15 @@ msgstr "Заключено текстово поле"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Tab 1"
-msgstr ""
+msgstr "Раздел 1"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Tab 2"
-msgstr ""
+msgstr "Раздел 2"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Tab 3"
-msgstr ""
+msgstr "Раздел 3"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Editable Item"
@@ -7866,32 +7926,32 @@ msgstr "Редактируем елемент"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Subtree"
-msgstr ""
+msgstr "Поддърво"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Has,Many,Options"
-msgstr ""
+msgstr "Има,Много,Опции"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Data Type:"
-msgstr ""
+msgstr "Тип на данните:"
#: editor/plugins/theme_editor_plugin.cpp
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Icon"
-msgstr ""
+msgstr "Иконка"
#: editor/plugins/theme_editor_plugin.cpp editor/rename_dialog.cpp
msgid "Style"
-msgstr ""
+msgstr "Стил"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Font"
-msgstr ""
+msgstr "Шрифт"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
-msgstr ""
+msgstr "Цват"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Theme File"
@@ -7899,11 +7959,11 @@ msgstr "Файл с тема"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Erase Selection"
-msgstr ""
+msgstr "Изтриване на избраното"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Fix Invalid Tiles"
-msgstr ""
+msgstr "Поправка на неправилните плочки"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
@@ -9642,6 +9702,11 @@ msgid "Projects"
msgstr "Проекти"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Зареждане…"
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10002,6 +10067,11 @@ msgstr ""
msgid "Plugins"
msgstr "Приставки"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Внасяне на преводи"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10245,6 +10315,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Поставяне на възлите"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Разкачане на скрипта"
@@ -10365,6 +10444,11 @@ msgid "Attach Script"
msgstr "Закачане на скрипт"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Изрязване на възлите"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11156,6 +11240,8 @@ msgstr "Филтриране на полигонните мрежи"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Give a MeshLibrary resource to this GridMap to use its meshes."
msgstr ""
+"Задайте ресурс от тип MeshLibrary в този GridMap, за да можете да използвате "
+"полигонните му мрежи."
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Begin Bake"
@@ -11196,11 +11282,11 @@ msgstr ""
#: modules/recast/navigation_mesh_editor_plugin.cpp
msgid "Bake NavMesh"
-msgstr ""
+msgstr "Изпичане на NavMesh"
#: modules/recast/navigation_mesh_editor_plugin.cpp
msgid "Clear the navigation mesh."
-msgstr ""
+msgstr "Изчистване на навигационната полигонна мрежа."
#: modules/recast/navigation_mesh_generator.cpp
msgid "Setting up Configuration..."
@@ -11236,15 +11322,15 @@ msgstr ""
#: modules/recast/navigation_mesh_generator.cpp
msgid "Creating polymesh..."
-msgstr ""
+msgstr "Създаване на полигонна мрежа…"
#: modules/recast/navigation_mesh_generator.cpp
msgid "Converting to native navigation mesh..."
-msgstr ""
+msgstr "Преобразуване на навигационната полигонна мрежа в собствения формат…"
#: modules/recast/navigation_mesh_generator.cpp
msgid "Navigation Mesh Generator Setup:"
-msgstr ""
+msgstr "Настройка на генератора на навигационни полигонни мрежи:"
#: modules/recast/navigation_mesh_generator.cpp
msgid "Parsing Geometry..."
@@ -11959,6 +12045,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Празен CollisionPolygon2D не влияе на колизиите."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12147,7 +12241,7 @@ msgstr ""
#: scene/3d/baked_lightmap.cpp
msgid "Finding meshes and lights"
-msgstr ""
+msgstr "Търсене на полигонни мрежи и светлини"
#: scene/3d/baked_lightmap.cpp
msgid "Preparing geometry (%d/%d)"
@@ -12215,7 +12309,7 @@ msgstr ""
#: scene/3d/cpu_particles.cpp
msgid "Nothing is visible because no mesh has been assigned."
-msgstr ""
+msgstr "Не се вижда нищо, той като няма зададена полигонна мрежа."
#: scene/3d/cpu_particles.cpp
msgid ""
@@ -12225,7 +12319,7 @@ msgstr ""
#: scene/3d/gi_probe.cpp
msgid "Plotting Meshes"
-msgstr ""
+msgstr "Построяване на полигонните мрежи"
#: scene/3d/gi_probe.cpp
msgid "Finishing Plot"
@@ -12237,11 +12331,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -12249,12 +12338,16 @@ msgstr ""
#: scene/3d/navigation_mesh.cpp
msgid "A NavigationMesh resource must be set or created for this node to work."
msgstr ""
+"Трябва да се зададе или създаде ресурс от тип NavigationMesh, за може да "
+"работи този възел."
#: scene/3d/navigation_mesh.cpp
msgid ""
"NavigationMeshInstance must be a child or grandchild to a Navigation node. "
"It only provides navigation data."
msgstr ""
+"NavigationMeshInstance трябва да бъде дъщерен или под-дъщерен на възел от "
+"тип Navigation. Той само предоставя данните за навигирането."
#: scene/3d/particles.cpp
msgid ""
@@ -12267,6 +12360,8 @@ msgstr ""
msgid ""
"Nothing is visible because meshes have not been assigned to draw passes."
msgstr ""
+"Не се вижда нищо, тъй като полигонните мрежи не са били свързани към стъпки "
+"на изчертаване."
#: scene/3d/particles.cpp
msgid ""
@@ -12321,7 +12416,7 @@ msgstr ""
#: scene/3d/soft_body.cpp
msgid "This body will be ignored until you set a mesh."
-msgstr ""
+msgstr "Това тяло ще бъде игнорирано, докато не зададете полигонна мрежа."
#: scene/3d/soft_body.cpp
msgid ""
@@ -12827,9 +12922,6 @@ msgstr "Константите не могат да бъдат променен
#~ msgid "Import Large Texture"
#~ msgstr "Внасяне на голяма текстура"
-#~ msgid "Import Translations"
-#~ msgstr "Внасяне на преводи"
-
#~ msgid "Couldn't import!"
#~ msgstr "Неуспешно внасяне!"
diff --git a/editor/translations/bn.po b/editor/translations/bn.po
index 4482328985..ca8fff0724 100644
--- a/editor/translations/bn.po
+++ b/editor/translations/bn.po
@@ -8,14 +8,14 @@
# Tawhid H. <Tawhidk757@yahoo.com>, 2019.
# Hasibul Hasan <hasibeng78@gmail.com>, 2019.
# Oymate <dhruboadittya96@gmail.com>, 2020.
-# Mokarrom Hossain <mhb2016.bzs@gmail.com>, 2020.
+# Mokarrom Hossain <mhb2016.bzs@gmail.com>, 2020, 2021.
# Sagen Soren <sagensoren03@gmail.com>, 2020.
# Hasibul Hasan <d1hasib@yahoo.com>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-12-27 02:25+0000\n"
+"PO-Revision-Date: 2021-02-15 10:51+0000\n"
"Last-Translator: Mokarrom Hossain <mhb2016.bzs@gmail.com>\n"
"Language-Team: Bengali <https://hosted.weblate.org/projects/godot-engine/"
"godot/bn/>\n"
@@ -24,7 +24,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.4.1-dev\n"
+"X-Generator: Weblate 4.5-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -268,7 +268,6 @@ msgid "Loop Wrap Mode (Interpolate end with beginning on loop)"
msgstr "লুপ Wrap মোড (লুপ দিয়ে শুরু দিয়ে ইন্টারপোলেট শেষ)"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Remove this track."
msgstr "নির্বাচিত ট্র্যাক/পথ অপসারণ করুন।"
@@ -440,28 +439,24 @@ msgid "Track is not of type Spatial, can't insert key"
msgstr "ট্র্যাক Spatial টাইপের নয়, কী সন্নিবেশ করতে পারে না"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Add Transform Track Key"
-msgstr "রুপান্তরের ধরণ"
+msgstr "ট্রান্সফর্ম ট্র্যাক কী যুক্ত করুন"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Add Track Key"
-msgstr "অ্যানিমেশন (Anim) ট্র্যাক যোগ করুন"
+msgstr "ট্র্যাক কী যুক্ত করুন"
#: editor/animation_track_editor.cpp
msgid "Track path is invalid, so can't add a method key."
-msgstr ""
+msgstr "ট্র্যাক পাথটি অবৈধ, সুতরাং কোনও পদ্ধতি key যুক্ত করতে পারে না।"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Add Method Track Key"
-msgstr "অ্যানিমেশনে (Anim) ট্র্যাক/পথ এবং চাবি যোগ করুন"
+msgstr "Method Track Key যুক্ত করুন"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Method not found in object: "
-msgstr "স্ক্রিপ্টে চলক-প্রাপক (VariableGet) পাওয়া যায়নি: "
+msgstr "Object এ Method পাওয়া যায় নি: "
#: editor/animation_track_editor.cpp
msgid "Anim Move Keys"
@@ -472,7 +467,6 @@ msgid "Clipboard is empty"
msgstr "ক্লীপবোর্ড খালি"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Paste Tracks"
msgstr "মানসমূহ প্রতিলেপন/পেস্ট করুন"
@@ -484,6 +478,7 @@ msgstr "অ্যানিমেশনের (Anim) চাবিসমূহে
msgid ""
"This option does not work for Bezier editing, as it's only a single track."
msgstr ""
+"এই বিকল্পটি বেজিয়ার সম্পাদনার জন্য কাজ করে না, কারণ এটি কেবলমাত্র Single ট্র্যাক।"
#: editor/animation_track_editor.cpp
msgid ""
@@ -497,24 +492,31 @@ msgid ""
"Alternatively, use an import preset that imports animations to separate "
"files."
msgstr ""
+"এই অ্যানিমেশনটি আমদানি করা দৃশ্যের সাথে সম্পর্কিত, তাই আমদানি করা ট্র্যাকগুলিতে "
+"পরিবর্তনগুলি সংরক্ষণ করা হবে না।\n"
+"\n"
+"কাস্টম ট্র্যাক যুক্ত করার ক্ষমতা সক্ষম করতে, দৃশ্যের আমদানি সেটিংসে নেভিগেট করুন এবং "
+"সেট করুন\n"
+"\"ফাইলগুলি\" এ \"অ্যানিমেশন> সঞ্চয়স্থান\", \"অ্যানিমেশন> কাস্টম ট্র্যাক রাখুন\" সক্ষম "
+"করুন, তারপরে পুনরায় আমদানি করুন।\n"
+"বিকল্পভাবে, একটি আমদানি প্রিসেট ব্যবহার করুন যা পৃথক ফাইলগুলিতে অ্যানিমেশনগুলি "
+"আমদানি করে।"
#: editor/animation_track_editor.cpp
msgid "Warning: Editing imported animation"
-msgstr ""
+msgstr "সতর্কতা: Imported অ্যানিমেশন সম্পাদনা করা হচ্ছে"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Select an AnimationPlayer node to create and edit animations."
-msgstr ""
-"অ্যানিমেশনসমূহ সম্পাদন করতে দৃশ্যের তালিকা থেকে একটি AnimationPlayer নির্বাচন করুন।"
+msgstr "অ্যানিমেশন তৈরি এবং সম্পাদনা করতে একটি অ্যানিমেশনপ্লেয়ার নোড নির্বাচন করুন।"
#: editor/animation_track_editor.cpp
msgid "Only show tracks from nodes selected in tree."
-msgstr ""
+msgstr "Tree মধ্যে নির্বাচিত নোডগুলি থেকে কেবল ট্র্যাকগুলি দেখান।"
#: editor/animation_track_editor.cpp
msgid "Group tracks by node or display them as plain list."
-msgstr ""
+msgstr "নোড দ্বারা গ্রুপ ট্র্যাক করুন বা তাদের সরল তালিকা হিসাবে প্রদর্শন করুন।"
#: editor/animation_track_editor.cpp
msgid "Snap:"
@@ -548,9 +550,8 @@ msgid "Animation properties."
msgstr "অ্যানিমেশন বৈশিষ্ট্য।"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Copy Tracks"
-msgstr "মানসমূহ প্রতিলিপি/কপি করুন"
+msgstr "ট্র্যাকগুলি অনুলিপি করুন"
#: editor/animation_track_editor.cpp
msgid "Scale Selection"
@@ -569,9 +570,8 @@ msgid "Duplicate Transposed"
msgstr "পক্ষান্তরিত (Transposed) সমূহ অনুলিপি করুন"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Delete Selection"
-msgstr "নির্বাচিত সমূহ অপসারণ করুন"
+msgstr "নির্বাচিত সমূহ Delete করুন"
#: editor/animation_track_editor.cpp
msgid "Go to Next Step"
@@ -595,7 +595,7 @@ msgstr ""
#: editor/animation_track_editor.cpp
msgid "Use Bezier Curves"
-msgstr ""
+msgstr "বেজিয়ার কার্ভ ব্যবহার করুন"
#: editor/animation_track_editor.cpp
msgid "Anim. Optimizer"
@@ -642,16 +642,15 @@ msgid "Scale Ratio:"
msgstr "স্কেল/মাপের অনুপাত:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Select Tracks to Copy"
-msgstr "গুণাগুণ/বৈশিষ্ট্য বাছাই করুন"
+msgstr "গুণাগুণ/বৈশিষ্ট্য copy করুন"
#: editor/animation_track_editor.cpp editor/editor_log.cpp
#: editor/editor_properties.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "প্রতিলিপি/কপি করুন"
@@ -1487,14 +1486,12 @@ msgstr ""
"পারবে না।"
#: editor/editor_autoload_settings.cpp
-#, fuzzy
msgid "Must not collide with an existing built-in type name."
msgstr ""
"অগ্রহনযোগ্য নাম। নামটি অবশ্যই বিদ্যমান পূর্বনির্মিত ধরণের নামের সাথে পরম্পরবিরোধী "
"হতে পারবে না।"
#: editor/editor_autoload_settings.cpp
-#, fuzzy
msgid "Must not collide with an existing global constant name."
msgstr ""
"অগ্রহনযোগ্য নাম। নামটি অবশ্যই বিদ্যমান সার্বজনীন ধ্রুবকের নামের সাথে পরম্পরবিরোধী "
@@ -1774,14 +1771,12 @@ msgid "Enabled Properties:"
msgstr "প্রোপার্টি-সমূহ:"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Enabled Features:"
-msgstr "গঠনবিন্যাস"
+msgstr "গঠনবিন্যাস :"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Enabled Classes:"
-msgstr "ক্লাসের অনুসন্ধান করুন"
+msgstr "Enabled ক্লাস:"
#: editor/editor_feature_profile.cpp
msgid "File '%s' format is invalid, import aborted."
@@ -1931,8 +1926,8 @@ msgid "Open a File or Directory"
msgstr "ফাইল বা পথ/ডিরেক্টরি খুলুন"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "সংরক্ষন করুন"
@@ -2646,7 +2641,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr "অ্যাড-অন প্লাগইন এনাবল করা সম্ভব হয় নি। কনফিগার পার্সিং ('%s') ব্যর্থ হয়েছে।"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"'res://addons/%s' লোকেশনে অ্যাড-অন প্লাগইনের স্ক্রিপ্ট ফাইল খুঁজে পাওয়া যায়নি।"
@@ -3110,14 +3106,6 @@ msgid "Help"
msgstr "হেল্প"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "অনুসন্ধান করুন"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
#, fuzzy
msgid "Online Docs"
@@ -3284,6 +3272,25 @@ msgstr "একটি স্ক্রিপ্ট খুলুন এবং চ
#: editor/editor_node.cpp
#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"নিম্নোক্ত ফাইলসমূহ ডিস্কে নতুনতর।\n"
+"কোন সিধান্তটি নেয়া উচিত হবে?:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "রিলোড"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "পুনঃসংরক্ষণ"
+
+#: editor/editor_node.cpp
+#, fuzzy
msgid "New Inherited"
msgstr "নতুন উত্তরাধিকারী দৃশ্য..."
@@ -3509,7 +3516,7 @@ msgstr "বোন্‌/হাড় তৈরি করুন"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "প্রতিলেপন/পেস্ট করুন"
@@ -4300,6 +4307,21 @@ msgstr ""
msgid "Saving..."
msgstr "সংরক্ষিত হচ্ছে..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "মোড (Mode) বাছাই করুন"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "ইম্পোর্ট"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "প্রাথমিক sRGB ব্যবহার করুন"
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -5344,7 +5366,8 @@ msgid "Got:"
msgstr "প্রাপ্ত:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "sha256 হ্যাশ চেক ব্যর্থ হয়েছে"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5460,7 +5483,6 @@ msgid "Sort:"
msgstr "সাজান:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "বিভাগ:"
@@ -7408,6 +7430,14 @@ msgstr "ডকুমেন্টসমূহ বন্ধ করুন"
msgid "Run"
msgstr "চালান"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "অনুসন্ধান করুন"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "পদার্পণ করুন"
@@ -7464,16 +7494,6 @@ msgstr ""
"নিম্নোক্ত ফাইলসমূহ ডিস্কে নতুনতর।\n"
"কোন সিধান্তটি নেয়া উচিত হবে?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "রিলোড"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "পুনঃসংরক্ষণ"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "ডিবাগার"
@@ -7576,8 +7596,8 @@ msgstr "বিন্দু অপসারণ করুন"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "কর্তন/কাট করুন"
@@ -7823,6 +7843,11 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "সেল (Cell)-এর আকার:"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "অবজেক্ট আঁকা হয়েছে"
@@ -10611,6 +10636,11 @@ msgid "Projects"
msgstr "নতুন প্রকল্প"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "মিরর রিট্রাইভ করা হচ্ছে, দযা করে অপেক্ষা করুন..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10997,6 +11027,11 @@ msgstr "স্বয়ংক্রিয়-লোড"
msgid "Plugins"
msgstr "প্লাগইন-সমূহ"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "লোড ডিফল্ট"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "প্রিসেট..."
@@ -11262,6 +11297,16 @@ msgstr "শীষ্য নোড ইন্সট্যান্স করুন
#: editor/scene_tree_dock.cpp
#, fuzzy
+msgid "Can't paste root node into the same scene."
+msgstr "বাহিরের দৃশ্যের নোডে এটি করা সম্ভব হবে না!"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "নোড-সমূহ প্রতিলেপন/পেস্ট করুন"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
msgid "Detach Script"
msgstr "স্ক্রিপ্ট সংযুক্ত করুন"
@@ -11393,6 +11438,11 @@ msgid "Attach Script"
msgstr "স্ক্রিপ্ট সংযুক্ত করুন"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "নোড-সমূহ কর্তন/কাট করুন"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "নোড(সমূহ) অপসারণ করুন"
@@ -13173,6 +13223,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "সংঘর্ষে ফাঁকা/শুন্য CollisionPolygon2D-এর কোনো প্রভাব নেই।"
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -13464,11 +13522,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -15409,9 +15462,6 @@ msgstr ""
#~ msgid "Use Default Light"
#~ msgstr "প্রাথমিক লাইট ব্যবহার করুন"
-#~ msgid "Use Default sRGB"
-#~ msgstr "প্রাথমিক sRGB ব্যবহার করুন"
-
#~ msgid "Default Light Normal:"
#~ msgstr "লাইটের প্রাথমিক নরমাল:"
diff --git a/editor/translations/br.po b/editor/translations/br.po
index a20210c2bc..7600dd4eb1 100644
--- a/editor/translations/br.po
+++ b/editor/translations/br.po
@@ -643,7 +643,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1812,8 +1812,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2447,7 +2447,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2837,14 +2837,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2998,6 +2990,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3200,7 +3208,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3881,6 +3889,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4828,7 +4848,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4932,7 +4952,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6699,6 +6718,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6750,16 +6777,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6852,8 +6869,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7074,6 +7091,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9594,6 +9615,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9954,6 +9979,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10197,6 +10226,14 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10317,6 +10354,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11891,6 +11932,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12146,11 +12195,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/ca.po b/editor/translations/ca.po
index ed171e7934..141f2cd58f 100644
--- a/editor/translations/ca.po
+++ b/editor/translations/ca.po
@@ -655,7 +655,7 @@ msgstr "Seleccioneu les Pistes a Copiar"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copiar"
@@ -1871,8 +1871,8 @@ msgid "Open a File or Directory"
msgstr "Obre un Fitxer o Directori"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Desa"
@@ -2547,7 +2547,8 @@ msgstr ""
"configuració."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"No s'ha pogut trobar el camp d'Script per al complement a: 'res: // addons /"
"%s'."
@@ -2987,14 +2988,6 @@ msgid "Help"
msgstr "Ajuda"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Cerca"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Documentació en línia"
@@ -3166,6 +3159,25 @@ msgid "Open & Run a Script"
msgstr "Obre i Executa un Script"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"El disc conté versions més recents dels fitxer següents. \n"
+"Quina acció voleu seguir?:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Torna a Carregar"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Torna a Desar"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Nou Heretat"
@@ -3379,7 +3391,7 @@ msgstr "Fes-lo Únic"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Enganxa"
@@ -4093,6 +4105,21 @@ msgstr ""
msgid "Saving..."
msgstr "Desant..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Mode de selecció"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importa"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Carrega Valors predeterminats"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Fitxers"
@@ -5075,7 +5102,8 @@ msgid "Got:"
msgstr "Rebut:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "Ha fallat la comprovació del hash sha256"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5184,7 +5212,6 @@ msgid "Sort:"
msgstr "Ordena:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Categoria:"
@@ -7071,6 +7098,14 @@ msgstr "Tanca la Documentació"
msgid "Run"
msgstr "Executar"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Cerca"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Pas a Pas (per instruccions)"
@@ -7124,16 +7159,6 @@ msgstr ""
"El disc conté versions més recents dels fitxer següents. \n"
"Quina acció voleu seguir?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Torna a Carregar"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Torna a Desar"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Depurador"
@@ -7232,8 +7257,8 @@ msgstr "Punts d’interrupció"
msgid "Go To"
msgstr "Anar a"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Talla"
@@ -7466,6 +7491,11 @@ msgid "Yaw"
msgstr "Guinyada"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "Mida: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Objectes Dibuixats"
@@ -10292,6 +10322,11 @@ msgstr "Projecte"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Loading, please wait..."
+msgstr "S'estan buscant rèpliques..."
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Last Modified"
msgstr "Última modificació"
@@ -10664,6 +10699,11 @@ msgstr "Càrrega Automàtica"
msgid "Plugins"
msgstr "Connectors"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Carrega Valors predeterminats"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Configuració..."
@@ -10925,6 +10965,16 @@ msgstr "Instancia una Escena Filla"
#: editor/scene_tree_dock.cpp
#, fuzzy
+msgid "Can't paste root node into the same scene."
+msgstr "No es pot operar en Nodes d'una escena externa!"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Enganxa els Nodes"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
msgid "Detach Script"
msgstr "Adjunta-li un Script"
@@ -11059,6 +11109,11 @@ msgid "Attach Script"
msgstr "Adjunta-li un Script"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Talla els Nodes"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Elimina els Nodes"
@@ -12791,6 +12846,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Un CollisionPolygon2D buit no té cap efecte en la col·lisió."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -13112,11 +13175,6 @@ msgstr ""
"Les GIProbes no estan suportades pel controlador de vídeo GLES2.\n"
"Utilitzeu un BakedLightmap en el seu lloc."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
#, fuzzy
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
diff --git a/editor/translations/cs.po b/editor/translations/cs.po
index b37b7d15cd..2c21fc0e63 100644
--- a/editor/translations/cs.po
+++ b/editor/translations/cs.po
@@ -11,12 +11,12 @@
# zxey <r.hozak@seznam.cz>, 2018.
# Vojtěch Šamla <auzkok@seznam.cz>, 2018, 2019, 2020, 2021.
# Peeter Angelo <contact@peeterangelo.com>, 2019.
-# VojtechBrezina <vojta.brezina@gmail.com>, 2019.
+# VojtechBrezina <vojta.brezina@gmail.com>, 2019, 2021.
# Garrom Orc Shaman <garromorcshaman@gmail.com>, 2019.
# David Husička <davidek251@seznam.cz>, 2019.
# Luboš Nečas <lubosnecas506@seznam.cz>, 2019.
# David Kubeš <kubesdavid@email.cz>, 2019.
-# Emil Jiří Tywoniak <emil.tywoniak@gmail.com>, 2020.
+# Emil Jiří Tywoniak <emil.tywoniak@gmail.com>, 2020, 2021.
# Filip Vincůrek <vincurek.f@gmail.com>, 2020.
# Ondrej Pavelka <ondrej.pavelka@outlook.com>, 2020.
# Zbyněk <zbynek.fiala@gmail.com>, 2020.
@@ -28,7 +28,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-22 10:21+0000\n"
+"PO-Revision-Date: 2021-03-08 15:33+0000\n"
"Last-Translator: Václav Blažej <vaclavblazej@seznam.cz>\n"
"Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot/"
"cs/>\n"
@@ -37,7 +37,7 @@ 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.5-dev\n"
+"X-Generator: Weblate 4.5.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -186,11 +186,11 @@ msgstr "Animace: Změna času klíčových snímků"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Transition"
-msgstr "Animace: změna přechodů"
+msgstr "Animace: Změna přechodů"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Transform"
-msgstr "Animace: změna transformací"
+msgstr "Animace: Změna transformací"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Value"
@@ -198,7 +198,7 @@ msgstr "Animace: Změnit hodnotu klíčových snímků"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Call"
-msgstr "Animace: změna volání"
+msgstr "Animace: Změna více volání"
#: editor/animation_track_editor.cpp
msgid "Change Animation Length"
@@ -292,7 +292,7 @@ msgstr "Čas (s): "
#: editor/animation_track_editor.cpp
msgid "Toggle Track Enabled"
-msgstr "Přepínací stopa povolena"
+msgstr "Povolit stopu"
#: editor/animation_track_editor.cpp
msgid "Continuous"
@@ -666,7 +666,7 @@ msgstr "Vybrat stopy ke kopírování"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopírovat"
@@ -676,7 +676,7 @@ msgstr "Vybrat vše/nic"
#: editor/animation_track_editor_plugins.cpp
msgid "Add Audio Track Clip"
-msgstr "Přidat klip audio stopy"
+msgstr "Přidat audio klip"
#: editor/animation_track_editor_plugins.cpp
msgid "Change Audio Track Clip Start Offset"
@@ -1299,7 +1299,7 @@ msgstr "Přepnout bypass efektů na zvukové sběrnice"
#: editor/editor_audio_buses.cpp
msgid "Select Audio Bus Send"
-msgstr "Vybrat přenos zvukové sběrnice"
+msgstr "Vybrat cíl zvukové sběrnice"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
@@ -1867,8 +1867,8 @@ msgid "Open a File or Directory"
msgstr "Otevřít soubor nebo složku"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Uložit"
@@ -2477,7 +2477,7 @@ msgid ""
"The current scene has unsaved changes.\n"
"Reload the saved scene anyway? This action cannot be undone."
msgstr ""
-"Tato scéna obsahuje neuložené změny.\n"
+"Aktuální scéna obsahuje neuložené změny.\n"
"Přesto znovu načíst? Tuto akci nelze vrátit zpět."
#: editor/editor_node.cpp
@@ -2538,9 +2538,8 @@ msgstr ""
"Nelze povolit rozšiřující plugin: '%s' parsování konfigurace se nezdařilo."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr ""
-"Nelze najít záznam skriptu pro rozšiřující plugin v: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "Nelze najít záznam skriptu pro rozšiřující plugin v: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2967,14 +2966,6 @@ msgid "Help"
msgstr "Nápověda"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Hledat"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Online dokumentace"
@@ -3139,6 +3130,24 @@ msgid "Open & Run a Script"
msgstr "Otevřít a spustit skript"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Následující soubory mají novější verzi na disku.\n"
+"Jaká akce se má vykonat?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Znovu načíst"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Znovu uložit"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Nové zděděné"
@@ -3349,7 +3358,7 @@ msgstr "Vytvořit unikátní"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Vložit"
@@ -4052,6 +4061,21 @@ msgstr "Vrátili jste objekt, který dědí z Node metodou `post_import()`?"
msgid "Saving..."
msgstr "Ukládání..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Režim výběru"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Import"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Načíst výchozí"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d souborů"
@@ -5014,8 +5038,8 @@ msgid "Got:"
msgstr "Staženo:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Neúspěšná kontrola sha256 hashe"
+msgid "Failed SHA-256 hash check"
+msgstr "Neúspěšná kontrola SHA-256 hashe"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5118,7 +5142,6 @@ msgid "Sort:"
msgstr "Řadit podle:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategorie:"
@@ -6289,9 +6312,8 @@ msgid "Can only set point into a ParticlesMaterial process material"
msgstr "Bod lze vložit pouze do process materiálu ParticlesMaterial"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Convert to CPUParticles2D"
-msgstr "Převést na CPUParticles"
+msgstr "Převést na CPUParticles2D"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
@@ -6941,6 +6963,14 @@ msgstr "Zavřít dokumentaci"
msgid "Run"
msgstr "Spustit"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Hledat"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Vstoupit do"
@@ -6994,16 +7024,6 @@ msgstr ""
"Následující soubory mají novější verzi na disku.\n"
"Jaká akce se má vykonat?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Znovu načíst"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Znovu uložit"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Ladicí program"
@@ -7096,8 +7116,8 @@ msgstr "Breakpointy"
msgid "Go To"
msgstr "Přejít na"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Vyjmout"
@@ -7320,6 +7340,11 @@ msgid "Yaw"
msgstr "Náklon"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "Velikost: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Objekty vykreslené"
@@ -9990,6 +10015,10 @@ msgid "Projects"
msgstr "Projekty"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Načítání, prosím čekejte..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Datum modifikace"
@@ -10360,6 +10389,11 @@ msgstr "Autoload"
msgid "Plugins"
msgstr "Pluginy"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Načíst výchozí"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Předvolba..."
@@ -10608,6 +10642,15 @@ msgid "Instance Child Scene"
msgstr "Přidat instanci scény"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Can't paste root node into the same scene."
+msgstr "Nelze manipulovat s uzly z cizí scény!"
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Vložit uzly"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Odpojit skript"
@@ -10734,6 +10777,10 @@ msgid "Attach Script"
msgstr "Připojit skript"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Vyjmout uzly"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Odstranit uzel/uzly"
@@ -11540,29 +11587,25 @@ msgstr "Přiřaďte uzlu GridMap zdroj MeshLibrary k použití jeho sítě."
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Begin Bake"
-msgstr ""
+msgstr "Začít zapečení"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Preparing data structures"
-msgstr ""
+msgstr "Připravování datových struktur"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Generate buffers"
-msgstr "Vygenerovat AABB"
+msgstr "Vygenerovat buffery"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Direct lighting"
-msgstr "Směry"
+msgstr "Přímé osvětlení"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Indirect lighting"
-msgstr "Odsadit zprava"
+msgstr "Nepřímé osvětlení"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Post processing"
msgstr "Následné zpracování"
@@ -12076,9 +12119,8 @@ msgid "Select device from the list"
msgstr "Vyberte zařízení ze seznamu"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Unable to find the 'apksigner' tool."
-msgstr "Nelze najít nástroj zipalign."
+msgstr "Nelze najít nástroj 'apksigner'."
#: platform/android/export/export.cpp
msgid ""
@@ -12100,14 +12142,12 @@ msgstr ""
"Úložiště klíčů pro vydání je nakonfigurováno nesprávně v profilu exportu."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "A valid Android SDK path is required in Editor Settings."
-msgstr "Nesprávná cesta Android SDK pro vlastní sestavení v Nastavení editoru."
+msgstr "Je vyžadována platná cesta Android SDK v Nastavení editoru."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Invalid Android SDK path in Editor Settings."
-msgstr "Nesprávná cesta Android SDK pro vlastní sestavení v Nastavení editoru."
+msgstr "Neplatná cesta k Android SDK v Nastavení editoru."
#: platform/android/export/export.cpp
msgid "Missing 'platform-tools' directory!"
@@ -12115,12 +12155,11 @@ msgstr "Chybí složka \"platform-tools\"!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK platform-tools' adb command."
-msgstr ""
+msgstr "Nelze najít příkaz adb z nástrojů platformy Android SDK."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Please check in the Android SDK directory specified in Editor Settings."
-msgstr "Nesprávná cesta Android SDK pro vlastní sestavení v Nastavení editoru."
+msgstr "Zkontrolujte ve složce Android SDK uvedené v Nastavení editoru."
#: platform/android/export/export.cpp
msgid "Missing 'build-tools' directory!"
@@ -12128,7 +12167,7 @@ msgstr "Chybí složka \"build-tools\"!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK build-tools' apksigner command."
-msgstr ""
+msgstr "Nelze najít apksigner, nástrojů Android SDK."
#: platform/android/export/export.cpp
msgid "Invalid public key for APK expansion."
@@ -12386,6 +12425,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Prázdný CollisionPolygon2D nemá při kolizi žádný efekt."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12589,27 +12636,23 @@ msgstr "ARVROrigin musí mít uzel ARVRCamera jako potomka."
#: scene/3d/baked_lightmap.cpp
msgid "Finding meshes and lights"
-msgstr ""
+msgstr "Hledat mřížky a světla"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing geometry (%d/%d)"
-msgstr "Parsuji geometrii..."
+msgstr "Připravuji geometrii (%d/%d)"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing environment"
-msgstr "Zobrazit prostředí"
+msgstr "Připravuji prostředí"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Generating capture"
-msgstr "Generování světelné mapy"
+msgstr "Generování snímání"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Saving lightmaps"
-msgstr "Generování světelné mapy"
+msgstr "Ukládám světelné mapy"
#: scene/3d/baked_lightmap.cpp
msgid "Done"
@@ -12699,11 +12742,6 @@ msgstr ""
"Video driver GLES2 nepodporuje GIProby.\n"
"Místo toho použijte BakedLightmap."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "Uzel InterpolatedCamera je zastaralý a bude odstraněn v Godot 4.0."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "SpotLight s úhlem širším než 90 stupňů nemůže vrhat stíny."
@@ -13041,6 +13079,10 @@ msgstr "Odlišnosti mohou být přiřazeny pouze ve vertex funkci."
msgid "Constants cannot be modified."
msgstr "Konstanty není možné upravovat."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr "Uzel InterpolatedCamera je zastaralý a bude odstraněn v Godot 4.0."
+
#~ msgid "No"
#~ msgstr "Ne"
diff --git a/editor/translations/da.po b/editor/translations/da.po
index 1a461ad0f4..72b2bf0e81 100644
--- a/editor/translations/da.po
+++ b/editor/translations/da.po
@@ -15,15 +15,15 @@
# Mads K. Bredager <mbredager@gmail.com>, 2019.
# Kristoffer Andersen <kjaa@google.com>, 2019.
# Joe Osborne <reachjoe.o@gmail.com>, 2020.
-# Autowinto <happymansi@hotmail.com>, 2020.
+# Autowinto <happymansi@hotmail.com>, 2020, 2021.
# Mikkel Mouridsen <mikkelmouridsen@me.com>, 2020, 2021.
# snakatk <snaqii@live.dk>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-26 16:32+0000\n"
-"Last-Translator: Mikkel Mouridsen <mikkelmouridsen@me.com>\n"
+"PO-Revision-Date: 2021-03-16 10:40+0000\n"
+"Last-Translator: snakatk <snaqii@live.dk>\n"
"Language-Team: Danish <https://hosted.weblate.org/projects/godot-engine/"
"godot/da/>\n"
"Language: da\n"
@@ -31,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.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -142,7 +142,7 @@ msgstr "Tilføj Bezier-punkt"
#: editor/animation_bezier_editor.cpp
msgid "Move Bezier Points"
-msgstr "Flyt punkt"
+msgstr "Flyt Bezier-punkter"
#: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp
msgid "Anim Duplicate Keys"
@@ -198,9 +198,8 @@ msgid "Anim Multi Change Call"
msgstr "Anim Skift Call"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Change Animation Length"
-msgstr "Ændre Animation Navn:"
+msgstr "Ændre Animationslængde"
#: editor/animation_track_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
@@ -681,7 +680,7 @@ msgstr "Vælg spor til kopiering:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopier"
@@ -1649,16 +1648,22 @@ msgid "Packing"
msgstr "Pakker"
#: editor/editor_export.cpp
+#, fuzzy
msgid ""
"Target platform requires 'ETC' texture compression for GLES2. Enable 'Import "
"Etc' in Project Settings."
msgstr ""
+"Målplatform kræver 'ETC' teksturkomprimering for GLES2. Aktivér 'Import Etc' "
+"i Projektindstillingerne."
#: editor/editor_export.cpp
+#, fuzzy
msgid ""
"Target platform requires 'ETC2' texture compression for GLES3. Enable "
"'Import Etc 2' in Project Settings."
msgstr ""
+"Målplatform kræver 'ETC2' teksturkomprimering for GLES3. Aktivér 'Import Etc "
+"2' i Projektindstillingerne."
#: editor/editor_export.cpp
msgid ""
@@ -1691,15 +1696,14 @@ msgstr ""
#: editor/editor_export.cpp platform/android/export/export.cpp
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
#: platform/osx/export/export.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Custom debug template not found."
-msgstr "Skabelonfil ikke fundet:"
+msgstr "Brugerdefineret debug skabelonfil ikke fundet:"
#: editor/editor_export.cpp platform/android/export/export.cpp
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
#: platform/osx/export/export.cpp platform/uwp/export/export.cpp
msgid "Custom release template not found."
-msgstr ""
+msgstr "Brugerdefineret release skabelonfil ikke fundet."
#: editor/editor_export.cpp platform/javascript/export/export.cpp
msgid "Template file not found:"
@@ -1744,13 +1748,12 @@ msgid "Import Dock"
msgstr "Importer"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Erase profile '%s'? (no undo)"
-msgstr "Erstat Alle"
+msgstr "Slet profil '%s'? (kan ikke fortrydes)"
#: editor/editor_feature_profile.cpp
msgid "Profile must be a valid filename and must not contain '.'"
-msgstr ""
+msgstr "Profil skal være et gyldigt filnavn og må ikke indeholde '.'"
#: editor/editor_feature_profile.cpp
#, fuzzy
@@ -1829,7 +1832,7 @@ msgstr "(Nuværende)"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/version_control_editor_plugin.cpp
msgid "New"
-msgstr ""
+msgstr "Ny"
#: editor/editor_feature_profile.cpp editor/editor_node.cpp
#: editor/project_manager.cpp
@@ -1939,8 +1942,8 @@ msgid "Open a File or Directory"
msgstr "Åben en Fil eller Mappe"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Gem"
@@ -2627,7 +2630,8 @@ msgstr ""
"mislykkedes."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr "Kan ikke finde scriptfelt for addon plugin på: 'res://addons/%s'."
#: editor/editor_node.cpp
@@ -3073,14 +3077,6 @@ msgid "Help"
msgstr "Hjælp"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Søg"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Online Dokumentation"
@@ -3241,6 +3237,23 @@ msgid "Open & Run a Script"
msgstr "Åben & Kør et Script"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr "De følgende filer kunne ikke trækkes ud af pakken:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Ny Arved"
@@ -3449,7 +3462,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Indsæt"
@@ -4190,6 +4203,21 @@ msgstr ""
msgid "Saving..."
msgstr "Gemmer..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Vælg Node"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importer"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Indlæs Default"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Filer"
@@ -5218,7 +5246,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5325,7 +5353,6 @@ msgid "Sort:"
msgstr "Sorter:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategori:"
@@ -7181,6 +7208,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Søg"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -7234,16 +7269,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7344,8 +7369,8 @@ msgstr "Slet points"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Cut"
@@ -7584,6 +7609,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -10250,6 +10279,11 @@ msgid "Projects"
msgstr "Projekt"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Henter spejle, vent venligst ..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10622,6 +10656,11 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Indlæs Default"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Forudindstillet..."
@@ -10877,6 +10916,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Indsæt Node"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Ryd Script"
@@ -11007,6 +11055,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Indsæt Node"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12700,6 +12753,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "En tom CollisionPolygon2D har ingen effekt på kollision."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12989,11 +13050,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13551,10 +13607,6 @@ msgstr "Konstanter kan ikke ændres."
#~ msgid "Create folder"
#~ msgstr "Opret mappe"
-#, fuzzy
-#~ msgid "Custom Node"
-#~ msgstr "Indsæt Node"
-
#~ msgid "Invalid Path"
#~ msgstr "Ugyldig sti"
diff --git a/editor/translations/de.po b/editor/translations/de.po
index d4f7db5298..ffd8a8874e 100644
--- a/editor/translations/de.po
+++ b/editor/translations/de.po
@@ -62,11 +62,16 @@
# Patric Wust <patric.wust@gmx.de>, 2020.
# Jonathan Hassel <jonathan.hassel@icloud.com>, 2020.
# Artur Schönfeld <schoenfeld.artur@ymail.com>, 2020.
+# kidinashell <kidinashell@protonmail.com>, 2021.
+# Daniel Glocker <mystboy666@gmail.com>, 2021.
+# Raphipod <podraphi@googlemail.com>, 2021.
+# Daniel Plaster <danimineiromc@googlemail.com>, 2021.
+# El Captian <elcaptian@posteo.me>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-16 01:28+0000\n"
+"PO-Revision-Date: 2021-03-09 04:13+0000\n"
"Last-Translator: So Wieso <sowieso@dukun.de>\n"
"Language-Team: German <https://hosted.weblate.org/projects/godot-engine/"
"godot/de/>\n"
@@ -75,7 +80,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.5-dev\n"
+"X-Generator: Weblate 4.5.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -707,7 +712,7 @@ msgstr "Zu kopierende Spuren auswählen"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopieren"
@@ -1920,8 +1925,8 @@ msgid "Open a File or Directory"
msgstr "Datei oder Verzeichnis öffnen"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Speichern"
@@ -2442,7 +2447,7 @@ msgid ""
"Please read the documentation relevant to debugging to better understand "
"this workflow."
msgstr ""
-"Dies ist ein nicht-lokales Objekt, Änderungen an ihm werden nicht "
+"Dies ist ein Laufzeit-Objekt Objekt, Änderungen an ihm werden nicht "
"gespeichert.\n"
"Die Dokumentation zum Debugging beschreibt den nötigen Arbeitsablauf."
@@ -2601,7 +2606,7 @@ msgstr ""
"fehlgeschlagen."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"Skript-Feld für Erweiterung in ‚res://addons/%s‘ konnte nicht gefunden "
"werden."
@@ -3042,14 +3047,6 @@ msgid "Help"
msgstr "Hilfe"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Suchen"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Internetdokumentation"
@@ -3068,7 +3065,7 @@ msgstr "Dokumentationsvorschläge senden"
#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
msgid "Community"
-msgstr "Community"
+msgstr "Gemeinschaft"
#: editor/editor_node.cpp
msgid "About"
@@ -3215,6 +3212,24 @@ msgid "Open & Run a Script"
msgstr "Skript öffnen und ausführen"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Die folgenden Dateien wurden im Dateisystem verändert.\n"
+"Wie soll weiter vorgegangen werden?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Neu laden"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Erneut speichern"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Neu Geerbte"
@@ -3426,7 +3441,7 @@ msgstr "Einzigartig machen"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Einfügen"
@@ -4132,6 +4147,18 @@ msgstr ""
msgid "Saving..."
msgstr "Speichere..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "Importer auswählen"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "Importer:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Auf Standardwerte zurücksetzen"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Dateien"
@@ -4895,7 +4922,7 @@ msgstr "Abspielmodus:"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "AnimationTree"
-msgstr "AnimationTree"
+msgstr "AnimationsBaum"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "New name:"
@@ -5102,8 +5129,8 @@ msgid "Got:"
msgstr "Erhalten:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Sha256-Prüfung fehlgeschlagen"
+msgid "Failed SHA-256 hash check"
+msgstr "Sha256 Checksummen prüfung fehlgeschlagen"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5206,7 +5233,6 @@ msgid "Sort:"
msgstr "Sortiere:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategorie:"
@@ -5261,7 +5287,7 @@ msgstr ""
msgid "Failed determining lightmap size. Maximum lightmap size too small?"
msgstr ""
"Die Größe des Lightmaps kann nicht bestimmt werden. Möglicherweise ist die "
-"maximale Lightmap-Größe zu klein."
+"maximale Lightmap-Größe zu klein?"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
@@ -7042,6 +7068,14 @@ msgstr "Dokumentation schließen"
msgid "Run"
msgstr "Ausführen"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Suchen"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Hineinspringen"
@@ -7095,16 +7129,6 @@ msgstr ""
"Die folgenden Dateien wurden im Dateisystem verändert.\n"
"Wie soll weiter vorgegangen werden?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Neu laden"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Erneut speichern"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Debugger"
@@ -7200,8 +7224,8 @@ msgstr "Haltepunkte"
msgid "Go To"
msgstr "Springe zu"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Ausschneiden"
@@ -7343,7 +7367,7 @@ msgstr "Knochen in Ruhe-Pose setzen"
#: editor/plugins/skeleton_2d_editor_plugin.cpp
msgid "Skeleton2D"
-msgstr "Skeleton2D"
+msgstr "Skelett2D"
#: editor/plugins/skeleton_2d_editor_plugin.cpp
msgid "Make Rest Pose (From Bones)"
@@ -7426,6 +7450,10 @@ msgid "Yaw"
msgstr "Gieren"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Größe"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Gezeichnete Objekte"
@@ -7447,7 +7475,7 @@ msgstr "Zeichenaufrufe"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Vertices"
-msgstr "Vertices"
+msgstr "Eckpunkte"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Top View."
@@ -8500,7 +8528,7 @@ msgstr "Keine Textur zum Entfernen ausgewählt."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create from scene? This will overwrite all current tiles."
-msgstr "Aus Szene erstellen? Alle aktuellen Kacheln werden überschrieben!"
+msgstr "Aus Szene erstellen? Alle aktuellen Kacheln werden überschrieben."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Merge from scene?"
@@ -9634,7 +9662,7 @@ msgstr ""
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "VisualShader"
-msgstr "VisualShader"
+msgstr "VisuellerShader"
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Edit Visual Property"
@@ -10123,6 +10151,10 @@ msgid "Projects"
msgstr "Projekte"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Projekte werden geladen, bitte warten..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Zuletzt bearbeitet"
@@ -10495,6 +10527,10 @@ msgstr "Autoload"
msgid "Plugins"
msgstr "Erweiterungen"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "Standardwerte importieren"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Voreinstellungen..."
@@ -10746,6 +10782,14 @@ msgid "Instance Child Scene"
msgstr "Szene hier instantiieren"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "Einfügen der Wurzelnode in dieselbe Szene nicht möglich."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Node(s) einfügen"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Skript loslösen"
@@ -10873,6 +10917,10 @@ msgid "Attach Script"
msgstr "Skript hinzufügen"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Node(s) trennen"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Entferne Node(s)"
@@ -11512,7 +11560,7 @@ msgstr "Bibliotheken: "
#: modules/gdnative/register_types.cpp
msgid "GDNative"
-msgstr "GDNative"
+msgstr "GDNativ"
#: modules/gdscript/gdscript_functions.cpp
msgid "Step argument is zero!"
@@ -12543,6 +12591,18 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Ein leeres CollisionPolygon2D hat keinen Effekt auf Kollisionen."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+"Ungültiges Polygon. Mindestens drei Punkte werden im ‚Festkörper‘-Baumodus "
+"benötigt."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+"Ungültiges Polygon. Mindestens zwei Punkte werden im ‚Segment‘-Baumodus "
+"benötigt."
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12872,11 +12932,6 @@ msgstr ""
"GIProbes werden vom GLES2-Videotreiber nicht unterstützt.\n"
"BakedLightmaps können als Alternative verwendet werden."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamera ist veraltet und wird in Godot 4.0 entfernt werden."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13235,6 +13290,11 @@ msgstr "Varyings können nur in Vertex-Funktion zugewiesen werden."
msgid "Constants cannot be modified."
msgstr "Konstanten können nicht verändert werden."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr ""
+#~ "InterpolatedCamera ist veraltet und wird in Godot 4.0 entfernt werden."
+
#~ msgid "No"
#~ msgstr "Nein"
@@ -15078,9 +15138,6 @@ msgstr "Konstanten können nicht verändert werden."
#~ msgid "Use Default Light"
#~ msgstr "Nutze Standardlicht"
-#~ msgid "Use Default sRGB"
-#~ msgstr "Nutze Standard-sRGB"
-
#~ msgid "Default Light Normal:"
#~ msgstr "Standardlichtnormale:"
diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot
index b9cf1e9087..d11d4f42ac 100644
--- a/editor/translations/editor.pot
+++ b/editor/translations/editor.pot
@@ -621,7 +621,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1790,8 +1790,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2425,7 +2425,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2815,14 +2815,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2976,6 +2968,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3178,7 +3186,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3859,6 +3867,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4806,7 +4826,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4910,7 +4930,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6677,6 +6696,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6728,16 +6755,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6830,8 +6847,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7052,6 +7069,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9572,6 +9593,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9932,6 +9957,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10175,6 +10204,14 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10295,6 +10332,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11869,6 +11910,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12124,11 +12173,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/el.po b/editor/translations/el.po
index fee8490872..8cd3397399 100644
--- a/editor/translations/el.po
+++ b/editor/translations/el.po
@@ -10,12 +10,13 @@
# pandektis <pandektis@gmail.com>, 2020.
# KostasMSC <kargyris@athtech.gr>, 2020.
# lawfulRobot <czavantias@gmail.com>, 2020.
+# Michalis <michalisntovas@yahoo.gr>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-09-30 12:32+0000\n"
-"Last-Translator: lawfulRobot <czavantias@gmail.com>\n"
+"PO-Revision-Date: 2021-03-03 15:50+0000\n"
+"Last-Translator: Michalis <michalisntovas@yahoo.gr>\n"
"Language-Team: Greek <https://hosted.weblate.org/projects/godot-engine/godot/"
"el/>\n"
"Language: el\n"
@@ -23,7 +24,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.3-dev\n"
+"X-Generator: Weblate 4.5.1-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -656,7 +657,7 @@ msgstr "Επιλογή Κομματιών για Αντιγραφή"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Αντιγραφή"
@@ -1866,8 +1867,8 @@ msgid "Open a File or Directory"
msgstr "Άνοιγμα αρχείου ή φακέλου"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Αποθήκευση"
@@ -1878,7 +1879,7 @@ msgstr "Αποθήκευση αρχείου"
#: editor/editor_file_dialog.cpp
msgid "Go Back"
-msgstr "Πήγαινε πίσω"
+msgstr "Επιστροφή"
#: editor/editor_file_dialog.cpp
msgid "Go Forward"
@@ -2542,7 +2543,8 @@ msgstr ""
"αρχείου ρύθμισης."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"Αδύνατη η έυρεση του πεδίου 'script' για την πρόσθετη επέκταση στο: 'res://"
"addons/%s'."
@@ -2983,14 +2985,6 @@ msgid "Help"
msgstr "Βοήθεια"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Αναζήτηση"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Ηλεκτρονική τεκμηρίωση"
@@ -3158,6 +3152,25 @@ msgid "Open & Run a Script"
msgstr "Άνοιξε & Τρέξε μία δέσμη ενεργειών"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Τα ακόλουθα αρχεία είναι νεότερα στον δίσκο.\n"
+"Τι δράση να ληφθεί;:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Επαναφόρτωση"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Επαναποθήκευση"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Νέα κληρονομημένη"
@@ -3368,7 +3381,7 @@ msgstr "Κάνε μοναδικό"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Επικόλληση"
@@ -3905,7 +3918,7 @@ msgstr "Αντικατάσταση..."
#: editor/find_in_files.cpp editor/progress_dialog.cpp scene/gui/dialogs.cpp
msgid "Cancel"
-msgstr "Ακύρωση"
+msgstr "Άκυρο"
#: editor/find_in_files.cpp
msgid "Find: "
@@ -4075,6 +4088,21 @@ msgstr ""
msgid "Saving..."
msgstr "Αποθήκευση..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Επιλογή Λειτουργίας"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Εισαγωγή"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Χρήση προεπιλεγμένου sRGB"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d αρχεία"
@@ -5045,7 +5073,8 @@ msgid "Got:"
msgstr "Δοσμένο:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "Η δοκιμή κατακερματισμού sha256 απέτυχε"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5149,7 +5178,6 @@ msgid "Sort:"
msgstr "Ταξινόμηση:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Κατηγορία:"
@@ -7000,6 +7028,14 @@ msgstr "Κλείσιμο Τεκμηρίωσης"
msgid "Run"
msgstr "Εκτέλεση"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Αναζήτηση"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Βήμα μέσα"
@@ -7015,7 +7051,7 @@ msgstr "Διακοπή"
#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_editor_debugger.cpp
msgid "Continue"
-msgstr "Συνέχιση"
+msgstr "Συνέχεια"
#: editor/plugins/script_editor_plugin.cpp
msgid "Keep Debugger Open"
@@ -7053,16 +7089,6 @@ msgstr ""
"Τα ακόλουθα αρχεία είναι νεότερα στον δίσκο.\n"
"Τι δράση να ληφθεί;:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Επαναφόρτωση"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Επαναποθήκευση"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Αποσφαλματωτής"
@@ -7159,8 +7185,8 @@ msgstr "Σημεία Διακοπής"
msgid "Go To"
msgstr "Πήγαινε Σε"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Αποκοπή"
@@ -7385,6 +7411,11 @@ msgid "Yaw"
msgstr "Παρέκκλιση"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "Μέγεθος: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Ζωγραφισμένα αντικείμενα"
@@ -8645,7 +8676,7 @@ msgstr "Κανένα αρχείο δεν προστέθηκε στο στάδι
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Commit"
-msgstr "Δέσμευση"
+msgstr "Υποβολή"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "VCS Addon is not initialized"
@@ -10081,6 +10112,11 @@ msgid "Projects"
msgstr "Έργα"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Ανάκτηση δεδοένων κατοπτρισμού, παρακαλώ περιμένετε..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Τελευταία Τροποποιημένα"
@@ -10451,6 +10487,11 @@ msgstr "Αυτόματη φόρτωση"
msgid "Plugins"
msgstr "Πρόσθετα"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Φόρτωση προεπιλογής"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Διαμόρφωση..."
@@ -10700,6 +10741,16 @@ msgid "Instance Child Scene"
msgstr "Αρχικοποίηση σκηνής ως παιδί"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Can't paste root node into the same scene."
+msgstr "Δεν είναι δυνατή η λειτουργία σε κόμβους από ξένη σκηνή!"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Επικόλληση κόμβων"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Αποσύνδεση Δέσμης Ενεργειών"
@@ -10832,6 +10883,11 @@ msgid "Attach Script"
msgstr "Σύνδεση Δέσμης Ενεργειών"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Αποκοπή κόμβων"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Αφαίρεση κόμβων"
@@ -12510,6 +12566,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Ένα άδειο ColisionPollygon2D δεν επηρεάζει τη σύγκρουση."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12837,11 +12901,6 @@ msgstr ""
"Τα GIProbes δεν υποστηρίζονται από το πρόγραμμα οδήγησης οθόνης GLES2.\n"
"Εναλλακτικά, χρησιμοποιήστε ένα BakedLightmap."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "Η InterpolatedCamera έχει καταργηθεί και θα αφαιρεθεί στο Godot 4.0."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13189,6 +13248,11 @@ msgstr "Τα «varying» μπορούν να ανατεθούν μόνο στη
msgid "Constants cannot be modified."
msgstr "Οι σταθερές δεν μπορούν να τροποποιηθούν."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr ""
+#~ "Η InterpolatedCamera έχει καταργηθεί και θα αφαιρεθεί στο Godot 4.0."
+
#~ msgid "No"
#~ msgstr "Όχι"
@@ -15017,9 +15081,6 @@ msgstr "Οι σταθερές δεν μπορούν να τροποποιηθο
#~ msgid "Use Default Light"
#~ msgstr "Χρήση προεπιλεγμέου φωτός"
-#~ msgid "Use Default sRGB"
-#~ msgstr "Χρήση προεπιλεγμένου sRGB"
-
#~ msgid "Default Light Normal:"
#~ msgstr "Προεπιλεγμένο διάνυσμα κανονικής ανάκλασης φωτός:"
diff --git a/editor/translations/eo.po b/editor/translations/eo.po
index bd5d35cf43..46e3a6b28d 100644
--- a/editor/translations/eo.po
+++ b/editor/translations/eo.po
@@ -10,18 +10,19 @@
# Sr Half <flavio05@outlook.com>, 2020.
# Cristian Yepez <cristianyepez@gmail.com>, 2020.
# BinotaLIU <me@binota.org>, 2020.
+# Jakub Fabijan <animatorzPolski@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2020-11-20 23:08+0000\n"
-"Last-Translator: BinotaLIU <me@binota.org>\n"
+"PO-Revision-Date: 2021-02-21 10:51+0000\n"
+"Last-Translator: Jakub Fabijan <animatorzPolski@gmail.com>\n"
"Language-Team: Esperanto <https://hosted.weblate.org/projects/godot-engine/"
"godot/eo/>\n"
"Language: eo\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.4-dev\n"
+"X-Generator: Weblate 4.5\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -646,14 +647,13 @@ msgstr "Elekti vojetojn por duplikati"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Duplikati"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Select All/None"
-msgstr "Elektaro nur"
+msgstr "Elekti Ĉiuj/Neniuj"
#: editor/animation_track_editor_plugins.cpp
msgid "Add Audio Track Clip"
@@ -1836,8 +1836,8 @@ msgid "Open a File or Directory"
msgstr "Malfermi dosieron aŭ dosierujon"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Konservi"
@@ -2491,7 +2491,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2911,14 +2911,6 @@ msgid "Help"
msgstr "Helpo"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Serĉo"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
#, fuzzy
msgid "Online Docs"
@@ -3075,6 +3067,22 @@ msgid "Open & Run a Script"
msgstr "Malfermi & ruli skripto"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3279,7 +3287,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3971,6 +3979,20 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Selektu nodo(j)n por enporti"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Enporti"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -4924,7 +4946,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5028,7 +5050,6 @@ msgid "Sort:"
msgstr "Ordigi:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6806,6 +6827,14 @@ msgstr ""
msgid "Run"
msgstr "Ruli"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Serĉo"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6858,16 +6887,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6960,8 +6979,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7183,6 +7202,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9727,6 +9750,10 @@ msgid "Projects"
msgstr "Projektoj"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
#, fuzzy
msgid "Last Modified"
msgstr "Modifita"
@@ -10088,6 +10115,11 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Enporti dokon"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10332,6 +10364,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Skali Elektaron"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Krei skripton"
@@ -10456,6 +10497,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12049,6 +12094,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12304,11 +12357,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/es.po b/editor/translations/es.po
index 0b354dbd08..4f8441fbfc 100644
--- a/editor/translations/es.po
+++ b/editor/translations/es.po
@@ -18,7 +18,7 @@
# Jose Maria Martinez <josemar1992@hotmail.com>, 2018.
# Juan Quiroga <juanquiroga9@gmail.com>, 2017.
# Kiji Pixel <raccoon.fella@gmail.com>, 2017.
-# Lisandro Lorea <lisandrolorea@gmail.com>, 2016-2017, 2019, 2020.
+# Lisandro Lorea <lisandrolorea@gmail.com>, 2016-2017, 2019, 2020, 2021.
# Lonsfor <lotharw@protonmail.com>, 2017-2018.
# Mario Nachbaur <manachbaur@gmail.com>, 2018.
# Oscar Carballal <oscar.carballal@protonmail.com>, 2017-2018.
@@ -58,11 +58,12 @@
# Ricardo Pérez <ricpelo@gmail.com>, 2021.
# A <kaieltroll@gmail.com>, 2021.
# Lucasdelpiero <lucasdelpiero98@gmail.com>, 2021.
+# SteamGoblin <SteamGoblin860@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-16 01:29+0000\n"
+"PO-Revision-Date: 2021-03-10 22:14+0000\n"
"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/"
"godot/es/>\n"
@@ -71,7 +72,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.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -577,7 +578,7 @@ msgstr "Agrupar las pistas por nodo o mostrarlas como una lista plana."
#: editor/animation_track_editor.cpp
msgid "Snap:"
-msgstr "Snap:"
+msgstr "Ajuste:"
#: editor/animation_track_editor.cpp
msgid "Animation step value."
@@ -707,7 +708,7 @@ msgstr "Selecciona las Pistas a Copiar"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copiar"
@@ -1641,7 +1642,7 @@ msgid ""
"Etc' in Project Settings."
msgstr ""
"La plataforma de destino requiere compresión de texturas 'ETC' para GLES2. "
-"Activa 'Import Etc' en Ajustes del Proyecto."
+"Activa 'Import Etc' en Configuración del Proyecto."
#: editor/editor_export.cpp
msgid ""
@@ -1649,7 +1650,7 @@ msgid ""
"'Import Etc 2' in Project Settings."
msgstr ""
"La plataforma de destino requiere compresión de texturas 'ETC2' para GLES3. "
-"Activa 'Import Etc 2' en Ajustes del Proyecto."
+"Activa 'Import Etc 2' en Configuración del Proyecto."
#: editor/editor_export.cpp
msgid ""
@@ -1660,8 +1661,8 @@ msgid ""
msgstr ""
"La plataforma de destino requiere compresión de texturas 'ETC' para usar "
"GLES2 como controlador de respaldo.\n"
-"Activa 'Import Etc' en Ajustes del Proyecto, o desactiva 'Driver Fallback "
-"Enabled'."
+"Activa 'Import Etc' en Configuración del Proyecto, o desactiva 'Driver "
+"Fallback Enabled'."
#: editor/editor_export.cpp
msgid ""
@@ -1669,7 +1670,7 @@ msgid ""
"'Import Pvrtc' in Project Settings."
msgstr ""
"La plataforma de destino requiere compresión de texturas 'PVRTC' para GLES2. "
-"Activa 'Import Pvrtc' en Ajustes del Proyecto."
+"Activa 'Import Pvrtc' en Configuración del Proyecto."
#: editor/editor_export.cpp
msgid ""
@@ -1677,7 +1678,8 @@ msgid ""
"Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings."
msgstr ""
"La plataforma de destino requiere compresión de texturas 'ETC2' o 'PVRTC' "
-"para GLES3. Activa 'Import Etc 2' o 'Import Pvrtc' en Ajustes del Proyecto."
+"para GLES3. Activa 'Import Etc 2' o 'Import Pvrtc' en Configuración del "
+"Proyecto."
#: editor/editor_export.cpp
msgid ""
@@ -1688,7 +1690,7 @@ msgid ""
msgstr ""
"La plataforma del objetivo requiere compresión de texturas 'PVRTC' para el "
"driver fallback de GLES2.\n"
-"Activa Import Pvrtc' en la Ajustes del Proyecto, o desactiva 'Driver "
+"Activa Import Pvrtc' en Configuración del Proyecto, o desactiva 'Driver "
"Fallback Enabled'."
#: editor/editor_export.cpp platform/android/export/export.cpp
@@ -1920,8 +1922,8 @@ msgid "Open a File or Directory"
msgstr "Abrir un archivo o directorio"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Guardar"
@@ -1992,7 +1994,7 @@ msgstr "Mostrar/Ocultar archivos ocultos."
#: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp
msgid "View items as a grid of thumbnails."
-msgstr "Ver ítems como un grid de miniaturas."
+msgstr "Ver ítems como una cuadrícula de miniaturas."
#: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp
msgid "View items as a list."
@@ -2599,10 +2601,8 @@ msgstr ""
"configuración de '%s'."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr ""
-"No se pudo encontrar el campo del script para el plugin addon en: 'res://"
-"addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "No se pudo encontrar el campo script para el plugin de addon en: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2662,8 +2662,8 @@ msgid ""
"category."
msgstr ""
"No se ha definido ninguna escena principal, ¿seleccionar una?\n"
-"Es posible cambiarla más tarde en \"Ajustes del Proyecto\" bajo la categoría "
-"'application'."
+"Es posible cambiarla más tarde en \"Configuración del Proyecto\" bajo la "
+"categoría 'application'."
#: editor/editor_node.cpp
msgid ""
@@ -2672,8 +2672,8 @@ msgid ""
"category."
msgstr ""
"La escena seleccionada '%s' no existe, ¿seleccionar una válida?\n"
-"Es posible cambiarla más tarde en \"Ajustes del Proyecto\" bajo la categoría "
-"'application'."
+"Es posible cambiarla más tarde en \"Configuración del Proyecto\" bajo la "
+"categoría 'application'."
#: editor/editor_node.cpp
msgid ""
@@ -2683,8 +2683,8 @@ msgid ""
msgstr ""
"La escena '%s' seleccionada no es un archivo de escena, ¿seleccionar uno "
"válido?\n"
-"Es posible cambiarla más tarde en \"Ajustes del Proyecto\" bajo la categoría "
-"'application'."
+"Es posible cambiarla más tarde en \"Configuración del Proyecto\" bajo la "
+"categoría 'application'."
#: editor/editor_node.cpp
msgid "Save Layout"
@@ -2845,7 +2845,7 @@ msgstr "Proyecto"
#: editor/editor_node.cpp
msgid "Project Settings..."
-msgstr "Ajustes del Proyecto..."
+msgstr "Configuración del Proyecto..."
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Version Control"
@@ -3039,14 +3039,6 @@ msgid "Help"
msgstr "Ayuda"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Buscar"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Documentación Online"
@@ -3214,6 +3206,24 @@ msgid "Open & Run a Script"
msgstr "Abrir y Ejecutar un Script"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Los siguientes archivos son nuevos en disco.\n"
+"¿Qué acción se debería tomar?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Recargar"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Volver a Guardar"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Nueva Escena Heredada"
@@ -3425,7 +3435,7 @@ msgstr "Hacer Único"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Pegar"
@@ -3956,7 +3966,7 @@ msgid ""
"ProjectSettings."
msgstr ""
"Incluye los archivos con las siguientes extensiones. Añádelos o elimínalos "
-"en Ajustes del proyecto."
+"en Configuración del Proyecto."
#: editor/find_in_files.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
@@ -4134,6 +4144,18 @@ msgstr "¿Devolviste un objeto derivado de Node en el método `post_import()`?"
msgid "Saving..."
msgstr "Guardando..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "Seleccionar Importador"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "Importador:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Restablecer Valores por Defecto"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d archivos"
@@ -4406,7 +4428,7 @@ msgstr "Seleccionar y mover puntos, crear puntos con clic derecho."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp scene/gui/graph_edit.cpp
msgid "Enable snap and show grid."
-msgstr "Activar snap y mostrar grid."
+msgstr "Activar ajuste y mostrar cuadrícula."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
@@ -5106,8 +5128,8 @@ msgid "Got:"
msgstr "Tiene:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Fallo en la comprobación del hash sha256"
+msgid "Failed SHA-256 hash check"
+msgstr "Fallo en la comprobación del hash SHA-256"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5210,7 +5232,6 @@ msgid "Sort:"
msgstr "Ordenar:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Categoría:"
@@ -5297,15 +5318,15 @@ msgstr "Vista Previa"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Configure Snap"
-msgstr "Configurar Snap"
+msgstr "Configurar Ajuste"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Grid Offset:"
-msgstr "Grid Offset:"
+msgstr "Desplazamiento de Cuadrícula:"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Grid Step:"
-msgstr "Grid Step:"
+msgstr "Paso de Cuadrícula:"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Primary Line Every:"
@@ -5469,11 +5490,11 @@ msgstr "Ancho Inferior"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "VCenter Wide"
-msgstr "Ancho Centro Vert."
+msgstr "Centro Vert. Ancho"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "HCenter Wide"
-msgstr "Ancho Centro Horiz."
+msgstr "Centro Horiz. Ancho"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Full Rect"
@@ -5633,48 +5654,48 @@ msgstr "Modo de Regla"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Toggle smart snapping."
-msgstr "Alternar acople inteligente."
+msgstr "Act./Desact. ajuste inteligente."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Smart Snap"
-msgstr "Usar Snap Inteligente"
+msgstr "Usar Ajuste Inteligente"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Toggle grid snapping."
-msgstr "Act./Desact. grid snapping."
+msgstr "Act./Desact. ajuste de cuadrícula."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Grid Snap"
-msgstr "Usar Grid Snap"
+msgstr "Usar Ajuste de Cuadrícula"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snapping Options"
-msgstr "Opciones de Snapping"
+msgstr "Opciones de Ajuste"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Rotation Snap"
-msgstr "Usar Snap de Rotación"
+msgstr "Usar Ajuste de Rotación"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Scale Snap"
-msgstr "Usar Snap de Escalado"
+msgstr "Usar Ajuste de Escalado"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap Relative"
-msgstr "Snap Relativo"
+msgstr "Ajuste Relativo"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Pixel Snap"
-msgstr "Usar Pixel Snap"
+msgstr "Usar Ajuste de Píxeles"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Smart Snapping"
-msgstr "Snapping Inteligente"
+msgstr "Ajuste Inteligente"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Configure Snap..."
-msgstr "Configurar Snap..."
+msgstr "Configurar Ajuste..."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap to Parent"
@@ -5743,7 +5764,7 @@ msgstr "Ver"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Always Show Grid"
-msgstr "Mostrar Siempre el Grid"
+msgstr "Mostrar Siempre la Cuadrícula"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Show Helpers"
@@ -5832,11 +5853,11 @@ msgstr "Limpiar Pose"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Multiply grid step by 2"
-msgstr "Multiplicar grid step por 2"
+msgstr "Multiplicar paso de cuadrícula por 2"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Divide grid step by 2"
-msgstr "Dividir grid step por 2"
+msgstr "Dividir paso de cuadrícula por 2"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Pan View"
@@ -6753,43 +6774,43 @@ msgstr "Limpiar UV"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Grid Settings"
-msgstr "Configuración del Grid"
+msgstr "Configuración de la Cuadrícula"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Snap"
-msgstr "Snap"
+msgstr "Ajuste"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Enable Snap"
-msgstr "Activar Snap"
+msgstr "Activar Ajuste"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Grid"
-msgstr "Grid"
+msgstr "Cuadrícula"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Show Grid"
-msgstr "Ver Grid"
+msgstr "Ver Cuadrícula"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Configure Grid:"
-msgstr "Configurar Grid:"
+msgstr "Configurar Cuadrícula:"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Grid Offset X:"
-msgstr "Grid Offset X:"
+msgstr "Desplazamiento de Cuadrícula en X:"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Grid Offset Y:"
-msgstr "Grid Offset Y:"
+msgstr "Desplazamiento de Cuadrícula en Y:"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Grid Step X:"
-msgstr "Grid Step X:"
+msgstr "Paso de Cuadrícula en X:"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Grid Step Y:"
-msgstr "Grid Step Y:"
+msgstr "Paso de Cuadrícula en Y:"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Sync Bones to Polygon"
@@ -7047,6 +7068,14 @@ msgstr "Cerrar Documentación"
msgid "Run"
msgstr "Ejecutar"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Buscar"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Entrar En"
@@ -7100,16 +7129,6 @@ msgstr ""
"Los siguientes archivos son nuevos en disco.\n"
"¿Qué es lo que quieres hacer?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Recargar"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Volver a Guardar"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Depurador"
@@ -7205,8 +7224,8 @@ msgstr "Breakpoints"
msgid "Go To"
msgstr "Ir A"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Cortar"
@@ -7426,7 +7445,11 @@ msgstr "Altura"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Yaw"
-msgstr "Yaw"
+msgstr "Guiñada"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Tamaño"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
@@ -7752,7 +7775,7 @@ msgstr "Ver Origen"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Grid"
-msgstr "Ver Grid"
+msgstr "Ver Cuadrícula"
#: editor/plugins/spatial_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
@@ -7761,19 +7784,19 @@ msgstr "Configuración..."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Snap Settings"
-msgstr "Ajustes de Snap"
+msgstr "Configuración de Ajuste"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Translate Snap:"
-msgstr "Snap de Traslación:"
+msgstr "Ajuste de Traslación:"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotate Snap (deg.):"
-msgstr "Snap de Rotación (grados):"
+msgstr "Ajuste de Rotación (grados):"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Scale Snap (%):"
-msgstr "Snap de Escala (%):"
+msgstr "Ajuste de Escala (%):"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Viewport Settings"
@@ -8042,7 +8065,7 @@ msgstr "Asignar Margen"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Snap Mode:"
-msgstr "Modo Snap:"
+msgstr "Modo de Ajuste:"
#: editor/plugins/texture_region_editor_plugin.cpp
#: scene/resources/visual_shader.cpp
@@ -8051,11 +8074,11 @@ msgstr "Ninguno"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Pixel Snap"
-msgstr "Pixel Snap"
+msgstr "Ajuste de Píxeles"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Grid Snap"
-msgstr "Grid Snap"
+msgstr "Ajuste de Cuadrícula"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Auto Slice"
@@ -8473,7 +8496,8 @@ msgstr "Mantener el polígono dentro del region Rect."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Enable snap and show grid (configurable via the Inspector)."
-msgstr "Activar snap y mostrar grid (configurable a través del Inspector)."
+msgstr ""
+"Activar ajuste y mostrar cuadrícula (configurable a través del Inspector)."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Display Tile Names (Hold Alt Key)"
@@ -9664,7 +9688,7 @@ msgid ""
msgstr ""
"No se pudo exportar el proyecto para la plataforma '%s'.\n"
"Esto puede ser debido a un problema de configuración en el preset de "
-"exportación o en los ajustes de exportación."
+"exportación o en la configuración de exportación."
#: editor/project_export.cpp
msgid "Release"
@@ -10054,8 +10078,8 @@ msgid ""
"the \"Application\" category."
msgstr ""
"No se puede ejecutar el proyecto: no hay una escena principal definida.\n"
-"Por favor, edita el proyecto y configura la escena principal en los Ajustes "
-"del proyecto, en la categoría \"Application\"."
+"Por favor, edita el proyecto y configura la escena principal en "
+"Configuración del Proyecto, en la categoría \"Application\"."
#: editor/project_manager.cpp
msgid ""
@@ -10121,6 +10145,10 @@ msgid "Projects"
msgstr "Proyectos"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Cargando, espera por favor..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Ultima Modificación"
@@ -10397,7 +10425,7 @@ msgstr "Cambiar Modo de Filtro Local"
#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
-msgstr "Ajustes del Proyecto (project.godot)"
+msgstr "Configuración del Proyecto (project.godot)"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
msgid "General"
@@ -10491,6 +10519,10 @@ msgstr "AutoLoad"
msgid "Plugins"
msgstr "Plugins"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "Valores de Importación por Defecto"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Preset..."
@@ -10741,6 +10773,14 @@ msgid "Instance Child Scene"
msgstr "Instanciar Escena Hija"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "No se puede pegar el nodo raíz en la misma escena."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Pegar Nodo(s)"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Sustraer Script"
@@ -10868,6 +10908,10 @@ msgid "Attach Script"
msgstr "Añadir Script"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Cortar Nodos(s)"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Eliminar Nodo(s)"
@@ -11576,7 +11620,7 @@ msgstr "Plano:"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "GridMap Delete Selection"
-msgstr "GridMap Eliminar Seleccionados"
+msgstr "Eliminar Selección de GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "GridMap Fill Selection"
@@ -11584,7 +11628,7 @@ msgstr "Rellenar Selección en GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "GridMap Paste Selection"
-msgstr "Pegar lo Seleccionado en GridMap"
+msgstr "Pegar Selección en GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "GridMap Paint"
@@ -11592,7 +11636,7 @@ msgstr "Pintar GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Grid Map"
-msgstr "Grid Map"
+msgstr "Mapeo de Cuadrícula"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
@@ -11729,7 +11773,7 @@ msgstr "Estableciendo la configuración..."
#: modules/recast/navigation_mesh_generator.cpp
msgid "Calculating grid size..."
-msgstr "Calculando tamaño de grid..."
+msgstr "Calculando tamaño la cuadrícula..."
#: modules/recast/navigation_mesh_generator.cpp
msgid "Creating heightfield..."
@@ -12554,6 +12598,18 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Un CollisionPolygon2D vacío no tiene ningún efecto en las colisiones."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+"Polígono inválido. Se necesitan al menos 3 puntos en modo de construcción "
+"'Solids'."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+"Polígono inválido. Se necesitan al menos 2 puntos en modo de construcción "
+"'Segments'."
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12767,7 +12823,7 @@ msgstr "ARVROrigin requiere un nodo hijo ARVRCamera."
#: scene/3d/baked_lightmap.cpp
msgid "Finding meshes and lights"
-msgstr "Encontrar mallas y luces"
+msgstr "Encontrando mallas y luces"
#: scene/3d/baked_lightmap.cpp
msgid "Preparing geometry (%d/%d)"
@@ -12874,11 +12930,6 @@ msgstr ""
"Las GIProbes no están soportadas por el controlador de vídeo GLES2.\n"
"Usa un BakedLightmap en su lugar."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamera ha sido desaprobado y será eliminado en Godot 4.0."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13170,7 +13221,7 @@ msgid ""
"Default Environment as specified in Project Settings (Rendering -> "
"Environment -> Default Environment) could not be loaded."
msgstr ""
-"El Entorno por Defecto como se especifica en los Ajustes del Proyecto "
+"El Entorno por Defecto como se especifica en Configuración del Proyecto "
"(Rendering -> Environment -> Default Environment) no se ha podido cargar."
#: scene/main/viewport.cpp
@@ -13228,6 +13279,11 @@ msgstr "Solo se pueden asignar variaciones en funciones de vértice."
msgid "Constants cannot be modified."
msgstr "Las constantes no pueden modificarse."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr ""
+#~ "InterpolatedCamera ha sido desaprobado y será eliminado en Godot 4.0."
+
#~ msgid "No"
#~ msgstr "No"
@@ -15112,9 +15168,6 @@ msgstr "Las constantes no pueden modificarse."
#~ msgid "Use Default Light"
#~ msgstr "Usar iluminación predeterminada"
-#~ msgid "Use Default sRGB"
-#~ msgstr "Usar sRGB predeterminado"
-
#~ msgid "Default Light Normal:"
#~ msgstr "Iluminación por normales predeterminada:"
diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po
index 4a3624c026..11e55b2dfa 100644
--- a/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
@@ -3,7 +3,7 @@
# Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
# This file is distributed under the same license as the Godot source code.
# Diego López <diegodario21@gmail.com>, 2017.
-# Lisandro Lorea <lisandrolorea@gmail.com>, 2016-2018, 2019, 2020.
+# Lisandro Lorea <lisandrolorea@gmail.com>, 2016-2018, 2019, 2020, 2021.
# Roger Blanco Ribera <roger.blancoribera@gmail.com>, 2016-2018.
# Sebastian Silva <sebastian@sugarlabs.org>, 2016.
# Jose Luis Bossio <joseluisbossio@gmail.com>, 2018.
@@ -21,7 +21,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-12-29 21:52+0000\n"
+"PO-Revision-Date: 2021-03-09 04:13+0000\n"
"Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n"
"Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/"
"godot-engine/godot/es_AR/>\n"
@@ -30,7 +30,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.4.1-dev\n"
+"X-Generator: Weblate 4.5.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -664,7 +664,7 @@ msgstr "Elegir Pistas a Copiar"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copiar"
@@ -1876,8 +1876,8 @@ msgid "Open a File or Directory"
msgstr "Abrir un Archivo o Directorio"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Guardar"
@@ -2408,7 +2408,7 @@ msgstr "No hay escena definida para ejecutar."
#: editor/editor_node.cpp
msgid "Save scene before running..."
-msgstr ""
+msgstr "Guardar escena antes de ejecutar..."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -2556,10 +2556,8 @@ msgstr ""
"configuración."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr ""
-"No se pudo encontrar el campo script para el plugin de addon en: 'res://"
-"addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "No se pudo encontrar el campo script para el plugin de addon en: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2994,14 +2992,6 @@ msgid "Help"
msgstr "Ayuda"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Buscar"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Documentación Online"
@@ -3169,6 +3159,24 @@ msgid "Open & Run a Script"
msgstr "Abrir y Correr un Script"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Los siguientes archivos son nuevos en disco.\n"
+"¿Qué acción se debería tomar?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Volver a Cargar"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Volver a Guardar"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Nuevo Heredado"
@@ -3379,7 +3387,7 @@ msgstr "Convertir en Unico"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Pegar"
@@ -4087,6 +4095,18 @@ msgstr "¿Devolviste un objeto derivado de Node en el método `post_import()`?"
msgid "Saving..."
msgstr "Guardando..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "Seleccionar Importador"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "Importador:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Restablecer Valores Por Defecto"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Archivos"
@@ -5060,8 +5080,8 @@ msgid "Got:"
msgstr "Recibido:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Fallo el chequeo del hash sha256"
+msgid "Failed SHA-256 hash check"
+msgstr "Fallo el chequeo del hash SHA-256"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5164,7 +5184,6 @@ msgid "Sort:"
msgstr "Ordenar:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Categoría:"
@@ -5193,14 +5212,13 @@ msgid "Assets ZIP File"
msgstr "Archivo ZIP de Assets"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid ""
"Can't determine a save path for lightmap images.\n"
"Save your scene and try again."
msgstr ""
-"No se pudo determinar una ruta de guardado para las imagenes de lightmap.\n"
-"Guardá tu escena (para imagenes a ser guardadas en el mismo directorio), o "
-"elegí una ruta de guardado desde las propiedades de BakedLightmap."
+"No se puede determinar una ruta de guardado para las imágenes de los "
+"lightmaps.\n"
+"Guardá tu escena e inténtalo de nuevo."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
@@ -5219,26 +5237,31 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Failed determining lightmap size. Maximum lightmap size too small?"
msgstr ""
+"Falló al determinar el tamaño del lightmap ¿El tamaño máximo de lightmap es "
+"demasiado pequeño?"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
"Some mesh is invalid. Make sure the UV2 channel values are contained within "
"the [0.0,1.0] square region."
msgstr ""
+"Alguna malla es inválida. Asegurate de que los valores del canal UV2 estén "
+"contenidos dentro de la región cuadrada [0,0,1,0]."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
+"El editor de Godot se compiló sin soporte de ray tracing, los lightmaps no "
+"pueden ser bakeados."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
msgstr "Bake Lightmaps"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid "Select lightmap bake file:"
-msgstr "Elegir Archivo de Plantilla"
+msgstr "Selecciona un archivo de lightmap bakeado:"
#: editor/plugins/camera_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -6336,9 +6359,8 @@ msgstr ""
"Solo se puede setear un punto en un material de proceso ParticlesMaterial"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Convert to CPUParticles2D"
-msgstr "Convertir A CPUParticles"
+msgstr "Convertir a CPUParticles2D"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
@@ -6992,6 +7014,14 @@ msgstr "Cerrar Docs"
msgid "Run"
msgstr "Ejecutar"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Buscar"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Step Into"
@@ -7045,16 +7075,6 @@ msgstr ""
"Los siguientes archivos son nuevos en disco.\n"
"¿Qué acción se debería tomar?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Volver a Cargar"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Volver a Guardar"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Depurador"
@@ -7150,8 +7170,8 @@ msgstr "Puntos de interrupción"
msgid "Go To"
msgstr "Ir A"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Cortar"
@@ -7374,6 +7394,10 @@ msgid "Yaw"
msgstr "Yaw"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Tamaño"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Objetos Dibujados"
@@ -10065,6 +10089,10 @@ msgid "Projects"
msgstr "Proyectos"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Cargando, esperá, por favor..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Ultima Modificación"
@@ -10435,6 +10463,10 @@ msgstr "AutoLoad"
msgid "Plugins"
msgstr "Plugins"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "Valores de Importacion Por Defecto"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Preseteo..."
@@ -10685,6 +10717,14 @@ msgid "Instance Child Scene"
msgstr "Instanciar Escena Hija"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "No se puede pegar el nodo raiz en la misma escena."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Pegar Nodo(s)"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Desasignar Script"
@@ -10813,6 +10853,10 @@ msgid "Attach Script"
msgstr "Adjuntar Script"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Cortar Nodo(s)"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Quitar Nodo(s)"
@@ -11624,36 +11668,31 @@ msgstr "Asignar un recurso MeshLibrary a este GridMap para usar sus meshes."
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Begin Bake"
-msgstr ""
+msgstr "Iniciar Bake"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Preparing data structures"
-msgstr ""
+msgstr "Preparando estructuras de datos"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Generate buffers"
-msgstr "Generar AABB"
+msgstr "Generar buffers"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Direct lighting"
-msgstr "Direcciones"
+msgstr "Iluminación directa"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Indirect lighting"
-msgstr "Indentar a la Der"
+msgstr "Iluminación indirecta"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Post processing"
-msgstr "Post-Procesado"
+msgstr "Post procesado"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Plotting lightmaps"
-msgstr "Trazando Luces:"
+msgstr "Trazando lightmatps"
#: modules/mono/csharp_script.cpp
msgid "Class name can't be a reserved keyword"
@@ -12173,7 +12212,7 @@ msgstr "Seleccionar dispositivo de la lista"
#: platform/android/export/export.cpp
msgid "Unable to find the 'apksigner' tool."
-msgstr ""
+msgstr "No se pudo encontrar la herramienta 'apksigner'."
#: platform/android/export/export.cpp
msgid ""
@@ -12195,18 +12234,13 @@ msgstr ""
"exportación."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "A valid Android SDK path is required in Editor Settings."
msgstr ""
-"Ruta del SDK de Android inválida para la compilación personalizada en "
-"Configuración del Editor."
+"Se requiere una ruta válida al SDK de Android en la Configuración del Editor."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Invalid Android SDK path in Editor Settings."
-msgstr ""
-"Ruta del SDK de Android inválida para la compilación personalizada en "
-"Configuración del Editor."
+msgstr "Ruta del SDK de Android inválida en la Configuración del Editor."
#: platform/android/export/export.cpp
msgid "Missing 'platform-tools' directory!"
@@ -12214,23 +12248,22 @@ msgstr "¡No se encontró el directorio 'platform-tools'!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK platform-tools' adb command."
-msgstr ""
+msgstr "No se pudo encontrar el comando adb en las Android SDK platform-tools."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Please check in the Android SDK directory specified in Editor Settings."
msgstr ""
-"Ruta del SDK de Android inválida para la compilación personalizada en "
+"Por favor, comprueba el directorio del SDK de Android especificado en la "
"Configuración del Editor."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Missing 'build-tools' directory!"
-msgstr "¡No se encontró el directorio 'platform-tools'!"
+msgstr "¡No se encontró el directorio 'build-tools'!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK build-tools' apksigner command."
msgstr ""
+"No se pudo encontrar el comando apksigner en las Android SDK build-tools."
#: platform/android/export/export.cpp
msgid "Invalid public key for APK expansion."
@@ -12500,6 +12533,18 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Un CollisionPolygon2D vacío no tiene efecto en la colisión."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+"Polígono inválido. Se necesitan al menos 3 puntos en modo de construcción "
+"\"Sólidos\"."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+"Polígono inválido. Se necesitan al menos 2 puntos en modo de construcción "
+"\"Segmentos\"."
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12713,27 +12758,23 @@ msgstr "ARVROrigin requiere un nodo hijo ARVRCamera."
#: scene/3d/baked_lightmap.cpp
msgid "Finding meshes and lights"
-msgstr ""
+msgstr "Encontrar mallas y luces"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing geometry (%d/%d)"
-msgstr "Parseando Geometría..."
+msgstr "Preparando geometría (%d/%d)"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing environment"
-msgstr "Ver Entorno"
+msgstr "Preparando entorno"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Generating capture"
-msgstr "Generando Lightmaps"
+msgstr "Generando capturas"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Saving lightmaps"
-msgstr "Generando Lightmaps"
+msgstr "Guardando lightmaps"
#: scene/3d/baked_lightmap.cpp
msgid "Done"
@@ -12824,11 +12865,6 @@ msgstr ""
"Las GIProbes no están soportadas por el controlador de video GLES2.\n"
"Usá un BakedLightmap en su lugar."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamera ha sido deprecado y será eliminado en Godot 4.0."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13142,6 +13178,8 @@ msgid ""
"The sampler port is connected but not used. Consider changing the source to "
"'SamplerPort'."
msgstr ""
+"El puerto de muestreo está conectado, pero no se utiliza. Considerá la "
+"posibilidad de cambiar la fuente a \"SamplerPort\"."
#: scene/resources/visual_shader_nodes.cpp
msgid "Invalid source for preview."
@@ -13171,6 +13209,10 @@ msgstr "Solo se pueden asignar variaciones en funciones de vértice."
msgid "Constants cannot be modified."
msgstr "Las constantes no pueden modificarse."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr "InterpolatedCamera ha sido deprecado y será eliminado en Godot 4.0."
+
#~ msgid "No"
#~ msgstr "No"
@@ -14839,9 +14881,6 @@ msgstr "Las constantes no pueden modificarse."
#~ msgid "Use Default Light"
#~ msgstr "Usar Luz por Defecto"
-#~ msgid "Use Default sRGB"
-#~ msgstr "Usar sRGB por Defecto"
-
#~ msgid "Default Light Normal:"
#~ msgstr "Normales de Luces por Defecto:"
diff --git a/editor/translations/et.po b/editor/translations/et.po
index a6576ad312..ba7272db84 100644
--- a/editor/translations/et.po
+++ b/editor/translations/et.po
@@ -10,7 +10,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2021-01-22 10:21+0000\n"
+"PO-Revision-Date: 2021-03-07 06:04+0000\n"
"Last-Translator: Kritzmensch <streef.gtx@gmail.com>\n"
"Language-Team: Estonian <https://hosted.weblate.org/projects/godot-engine/"
"godot/et/>\n"
@@ -18,7 +18,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.5-dev\n"
+"X-Generator: Weblate 4.5.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -635,7 +635,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopeeri"
@@ -697,7 +697,7 @@ msgstr ""
#: editor/code_editor.cpp
msgid "Replace"
-msgstr ""
+msgstr "Asenda"
#: editor/code_editor.cpp
msgid "Replace All"
@@ -814,7 +814,7 @@ msgstr ""
#: editor/connections_dialog.cpp
msgid "Oneshot"
-msgstr ""
+msgstr "Ainulaadne"
#: editor/connections_dialog.cpp
msgid "Disconnects the signal after its first emission."
@@ -840,7 +840,7 @@ msgstr "Sulge"
#: editor/connections_dialog.cpp
msgid "Connect"
-msgstr ""
+msgstr "Ühenda"
#: editor/connections_dialog.cpp
msgid "Signal:"
@@ -860,12 +860,12 @@ msgstr ""
#: editor/connections_dialog.cpp
msgid "Connect..."
-msgstr ""
+msgstr "Ühenda..."
#: editor/connections_dialog.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "Disconnect"
-msgstr ""
+msgstr "Katkesta ühendus"
#: editor/connections_dialog.cpp
msgid "Connect a Signal to a Method"
@@ -898,7 +898,7 @@ msgstr ""
#: editor/connections_dialog.cpp
msgid "Edit..."
-msgstr ""
+msgstr "Muuda..."
#: editor/connections_dialog.cpp
msgid "Go To Method"
@@ -910,7 +910,7 @@ msgstr ""
#: editor/create_dialog.cpp editor/project_settings_editor.cpp
msgid "Change"
-msgstr ""
+msgstr "Muuda"
#: editor/create_dialog.cpp
msgid "Create New %s"
@@ -968,20 +968,20 @@ msgstr ""
#: editor/dependency_editor.cpp
#: modules/gdnative/gdnative_library_editor_plugin.cpp
msgid "Dependencies"
-msgstr ""
+msgstr "Sõltuvused"
#: editor/dependency_editor.cpp
msgid "Resource"
-msgstr ""
+msgstr "Ressurss"
#: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp
#: editor/project_manager.cpp editor/project_settings_editor.cpp
msgid "Path"
-msgstr ""
+msgstr "Tee"
#: editor/dependency_editor.cpp
msgid "Dependencies:"
-msgstr ""
+msgstr "Sõltuvused:"
#: editor/dependency_editor.cpp
msgid "Fix Broken"
@@ -1213,7 +1213,7 @@ msgstr ""
#: editor/editor_asset_installer.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Success!"
-msgstr ""
+msgstr "Õnnestus!"
#: editor/editor_asset_installer.cpp
msgid "Package Contents:"
@@ -1221,7 +1221,7 @@ msgstr ""
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
-msgstr ""
+msgstr "Paigalda"
#: editor/editor_asset_installer.cpp
msgid "Package Installer"
@@ -1285,7 +1285,7 @@ msgstr "Vaigista"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "Jäta vahele"
#: editor/editor_audio_buses.cpp
msgid "Bus options"
@@ -1306,7 +1306,7 @@ msgstr ""
#: editor/editor_audio_buses.cpp
msgid "Audio"
-msgstr ""
+msgstr "Heli"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus"
@@ -1830,8 +1830,8 @@ msgid "Open a File or Directory"
msgstr "Ava kaust või kataloog"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Salvesta"
@@ -2171,7 +2171,7 @@ msgstr "Imporditud ressursse ei saa salvestada."
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: scene/gui/dialogs.cpp
msgid "OK"
-msgstr ""
+msgstr "Olgu"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
msgid "Error saving resource!"
@@ -2427,7 +2427,7 @@ msgstr "Välju"
#: editor/editor_node.cpp
msgid "Yes"
-msgstr ""
+msgstr "Jah"
#: editor/editor_node.cpp
msgid "Exit the editor?"
@@ -2472,8 +2472,9 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr ""
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "Lisa-skripti ei olnud võimalik laadida teelt: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2869,14 +2870,6 @@ msgid "Help"
msgstr "Abi"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Otsi"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Veebidokumentatsioonid"
@@ -3030,6 +3023,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3039,7 +3048,7 @@ msgstr "Laadimisvead"
#: editor/editor_node.cpp editor/plugins/tile_map_editor_plugin.cpp
msgid "Select"
-msgstr ""
+msgstr "Vali"
#: editor/editor_node.cpp
msgid "Open 2D Editor"
@@ -3079,7 +3088,7 @@ msgstr ""
#: editor/editor_plugin.cpp
msgid "Thumbnail..."
-msgstr ""
+msgstr "Pisipilt..."
#: editor/editor_plugin_settings.cpp
msgid "Main Script:"
@@ -3136,7 +3145,7 @@ msgstr ""
#: editor/editor_profiler.cpp
msgid "Inclusive"
-msgstr ""
+msgstr "Kaasav"
#: editor/editor_profiler.cpp
msgid "Self"
@@ -3160,11 +3169,11 @@ msgstr ""
#: editor/editor_properties.cpp editor/script_create_dialog.cpp
msgid "On"
-msgstr ""
+msgstr "Sees"
#: editor/editor_properties.cpp
msgid "Layer"
-msgstr ""
+msgstr "Kiht"
#: editor/editor_properties.cpp
msgid "Bit %d, value %d"
@@ -3172,11 +3181,11 @@ msgstr ""
#: editor/editor_properties.cpp
msgid "[Empty]"
-msgstr ""
+msgstr "[Tühi]"
#: editor/editor_properties.cpp editor/plugins/root_motion_editor_plugin.cpp
msgid "Assign..."
-msgstr ""
+msgstr "Määra..."
#: editor/editor_properties.cpp
msgid "Invalid RID"
@@ -3232,9 +3241,9 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
-msgstr ""
+msgstr "Kleebi"
#: editor/editor_properties.cpp editor/property_editor.cpp
msgid "Convert To %s"
@@ -3246,7 +3255,7 @@ msgstr ""
#: editor/editor_properties_array_dict.cpp
msgid "Size: "
-msgstr ""
+msgstr "Suurus: "
#: editor/editor_properties_array_dict.cpp
msgid "Page: "
@@ -3330,7 +3339,7 @@ msgstr ""
#: editor/export_template_manager.cpp
msgid "(Installed)"
-msgstr ""
+msgstr "(Paigaldatud)"
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -3343,11 +3352,11 @@ msgstr ""
#: editor/export_template_manager.cpp
msgid "(Missing)"
-msgstr ""
+msgstr "(Puudub)"
#: editor/export_template_manager.cpp
msgid "(Current)"
-msgstr ""
+msgstr "(Praegune)"
#: editor/export_template_manager.cpp
msgid "Retrieving mirrors, please wait..."
@@ -3468,7 +3477,7 @@ msgstr ""
#: editor/export_template_manager.cpp
msgid "Connected"
-msgstr ""
+msgstr "Ühendatud"
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -3529,7 +3538,7 @@ msgstr ""
#: editor/filesystem_dock.cpp
msgid "Favorites"
-msgstr ""
+msgstr "Lemmikud"
#: editor/filesystem_dock.cpp
msgid "Status: Import of file failed. Please fix file and reimport manually."
@@ -3913,6 +3922,21 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Valimisrežiim"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Impordi"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Laadi vaikimisi"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4860,7 +4884,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4953,7 +4977,7 @@ msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Import..."
-msgstr ""
+msgstr "Impordi..."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Plugins..."
@@ -4964,7 +4988,6 @@ msgid "Sort:"
msgstr "Sordi:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategooria:"
@@ -6731,6 +6754,14 @@ msgstr ""
msgid "Run"
msgstr "Käivita"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Otsi"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Trepi sissepoole"
@@ -6782,16 +6813,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Siluja"
@@ -6884,8 +6905,8 @@ msgstr "Katkepunktid"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7106,6 +7127,10 @@ msgid "Yaw"
msgstr "Sagitaal"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Objekte kuvatud"
@@ -9579,12 +9604,17 @@ msgid ""
"Please edit the project and set the main scene in the Project Settings under "
"the \"Application\" category."
msgstr ""
+"Projekti ei saa käivitada: peastseeni ei ole määratud.\n"
+"Redigeerige project.godot faili ja määrake projekti peastseen \"application"
+"\" alajaotuses."
#: editor/project_manager.cpp
msgid ""
"Can't run project: Assets need to be imported.\n"
"Please edit the project to trigger the initial import."
msgstr ""
+"Projekti ei saa käivitada: varad tuleb importida.\n"
+"Redigeerige projekti käivitama algset importimise protsessi."
#: editor/project_manager.cpp
msgid "Are you sure to run %d projects at once?"
@@ -9630,6 +9660,10 @@ msgid "Projects"
msgstr "Projektid"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9659,7 +9693,7 @@ msgstr ""
#: editor/project_manager.cpp
msgid "Can't run project"
-msgstr ""
+msgstr "Projekti ei saa käivitada"
#: editor/project_manager.cpp
msgid ""
@@ -9990,6 +10024,11 @@ msgstr ""
msgid "Plugins"
msgstr "Pistikprogrammid"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Laadi vaikimisi"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10233,6 +10272,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Kustuta sõlm(ed)"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10354,6 +10402,11 @@ msgid "Attach Script"
msgstr "Manusta skript"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Kustuta sõlm(ed)"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11311,7 +11364,7 @@ msgstr ""
#: modules/visual_script/visual_script_editor.cpp
msgid "Signals:"
-msgstr ""
+msgstr "Signaalid:"
#: modules/visual_script/visual_script_editor.cpp
msgid "Create a new signal."
@@ -11929,6 +11982,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12185,11 +12246,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -12387,7 +12443,7 @@ msgstr ""
#: scene/gui/dialogs.cpp
msgid "Alert!"
-msgstr ""
+msgstr "Tähelepanu!"
#: scene/gui/dialogs.cpp
msgid "Please Confirm..."
@@ -12421,7 +12477,7 @@ msgstr ""
#: scene/gui/tree.cpp
msgid "(Other)"
-msgstr ""
+msgstr "(Muu)"
#: scene/main/scene_tree.cpp
msgid ""
diff --git a/editor/translations/eu.po b/editor/translations/eu.po
index cb8cac87ea..95e87167e5 100644
--- a/editor/translations/eu.po
+++ b/editor/translations/eu.po
@@ -626,7 +626,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1804,8 +1804,8 @@ msgid "Open a File or Directory"
msgstr "Ireki fitxategia edo direktorioa"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Gorde"
@@ -2440,7 +2440,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2830,14 +2830,6 @@ msgid "Help"
msgstr "Laguntza"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Bilatu"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Lineako dokumentuak"
@@ -2991,6 +2983,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3193,7 +3201,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3878,6 +3886,20 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Hautatu inportatu nahi dituzun nodoak"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Inportatu azala"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d fitxategi"
@@ -4827,7 +4849,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4931,7 +4953,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6699,6 +6720,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Bilatu"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6750,16 +6779,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6852,8 +6871,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7074,6 +7093,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9598,6 +9621,13 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr ""
+"Fitxategiak arakatzen,\n"
+"Itxaron mesedez..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9960,6 +9990,11 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Inportatu profila(k)"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10204,6 +10239,14 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Scripta"
@@ -10325,6 +10368,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11901,6 +11948,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12156,11 +12211,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/fa.po b/editor/translations/fa.po
index 39983dc201..1ac27a6fd6 100644
--- a/editor/translations/fa.po
+++ b/editor/translations/fa.po
@@ -19,12 +19,13 @@
# MSKF <walkingdeadstudio@outlook.com>, 2020.
# Ahmad Maftoun <CarCedo.Pro@gmail.com>, 2020.
# ItzMiad44909858f5774b6d <maidggg@gmail.com>, 2020.
+# YASAN <yasandev@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-11-08 10:26+0000\n"
-"Last-Translator: MSKF <walkingdeadstudio@outlook.com>\n"
+"PO-Revision-Date: 2021-03-16 10:40+0000\n"
+"Last-Translator: YASAN <yasandev@gmail.com>\n"
"Language-Team: Persian <https://hosted.weblate.org/projects/godot-engine/"
"godot/fa/>\n"
"Language: fa\n"
@@ -32,16 +33,16 @@ 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.3.2\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
-msgstr "نوع ورودی برای ()convert نامعتبر است, ثوابت *_TYPE‌ بکار گیرید ."
+msgstr "نوع نامعتبر ورودی برای ()convert، ثوابت *_TYPE‌ را بکار گیرید."
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
msgid "Expected a string of length 1 (a character)."
-msgstr "یک رشته (string) در اندازه 1 (کاراکتر) انتظار می رود."
+msgstr "یک رشته به‌طول 1 ( یک کاراکتر) مورد انتظار است."
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/mono/glue/gd_glue.cpp
@@ -658,7 +659,7 @@ msgstr "انتخاب میسرها جهت تکثیر"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "کپی"
@@ -1040,11 +1041,10 @@ msgid "Owners Of:"
msgstr "مالکانِ:"
#: editor/dependency_editor.cpp
-#, fuzzy
msgid ""
"Remove selected files from the project? (no undo)\n"
"You can find the removed files in the system trash to restore them."
-msgstr "آیا پرونده‌های انتخاب شده از طرح حذف شوند؟ (نمی‌توان بازیابی کرد)"
+msgstr "آیا پرونده‌های انتخاب شده از طرح حذف شوند؟ (غیر قابل بازیابی)"
#: editor/dependency_editor.cpp
#, fuzzy
@@ -1846,8 +1846,8 @@ msgid "Open a File or Directory"
msgstr "یک پرونده یا پوشه را باز کن"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "ذخیره"
@@ -2481,8 +2481,9 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr ""
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "امکان بارگیری اسکریپت افزونه از مسیر وجود ندارد: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2879,14 +2880,6 @@ msgid "Help"
msgstr "راهنما"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "جستجو"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -3046,6 +3039,23 @@ msgid "Open & Run a Script"
msgstr "گشودن و اجرای یک اسکریپت"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr "استخراج پرونده های زیر از بسته بندی انجام نشد:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "وارث جدید"
@@ -3258,7 +3268,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "چسباندن"
@@ -3991,6 +4001,21 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "انتخاب حالت"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "وارد کردن"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "بارگیری پیش فرض"
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -5003,7 +5028,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5115,7 +5140,6 @@ msgid "Sort:"
msgstr "مرتب‌سازی:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "طبقه‌بندی:"
@@ -6974,6 +6998,14 @@ msgstr ""
msgid "Run"
msgstr "اجرا"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "جستجو"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -7028,16 +7060,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7138,8 +7160,8 @@ msgstr "حذف کن"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "برش"
@@ -7379,6 +7401,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -10059,6 +10085,11 @@ msgid "Projects"
msgstr "طرح ها"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "بارگیری"
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10437,6 +10468,11 @@ msgstr "AutoLoad"
msgid "Plugins"
msgstr "افزونه‌ها"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "بارگیری پیش فرض"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10695,6 +10731,15 @@ msgid "Instance Child Scene"
msgstr "ارث‌بری صحنهٔ فرزند"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "مسیر به سمت گره:"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "پیوست کردن اسکریپت"
@@ -10826,6 +10871,11 @@ msgid "Attach Script"
msgstr "پیوست کردن اسکریپت"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "ساختن گره"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "حذف گره(ها)"
@@ -12538,6 +12588,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "یک CollisionPolygon2D خالی جلوه بر برخورد ندارد."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12828,11 +12886,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13350,10 +13403,6 @@ msgstr "ثوابت قابل تغییر نیستند."
#~ msgstr "ساختن پوشه"
#, fuzzy
-#~ msgid "Custom Node"
-#~ msgstr "ساختن گره"
-
-#, fuzzy
#~ msgid "Invalid Path"
#~ msgstr "مسیر نامعتبر."
diff --git a/editor/translations/fi.po b/editor/translations/fi.po
index 941f970853..4d690bd29d 100644
--- a/editor/translations/fi.po
+++ b/editor/translations/fi.po
@@ -15,7 +15,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-21 11:57+0000\n"
+"PO-Revision-Date: 2021-03-10 22:14+0000\n"
"Last-Translator: Tapani Niemi <tapani.niemi@kapsi.fi>\n"
"Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/"
"godot/fi/>\n"
@@ -24,7 +24,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.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -648,7 +648,7 @@ msgstr "Valitse kopioitavat raidat"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopioi"
@@ -1857,8 +1857,8 @@ msgid "Open a File or Directory"
msgstr "Avaa tiedosto tai hakemisto"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Tallenna"
@@ -2530,8 +2530,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr "Lisäosan '%s' aktivointi epäonnistui, virheellinen asetustiedosto."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr "Skriptikenttää ei löytynyt lisäosan tiedostosta: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "Skriptikenttää ei löytynyt lisäosan tiedostosta: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2957,14 +2957,6 @@ msgid "Help"
msgstr "Ohje"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Hae"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Dokumentaatio"
@@ -3129,6 +3121,24 @@ msgid "Open & Run a Script"
msgstr "Avaa ja suorita skripti"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Seuraavat tiedostot ovat uudempia levyllä.\n"
+"Mikä toimenpide tulisi suorittaa?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Lataa uudelleen"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Tallenna uudelleen"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Uusi peritty skene"
@@ -3340,7 +3350,7 @@ msgstr "Tee yksilölliseksi"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Liitä"
@@ -4045,6 +4055,18 @@ msgstr ""
msgid "Saving..."
msgstr "Tallennetaan..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "Valitse tuoja"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "Tuoja:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Palauta oletusarvoihin"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d tiedostoa"
@@ -5014,8 +5036,8 @@ msgid "Got:"
msgstr "Saatiin:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "sha256-hajautusarvon tarkistus epäonnistui"
+msgid "Failed SHA-256 hash check"
+msgstr "SHA-256 hajautusarvon tarkistus epäonnistui"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5118,7 +5140,6 @@ msgid "Sort:"
msgstr "Lajittele:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategoria:"
@@ -6946,6 +6967,14 @@ msgstr "Sulje dokumentaatio"
msgid "Run"
msgstr "Suorita"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Hae"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Siirry sisään"
@@ -6999,16 +7028,6 @@ msgstr ""
"Seuraavat tiedostot ovat uudempia levyllä.\n"
"Mikä toimenpide tulisi suorittaa?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Lataa uudelleen"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Tallenna uudelleen"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Debuggeri"
@@ -7103,8 +7122,8 @@ msgstr "Keskeytyskohdat"
msgid "Go To"
msgstr "Mene"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Leikkaa"
@@ -7327,6 +7346,10 @@ msgid "Yaw"
msgstr "Käännös (yaw)"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Koko"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Objekteja piirretty"
@@ -10009,6 +10032,10 @@ msgid "Projects"
msgstr "Projektit"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Ladataan, hetkinen..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Viimeksi muutettu"
@@ -10378,6 +10405,10 @@ msgstr "Automaattilataus"
msgid "Plugins"
msgstr "Liitännäiset"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "Lataa oletusarvot"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Esiasetus..."
@@ -10627,6 +10658,14 @@ msgid "Instance Child Scene"
msgstr "Luo aliskenen ilmentymä"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "Juurisolmua ei voida liittää samaan skeneen."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Liitä solmu(t)"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Irrota skripti"
@@ -10756,6 +10795,10 @@ msgid "Attach Script"
msgstr "Liitä skripti"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Leikkaa solmu(t)"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Poista solmu(t)"
@@ -12416,6 +12459,18 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Tyhjällä CollisionPolygon2D solmulla ei ole vaikutusta törmäyksessä."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+"Virheellinen polygoni. 'Solids' luontitilassa tarvitaan ainakin kolme "
+"pistettä."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+"Virheellinen polygoni. 'Segments' luontitilassa tarvitaan ainakin kaksi "
+"pistettä."
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12734,11 +12789,6 @@ msgstr ""
"GIProbe ei ole tuettu GLES2 näyttöajurissa.\n"
"Käytä sen sijaan BakedLightmap resurssia."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamera on vanhentunut ja poistetaan Godot 4.0 versiossa."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13082,6 +13132,11 @@ msgstr "Varying tyypin voi sijoittaa vain vertex-funktiossa."
msgid "Constants cannot be modified."
msgstr "Vakioita ei voi muokata."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr ""
+#~ "InterpolatedCamera on vanhentunut ja poistetaan Godot 4.0 versiossa."
+
#~ msgid "No"
#~ msgstr "Ei"
diff --git a/editor/translations/fil.po b/editor/translations/fil.po
index 575e1370b3..e9c24cf0f2 100644
--- a/editor/translations/fil.po
+++ b/editor/translations/fil.po
@@ -634,7 +634,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopya"
@@ -1804,8 +1804,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2440,7 +2440,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2830,14 +2830,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2992,6 +2984,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3195,7 +3203,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3876,6 +3884,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4824,7 +4844,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4928,7 +4948,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6699,6 +6718,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6750,16 +6777,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6852,8 +6869,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7074,6 +7091,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9598,6 +9619,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9958,6 +9983,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10202,6 +10231,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Burahin ang (mga) Napiling Key"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10322,6 +10360,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11901,6 +11943,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12156,11 +12206,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/fr.po b/editor/translations/fr.po
index befd55180d..7b9d411e6d 100644
--- a/editor/translations/fr.po
+++ b/editor/translations/fr.po
@@ -728,7 +728,7 @@ msgstr "Sélectionner les pistes à copier"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copier"
@@ -1938,8 +1938,8 @@ msgid "Open a File or Directory"
msgstr "Ouvrir un fichier ou un répertoire"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Enregistrer"
@@ -2619,14 +2619,12 @@ msgstr "Réouvrir la scène fermée"
#: editor/editor_node.cpp
msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
-"Impossible d'activer le greffon depuis : « %s », l’analyse syntaxique de la "
+"Impossible d'activer le plugin depuis : « %s », l’analyse syntaxique de la "
"configuration a échoué."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr ""
-"Impossible de trouver le champ de script pour le plugin dans : « res://"
-"addons/%s »."
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "Impossible de trouver le champ de script pour le plugin dans : « %s »."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -3065,14 +3063,6 @@ msgid "Help"
msgstr "Aide"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Rechercher"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Documentation en ligne"
@@ -3239,6 +3229,24 @@ msgid "Open & Run a Script"
msgstr "Ouvrir et exécuter un script"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Les fichiers suivants sont plus récents sur le disque.\n"
+"Quelle action doit être prise ?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Recharger"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Ré-enregistrer"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Nouveau hérité"
@@ -3450,7 +3458,7 @@ msgstr "Rendre unique"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Coller"
@@ -4159,17 +4167,29 @@ msgstr ""
msgid "Saving..."
msgstr "Enregistrement…"
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "Sélectionnez un importeur"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "Importeur :"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Réinitialiser"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d fichiers"
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr "Définir comme défaut pour « %s »"
+msgstr "Définir comme préréglage pour « %s »"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr "Effacer le préréglage par défaut pour « %s »"
+msgstr "Effacer le préréglage pour « %s »"
#: editor/import_dock.cpp
msgid "Import As:"
@@ -4177,7 +4197,7 @@ msgstr "Importer comme :"
#: editor/import_dock.cpp
msgid "Preset"
-msgstr "Pré-réglage"
+msgstr "Préréglage"
#: editor/import_dock.cpp
msgid "Reimport"
@@ -4290,7 +4310,7 @@ msgstr "Modifier un plugin"
#: editor/plugin_config_dialog.cpp
msgid "Create a Plugin"
-msgstr "Créer un Plugin"
+msgstr "Créer un plugin"
#: editor/plugin_config_dialog.cpp
msgid "Plugin Name:"
@@ -5134,8 +5154,8 @@ msgid "Got:"
msgstr "A :"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Vérification de brouillage sha256 échouée"
+msgid "Failed SHA-256 hash check"
+msgstr "Vérification du hachage SHA-256 échouée"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5238,7 +5258,6 @@ msgid "Sort:"
msgstr "Trier :"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Catégorie :"
@@ -6021,7 +6040,7 @@ msgstr "Modifier la tangente de courbes"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Load Curve Preset"
-msgstr "Charger un pré-réglage de courbe"
+msgstr "Charger un préréglage de courbe"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Add Point"
@@ -7080,6 +7099,14 @@ msgstr "Fermer les documentations"
msgid "Run"
msgstr "Lancer"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Rechercher"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Rentrer"
@@ -7133,16 +7160,6 @@ msgstr ""
"Les fichiers suivants sont plus récents sur le disque.\n"
"Quelle action doit être prise ? :"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Recharger"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Ré-enregistrer"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Débogueur"
@@ -7239,8 +7256,8 @@ msgstr "Point d'arrêts"
msgid "Go To"
msgstr "Atteindre"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Couper"
@@ -7463,6 +7480,10 @@ msgid "Yaw"
msgstr "Lacet (hauteur)"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Taille"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Objets dessinés"
@@ -9689,7 +9710,7 @@ msgstr "Exécutable"
#: editor/project_export.cpp
msgid "Delete preset '%s'?"
-msgstr "Supprimer le pré-réglage « %s » ?"
+msgstr "Supprimer le préréglage « %s » ?"
#: editor/project_export.cpp
msgid ""
@@ -9727,7 +9748,7 @@ msgstr "Modèles d'exportation manquants ou corrompus pour cette plateforme :"
#: editor/project_export.cpp
msgid "Presets"
-msgstr "Pré-réglages"
+msgstr "Préréglages"
#: editor/project_export.cpp editor/project_settings_editor.cpp
msgid "Add..."
@@ -9738,9 +9759,9 @@ msgid ""
"If checked, the preset will be available for use in one-click deploy.\n"
"Only one preset per platform may be marked as runnable."
msgstr ""
-"Si cette option est activée, le pré-réglage sera disponible pour le "
+"Si cette option est activée, le préréglage sera disponible pour le "
"déploiement en un clic.\n"
-"Un seul pré-réglage par plateforme peut être marqué comme exécutable."
+"Un seul préréglage par plateforme peut être marqué comme exécutable."
#: editor/project_export.cpp
msgid "Export Path"
@@ -10166,6 +10187,10 @@ msgid "Projects"
msgstr "Projets"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Chargement en cours, veuillez patienter..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Dernière modification"
@@ -10536,9 +10561,13 @@ msgstr "AutoLoad"
msgid "Plugins"
msgstr "Extensions"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "Préréglage des importeurs"
+
#: editor/property_editor.cpp
msgid "Preset..."
-msgstr "Pré-réglage…"
+msgstr "Préréglage…"
#: editor/property_editor.cpp
msgid "Zero"
@@ -10785,6 +10814,14 @@ msgid "Instance Child Scene"
msgstr "Instancier une scène enfant"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "Impossible de copier le nœud racine dans la même scène."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Coller le(s) nœud(s)"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Détacher le script"
@@ -10911,6 +10948,10 @@ msgid "Attach Script"
msgstr "Attacher un script"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Couper le(s) nœud(s)"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Supprimer le(s) nœud(s)"
@@ -12604,6 +12645,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Un CollisionPolygon2D vide n'a pas d'effet sur les collisions."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12928,11 +12977,6 @@ msgstr ""
"Les GIProps ne sont pas supporter par le pilote de vidéos GLES2.\n"
"A la place utilisez une BakedLightMap."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamera a été déprécié et sera supprimé dans Godot 4.0."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13136,7 +13180,7 @@ msgid ""
msgstr ""
"Couleur : #%s\n"
"Clic gauche : Définir la couleur\n"
-"Clic droit : Supprimer le pré-réglage"
+"Clic droit : Supprimer le préréglage"
#: scene/gui/color_picker.cpp
msgid "Pick a color from the editor window."
@@ -13156,7 +13200,7 @@ msgstr "Alterner entre les valeurs hexadécimales ou brutes."
#: scene/gui/color_picker.cpp
msgid "Add current color as a preset."
-msgstr "Ajouter la couleur courante comme pré-réglage."
+msgstr "Ajouter la couleur courante comme préréglage."
#: scene/gui/container.cpp
msgid ""
@@ -13286,6 +13330,10 @@ msgstr "Les variations ne peuvent être affectées que dans la fonction vertex."
msgid "Constants cannot be modified."
msgstr "Les constantes ne peuvent être modifiées."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr "InterpolatedCamera a été déprécié et sera supprimé dans Godot 4.0."
+
#~ msgid "No"
#~ msgstr "Non"
diff --git a/editor/translations/ga.po b/editor/translations/ga.po
index 6036193c24..4e537d9882 100644
--- a/editor/translations/ga.po
+++ b/editor/translations/ga.po
@@ -627,7 +627,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1798,8 +1798,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2435,7 +2435,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2825,14 +2825,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2986,6 +2978,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3188,7 +3196,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3871,6 +3879,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -4821,7 +4841,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4925,7 +4945,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6693,6 +6712,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6744,16 +6771,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6846,8 +6863,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7068,6 +7085,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9593,6 +9614,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9953,6 +9978,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10196,6 +10225,14 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10316,6 +10353,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11897,6 +11938,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12152,11 +12201,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/gl.po b/editor/translations/gl.po
new file mode 100644
index 0000000000..5559444f0c
--- /dev/null
+++ b/editor/translations/gl.po
@@ -0,0 +1,12861 @@
+# Galician translation of the Godot Engine editor.
+# Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
+# Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
+# This file is distributed under the same license as the Godot source code.
+#
+# Andy Barcia <andybarcia4@gmail.com>, 2021.
+# PokeGalaico <abloodyfreaks@gmail.com>, 2021.
+msgid ""
+msgstr ""
+"Project-Id-Version: Godot Engine editor\n"
+"PO-Revision-Date: 2021-02-15 10:51+0000\n"
+"Last-Translator: Andy Barcia <andybarcia4@gmail.com>\n"
+"Language-Team: Galician <https://hosted.weblate.org/projects/godot-engine/"
+"godot/gl/>\n"
+"Language: gl\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.5-dev\n"
+
+#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
+#: modules/visual_script/visual_script_builtin_funcs.cpp
+msgid "Invalid type argument to convert(), use TYPE_* constants."
+msgstr "Tipo de argumento inválido para convert(), utiliza constantes TYPE_*."
+
+#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
+msgid "Expected a string of length 1 (a character)."
+msgstr "Esperábase un string de lonxitude 1 (un carácter)."
+
+#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
+#: 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 ""
+"Non hai insuficientes \"bytes\" para descodificar, ou o formato é inválido."
+
+#: core/math/expression.cpp
+msgid "Invalid input %i (not passed) in expression"
+msgstr "Entrada inválida %i (non recibida) na expresión"
+
+#: core/math/expression.cpp
+msgid "self can't be used because instance is null (not passed)"
+msgstr "Non se pode usar \"self\" porque a instancia é nula (non recibida)"
+
+#: core/math/expression.cpp
+msgid "Invalid operands to operator %s, %s and %s."
+msgstr "Operandos inválidos para o operador %s, %s e %s."
+
+#: core/math/expression.cpp
+msgid "Invalid index of type %s for base type %s"
+msgstr "Índice de tipo %s inválido para tipo base %s"
+
+#: core/math/expression.cpp
+msgid "Invalid named index '%s' for base type %s"
+msgstr "O índice do nome '%s' non é válido para o tipo de base %s"
+
+#: core/math/expression.cpp
+msgid "Invalid arguments to construct '%s'"
+msgstr "Argumentos inválidos para construir '%s'"
+
+#: core/math/expression.cpp
+msgid "On call to '%s':"
+msgstr "En chamada a '%s':"
+
+#: core/ustring.cpp
+msgid "B"
+msgstr "B"
+
+#: core/ustring.cpp
+msgid "KiB"
+msgstr "KiB"
+
+#: core/ustring.cpp
+msgid "MiB"
+msgstr "MiB"
+
+#: core/ustring.cpp
+msgid "GiB"
+msgstr "GiB"
+
+#: core/ustring.cpp
+msgid "TiB"
+msgstr "TiB"
+
+#: core/ustring.cpp
+msgid "PiB"
+msgstr "PiB"
+
+#: core/ustring.cpp
+msgid "EiB"
+msgstr "EiB"
+
+#: editor/animation_bezier_editor.cpp
+msgid "Free"
+msgstr "Libre"
+
+#: editor/animation_bezier_editor.cpp
+msgid "Balanced"
+msgstr "Balanceado"
+
+#: editor/animation_bezier_editor.cpp
+msgid "Mirror"
+msgstr "Espello"
+
+#: editor/animation_bezier_editor.cpp editor/editor_profiler.cpp
+msgid "Time:"
+msgstr "Tempo:"
+
+#: editor/animation_bezier_editor.cpp
+msgid "Value:"
+msgstr "Valor:"
+
+#: editor/animation_bezier_editor.cpp
+msgid "Insert Key Here"
+msgstr "Introducir Clave Aquí"
+
+#: editor/animation_bezier_editor.cpp
+msgid "Duplicate Selected Key(s)"
+msgstr "Duplicar Clave(s) Seleccionadas(s)"
+
+#: editor/animation_bezier_editor.cpp
+msgid "Delete Selected Key(s)"
+msgstr "Eliminar Clave(s) Seleccionada(s)"
+
+#: editor/animation_bezier_editor.cpp
+msgid "Add Bezier Point"
+msgstr "Engadir Punto Bezier"
+
+#: editor/animation_bezier_editor.cpp
+msgid "Move Bezier Points"
+msgstr "Mover Punto Bezier"
+
+#: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp
+msgid "Anim Duplicate Keys"
+msgstr "Duplicar Claves de Animación"
+
+#: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp
+msgid "Anim Delete Keys"
+msgstr "Eliminar Claves de Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Change Keyframe Time"
+msgstr "Cambiar Tempo do Fotograma Clave"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Change Transition"
+msgstr "Cambiar Transición de Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Change Transform"
+msgstr "Cambiar Transformación da Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Change Keyframe Value"
+msgstr "Cambiar Valor do Fotograma Clave da Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Change Call"
+msgstr "Cambiar Chamada da Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Multi Change Keyframe Time"
+msgstr "Cambiar Tempo de Múltiples Fotogramas Claves de Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Multi Change Transition"
+msgstr "Cambiar Múltiples Transicións da Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Multi Change Transform"
+msgstr "Cambiar Múltiples Transformacións da Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Multi Change Keyframe Value"
+msgstr "Cambiar Múltiples Valores do Fotograma Clave da Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Multi Change Call"
+msgstr "Cambiar Múltiples Chamadas da Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Change Animation Length"
+msgstr "Cambiar Lonxitude da Animación"
+
+#: editor/animation_track_editor.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Change Animation Loop"
+msgstr "Cambiar Ciclo da Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Property Track"
+msgstr "Pista de Propiedades"
+
+#: editor/animation_track_editor.cpp
+msgid "3D Transform Track"
+msgstr "Pista de Transformación 3D"
+
+#: editor/animation_track_editor.cpp
+msgid "Call Method Track"
+msgstr "Pista de Chamadas de Métodos"
+
+#: editor/animation_track_editor.cpp
+msgid "Bezier Curve Track"
+msgstr "Pista de Curva Bezier"
+
+#: editor/animation_track_editor.cpp
+msgid "Audio Playback Track"
+msgstr "Pista de Reprodución de Audio"
+
+#: editor/animation_track_editor.cpp
+msgid "Animation Playback Track"
+msgstr "Pista de Reprodución de Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Animation length (frames)"
+msgstr "Lonxitude da Animacion (en fotogramas)"
+
+#: editor/animation_track_editor.cpp
+msgid "Animation length (seconds)"
+msgstr "Lonxitude da Animación (en segundos)"
+
+#: editor/animation_track_editor.cpp
+msgid "Add Track"
+msgstr "Engadir Pista"
+
+#: editor/animation_track_editor.cpp
+msgid "Animation Looping"
+msgstr "Animación en Bucle"
+
+#: editor/animation_track_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Functions:"
+msgstr "Funciones:"
+
+#: editor/animation_track_editor.cpp
+msgid "Audio Clips:"
+msgstr "Clips de Audio:"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Clips:"
+msgstr "Clips de Animación:"
+
+#: editor/animation_track_editor.cpp
+msgid "Change Track Path"
+msgstr "Cambiar Ruta da Pista"
+
+#: editor/animation_track_editor.cpp
+msgid "Toggle this track on/off."
+msgstr "Act./Desact. esta pista."
+
+#: editor/animation_track_editor.cpp
+msgid "Update Mode (How this property is set)"
+msgstr "Modo de Actualización (cómo se establece esta propiedade)"
+
+#: editor/animation_track_editor.cpp
+msgid "Interpolation Mode"
+msgstr "Modo de Interpolación"
+
+#: editor/animation_track_editor.cpp
+msgid "Loop Wrap Mode (Interpolate end with beginning on loop)"
+msgstr "Modo de Bucle Envolvente (interpola o final co comezo do bucle)"
+
+#: editor/animation_track_editor.cpp
+msgid "Remove this track."
+msgstr "Eliminar esta pista."
+
+#: editor/animation_track_editor.cpp
+msgid "Time (s): "
+msgstr "Tempo (s): "
+
+#: editor/animation_track_editor.cpp
+msgid "Toggle Track Enabled"
+msgstr "Act./Desact. Pista"
+
+#: editor/animation_track_editor.cpp
+msgid "Continuous"
+msgstr "Continuo"
+
+#: editor/animation_track_editor.cpp
+msgid "Discrete"
+msgstr "Discreto"
+
+#: editor/animation_track_editor.cpp
+msgid "Trigger"
+msgstr "Detonante (Trigger)"
+
+#: editor/animation_track_editor.cpp
+msgid "Capture"
+msgstr "Captura"
+
+#: editor/animation_track_editor.cpp
+msgid "Nearest"
+msgstr "Máis Cercano"
+
+#: editor/animation_track_editor.cpp editor/plugins/curve_editor_plugin.cpp
+#: editor/property_editor.cpp
+msgid "Linear"
+msgstr "Lineal"
+
+#: editor/animation_track_editor.cpp
+msgid "Cubic"
+msgstr "Cúbica"
+
+#: editor/animation_track_editor.cpp
+msgid "Clamp Loop Interp"
+msgstr "Interpolación de Bucle Recortado"
+
+#: editor/animation_track_editor.cpp
+msgid "Wrap Loop Interp"
+msgstr "Interpolación de Bucle Envolvente"
+
+#: editor/animation_track_editor.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Insert Key"
+msgstr "Engadir Chave"
+
+#: editor/animation_track_editor.cpp
+msgid "Duplicate Key(s)"
+msgstr "Duplicar Chave(s)"
+
+#: editor/animation_track_editor.cpp
+msgid "Delete Key(s)"
+msgstr "Eliminar Chave(s)"
+
+#: editor/animation_track_editor.cpp
+msgid "Change Animation Update Mode"
+msgstr "Cambiar Modo de Actualización da Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Change Animation Interpolation Mode"
+msgstr "Cambiar Modo de Interpolación da Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Change Animation Loop Mode"
+msgstr "Cambiar Modo de Bucle da Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Remove Anim Track"
+msgstr "Eliminar Pista de Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Create NEW track for %s and insert key?"
+msgstr "Crear nova pista para %s e engadir chave?"
+
+#: editor/animation_track_editor.cpp
+msgid "Create %d NEW tracks and insert keys?"
+msgstr "Crear %d novas pistas e engadir chaves?"
+
+#: editor/animation_track_editor.cpp editor/create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/editor_feature_profile.cpp
+#: editor/editor_plugin_settings.cpp editor/plugin_config_dialog.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+#: editor/plugins/particles_editor_plugin.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp
+#: editor/script_create_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Create"
+msgstr "Crear"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Insert"
+msgstr "Engadir Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "AnimationPlayer can't animate itself, only other players."
+msgstr "Un AnimationPlayer non pode animarse a si mesmo, só a outros players."
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Create & Insert"
+msgstr "Crear e Engadir Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Insert Track & Key"
+msgstr "Engadir Pista e Chave de Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Insert Key"
+msgstr "Engadir Chave de Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Change Animation Step"
+msgstr "Cambiar Paso de Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Rearrange Tracks"
+msgstr "Reordenar Pistas"
+
+#: editor/animation_track_editor.cpp
+msgid "Transform tracks only apply to Spatial-based nodes."
+msgstr "As pistas de transformación só aplícanse a nodos basados en Spatial."
+
+#: editor/animation_track_editor.cpp
+msgid ""
+"Audio tracks can only point to nodes of type:\n"
+"-AudioStreamPlayer\n"
+"-AudioStreamPlayer2D\n"
+"-AudioStreamPlayer3D"
+msgstr ""
+"As pistas de audio só poden apuntar a nodos de tipo:\n"
+"-AudioStreamPlayer\n"
+"-AudioStreamPlayer2D\n"
+"-AudioStreamPlayer3D"
+
+#: editor/animation_track_editor.cpp
+msgid "Animation tracks can only point to AnimationPlayer nodes."
+msgstr "As pistas de animación só poden apuntar a nodos AnimationPlayer."
+
+#: editor/animation_track_editor.cpp
+msgid "An animation player can't animate itself, only other players."
+msgstr ""
+"Un reproductor de animacións non pode animarse a si mesmo, só a outros "
+"reproductores."
+
+#: editor/animation_track_editor.cpp
+msgid "Not possible to add a new track without a root"
+msgstr "Non é posible engadir unha nova pista sen unha raíz"
+
+#: editor/animation_track_editor.cpp
+msgid "Invalid track for Bezier (no suitable sub-properties)"
+msgstr "Pista inválida para Bezier (non hai sub-propiedades axeitadas)"
+
+#: editor/animation_track_editor.cpp
+msgid "Add Bezier Track"
+msgstr "Engadir Pista Bezier"
+
+#: editor/animation_track_editor.cpp
+msgid "Track path is invalid, so can't add a key."
+msgstr "A ruta á pista é inválida, polo que non se poden engadir chaves."
+
+#: editor/animation_track_editor.cpp
+msgid "Track is not of type Spatial, can't insert key"
+msgstr "A pista non é de tipo Spatial, e non se pode engadir chave"
+
+#: editor/animation_track_editor.cpp
+msgid "Add Transform Track Key"
+msgstr "Engadir Chave de Pista de Transformación"
+
+#: editor/animation_track_editor.cpp
+msgid "Add Track Key"
+msgstr "Engadir Chave de Pista"
+
+#: editor/animation_track_editor.cpp
+msgid "Track path is invalid, so can't add a method key."
+msgstr ""
+"A ruta á pista é inválida, polo que non se pode engadir unha clave de método."
+
+#: editor/animation_track_editor.cpp
+msgid "Add Method Track Key"
+msgstr "Engadir Chave de Pista de Método"
+
+#: editor/animation_track_editor.cpp
+msgid "Method not found in object: "
+msgstr "Método non encontrado no obxecto: "
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Move Keys"
+msgstr "Mover Claves de Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Clipboard is empty"
+msgstr "O portapapeis está baleiro"
+
+#: editor/animation_track_editor.cpp
+msgid "Paste Tracks"
+msgstr "Pegar Pistas"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim Scale Keys"
+msgstr "Escalar Chaves de Animación"
+
+#: editor/animation_track_editor.cpp
+msgid ""
+"This option does not work for Bezier editing, as it's only a single track."
+msgstr ""
+"Esta opción non funciona con edición Bezier, xa que é unha única pista."
+
+#: editor/animation_track_editor.cpp
+msgid ""
+"This animation belongs to an imported scene, so changes to imported tracks "
+"will not be saved.\n"
+"\n"
+"To enable the ability to add custom tracks, navigate to the scene's import "
+"settings and set\n"
+"\"Animation > Storage\" to \"Files\", enable \"Animation > Keep Custom Tracks"
+"\", then re-import.\n"
+"Alternatively, use an import preset that imports animations to separate "
+"files."
+msgstr ""
+"Esta animación pertence a unha escena importada, polo que os cambios nas "
+"pistas importadas non quedaran gardados.\n"
+"\n"
+"Para habilitar a capacidade de engadir pistas personalizadas, vai á "
+"configuración de importación da escena e establece\n"
+"\"Animación > Almacenamento\" a \"Arquivos\", activa \"Animación > Manter "
+"Pistas Personalizadas\", e logo reimportaa.\n"
+"Tamén poder usar un preset de importación que importa animacións para "
+"separar arquivos."
+
+#: editor/animation_track_editor.cpp
+msgid "Warning: Editing imported animation"
+msgstr "Advertencia: Estase editando unha animación importada"
+
+#: editor/animation_track_editor.cpp
+msgid "Select an AnimationPlayer node to create and edit animations."
+msgstr "Selecciona un nodo AnimationPlayer para crear e editar animacións."
+
+#: editor/animation_track_editor.cpp
+msgid "Only show tracks from nodes selected in tree."
+msgstr "Só mostrar pistas de nodos seleccionados na árbore."
+
+#: editor/animation_track_editor.cpp
+msgid "Group tracks by node or display them as plain list."
+msgstr "Agrupar pistas por nodo ou mostralas coma unha simple lista."
+
+#: editor/animation_track_editor.cpp
+msgid "Snap:"
+msgstr "Axuste de Cuadrícula:"
+
+#: editor/animation_track_editor.cpp
+msgid "Animation step value."
+msgstr "Valor de paso de animación."
+
+#: editor/animation_track_editor.cpp
+msgid "Seconds"
+msgstr "Segundos"
+
+#: editor/animation_track_editor.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "FPS"
+msgstr "FPS"
+
+#: editor/animation_track_editor.cpp editor/editor_properties.cpp
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/tile_set_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Editar"
+
+#: editor/animation_track_editor.cpp
+msgid "Animation properties."
+msgstr "Propiedades de Animación."
+
+#: editor/animation_track_editor.cpp
+msgid "Copy Tracks"
+msgstr "Copiar Pistas"
+
+#: editor/animation_track_editor.cpp
+msgid "Scale Selection"
+msgstr "Escalar Selección"
+
+#: editor/animation_track_editor.cpp
+msgid "Scale From Cursor"
+msgstr "Escalar desde o Cursor"
+
+#: editor/animation_track_editor.cpp modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Duplicate Selection"
+msgstr "Duplicar Selección"
+
+#: editor/animation_track_editor.cpp
+msgid "Duplicate Transposed"
+msgstr "Duplicar Transposto"
+
+#: editor/animation_track_editor.cpp
+msgid "Delete Selection"
+msgstr "Eliminar Selección"
+
+#: editor/animation_track_editor.cpp
+msgid "Go to Next Step"
+msgstr "Ir ao Seguinte Paso"
+
+#: editor/animation_track_editor.cpp
+msgid "Go to Previous Step"
+msgstr "Ir ao Anterior Paso"
+
+#: editor/animation_track_editor.cpp
+msgid "Optimize Animation"
+msgstr "Optimizar Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Clean-Up Animation"
+msgstr "Limpiar Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Pick the node that will be animated:"
+msgstr "Elixe o nodo que será animado:"
+
+#: editor/animation_track_editor.cpp
+msgid "Use Bezier Curves"
+msgstr "Usar Curvas Bezier"
+
+#: editor/animation_track_editor.cpp
+msgid "Anim. Optimizer"
+msgstr "Optimizador de Animación"
+
+#: editor/animation_track_editor.cpp
+msgid "Max. Linear Error:"
+msgstr "Erro Lineal Máximo:"
+
+#: editor/animation_track_editor.cpp
+msgid "Max. Angular Error:"
+msgstr "Erro Angular Máximo:"
+
+#: editor/animation_track_editor.cpp
+msgid "Max Optimizable Angle:"
+msgstr "Ángulo Optimizable Máximo:"
+
+#: editor/animation_track_editor.cpp
+msgid "Optimize"
+msgstr "Optimizar"
+
+#: editor/animation_track_editor.cpp
+msgid "Remove invalid keys"
+msgstr "Eliminar chaves inválidas"
+
+#: editor/animation_track_editor.cpp
+msgid "Remove unresolved and empty tracks"
+msgstr "Eliminar pistas baleiras e sen resolver"
+
+#: editor/animation_track_editor.cpp
+msgid "Clean-up all animations"
+msgstr "Limpiar tódolas animacións"
+
+#: editor/animation_track_editor.cpp
+msgid "Clean-Up Animation(s) (NO UNDO!)"
+msgstr "Limpiar Animación(s) (NON HAI VOLTA ATRÁS!)"
+
+#: editor/animation_track_editor.cpp
+msgid "Clean-Up"
+msgstr "Limpiar"
+
+#: editor/animation_track_editor.cpp
+msgid "Scale Ratio:"
+msgstr "Relación de Escalado:"
+
+#: editor/animation_track_editor.cpp
+msgid "Select Tracks to Copy"
+msgstr "Selecciona as Pistas a Copiar"
+
+#: editor/animation_track_editor.cpp editor/editor_log.cpp
+#: editor/editor_properties.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+msgid "Copy"
+msgstr "Copiar"
+
+#: editor/animation_track_editor.cpp
+msgid "Select All/None"
+msgstr "Seleccionar Todas/Ningunha"
+
+#: editor/animation_track_editor_plugins.cpp
+msgid "Add Audio Track Clip"
+msgstr "Engadir Clip de Pista de Audio"
+
+#: editor/animation_track_editor_plugins.cpp
+msgid "Change Audio Track Clip Start Offset"
+msgstr "Cambiar Inicio do Clip na Pista de Audio"
+
+#: editor/animation_track_editor_plugins.cpp
+msgid "Change Audio Track Clip End Offset"
+msgstr "Cambiar Final do Clip na Pista de Audio"
+
+#: editor/array_property_edit.cpp
+msgid "Resize Array"
+msgstr "Redimensionar Array"
+
+#: editor/array_property_edit.cpp
+msgid "Change Array Value Type"
+msgstr "Cambiar Tipo do Valor do Array"
+
+#: editor/array_property_edit.cpp
+msgid "Change Array Value"
+msgstr "Cambiar Valor do Array"
+
+#: editor/code_editor.cpp
+msgid "Go to Line"
+msgstr "Ir a Liña"
+
+#: editor/code_editor.cpp
+msgid "Line Number:"
+msgstr "Número de Liña:"
+
+#: editor/code_editor.cpp
+msgid "%d replaced."
+msgstr "%d substituído."
+
+#: editor/code_editor.cpp editor/editor_help.cpp
+msgid "%d match."
+msgstr "%d coincidencia."
+
+#: editor/code_editor.cpp editor/editor_help.cpp
+msgid "%d matches."
+msgstr "%d coincidencias."
+
+#: editor/code_editor.cpp editor/find_in_files.cpp
+msgid "Match Case"
+msgstr "Coincidir Maiús./Minús."
+
+#: editor/code_editor.cpp editor/find_in_files.cpp
+msgid "Whole Words"
+msgstr "Palabras Completas"
+
+#: editor/code_editor.cpp
+msgid "Replace"
+msgstr "Substituír"
+
+#: editor/code_editor.cpp
+msgid "Replace All"
+msgstr "Substituír Todo"
+
+#: editor/code_editor.cpp
+msgid "Selection Only"
+msgstr "Só a Selección"
+
+#: editor/code_editor.cpp editor/plugins/script_text_editor.cpp
+#: editor/plugins/text_editor.cpp
+msgid "Standard"
+msgstr "Estándar"
+
+#: editor/code_editor.cpp editor/plugins/script_editor_plugin.cpp
+msgid "Toggle Scripts Panel"
+msgstr "Act./Desact. Panel de Scripts"
+
+#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/texture_region_editor_plugin.cpp
+#: editor/plugins/tile_set_editor_plugin.cpp scene/gui/graph_edit.cpp
+msgid "Zoom In"
+msgstr "Aumentar Zoom"
+
+#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/texture_region_editor_plugin.cpp
+#: editor/plugins/tile_set_editor_plugin.cpp scene/gui/graph_edit.cpp
+msgid "Zoom Out"
+msgstr "Diminuír Zoom"
+
+#: editor/code_editor.cpp
+msgid "Reset Zoom"
+msgstr "Reiniciar Zoom"
+
+#: editor/code_editor.cpp
+msgid "Warnings"
+msgstr "Avisos"
+
+#: editor/code_editor.cpp
+msgid "Line and column numbers."
+msgstr "Números de liña e columna."
+
+#: editor/connections_dialog.cpp
+msgid "Method in target node must be specified."
+msgstr "Debe especificarse o método no nodo receptor."
+
+#: editor/connections_dialog.cpp
+msgid "Method name must be a valid identifier."
+msgstr "O nome do método debe ser un identificador válido."
+
+#: editor/connections_dialog.cpp
+msgid ""
+"Target method not found. Specify a valid method or attach a script to the "
+"target node."
+msgstr ""
+"Non se encontrou o método receptor. Especifique un método válido ou engada "
+"un script ao nodo receptor."
+
+#: editor/connections_dialog.cpp
+msgid "Connect to Node:"
+msgstr "Conectar ao Nodo:"
+
+#: editor/connections_dialog.cpp
+msgid "Connect to Script:"
+msgstr "Conectar ao Script:"
+
+#: editor/connections_dialog.cpp
+msgid "From Signal:"
+msgstr "Desde a Sinal:"
+
+#: editor/connections_dialog.cpp
+msgid "Scene does not contain any script."
+msgstr "A escena non conteñe ningún script."
+
+#: editor/connections_dialog.cpp editor/editor_autoload_settings.cpp
+#: editor/groups_editor.cpp editor/plugins/item_list_editor_plugin.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Add"
+msgstr "Engadir"
+
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/editor_feature_profile.cpp editor/groups_editor.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/theme_editor_plugin.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp
+msgid "Remove"
+msgstr "Eliminar"
+
+#: editor/connections_dialog.cpp
+msgid "Add Extra Call Argument:"
+msgstr "Engadir Argumento Extra á Chamada:"
+
+#: editor/connections_dialog.cpp
+msgid "Extra Call Arguments:"
+msgstr "Argumentos Extra da Chamada:"
+
+#: editor/connections_dialog.cpp
+msgid "Receiver Method:"
+msgstr "Método Receptor:"
+
+#: editor/connections_dialog.cpp
+msgid "Advanced"
+msgstr "Avanzado"
+
+#: editor/connections_dialog.cpp
+msgid "Deferred"
+msgstr "Diferido"
+
+#: editor/connections_dialog.cpp
+msgid ""
+"Defers the signal, storing it in a queue and only firing it at idle time."
+msgstr ""
+"Difire a sinal, almacenándoa nunha cola é só executándoa en tempo de "
+"inactividade."
+
+#: editor/connections_dialog.cpp
+msgid "Oneshot"
+msgstr "Execución Única (Oneshot)"
+
+#: editor/connections_dialog.cpp
+msgid "Disconnects the signal after its first emission."
+msgstr "Desconecta a sinal unha vez foi emitida por primeira vez."
+
+#: editor/connections_dialog.cpp
+msgid "Cannot connect signal"
+msgstr "No se pode conectar a sinal"
+
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp editor/groups_editor.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+#: editor/plugins/version_control_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Pechar"
+
+#: editor/connections_dialog.cpp
+msgid "Connect"
+msgstr "Conectar"
+
+#: editor/connections_dialog.cpp
+msgid "Signal:"
+msgstr "Sinal:"
+
+#: editor/connections_dialog.cpp
+msgid "Connect '%s' to '%s'"
+msgstr "Conectar '%s' con '%s'"
+
+#: editor/connections_dialog.cpp
+msgid "Disconnect '%s' from '%s'"
+msgstr "Desconectar '%s' de '%s'"
+
+#: editor/connections_dialog.cpp
+msgid "Disconnect all from signal: '%s'"
+msgstr "Desconectar todo da sinal: '%s'"
+
+#: editor/connections_dialog.cpp
+msgid "Connect..."
+msgstr "Conectar..."
+
+#: editor/connections_dialog.cpp
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Disconnect"
+msgstr "Desconectar"
+
+#: editor/connections_dialog.cpp
+msgid "Connect a Signal to a Method"
+msgstr "Conectar unha Sinal a un Método"
+
+#: editor/connections_dialog.cpp
+msgid "Edit Connection:"
+msgstr "Editar Conexión:"
+
+#: editor/connections_dialog.cpp
+msgid "Are you sure you want to remove all connections from the \"%s\" signal?"
+msgstr "Está seguro de que quere eliminar tódalas conexións da sinal '%s'?"
+
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
+msgid "Signals"
+msgstr "Sinais"
+
+#: editor/connections_dialog.cpp
+msgid "Filter signals"
+msgstr "Filtrar sinais"
+
+#: editor/connections_dialog.cpp
+msgid "Are you sure you want to remove all connections from this signal?"
+msgstr "Está seguro de que quere eliminar tódalas conexións desta sinal?"
+
+#: editor/connections_dialog.cpp
+msgid "Disconnect All"
+msgstr "Desconectar Todas"
+
+#: editor/connections_dialog.cpp
+msgid "Edit..."
+msgstr "Editar..."
+
+#: editor/connections_dialog.cpp
+msgid "Go To Method"
+msgstr "Ir ao Método"
+
+#: editor/create_dialog.cpp
+msgid "Change %s Type"
+msgstr "Cambiar o Tipo de %s"
+
+#: editor/create_dialog.cpp editor/project_settings_editor.cpp
+msgid "Change"
+msgstr "Cambiar"
+
+#: editor/create_dialog.cpp
+msgid "Create New %s"
+msgstr "Crear Novo %s"
+
+#: editor/create_dialog.cpp editor/editor_file_dialog.cpp
+#: editor/filesystem_dock.cpp
+msgid "Favorites:"
+msgstr "Favoritos:"
+
+#: editor/create_dialog.cpp editor/editor_file_dialog.cpp
+msgid "Recent:"
+msgstr "Recente:"
+
+#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: modules/visual_script/visual_script_property_selector.cpp
+msgid "Search:"
+msgstr "Buscar:"
+
+#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/property_selector.cpp editor/quick_open.cpp
+#: modules/visual_script/visual_script_property_selector.cpp
+msgid "Matches:"
+msgstr "Coincidencias:"
+
+#: editor/create_dialog.cpp editor/editor_plugin_settings.cpp
+#: editor/plugin_config_dialog.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/property_selector.cpp
+#: modules/visual_script/visual_script_property_selector.cpp
+msgid "Description:"
+msgstr "Descrición:"
+
+#: editor/dependency_editor.cpp
+msgid "Search Replacement For:"
+msgstr "Buscar Substitución Para:"
+
+#: editor/dependency_editor.cpp
+msgid "Dependencies For:"
+msgstr "Dependencias De:"
+
+#: editor/dependency_editor.cpp
+msgid ""
+"Scene '%s' is currently being edited.\n"
+"Changes will only take effect when reloaded."
+msgstr ""
+"A escena '%s' agora mesmo está sendo editada.\n"
+"Os cambios só terán efecto cando sexa recargada."
+
+#: editor/dependency_editor.cpp
+msgid ""
+"Resource '%s' is in use.\n"
+"Changes will only take effect when reloaded."
+msgstr ""
+"O recurso '%s' agora mesmo está sendo usado.\n"
+"Os cambios só terán efecto cando sexa recargado."
+
+#: editor/dependency_editor.cpp
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "Dependencies"
+msgstr "Dependencias"
+
+#: editor/dependency_editor.cpp
+msgid "Resource"
+msgstr "Recurso"
+
+#: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp
+#: editor/project_manager.cpp editor/project_settings_editor.cpp
+msgid "Path"
+msgstr "Ruta"
+
+#: editor/dependency_editor.cpp
+msgid "Dependencies:"
+msgstr "Dependencias:"
+
+#: editor/dependency_editor.cpp
+msgid "Fix Broken"
+msgstr "Corrixir Erros"
+
+#: editor/dependency_editor.cpp
+msgid "Dependency Editor"
+msgstr "Editor de Dependencias"
+
+#: editor/dependency_editor.cpp
+msgid "Search Replacement Resource:"
+msgstr "Buscar Recurso de Substitución:"
+
+#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
+#: editor/editor_help_search.cpp editor/editor_node.cpp
+#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/script_create_dialog.cpp
+#: modules/visual_script/visual_script_property_selector.cpp
+#: scene/gui/file_dialog.cpp
+msgid "Open"
+msgstr "Abrir"
+
+#: editor/dependency_editor.cpp
+msgid "Owners Of:"
+msgstr "Dono De:"
+
+#: editor/dependency_editor.cpp
+msgid ""
+"Remove selected files from the project? (no undo)\n"
+"You can find the removed files in the system trash to restore them."
+msgstr ""
+"Eliminar do proxecto os arquivos seleccionados? (non se pode reverter)\n"
+"Podes encontrar os arquivos eliminados na papeleira de reciclaxe do sistema "
+"para restaurarlos."
+
+#: editor/dependency_editor.cpp
+msgid ""
+"The files being removed are required by other resources in order for them to "
+"work.\n"
+"Remove them anyway? (no undo)\n"
+"You can find the removed files in the system trash to restore them."
+msgstr ""
+"Os arquivos sendo eliminados están requeridos por outros recursos para poder "
+"funcionar.\n"
+"Eliminalos de todas formas? (non se pode reverter)\n"
+"Podes encontrar os arquivos eliminados na papeleira de reciclaxe do sistema "
+"para restaurarlos."
+
+#: editor/dependency_editor.cpp
+msgid "Cannot remove:"
+msgstr "Non se pode eliminar:"
+
+#: editor/dependency_editor.cpp
+msgid "Error loading:"
+msgstr "Erro cargando:"
+
+#: editor/dependency_editor.cpp
+msgid "Load failed due to missing dependencies:"
+msgstr "Fallou a carga debido a dependencias ausentes:"
+
+#: editor/dependency_editor.cpp editor/editor_node.cpp
+msgid "Open Anyway"
+msgstr "Abrir de Todos Modos"
+
+#: editor/dependency_editor.cpp
+msgid "Which action should be taken?"
+msgstr "Que acción debería de tomarse?"
+
+#: editor/dependency_editor.cpp
+msgid "Fix Dependencies"
+msgstr "Corrixir Dependencias"
+
+#: editor/dependency_editor.cpp
+msgid "Errors loading!"
+msgstr "Erros na carga!"
+
+#: editor/dependency_editor.cpp
+msgid "Permanently delete %d item(s)? (No undo!)"
+msgstr "Eliminar permanentemente %d obxectos? (Non se pode reverter!)"
+
+#: editor/dependency_editor.cpp
+msgid "Show Dependencies"
+msgstr "Amosar Dependencias"
+
+#: editor/dependency_editor.cpp
+msgid "Orphan Resource Explorer"
+msgstr "Explorador de Recursos Orfos"
+
+#: editor/dependency_editor.cpp editor/editor_audio_buses.cpp
+#: editor/editor_file_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/item_list_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp
+msgid "Delete"
+msgstr "Eliminar"
+
+#: editor/dependency_editor.cpp
+msgid "Owns"
+msgstr "É Dono de"
+
+#: editor/dependency_editor.cpp
+msgid "Resources Without Explicit Ownership:"
+msgstr "Recursos Sen Dono Explícito:"
+
+#: editor/dictionary_property_edit.cpp
+msgid "Change Dictionary Key"
+msgstr "Cambiar Chave do Dicionario"
+
+#: editor/dictionary_property_edit.cpp
+msgid "Change Dictionary Value"
+msgstr "Cambiar Valor do Dicionario"
+
+#: editor/editor_about.cpp
+msgid "Thanks from the Godot community!"
+msgstr "Moitas grazas de parte da comunidade de Godot!"
+
+#: editor/editor_about.cpp
+msgid "Godot Engine contributors"
+msgstr "Colaboradores de Godot Engine"
+
+#: editor/editor_about.cpp
+msgid "Project Founders"
+msgstr "Fundadores do Proxecto"
+
+#: editor/editor_about.cpp
+msgid "Lead Developer"
+msgstr "Desenvolvedor Líder"
+
+#. TRANSLATORS: This refers to a job title.
+#. The trailing space is used to distinguish with the project list application,
+#. you do not have to keep it in your translation.
+#: editor/editor_about.cpp
+msgid "Project Manager "
+msgstr "Xestor do Proxecto "
+
+#: editor/editor_about.cpp
+msgid "Developers"
+msgstr "Desenvolvedores"
+
+#: editor/editor_about.cpp
+msgid "Authors"
+msgstr "Autores"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr "Patrocinadores Platino"
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr "Patrocinadores Ouro"
+
+#: editor/editor_about.cpp
+msgid "Silver Sponsors"
+msgstr "Patrocinadores Prata"
+
+#: editor/editor_about.cpp
+msgid "Bronze Sponsors"
+msgstr "Patrocinadores Bronce"
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr "Patrocinadores Mini"
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr "Doadores Ouro"
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr "Doadores Prata"
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr "Doadores Bronce"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr "Doadores"
+
+#: editor/editor_about.cpp
+msgid "License"
+msgstr "Licenza"
+
+#: editor/editor_about.cpp
+msgid "Third-party Licenses"
+msgstr "Licenzas de Terceiros"
+
+#: editor/editor_about.cpp
+msgid ""
+"Godot Engine relies on a number of third-party free and open source "
+"libraries, all compatible with the terms of its MIT license. The following "
+"is an exhaustive list of all such third-party components with their "
+"respective copyright statements and license terms."
+msgstr ""
+"Godot Engine depende dun número de bibliotecas de terceiros, gratis e open "
+"source; todas compatibles cos termos da licenza MIT. A seguinte e unha lista "
+"exhaustiva dos devanditos compoñentes de terceiros, coas suas respectivas "
+"declaracións de copyright e termos de licenza."
+
+#: editor/editor_about.cpp
+msgid "All Components"
+msgstr "Todos os Compoñentes"
+
+#: editor/editor_about.cpp
+msgid "Components"
+msgstr "Compoñentes"
+
+#: editor/editor_about.cpp
+msgid "Licenses"
+msgstr "Licenzas"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "Error opening package file, not in ZIP format."
+msgstr "Erro ao abrir o arquivo comprimido, non está en formato ZIP."
+
+#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr "%s (Xa Existe)"
+
+#: editor/editor_asset_installer.cpp
+msgid "Uncompressing Assets"
+msgstr "Descomprimindo Assets"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Os seguintes arquivos non se poideron extraer do paquete:"
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr "E %s arquivos máis."
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "Package installed successfully!"
+msgstr "Paquete instalado correctamente!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "Éxito!"
+
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr "Contenido do Paquete:"
+
+#: editor/editor_asset_installer.cpp editor/editor_node.cpp
+msgid "Install"
+msgstr "Instalar"
+
+#: editor/editor_asset_installer.cpp
+msgid "Package Installer"
+msgstr "Instalador de Paquetes"
+
+#: editor/editor_audio_buses.cpp
+msgid "Speakers"
+msgstr "Altofalantes"
+
+#: editor/editor_audio_buses.cpp
+msgid "Add Effect"
+msgstr "Engadir Efecto"
+
+#: editor/editor_audio_buses.cpp
+msgid "Rename Audio Bus"
+msgstr "Renomear Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Change Audio Bus Volume"
+msgstr "Cambiar Volume do Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Toggle Audio Bus Solo"
+msgstr "Act./Desact. Solo do Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Toggle Audio Bus Mute"
+msgstr "Act./Desact. Silencio do Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Toggle Audio Bus Bypass Effects"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Select Audio Bus Send"
+msgstr "Seleccionar Envío do Bus de Audio"
+
+#: editor/editor_audio_buses.cpp
+msgid "Add Audio Bus Effect"
+msgstr "Engadir Efecto ao Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Move Bus Effect"
+msgstr "Mover Efecto do Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Delete Bus Effect"
+msgstr "Eliminar Efecto do Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Drag & drop to rearrange."
+msgstr "Arrastrar e soltar para reordenar."
+
+#: editor/editor_audio_buses.cpp
+msgid "Solo"
+msgstr "Solo"
+
+#: editor/editor_audio_buses.cpp
+msgid "Mute"
+msgstr "Silenciar"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bypass"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "Opcións de Bus"
+
+#: editor/editor_audio_buses.cpp editor/filesystem_dock.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "Duplicate"
+msgstr "Duplicar"
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr "Restablecer Volume"
+
+#: editor/editor_audio_buses.cpp
+msgid "Delete Effect"
+msgstr "Eliminar Efecto"
+
+#: editor/editor_audio_buses.cpp
+msgid "Audio"
+msgstr "Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Add Audio Bus"
+msgstr "Engadir Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Master bus can't be deleted!"
+msgstr "Non se pode eliminar o Bus mestre!"
+
+#: editor/editor_audio_buses.cpp
+msgid "Delete Audio Bus"
+msgstr "Eliminar Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Duplicate Audio Bus"
+msgstr "Duplicar Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr "Restablecer Volume do Bus"
+
+#: editor/editor_audio_buses.cpp
+msgid "Move Audio Bus"
+msgstr "Mover Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "Save Audio Bus Layout As..."
+msgstr "Gardar Disposición do Bus de Son Como..."
+
+#: editor/editor_audio_buses.cpp
+msgid "Location for New Layout..."
+msgstr "Localización para a Nova Disposición..."
+
+#: editor/editor_audio_buses.cpp
+msgid "Open Audio Bus Layout"
+msgstr "Abrir Disposición do Bus de Son"
+
+#: editor/editor_audio_buses.cpp
+msgid "There is no '%s' file."
+msgstr "Non hai ningún arquivo '%s'."
+
+#: editor/editor_audio_buses.cpp editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Layout"
+msgstr "Disposición"
+
+#: editor/editor_audio_buses.cpp
+msgid "Invalid file, not an audio bus layout."
+msgstr "Arquivo invalido; non é unha disposición dun Bus de son."
+
+#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr "Erro gardando o arquivo: %s"
+
+#: editor/editor_audio_buses.cpp
+msgid "Add Bus"
+msgstr "Engadir Bus"
+
+#: editor/editor_audio_buses.cpp
+msgid "Add a new Audio Bus to this layout."
+msgstr "Engadir un novo Bus de Son a esta disposición."
+
+#: editor/editor_audio_buses.cpp editor/editor_properties.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
+msgid "Load"
+msgstr "Cargar"
+
+#: editor/editor_audio_buses.cpp
+msgid "Load an existing Bus Layout."
+msgstr "Cargar unha disposición de Bus xa existente."
+
+#: editor/editor_audio_buses.cpp
+msgid "Save As"
+msgstr "Gardar Como"
+
+#: editor/editor_audio_buses.cpp
+msgid "Save this Bus Layout to a file."
+msgstr "Gardar esta disposición de Bus a un arquivo."
+
+#: editor/editor_audio_buses.cpp editor/import_dock.cpp
+msgid "Load Default"
+msgstr "Cargar Valores por Defecto"
+
+#: editor/editor_audio_buses.cpp
+msgid "Load the default Bus Layout."
+msgstr "Cargar a disposición de Bus por defecto."
+
+#: editor/editor_audio_buses.cpp
+msgid "Create a new Bus Layout."
+msgstr "Crear unha nova Disposición de Bus."
+
+#: editor/editor_autoload_settings.cpp
+msgid "Invalid name."
+msgstr "Nome inválido."
+
+#: editor/editor_autoload_settings.cpp
+msgid "Valid characters:"
+msgstr "Caracteres válidos:"
+
+#: editor/editor_autoload_settings.cpp
+msgid "Must not collide with an existing engine class name."
+msgstr "Non debe coincidir co nome dunha clase xa existente no engine."
+
+#: editor/editor_autoload_settings.cpp
+msgid "Must not collide with an existing built-in type name."
+msgstr "Non debe coincidir co nome dun tipo xa existente no engine."
+
+#: editor/editor_autoload_settings.cpp
+msgid "Must not collide with an existing global constant name."
+msgstr "Non debe coincidir co nome dunha constante global xa existente."
+
+#: editor/editor_autoload_settings.cpp
+msgid "Keyword cannot be used as an autoload name."
+msgstr "Unha palabra clave non pode usarse como nome dun AutoCargador."
+
+#: editor/editor_autoload_settings.cpp
+msgid "Autoload '%s' already exists!"
+msgstr "Xa existe un AutoCargador nomeado '%s'!"
+
+#: editor/editor_autoload_settings.cpp
+msgid "Rename Autoload"
+msgstr "Renomear AutoCargador"
+
+#: editor/editor_autoload_settings.cpp
+msgid "Toggle AutoLoad Globals"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Move Autoload"
+msgstr "Mover AutoCargador"
+
+#: editor/editor_autoload_settings.cpp
+msgid "Remove Autoload"
+msgstr "Eliminar AutoCargador"
+
+#: editor/editor_autoload_settings.cpp editor/editor_plugin_settings.cpp
+msgid "Enable"
+msgstr "Activar"
+
+#: editor/editor_autoload_settings.cpp
+msgid "Rearrange Autoloads"
+msgstr "Reordenar AutoCargadores"
+
+#: editor/editor_autoload_settings.cpp
+msgid "Can't add autoload:"
+msgstr "Non se puido engadir AutoCargador:"
+
+#: editor/editor_autoload_settings.cpp
+msgid "Add AutoLoad"
+msgstr "Engadir AutoCargador"
+
+#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/script_create_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Path:"
+msgstr "Ruta:"
+
+#: editor/editor_autoload_settings.cpp
+msgid "Node Name:"
+msgstr "Nome do Nodo:"
+
+#: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp
+#: editor/editor_profiler.cpp editor/project_manager.cpp
+#: editor/settings_config_dialog.cpp
+msgid "Name"
+msgstr "Nome"
+
+#: editor/editor_autoload_settings.cpp
+msgid "Singleton"
+msgstr ""
+
+#: editor/editor_data.cpp editor/inspector_dock.cpp
+msgid "Paste Params"
+msgstr "Pegar Parámetros"
+
+#: editor/editor_data.cpp
+msgid "Updating Scene"
+msgstr "Actualizando Escena"
+
+#: editor/editor_data.cpp
+msgid "Storing local changes..."
+msgstr "Gardando cambios locales..."
+
+#: editor/editor_data.cpp
+msgid "Updating scene..."
+msgstr "Actualizando escena..."
+
+#: editor/editor_data.cpp editor/editor_properties.cpp
+msgid "[empty]"
+msgstr "[baleiro]"
+
+#: editor/editor_data.cpp
+msgid "[unsaved]"
+msgstr "[non gardado]"
+
+#: editor/editor_dir_dialog.cpp
+msgid "Please select a base directory first."
+msgstr "Por favor, seleccione primeiro un directorio base."
+
+#: editor/editor_dir_dialog.cpp
+msgid "Choose a Directory"
+msgstr "Elixir un Directorio"
+
+#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
+#: editor/filesystem_dock.cpp editor/project_manager.cpp
+#: scene/gui/file_dialog.cpp
+msgid "Create Folder"
+msgstr "Crear Cartafol"
+
+#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: modules/visual_script/visual_script_editor.cpp scene/gui/file_dialog.cpp
+msgid "Name:"
+msgstr "Nome:"
+
+#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
+msgid "Could not create folder."
+msgstr "Non se puido crear cartafol."
+
+#: editor/editor_dir_dialog.cpp
+msgid "Choose"
+msgstr "Elixir"
+
+#: editor/editor_export.cpp
+msgid "Storing File:"
+msgstr "Gardando Arquivo:"
+
+#: editor/editor_export.cpp
+msgid "No export template found at the expected path:"
+msgstr "Non se encontrou ningún modelo de exportación na ruta esperada:"
+
+#: editor/editor_export.cpp
+msgid "Packing"
+msgstr "Empaquetando"
+
+#: editor/editor_export.cpp
+msgid ""
+"Target platform requires 'ETC' texture compression for GLES2. Enable 'Import "
+"Etc' in Project Settings."
+msgstr ""
+"A plataforma actual require compresión de texturas 'ETC' para GLES2. Active "
+"'Importar Etc' na 'Configuración do Proxecto'."
+
+#: editor/editor_export.cpp
+msgid ""
+"Target platform requires 'ETC2' texture compression for GLES3. Enable "
+"'Import Etc 2' in Project Settings."
+msgstr ""
+"A plataforma actual require compresión de texturas 'ETC2' para GLES3. Active "
+"'Importar Etc 2' na 'Configuración do Proxecto'."
+
+#: editor/editor_export.cpp
+msgid ""
+"Target platform requires 'ETC' texture compression for the driver fallback "
+"to GLES2.\n"
+"Enable 'Import Etc' in Project Settings, or disable 'Driver Fallback "
+"Enabled'."
+msgstr ""
+"A plataforma actual require unha compresión de texturas 'ETC' para o "
+"controlador de respaldo a GLES2.\n"
+"Active 'Importar Etc' na 'Configuración do Proxecto' ou desactive "
+"'Controlador de Respaldo Activado'."
+
+#: editor/editor_export.cpp
+msgid ""
+"Target platform requires 'PVRTC' texture compression for GLES2. Enable "
+"'Import Pvrtc' in Project Settings."
+msgstr ""
+"A plataforma actual require compresión de texturas 'PVRTC' para GLES2. "
+"Active 'Importar Pvrtc' na 'Configuración do Proxecto'."
+
+#: editor/editor_export.cpp
+msgid ""
+"Target platform requires 'ETC2' or 'PVRTC' texture compression for GLES3. "
+"Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings."
+msgstr ""
+"A plataforma actual require compresión de texturas 'ETC2' ou 'PVRTC' para "
+"GLES3. Active 'Importar Etc 2' ou 'Importar Pvrtc' na 'Configuración do "
+"Proxecto'."
+
+#: editor/editor_export.cpp
+msgid ""
+"Target platform requires 'PVRTC' texture compression for the driver fallback "
+"to GLES2.\n"
+"Enable 'Import Pvrtc' in Project Settings, or disable 'Driver Fallback "
+"Enabled'."
+msgstr ""
+"A plataforma actual require unha compresión de texturas 'PVRTC' para o "
+"controlador de respaldo a GLES2.\n"
+"Active 'Importar Pvrtc' na 'Configuración do Proxecto' ou desactive "
+"'Controlador de Respaldo Activado'."
+
+#: editor/editor_export.cpp platform/android/export/export.cpp
+#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
+#: platform/osx/export/export.cpp platform/uwp/export/export.cpp
+msgid "Custom debug template not found."
+msgstr "Non se encontrou un modelo de depuración personalizado."
+
+#: editor/editor_export.cpp platform/android/export/export.cpp
+#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
+#: platform/osx/export/export.cpp platform/uwp/export/export.cpp
+msgid "Custom release template not found."
+msgstr ""
+
+#: editor/editor_export.cpp platform/javascript/export/export.cpp
+msgid "Template file not found:"
+msgstr "Non se encontrou o arquivo do modelo:"
+
+#: editor/editor_export.cpp
+msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
+msgstr "Na exportación de 32 bits o PCK integrado non pode ser maior de 4 GiB."
+
+#: editor/editor_feature_profile.cpp
+msgid "3D Editor"
+msgstr "Editor 3D"
+
+#: editor/editor_feature_profile.cpp
+msgid "Script Editor"
+msgstr "Editor de Scripts"
+
+#: editor/editor_feature_profile.cpp
+msgid "Asset Library"
+msgstr "Biblioteca de Assets"
+
+#: editor/editor_feature_profile.cpp
+msgid "Scene Tree Editing"
+msgstr "Edición de Árbore de Escenas"
+
+#: editor/editor_feature_profile.cpp
+msgid "Node Dock"
+msgstr "Panel de Nodos"
+
+#: editor/editor_feature_profile.cpp
+msgid "FileSystem Dock"
+msgstr "Panel de Sistema de Arquivos"
+
+#: editor/editor_feature_profile.cpp
+msgid "Import Dock"
+msgstr "Panel de Importación"
+
+#: editor/editor_feature_profile.cpp
+msgid "Erase profile '%s'? (no undo)"
+msgstr "Eliminar perfil '%s'? (non se pode deshacer)"
+
+#: editor/editor_feature_profile.cpp
+msgid "Profile must be a valid filename and must not contain '.'"
+msgstr "Un perfil debe ter un nome de arquivo válido, e non pode conter '.'"
+
+#: editor/editor_feature_profile.cpp
+msgid "Profile with this name already exists."
+msgstr "Un perfil con este nome xa existe."
+
+#: editor/editor_feature_profile.cpp
+msgid "(Editor Disabled, Properties Disabled)"
+msgstr "(Editor Desactivado, Propiedades Desactivadas)"
+
+#: editor/editor_feature_profile.cpp
+msgid "(Properties Disabled)"
+msgstr "(Propiedades Desactivadas)"
+
+#: editor/editor_feature_profile.cpp
+msgid "(Editor Disabled)"
+msgstr "(Editor Desactivado)"
+
+#: editor/editor_feature_profile.cpp
+msgid "Class Options:"
+msgstr "Opcións de Clase:"
+
+#: editor/editor_feature_profile.cpp
+msgid "Enable Contextual Editor"
+msgstr "Activar o Editor Contextual"
+
+#: editor/editor_feature_profile.cpp
+msgid "Enabled Properties:"
+msgstr "Propiedades Activadas:"
+
+#: editor/editor_feature_profile.cpp
+msgid "Enabled Features:"
+msgstr "Características Activadas:"
+
+#: editor/editor_feature_profile.cpp
+msgid "Enabled Classes:"
+msgstr "Clases Activadas:"
+
+#: editor/editor_feature_profile.cpp
+msgid "File '%s' format is invalid, import aborted."
+msgstr "O formato '%s' do arquivo non é válido, a importación foi cancelada."
+
+#: editor/editor_feature_profile.cpp
+msgid ""
+"Profile '%s' already exists. Remove it first before importing, import "
+"aborted."
+msgstr ""
+"O perfil '%s' xa existe. Elimínao antes de importar; importación abortada."
+
+#: editor/editor_feature_profile.cpp
+msgid "Error saving profile to path: '%s'."
+msgstr "Erro gardando o perfil á ruta: '%s'."
+
+#: editor/editor_feature_profile.cpp
+msgid "Unset"
+msgstr ""
+
+#: editor/editor_feature_profile.cpp
+msgid "Current Profile:"
+msgstr "Perfil Actual:"
+
+#: editor/editor_feature_profile.cpp
+msgid "Make Current"
+msgstr "Convertelo no Actual"
+
+#: editor/editor_feature_profile.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "New"
+msgstr "Novo"
+
+#: editor/editor_feature_profile.cpp editor/editor_node.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Importación"
+
+#: editor/editor_feature_profile.cpp editor/project_export.cpp
+msgid "Export"
+msgstr "Exportación"
+
+#: editor/editor_feature_profile.cpp
+msgid "Available Profiles:"
+msgstr "Perfils Dispoñibles:"
+
+#: editor/editor_feature_profile.cpp
+msgid "Class Options"
+msgstr "Opcións de Clase"
+
+#: editor/editor_feature_profile.cpp
+msgid "New profile name:"
+msgstr "Nome do novo perfil:"
+
+#: editor/editor_feature_profile.cpp
+msgid "Erase Profile"
+msgstr "Eliminar Perfil"
+
+#: editor/editor_feature_profile.cpp
+msgid "Godot Feature Profile"
+msgstr "Perfil de Características de Godot"
+
+#: editor/editor_feature_profile.cpp
+msgid "Import Profile(s)"
+msgstr "Importar Perfil(s)"
+
+#: editor/editor_feature_profile.cpp
+msgid "Export Profile"
+msgstr "Exportar Perfil"
+
+#: editor/editor_feature_profile.cpp
+msgid "Manage Editor Feature Profiles"
+msgstr "Administrar Perfils de Características de Godot"
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Select Current Folder"
+msgstr "Seleccionar Cartafol Actual"
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "File Exists, Overwrite?"
+msgstr "O arquivo xa existe ¿Queres sobreescribilo?"
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Select This Folder"
+msgstr "Seleccionar Este Cartafol"
+
+#: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp
+msgid "Copy Path"
+msgstr "Copiar Ruta"
+
+#: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp
+msgid "Open in File Manager"
+msgstr "Abrir no Explorador de Arquivos"
+
+#: editor/editor_file_dialog.cpp editor/editor_node.cpp
+#: editor/filesystem_dock.cpp editor/project_manager.cpp
+msgid "Show in File Manager"
+msgstr "Amosar no Explorador de Arquivos"
+
+#: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp
+msgid "New Folder..."
+msgstr "Novo Cartafol..."
+
+#: editor/editor_file_dialog.cpp editor/find_in_files.cpp
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Refresh"
+msgstr "Actualizar"
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "All Recognized"
+msgstr "Todos Recoñecidos"
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "All Files (*)"
+msgstr "Todos os Arquivos (*)"
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Open a File"
+msgstr "Abrir un Arquivo"
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Open File(s)"
+msgstr "Abrir Arquivo(s)"
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Open a Directory"
+msgstr "Abrir un Directorio"
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Open a File or Directory"
+msgstr "Abrir un Arquivo ou Directorio"
+
+#: editor/editor_file_dialog.cpp editor/editor_node.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
+msgid "Save"
+msgstr "Gardar"
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Save a File"
+msgstr "Gardar un Arquivo"
+
+#: editor/editor_file_dialog.cpp
+msgid "Go Back"
+msgstr "Retroceder"
+
+#: editor/editor_file_dialog.cpp
+msgid "Go Forward"
+msgstr "Avanzar"
+
+#: editor/editor_file_dialog.cpp
+msgid "Go Up"
+msgstr "Subir"
+
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Toggle Hidden Files"
+msgstr "Amosar/Ocultar Arquivos Ocultos"
+
+#: editor/editor_file_dialog.cpp
+msgid "Toggle Favorite"
+msgstr "Act./Desact. Favorito"
+
+#: editor/editor_file_dialog.cpp
+msgid "Toggle Mode"
+msgstr "Act./Desact. Modo"
+
+#: editor/editor_file_dialog.cpp
+msgid "Focus Path"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Move Favorite Up"
+msgstr "Subir Favorito"
+
+#: editor/editor_file_dialog.cpp
+msgid "Move Favorite Down"
+msgstr "Baixar Favorito"
+
+#: editor/editor_file_dialog.cpp
+msgid "Go to previous folder."
+msgstr "Ir ao cartafol anterior."
+
+#: editor/editor_file_dialog.cpp
+msgid "Go to next folder."
+msgstr "Ir ao cartafol seguinte."
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Go to parent folder."
+msgstr "Ir ao cartafol padre."
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Refresh files."
+msgstr "Actualizar Arquivos."
+
+#: editor/editor_file_dialog.cpp
+msgid "(Un)favorite current folder."
+msgstr "Quitar cartafol actual de favoritos."
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Toggle the visibility of hidden files."
+msgstr "Amosar/Ocultar arquivos ocultos."
+
+#: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails."
+msgstr "Ver elementos coma unha cuadrícula de miniaturas."
+
+#: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp
+msgid "View items as a list."
+msgstr "Ver elementos coma unha lista."
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Directories & Files:"
+msgstr "Directorios e Arquivos:"
+
+#: editor/editor_file_dialog.cpp editor/plugins/sprite_editor_plugin.cpp
+#: editor/plugins/style_box_editor_plugin.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/rename_dialog.cpp
+msgid "Preview:"
+msgstr "Vista Previa:"
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "File:"
+msgstr "Arquivo:"
+
+#: editor/editor_file_system.cpp
+msgid "ScanSources"
+msgstr "Escanear Fontes"
+
+#: editor/editor_file_system.cpp
+msgid ""
+"There are multiple importers for different types pointing to file %s, import "
+"aborted"
+msgstr ""
+
+#: editor/editor_file_system.cpp
+msgid "(Re)Importing Assets"
+msgstr "(Re)Importando Assets"
+
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Superior"
+
+#: editor/editor_help.cpp
+msgid "Class:"
+msgstr "Clase:"
+
+#: editor/editor_help.cpp editor/scene_tree_editor.cpp
+#: editor/script_create_dialog.cpp
+msgid "Inherits:"
+msgstr "Herda de:"
+
+#: editor/editor_help.cpp
+msgid "Inherited by:"
+msgstr "Herdado de:"
+
+#: editor/editor_help.cpp
+msgid "Description"
+msgstr "Descrición"
+
+#: editor/editor_help.cpp
+msgid "Online Tutorials"
+msgstr "Tutoriales en liña"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr "Propiedades"
+
+#: editor/editor_help.cpp
+msgid "override:"
+msgstr "sobrescribir:"
+
+#: editor/editor_help.cpp
+msgid "default:"
+msgstr "por defecto:"
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr "Métodos"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Theme Properties"
+msgstr "Propiedades do Tema"
+
+#: editor/editor_help.cpp
+msgid "Enumerations"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Constants"
+msgstr "Constantes"
+
+#: editor/editor_help.cpp
+msgid "Property Descriptions"
+msgstr "Descrición de Propiedades"
+
+#: editor/editor_help.cpp
+msgid "(value)"
+msgstr "(valor)"
+
+#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Actualmente non hai unha descripción desta propiedade. Axúdanos [color="
+"$color][url=$url]contribuíndo cunha descripción[/url][/color]!"
+
+#: editor/editor_help.cpp
+msgid "Method Descriptions"
+msgstr "Descrición de Métodos"
+
+#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Actualmente non hai unha descripción deste método. Axúdanos [color=$color]"
+"[url=$url]contribuíndo cunha descripción[/url][/color]!"
+
+#: editor/editor_help_search.cpp editor/editor_node.cpp
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Search Help"
+msgstr "Buscar na Axuda"
+
+#: editor/editor_help_search.cpp
+msgid "Case Sensitive"
+msgstr "Distinguir Maíusculas e Minúsculas"
+
+#: editor/editor_help_search.cpp
+msgid "Show Hierarchy"
+msgstr "Amosar Xerarquía"
+
+#: editor/editor_help_search.cpp
+msgid "Display All"
+msgstr "Amosar Todo"
+
+#: editor/editor_help_search.cpp
+msgid "Classes Only"
+msgstr "Só Clases"
+
+#: editor/editor_help_search.cpp
+msgid "Methods Only"
+msgstr "Só Métodos"
+
+#: editor/editor_help_search.cpp
+msgid "Signals Only"
+msgstr "Só Sinais"
+
+#: editor/editor_help_search.cpp
+msgid "Constants Only"
+msgstr "Só Constantes"
+
+#: editor/editor_help_search.cpp
+msgid "Properties Only"
+msgstr "Só Propiedades"
+
+#: editor/editor_help_search.cpp
+msgid "Theme Properties Only"
+msgstr "Só Propiedades de Temas"
+
+#: editor/editor_help_search.cpp
+msgid "Member Type"
+msgstr "Tipo do Membro"
+
+#: editor/editor_help_search.cpp
+msgid "Class"
+msgstr "Clase"
+
+#: editor/editor_help_search.cpp
+msgid "Method"
+msgstr "Método"
+
+#: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp
+msgid "Signal"
+msgstr "Sinal"
+
+#: editor/editor_help_search.cpp editor/plugins/theme_editor_plugin.cpp
+msgid "Constant"
+msgstr "Constante"
+
+#: editor/editor_help_search.cpp
+msgid "Property"
+msgstr "Propiedade"
+
+#: editor/editor_help_search.cpp
+msgid "Theme Property"
+msgstr "Propiedade de Temas"
+
+#: editor/editor_inspector.cpp editor/project_settings_editor.cpp
+msgid "Property:"
+msgstr "Propiedade:"
+
+#: editor/editor_inspector.cpp
+msgid "Set"
+msgstr "Establecer"
+
+#: editor/editor_inspector.cpp
+msgid "Set Multiple:"
+msgstr "Establecer Varios:"
+
+#: editor/editor_log.cpp
+msgid "Output:"
+msgstr "Saída:"
+
+#: editor/editor_log.cpp editor/plugins/tile_map_editor_plugin.cpp
+msgid "Copy Selection"
+msgstr "Copiar Selección"
+
+#: editor/editor_log.cpp editor/editor_network_profiler.cpp
+#: editor/editor_profiler.cpp editor/editor_properties.cpp
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+#: editor/property_editor.cpp editor/scene_tree_dock.cpp
+#: editor/script_editor_debugger.cpp
+#: modules/gdnative/gdnative_library_editor_plugin.cpp scene/gui/line_edit.cpp
+#: scene/gui/text_edit.cpp
+msgid "Clear"
+msgstr "Limpar"
+
+#: editor/editor_log.cpp
+msgid "Clear Output"
+msgstr "Limpar Saída"
+
+#: editor/editor_network_profiler.cpp editor/editor_node.cpp
+#: editor/editor_profiler.cpp
+msgid "Stop"
+msgstr "Deter"
+
+#: editor/editor_network_profiler.cpp editor/editor_profiler.cpp
+#: editor/plugins/animation_state_machine_editor.cpp editor/rename_dialog.cpp
+msgid "Start"
+msgstr "Iniciar"
+
+#: editor/editor_network_profiler.cpp
+msgid "%s/s"
+msgstr "%s/s"
+
+#: editor/editor_network_profiler.cpp
+msgid "Down"
+msgstr "Baixada"
+
+#: editor/editor_network_profiler.cpp
+msgid "Up"
+msgstr "Subida"
+
+#: editor/editor_network_profiler.cpp editor/editor_node.cpp
+msgid "Node"
+msgstr "Nodo"
+
+#: editor/editor_network_profiler.cpp
+msgid "Incoming RPC"
+msgstr "RPC Entrante"
+
+#: editor/editor_network_profiler.cpp
+msgid "Incoming RSET"
+msgstr "RSET Entrante"
+
+#: editor/editor_network_profiler.cpp
+msgid "Outgoing RPC"
+msgstr "RPC Saínte"
+
+#: editor/editor_network_profiler.cpp
+msgid "Outgoing RSET"
+msgstr "RSET Saínte"
+
+#: editor/editor_node.cpp editor/project_manager.cpp
+msgid "New Window"
+msgstr "Nova Xanela"
+
+#: editor/editor_node.cpp
+msgid "Imported resources can't be saved."
+msgstr "Os recursos importados non se poden gardar."
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: scene/gui/dialogs.cpp
+msgid "OK"
+msgstr "Vale"
+
+#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
+msgid "Error saving resource!"
+msgstr "Erro gardando o recurso!"
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource can't be saved because it does not belong to the edited scene. "
+"Make it unique first."
+msgstr ""
+"Este recurso non pode gardarse porque non pertence á escena actual. Primero "
+"fágao único."
+
+#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
+msgid "Save Resource As..."
+msgstr "Gardar Recurso Como..."
+
+#: editor/editor_node.cpp
+msgid "Can't open file for writing:"
+msgstr "Non se puido abrir o arquivo para escritura:"
+
+#: editor/editor_node.cpp
+msgid "Requested file format unknown:"
+msgstr "O formato do arquivo solicitado é descoñecido:"
+
+#: editor/editor_node.cpp
+msgid "Error while saving."
+msgstr "Erro ao gardar."
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+msgid "Can't open '%s'. The file could have been moved or deleted."
+msgstr ""
+"Non se puido abrir '%s'. Pode ser que o arquivo fose movido ou eliminado."
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr "Erro ao analizar sintacticamente '%s'."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr "Fin de arquivo inesperado en '%s'."
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr "Non se encontrou '%s' ou as súas dependencias."
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr "Erro ao cargar '%s'."
+
+#: editor/editor_node.cpp
+msgid "Saving Scene"
+msgstr "Gardando Escena"
+
+#: editor/editor_node.cpp
+msgid "Analyzing"
+msgstr "Analizando"
+
+#: editor/editor_node.cpp
+msgid "Creating Thumbnail"
+msgstr "Creando Miniatura"
+
+#: editor/editor_node.cpp
+msgid "This operation can't be done without a tree root."
+msgstr "Esta operación non pode realizarse sen un nodo raíz."
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene can't be saved because there is a cyclic instancing inclusion.\n"
+"Please resolve it and then attempt to save again."
+msgstr ""
+"Esta escena non pode gardarse porque hai unha relación de instanciación "
+"cíclica con outra escena.\n"
+"Por favor, solucione o problema e inténteo de novo."
+
+#: editor/editor_node.cpp
+msgid ""
+"Couldn't save scene. Likely dependencies (instances or inheritance) couldn't "
+"be satisfied."
+msgstr ""
+"Non se puido gardar a escena. Posiblemente as dependencias (instancias ou "
+"herenzas) non puideron satisfacerse."
+
+#: editor/editor_node.cpp editor/scene_tree_dock.cpp
+msgid "Can't overwrite scene that is still open!"
+msgstr "Non se pode sobreescribir escena que sigue aberta!"
+
+#: editor/editor_node.cpp
+msgid "Can't load MeshLibrary for merging!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error saving MeshLibrary!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Can't load TileSet for merging!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error saving TileSet!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"An error occurred while trying to save the editor layout.\n"
+"Make sure the editor's user data path is writable."
+msgstr ""
+"Produciuse un erro mentres se trataba de gardar a disposición das ventás do "
+"editor.\n"
+"Asegúrese de que o cartafol do editor ten dereitos de escritura."
+
+#: editor/editor_node.cpp
+msgid ""
+"Default editor layout overridden.\n"
+"To restore the Default layout to its base settings, use the Delete Layout "
+"option and delete the Default layout."
+msgstr ""
+"A disposición por defecto do editor foi sobreescrita.\n"
+"Para devolver a disposición por defecto a súa configuración orixinal, usa a "
+"opción 'Eliminar Disposición' e elimina a Disposición por defecto."
+
+#: editor/editor_node.cpp
+msgid "Layout name not found!"
+msgstr "Nome de disposición non encontrada!"
+
+#: editor/editor_node.cpp
+msgid "Restored the Default layout to its base settings."
+msgstr "Restableceuse a disposición por defecto aos seus valores orixinais."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"Este recurso pertence a unha escena importada, polo que non é editable.\n"
+"Por favor; lea a documentación referente a importación de escenas para "
+"entender o fluxo de traballo."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it won't be kept when saving the current scene."
+msgstr ""
+"Este recurso pertence a unha escena instanciada ou herdada.\n"
+"Os cambios que lle faga non se gardarán cando garde a escena actual."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+"Este recurso foi importado, polo que non é editable. Cambia a súa "
+"configuración no panel de importación, e reimportao."
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it won't be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"Esta escena foi importada, polo que cambios na escena non serán gardados.\n"
+"Instanciala ou herdala permitirá facerlle cambios permanentes.\n"
+"Por favor, lea a documentación referente a importación de escenas para "
+"entender o fluxo de traballo."
+
+#: editor/editor_node.cpp
+msgid ""
+"This is a remote object, so changes to it won't be kept.\n"
+"Please read the documentation relevant to debugging to better understand "
+"this workflow."
+msgstr ""
+"Este é un obxecto remoto, polo que os cambios que lle faga non serán "
+"permanentes.\n"
+"Por favor; lea a documentación referente a depuración para entender o fluxo "
+"de traballo."
+
+#: editor/editor_node.cpp
+msgid "There is no defined scene to run."
+msgstr "Non hai unha escena definida para executar."
+
+#: editor/editor_node.cpp
+msgid "Save scene before running..."
+msgstr "Garda a escena antes de executala..."
+
+#: editor/editor_node.cpp
+msgid "Could not start subprocess!"
+msgstr "Non se puido iniciar subproceso!"
+
+#: editor/editor_node.cpp editor/filesystem_dock.cpp
+msgid "Open Scene"
+msgstr "Abrir Escena"
+
+#: editor/editor_node.cpp
+msgid "Open Base Scene"
+msgstr "Abrir Escena Base"
+
+#: editor/editor_node.cpp
+msgid "Quick Open..."
+msgstr "Apertura Rápida..."
+
+#: editor/editor_node.cpp
+msgid "Quick Open Scene..."
+msgstr "Apertura Rápida de Escena..."
+
+#: editor/editor_node.cpp
+msgid "Quick Open Script..."
+msgstr "Apertura Rápida de Script..."
+
+#: editor/editor_node.cpp
+msgid "Save & Close"
+msgstr "Gardar e Pechar"
+
+#: editor/editor_node.cpp
+msgid "Save changes to '%s' before closing?"
+msgstr "Gardar os cambios de '%s' antes de pechar?"
+
+#: editor/editor_node.cpp
+msgid "Saved %s modified resource(s)."
+msgstr "Gardado(s) %s recurso(s) modificado(s)."
+
+#: editor/editor_node.cpp
+msgid "A root node is required to save the scene."
+msgstr "Necesítase un nodo raíz para gardar a escena."
+
+#: editor/editor_node.cpp
+msgid "Save Scene As..."
+msgstr "Gardar Escena Como..."
+
+#: editor/editor_node.cpp editor/scene_tree_dock.cpp
+msgid "This operation can't be done without a scene."
+msgstr "Esta operación non pode realizarse se unha escena."
+
+#: editor/editor_node.cpp
+msgid "Export Mesh Library"
+msgstr "Exportar Biblioteca de Mallas"
+
+#: editor/editor_node.cpp
+msgid "This operation can't be done without a root node."
+msgstr "Esta operación non pode realizarse sen un nodo raíz."
+
+#: editor/editor_node.cpp
+msgid "Export Tile Set"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "This operation can't be done without a selected node."
+msgstr "Esta operación non pode realizarse sen un nodo seleccionado."
+
+#: editor/editor_node.cpp
+msgid "Current scene not saved. Open anyway?"
+msgstr "Escena actual non gardada ¿Abrir de todos os modos?"
+
+#: editor/editor_node.cpp
+msgid "Can't reload a scene that was never saved."
+msgstr "Non se pode volver a cargar unha escena que nunca foi gardada."
+
+#: editor/editor_node.cpp
+msgid "Reload Saved Scene"
+msgstr "Recargar Escena Gardada"
+
+#: editor/editor_node.cpp
+msgid ""
+"The current scene has unsaved changes.\n"
+"Reload the saved scene anyway? This action cannot be undone."
+msgstr ""
+"A escena actual ten cambios non gardados.\n"
+"Quere volver a cargar a escena cargada de todos os modos? Esta acción non se "
+"pode deshacer."
+
+#: editor/editor_node.cpp
+msgid "Quick Run Scene..."
+msgstr "Execución Rápida de Escena..."
+
+#: editor/editor_node.cpp
+msgid "Quit"
+msgstr "Saír"
+
+#: editor/editor_node.cpp
+msgid "Yes"
+msgstr "Si"
+
+#: editor/editor_node.cpp
+msgid "Exit the editor?"
+msgstr "Saír do editor?"
+
+#: editor/editor_node.cpp
+msgid "Open Project Manager?"
+msgstr "Abrir o Administrador de Proxectos?"
+
+#: editor/editor_node.cpp
+msgid "Save & Quit"
+msgstr "Gardar e Saír"
+
+#: editor/editor_node.cpp
+msgid "Save changes to the following scene(s) before quitting?"
+msgstr "Gardar os cambios nas seguintes escenas antes de saír?"
+
+#: editor/editor_node.cpp
+msgid "Save changes the following scene(s) before opening Project Manager?"
+msgstr ""
+"Gardar os cambios nas seguintes escenas antes de abrir o Administrador de "
+"Proxectos?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+"Esta opción está anticuada. As situacións nas que a actualización debe ser "
+"forzada agora considéranse un erro. Por favor, repórtao."
+
+#: editor/editor_node.cpp
+msgid "Pick a Main Scene"
+msgstr "Elexir unha Escena Principal"
+
+#: editor/editor_node.cpp
+msgid "Close Scene"
+msgstr "Pechar Escena"
+
+#: editor/editor_node.cpp
+msgid "Reopen Closed Scene"
+msgstr "Reabrir Escena Pechada"
+
+#: editor/editor_node.cpp
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr ""
+"Non se puido activar a característica adicional (Plugin): Fallou a análise "
+"sintáctica da configuración de '%s'."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr ""
+"Non se puido encontrar o campo do Script na característica adicional "
+"(Plugin) en 'res://addons/%s'."
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s'."
+msgstr ""
+"Non se puido cargar Script de característica adicional (Addon) na ruta: '%s'."
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' There seems to be an error in "
+"the code, please check the syntax."
+msgstr ""
+"Non se puido cargar Script de característica adicional (Addon) na ruta: "
+"'%s'. Parece que hai un erro no código; por favor, comproba a sintaxe."
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr ""
+"Non se puido cargar o Script da característica adicional (Plugin): O tipo "
+"base de %s non é EditorPlugin."
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr ""
+"Non se puido cargar Script de característica adicional (Addon) na ruta: "
+"'%s'. O script non está en modo ferramenta (tool)."
+
+#: editor/editor_node.cpp
+msgid ""
+"Scene '%s' was automatically imported, so it can't be modified.\n"
+"To make changes to it, a new inherited scene can be created."
+msgstr ""
+"A escena '%s' foi automáticamente importada, polo que non pode modificarse.\n"
+"Para facerlle cambios pódese crear unha nova escena herdada."
+
+#: editor/editor_node.cpp
+msgid ""
+"Error loading scene, it must be inside the project path. Use 'Import' to "
+"open the scene, then save it inside the project path."
+msgstr ""
+"Erro cargando a escena: debe estar dentro da ruta do proxecto. Usa \"Importar"
+"\" para abrir a escena, e despois gardala dentro da ruta do proxecto."
+
+#: editor/editor_node.cpp
+msgid "Scene '%s' has broken dependencies:"
+msgstr "A escena '%s' ten dependencias rotas:"
+
+#: editor/editor_node.cpp
+msgid "Clear Recent Scenes"
+msgstr "Limpar Escenas Recentes"
+
+#: editor/editor_node.cpp
+msgid ""
+"No main scene has ever been defined, select one?\n"
+"You can change it later in \"Project Settings\" under the 'application' "
+"category."
+msgstr ""
+"Nunca se definiu unha escena principal. Seleccionar unha?\n"
+"Podes cambialo despois na \"Configuración do Proxecto\", na categoría "
+"\"Aplicación\"."
+
+#: editor/editor_node.cpp
+msgid ""
+"Selected scene '%s' does not exist, select a valid one?\n"
+"You can change it later in \"Project Settings\" under the 'application' "
+"category."
+msgstr ""
+"A escena seleccionada '%s' non existe. Seleccionar unha válida?\n"
+"Podes cambiala despois en \"Configuración do Proxecto\" na categoría "
+"\"aplicación\"."
+
+#: editor/editor_node.cpp
+msgid ""
+"Selected scene '%s' is not a scene file, select a valid one?\n"
+"You can change it later in \"Project Settings\" under the 'application' "
+"category."
+msgstr ""
+"A escena seleccionada '%s' non é un arquivo de escenas. Seleccionar un "
+"arquivo válido?\n"
+"Podes cambialo despois en \"Configuración do Proxecto\" na categoría "
+"\"aplicación\"."
+
+#: editor/editor_node.cpp
+msgid "Save Layout"
+msgstr "Gardar Disposición"
+
+#: editor/editor_node.cpp
+msgid "Delete Layout"
+msgstr "Eliminar Dispoción"
+
+#: editor/editor_node.cpp editor/import_dock.cpp
+#: editor/script_create_dialog.cpp
+msgid "Default"
+msgstr "Por Defecto"
+
+#: editor/editor_node.cpp editor/editor_properties.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_editor.cpp
+msgid "Show in FileSystem"
+msgstr "Amosar no Sistema de Arquivos"
+
+#: editor/editor_node.cpp
+msgid "Play This Scene"
+msgstr "Reproducir Esta Escena"
+
+#: editor/editor_node.cpp
+msgid "Close Tab"
+msgstr "Pechar Pestana"
+
+#: editor/editor_node.cpp
+msgid "Undo Close Tab"
+msgstr "Desfacer Pechar Pestana"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+msgid "Close Other Tabs"
+msgstr "Pechar Outras Pestanas"
+
+#: editor/editor_node.cpp
+msgid "Close Tabs to the Right"
+msgstr "Pechar Pestanas á Dereita"
+
+#: editor/editor_node.cpp
+msgid "Close All Tabs"
+msgstr "Pechar Todas as Pestanas"
+
+#: editor/editor_node.cpp
+msgid "Switch Scene Tab"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "%d more files or folders"
+msgstr "%d arquivos ou cartafois máis"
+
+#: editor/editor_node.cpp
+msgid "%d more folders"
+msgstr "%d cartafois máis"
+
+#: editor/editor_node.cpp
+msgid "%d more files"
+msgstr "%d arquivos máis"
+
+#: editor/editor_node.cpp
+msgid "Dock Position"
+msgstr "Posición do Panel"
+
+#: editor/editor_node.cpp
+msgid "Distraction Free Mode"
+msgstr "Modo Sen Distraccións"
+
+#: editor/editor_node.cpp
+msgid "Toggle distraction-free mode."
+msgstr "Act./Desact. modo sen distraccións."
+
+#: editor/editor_node.cpp
+msgid "Add a new scene."
+msgstr "Engadir unha nova escena."
+
+#: editor/editor_node.cpp
+msgid "Scene"
+msgstr "Escena"
+
+#: editor/editor_node.cpp
+msgid "Go to previously opened scene."
+msgstr "Ir á escena aberta previamente."
+
+#: editor/editor_node.cpp
+msgid "Copy Text"
+msgstr "Copiar Texto"
+
+#: editor/editor_node.cpp
+msgid "Next tab"
+msgstr "Seguinte pestana"
+
+#: editor/editor_node.cpp
+msgid "Previous tab"
+msgstr "Anterior Pestana"
+
+#: editor/editor_node.cpp
+msgid "Filter Files..."
+msgstr "Filtrar Arquivos..."
+
+#: editor/editor_node.cpp
+msgid "Operations with scene files."
+msgstr "Operacións con arquivos de escenas."
+
+#: editor/editor_node.cpp
+msgid "New Scene"
+msgstr "Nova Escena"
+
+#: editor/editor_node.cpp
+msgid "New Inherited Scene..."
+msgstr "Nova Escena Herdada..."
+
+#: editor/editor_node.cpp
+msgid "Open Scene..."
+msgstr "Abrir Escena..."
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+msgid "Open Recent"
+msgstr "Abrir Recente"
+
+#: editor/editor_node.cpp
+msgid "Save Scene"
+msgstr "Gardar Escena"
+
+#: editor/editor_node.cpp
+msgid "Save All Scenes"
+msgstr "Gardar Todas as Escenas"
+
+#: editor/editor_node.cpp
+msgid "Convert To..."
+msgstr "Converter a..."
+
+#: editor/editor_node.cpp
+msgid "MeshLibrary..."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "TileSet..."
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_text_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+msgid "Undo"
+msgstr "Desfacer"
+
+#: editor/editor_node.cpp editor/plugins/script_text_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+msgid "Redo"
+msgstr "Refacer"
+
+#: editor/editor_node.cpp
+msgid "Miscellaneous project or scene-wide tools."
+msgstr "Ferramentas varias do proxecto ou escena."
+
+#: editor/editor_node.cpp editor/project_manager.cpp
+#: editor/script_create_dialog.cpp
+msgid "Project"
+msgstr "Proxecto"
+
+#: editor/editor_node.cpp
+msgid "Project Settings..."
+msgstr "Axustes do Proxecto..."
+
+#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
+msgid "Version Control"
+msgstr "Control de Versións"
+
+#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
+msgid "Set Up Version Control"
+msgstr "Configurar Control de Versións"
+
+#: editor/editor_node.cpp
+msgid "Shut Down Version Control"
+msgstr "Desactivar Control de Versións"
+
+#: editor/editor_node.cpp
+msgid "Export..."
+msgstr "Exportar..."
+
+#: editor/editor_node.cpp
+msgid "Install Android Build Template..."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open Project Data Folder"
+msgstr "Abrir Cartafol de Datos do Proxecto"
+
+#: editor/editor_node.cpp editor/plugins/tile_set_editor_plugin.cpp
+msgid "Tools"
+msgstr "Ferramentas"
+
+#: editor/editor_node.cpp
+msgid "Orphan Resource Explorer..."
+msgstr "Explorador de Recursos Orfos..."
+
+#: editor/editor_node.cpp
+msgid "Quit to Project List"
+msgstr "Saír á Lista de Proxectos"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/project_export.cpp
+msgid "Debug"
+msgstr "Depuración"
+
+#: editor/editor_node.cpp
+msgid "Deploy with Remote Debug"
+msgstr "Exportar con Depuración Remota"
+
+#: editor/editor_node.cpp
+msgid ""
+"When this option is enabled, using one-click deploy will make the executable "
+"attempt to connect to this computer's IP so the running project can be "
+"debugged.\n"
+"This option is intended to be used for remote debugging (typically with a "
+"mobile device).\n"
+"You don't need to enable it to use the GDScript debugger locally."
+msgstr ""
+"Cando esta opción está activada, usar o despregue dun só clic fará que o "
+"executable intente conectarse a IP deste computador, para poder depurar o "
+"proxecto mentres este está executandose no dispositivo.\n"
+"Esta opción está pensada para ser utilizada coa depuración remota "
+"(normalmente nun dispositivo móbil).\n"
+"Non necesita activar esta opción para utilizar o depurador de GDScript de "
+"forma local."
+
+#: editor/editor_node.cpp
+msgid "Small Deploy with Network Filesystem"
+msgstr "Exportación Reducida co Sistema de Arquivos en Rede"
+
+#: editor/editor_node.cpp
+msgid ""
+"When this option is enabled, using one-click deploy for Android will only "
+"export an executable without the project data.\n"
+"The filesystem will be provided from the project by the editor over the "
+"network.\n"
+"On Android, deploying will use the USB cable for faster performance. This "
+"option speeds up testing for projects with large assets."
+msgstr ""
+"Cando esta opción está activada, usar o despregue don só clic para Android "
+"exportará só o executable, sen os datos do proxecto.\n"
+"O sistema de arquivos proporcionarase por o editor na rede.\n"
+"En Android ao despregar a aplicación usarase o USB para obter maior "
+"rendemento. Esta opción acelera o proceso de proba en proxectos con gran "
+"cantidade de Assets."
+
+#: editor/editor_node.cpp
+msgid "Visible Collision Shapes"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"When this option is enabled, collision shapes and raycast nodes (for 2D and "
+"3D) will be visible in the running project."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Visible Navigation"
+msgstr "Navegación Visible"
+
+#: editor/editor_node.cpp
+msgid ""
+"When this option is enabled, navigation meshes and polygons will be visible "
+"in the running project."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Synchronize Scene Changes"
+msgstr "Sincronizar Cambios na Escena"
+
+#: editor/editor_node.cpp
+msgid ""
+"When this option is enabled, any changes made to the scene in the editor "
+"will be replicated in the running project.\n"
+"When used remotely on a device, this is more efficient when the network "
+"filesystem option is enabled."
+msgstr ""
+"Cando esta opción está activada, calquera cambio na escena no editor verase "
+"reflectido no proxecto en execución.\n"
+"Cando é usado remotamente nun dispositivo, é máis eficiente cando o sistema "
+"de arquivos en rede está activado."
+
+#: editor/editor_node.cpp
+msgid "Synchronize Script Changes"
+msgstr "Sincronizar Cambios nos Scripts"
+
+#: editor/editor_node.cpp
+msgid ""
+"When this option is enabled, any script that is saved will be reloaded in "
+"the running project.\n"
+"When used remotely on a device, this is more efficient when the network "
+"filesystem option is enabled."
+msgstr ""
+"Cando esta opción está activada, calquera script gardada será recargada no "
+"proxecto mentras este está en execución.\n"
+"Cando é usado remotamente nun dispositivo, é máis eficiente cando o sistema "
+"de arquivos en rede está activado."
+
+#: editor/editor_node.cpp editor/script_create_dialog.cpp
+msgid "Editor"
+msgstr "Editor"
+
+#: editor/editor_node.cpp
+msgid "Editor Settings..."
+msgstr "Configuración do Editor..."
+
+#: editor/editor_node.cpp
+msgid "Editor Layout"
+msgstr "Disposición das Ventás do Editor"
+
+#: editor/editor_node.cpp
+msgid "Take Screenshot"
+msgstr "Captura de Pantalla"
+
+#: editor/editor_node.cpp
+msgid "Screenshots are stored in the Editor Data/Settings Folder."
+msgstr ""
+"As capturas de pantalla gárdanse no cartafol de Datos/Configuración do "
+"Editor."
+
+#: editor/editor_node.cpp
+msgid "Toggle Fullscreen"
+msgstr "Act./Desact. Pantalla Completa"
+
+#: editor/editor_node.cpp
+msgid "Toggle System Console"
+msgstr "Act./Desact. Consola do Sistema"
+
+#: editor/editor_node.cpp
+msgid "Open Editor Data/Settings Folder"
+msgstr "Abrir Cartafol de Datos/Configuración do Editor"
+
+#: editor/editor_node.cpp
+msgid "Open Editor Data Folder"
+msgstr "Abrir Cartafol de Datos do Editor"
+
+#: editor/editor_node.cpp
+msgid "Open Editor Settings Folder"
+msgstr "Abrir Cartafol de Configuración do Editor"
+
+#: editor/editor_node.cpp
+msgid "Manage Editor Features..."
+msgstr "Administrar Características do Editor..."
+
+#: editor/editor_node.cpp
+msgid "Manage Export Templates..."
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/shader_editor_plugin.cpp
+msgid "Help"
+msgstr "Axuda"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Online Docs"
+msgstr "Documentación En Liña"
+
+#: editor/editor_node.cpp
+msgid "Q&A"
+msgstr "Preguntas e Respostas"
+
+#: editor/editor_node.cpp
+msgid "Report a Bug"
+msgstr "Reportar un Erro"
+
+#: editor/editor_node.cpp
+msgid "Send Docs Feedback"
+msgstr "Reportar Problema ca Documentación"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Comunidade"
+
+#: editor/editor_node.cpp
+msgid "About"
+msgstr "Acerca De"
+
+#: editor/editor_node.cpp
+msgid "Play the project."
+msgstr "Reproduce o proxecto."
+
+#: editor/editor_node.cpp
+msgid "Play"
+msgstr "Executar"
+
+#: editor/editor_node.cpp
+msgid "Pause the scene execution for debugging."
+msgstr "Pausa a execución da escena para a depuración."
+
+#: editor/editor_node.cpp
+msgid "Pause Scene"
+msgstr "Pausar Escena"
+
+#: editor/editor_node.cpp
+msgid "Stop the scene."
+msgstr "Detén a escena."
+
+#: editor/editor_node.cpp
+msgid "Play the edited scene."
+msgstr "Reproduce a escena actual."
+
+#: editor/editor_node.cpp
+msgid "Play Scene"
+msgstr "Executar Escena"
+
+#: editor/editor_node.cpp
+msgid "Play custom scene"
+msgstr "Executar escena a elixir"
+
+#: editor/editor_node.cpp
+msgid "Play Custom Scene"
+msgstr "Executar Escena a Elixir"
+
+#: editor/editor_node.cpp
+msgid "Changing the video driver requires restarting the editor."
+msgstr "Cambiar o controlador de vídeo require reiniciar o editor."
+
+#: editor/editor_node.cpp editor/project_settings_editor.cpp
+#: editor/settings_config_dialog.cpp
+msgid "Save & Restart"
+msgstr "Gardar e Reinicar"
+
+#: editor/editor_node.cpp
+msgid "Spins when the editor window redraws."
+msgstr "Xira cando o editor actualiza a pantalla."
+
+#: editor/editor_node.cpp
+msgid "Update Continuously"
+msgstr "Actualizar de Maneira Continua"
+
+#: editor/editor_node.cpp
+msgid "Update When Changed"
+msgstr "Actualizar Cando Sexa Necesario"
+
+#: editor/editor_node.cpp
+msgid "Hide Update Spinner"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "FileSystem"
+msgstr "Sistema de Arquivos"
+
+#: editor/editor_node.cpp
+msgid "Inspector"
+msgstr "Inspector"
+
+#: editor/editor_node.cpp
+msgid "Expand Bottom Panel"
+msgstr "Estender Panel Inferior"
+
+#: editor/editor_node.cpp
+msgid "Output"
+msgstr "Saída"
+
+#: editor/editor_node.cpp
+msgid "Don't Save"
+msgstr "Non Gardar"
+
+#: editor/editor_node.cpp
+msgid "Android build template is missing, please install relevant templates."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Manage Templates"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This will set up your project for custom Android builds by installing the "
+"source template to \"res://android/build\".\n"
+"You can then apply modifications and build your own custom APK on export "
+"(adding modules, changing the AndroidManifest.xml, etc.).\n"
+"Note that in order to make custom builds instead of using pre-built APKs, "
+"the \"Use Custom Build\" option should be enabled in the Android export "
+"preset."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"The Android build template is already installed in this project and it won't "
+"be overwritten.\n"
+"Remove the \"res://android/build\" directory manually before attempting this "
+"operation again."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Import Templates From ZIP File"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Template Package"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Export Library"
+msgstr "Biblioteca de Exportación"
+
+#: editor/editor_node.cpp
+msgid "Merge With Existing"
+msgstr "Combinar Con Existentes"
+
+#: editor/editor_node.cpp
+msgid "Open & Run a Script"
+msgstr "Abrir e Executar un Script"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Este shader foi modificado en disco.\n"
+"Que acción deberían de tomarse?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Recargar"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Volver a Gardar"
+
+#: editor/editor_node.cpp
+msgid "New Inherited"
+msgstr "Nova Escena Herdada"
+
+#: editor/editor_node.cpp
+msgid "Load Errors"
+msgstr "Erros durante a Carga"
+
+#: editor/editor_node.cpp editor/plugins/tile_map_editor_plugin.cpp
+msgid "Select"
+msgstr "Elixir"
+
+#: editor/editor_node.cpp
+msgid "Open 2D Editor"
+msgstr "Abrir Editor 2D"
+
+#: editor/editor_node.cpp
+msgid "Open 3D Editor"
+msgstr "Abrir Editor 3D"
+
+#: editor/editor_node.cpp
+msgid "Open Script Editor"
+msgstr "Abrir Editor de Scripts"
+
+#: editor/editor_node.cpp editor/project_manager.cpp
+msgid "Open Asset Library"
+msgstr "Abrir Biblioteca de Assets"
+
+#: editor/editor_node.cpp
+msgid "Open the next Editor"
+msgstr "Abrir o seguinte editor"
+
+#: editor/editor_node.cpp
+msgid "Open the previous Editor"
+msgstr "Abrir o anterior editor"
+
+#: editor/editor_node.h
+msgid "Warning!"
+msgstr "Aviso!"
+
+#: editor/editor_path.cpp
+msgid "No sub-resources found."
+msgstr "Non se atopou ningún sub-recurso."
+
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr "Creando Previsualización de Mallas"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail..."
+msgstr "Miniatura..."
+
+#: editor/editor_plugin_settings.cpp
+msgid "Main Script:"
+msgstr "Script Principal:"
+
+#: editor/editor_plugin_settings.cpp
+msgid "Edit Plugin"
+msgstr "Editar Característica Adicional (Plugin)"
+
+#: editor/editor_plugin_settings.cpp
+msgid "Installed Plugins:"
+msgstr "Características Adicionais (Plugins) Instalados:"
+
+#: editor/editor_plugin_settings.cpp editor/plugin_config_dialog.cpp
+msgid "Update"
+msgstr "Actualizar"
+
+#: editor/editor_plugin_settings.cpp editor/plugin_config_dialog.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Versión:"
+
+#: editor/editor_plugin_settings.cpp editor/plugin_config_dialog.cpp
+msgid "Author:"
+msgstr "Autor:"
+
+#: editor/editor_plugin_settings.cpp
+msgid "Status:"
+msgstr "Estado:"
+
+#: editor/editor_plugin_settings.cpp
+msgid "Edit:"
+msgstr "Editar:"
+
+#: editor/editor_profiler.cpp
+msgid "Measure:"
+msgstr "Medida:"
+
+#: editor/editor_profiler.cpp
+msgid "Frame Time (sec)"
+msgstr "Duración de Fotograma (seg)"
+
+#: editor/editor_profiler.cpp
+msgid "Average Time (sec)"
+msgstr "Tempo Medio (seg)"
+
+#: editor/editor_profiler.cpp
+msgid "Frame %"
+msgstr "Fotograma %"
+
+#: editor/editor_profiler.cpp
+msgid "Physics Frame %"
+msgstr "Fotograma de Física %"
+
+#: editor/editor_profiler.cpp
+msgid "Inclusive"
+msgstr "Inclusivo"
+
+#: editor/editor_profiler.cpp
+msgid "Self"
+msgstr "Propio"
+
+#: editor/editor_profiler.cpp
+msgid "Frame #:"
+msgstr "Fotograma #:"
+
+#: editor/editor_profiler.cpp
+msgid "Time"
+msgstr "Tempo"
+
+#: editor/editor_profiler.cpp
+msgid "Calls"
+msgstr "Chamadas"
+
+#: editor/editor_properties.cpp
+msgid "Edit Text:"
+msgstr "Editar Texto:"
+
+#: editor/editor_properties.cpp editor/script_create_dialog.cpp
+msgid "On"
+msgstr "Activado"
+
+#: editor/editor_properties.cpp
+msgid "Layer"
+msgstr "Capa"
+
+#: editor/editor_properties.cpp
+msgid "Bit %d, value %d"
+msgstr "Bit %d, valor %d"
+
+#: editor/editor_properties.cpp
+msgid "[Empty]"
+msgstr "[Baleiro]"
+
+#: editor/editor_properties.cpp editor/plugins/root_motion_editor_plugin.cpp
+msgid "Assign..."
+msgstr "Asignar..."
+
+#: editor/editor_properties.cpp
+msgid "Invalid RID"
+msgstr "Identificador de Recurso (RID) inválido"
+
+#: editor/editor_properties.cpp
+msgid ""
+"The selected resource (%s) does not match any type expected for this "
+"property (%s)."
+msgstr ""
+"O recurso seleccionado (%s) non coincide con ningún tipo esperado para esta "
+"propiedade (%s)."
+
+#: editor/editor_properties.cpp
+msgid ""
+"Can't create a ViewportTexture on resources saved as a file.\n"
+"Resource needs to belong to a scene."
+msgstr ""
+"Non se pode crear un ViewportTexture nun recurso gardado coma un arquivo.\n"
+"O recurso ten que pertencer a unha escena."
+
+#: editor/editor_properties.cpp
+msgid ""
+"Can't create a ViewportTexture on this resource because it's not set as "
+"local to scene.\n"
+"Please switch on the 'local to scene' property on it (and all resources "
+"containing it up to a node)."
+msgstr ""
+
+#: editor/editor_properties.cpp editor/property_editor.cpp
+msgid "Pick a Viewport"
+msgstr "Selecciona unha Mini-Ventá (Viewport)"
+
+#: editor/editor_properties.cpp editor/property_editor.cpp
+msgid "New Script"
+msgstr "Novo Script"
+
+#: editor/editor_properties.cpp editor/scene_tree_dock.cpp
+msgid "Extend Script"
+msgstr "Estender Script"
+
+#: editor/editor_properties.cpp editor/property_editor.cpp
+msgid "New %s"
+msgstr "Novo %s"
+
+#: editor/editor_properties.cpp editor/property_editor.cpp
+msgid "Make Unique"
+msgstr "Facer Único"
+
+#: editor/editor_properties.cpp
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/animation_state_machine_editor.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+msgid "Paste"
+msgstr "Pegar"
+
+#: editor/editor_properties.cpp editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr "Converter a %s"
+
+#: editor/editor_properties.cpp editor/property_editor.cpp
+msgid "Selected node is not a Viewport!"
+msgstr "O nodo seleccionado non é unha Mini-Ventá (Viewport)!"
+
+#: editor/editor_properties_array_dict.cpp
+msgid "Size: "
+msgstr "Tamaño: "
+
+#: editor/editor_properties_array_dict.cpp
+msgid "Page: "
+msgstr "Páxina: "
+
+#: editor/editor_properties_array_dict.cpp
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Remove Item"
+msgstr "Eliminar Elemento"
+
+#: editor/editor_properties_array_dict.cpp
+msgid "New Key:"
+msgstr "Nova Chave:"
+
+#: editor/editor_properties_array_dict.cpp
+msgid "New Value:"
+msgstr "Novo Valor:"
+
+#: editor/editor_properties_array_dict.cpp
+msgid "Add Key/Value Pair"
+msgstr "Engadir Parella Chave/Valor"
+
+#: editor/editor_run_native.cpp
+msgid ""
+"No runnable export preset found for this platform.\n"
+"Please add a runnable preset in the Export menu or define an existing preset "
+"as runnable."
+msgstr ""
+"Non se encontraron axustes de exportación executables para esta plataforma.\n"
+"Engade uns axustes de exportación executables, ou define algún xa existente "
+"como executable."
+
+#: editor/editor_run_script.cpp
+msgid "Write your logic in the _run() method."
+msgstr "Escribe a túa lóxica no método '_run()'."
+
+#: editor/editor_run_script.cpp
+msgid "There is an edited scene already."
+msgstr "Xa hai unha escena editada."
+
+#: editor/editor_run_script.cpp
+msgid "Couldn't instance script:"
+msgstr "Non se puido instanciar o script:"
+
+#: editor/editor_run_script.cpp
+msgid "Did you forget the 'tool' keyword?"
+msgstr "Olvidaches a palabra clave 'tool'?"
+
+#: editor/editor_run_script.cpp
+msgid "Couldn't run script:"
+msgstr "Non se puido executar o script:"
+
+#: editor/editor_run_script.cpp
+msgid "Did you forget the '_run' method?"
+msgstr "Olvidaches o método '_run'?"
+
+#: editor/editor_spin_slider.cpp
+msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes."
+msgstr ""
+"Mantén pulsado Ctrl para redondear a enteiros. Mantén pulsado Shift para "
+"cambios máis precisos."
+
+#: editor/editor_sub_scene.cpp
+msgid "Select Node(s) to Import"
+msgstr "Selecciona o(s) Nodo(s) a Importar"
+
+#: editor/editor_sub_scene.cpp editor/project_manager.cpp
+msgid "Browse"
+msgstr "Examinar"
+
+#: editor/editor_sub_scene.cpp
+msgid "Scene Path:"
+msgstr "Ruta da Escena:"
+
+#: editor/editor_sub_scene.cpp
+msgid "Import From Node:"
+msgstr "Importar Desde Nodo:"
+
+#: editor/export_template_manager.cpp
+msgid "Redownload"
+msgstr "Volver a Descargar"
+
+#: editor/export_template_manager.cpp
+msgid "Uninstall"
+msgstr "Desinstalar"
+
+#: editor/export_template_manager.cpp
+msgid "(Installed)"
+msgstr "(Instalado)"
+
+#: editor/export_template_manager.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download"
+msgstr "Descargar"
+
+#: editor/export_template_manager.cpp
+msgid "Official export templates aren't available for development builds."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "(Missing)"
+msgstr "(Non encontrado)"
+
+#: editor/export_template_manager.cpp
+msgid "(Current)"
+msgstr "(Actual)"
+
+#: editor/export_template_manager.cpp
+msgid "Retrieving mirrors, please wait..."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Remove template version '%s'?"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Can't open export templates zip."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Invalid version.txt format inside templates: %s."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "No version.txt found inside templates."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Error creating path for templates:"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Extracting Export Templates"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Importing:"
+msgstr "Importando:"
+
+#: editor/export_template_manager.cpp
+msgid "Error getting the list of mirrors."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Error parsing JSON of mirror list. Please report this issue!"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid ""
+"No download links found for this version. Direct download is only available "
+"for official releases."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "Non se pode conectar."
+
+#: editor/export_template_manager.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "Sen resposta."
+
+#: editor/export_template_manager.cpp
+msgid "Request Failed."
+msgstr "A Petición Fracasou."
+
+#: editor/export_template_manager.cpp
+msgid "Redirect Loop."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Fracasado:"
+
+#: editor/export_template_manager.cpp
+msgid "Download Complete."
+msgstr "Descarga Completa."
+
+#: editor/export_template_manager.cpp
+msgid "Cannot remove temporary file:"
+msgstr "Non se pode eliminar o arquivo temporal:"
+
+#: editor/export_template_manager.cpp
+msgid ""
+"Templates installation failed.\n"
+"The problematic templates archives can be found at '%s'."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Error requesting URL:"
+msgstr "Erro ao solicitar a URL:"
+
+#: editor/export_template_manager.cpp
+msgid "Connecting to Mirror..."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Disconnected"
+msgstr "Desconectado"
+
+#: editor/export_template_manager.cpp
+msgid "Resolving"
+msgstr "Resolvendo"
+
+#: editor/export_template_manager.cpp
+msgid "Can't Resolve"
+msgstr "Non se puido Resolver"
+
+#: editor/export_template_manager.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting..."
+msgstr "Conectando..."
+
+#: editor/export_template_manager.cpp
+msgid "Can't Connect"
+msgstr "Non se Pode Conectar"
+
+#: editor/export_template_manager.cpp
+msgid "Connected"
+msgstr "Conectado"
+
+#: editor/export_template_manager.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting..."
+msgstr "Solicitando..."
+
+#: editor/export_template_manager.cpp
+msgid "Downloading"
+msgstr "Descargando"
+
+#: editor/export_template_manager.cpp
+msgid "Connection Error"
+msgstr "Erro de Conexión"
+
+#: editor/export_template_manager.cpp
+msgid "SSL Handshake Error"
+msgstr "Erro SSL Handshake"
+
+#: editor/export_template_manager.cpp
+msgid "Uncompressing Android Build Sources"
+msgstr "Descomprimindo Recursos de Compilación de Android"
+
+#: editor/export_template_manager.cpp
+msgid "Current Version:"
+msgstr "Versión Actual:"
+
+#: editor/export_template_manager.cpp
+msgid "Installed Versions:"
+msgstr "Versións Instaladas:"
+
+#: editor/export_template_manager.cpp
+msgid "Install From File"
+msgstr "Instalar Dende Arquivo"
+
+#: editor/export_template_manager.cpp
+msgid "Remove Template"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Select Template File"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Godot Export Templates"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Export Template Manager"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Download Templates"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Select mirror from list: (Shift+Click: Open in Browser)"
+msgstr "Seleccione un mirror da lista: (Shift+Clic: Abrir no Navegador)"
+
+#: editor/filesystem_dock.cpp
+msgid "Favorites"
+msgstr "Favoritos"
+
+#: editor/filesystem_dock.cpp
+msgid "Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
+"Estado: Fallou a importación do arquivo. Por favor, amaña o arquivo e "
+"impórtao manualmente."
+
+#: editor/filesystem_dock.cpp
+msgid "Cannot move/rename resources root."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Cannot move a folder into itself."
+msgstr "Non se pode mover un cartafol dentro de sí mesmo."
+
+#: editor/filesystem_dock.cpp
+msgid "Error moving:"
+msgstr "Erro ao mover:"
+
+#: editor/filesystem_dock.cpp
+msgid "Error duplicating:"
+msgstr "Erro ao duplicar:"
+
+#: editor/filesystem_dock.cpp
+msgid "Unable to update dependencies:"
+msgstr "Incapaz de actualizar dependencias:"
+
+#: editor/filesystem_dock.cpp editor/scene_tree_editor.cpp
+msgid "No name provided."
+msgstr "Nome non proporcionado."
+
+#: editor/filesystem_dock.cpp
+msgid "Provided name contains invalid characters."
+msgstr "O nome proporcionado contén caracteres inválidos."
+
+#: editor/filesystem_dock.cpp
+msgid "A file or folder with this name already exists."
+msgstr "Xa existe un arquivo ou cartafol con este nome."
+
+#: editor/filesystem_dock.cpp
+msgid "Name contains invalid characters."
+msgstr "O nome contén caracteres inválidos."
+
+#: editor/filesystem_dock.cpp
+msgid ""
+"The following files or folders conflict with items in the target location "
+"'%s':\n"
+"\n"
+"%s\n"
+"\n"
+"Do you wish to overwrite them?"
+msgstr ""
+"Os seguintes arquivos ou cartafois entran en conflicto con elementos da "
+"ubicación de destino '%s':\n"
+"\n"
+"%s\n"
+"\n"
+"Queres sobreescribilos?"
+
+#: editor/filesystem_dock.cpp
+msgid "Renaming file:"
+msgstr "Renomeando Arquivo:"
+
+#: editor/filesystem_dock.cpp
+msgid "Renaming folder:"
+msgstr "Renomeando Cartafol:"
+
+#: editor/filesystem_dock.cpp
+msgid "Duplicating file:"
+msgstr "Duplicando Arquivo:"
+
+#: editor/filesystem_dock.cpp
+msgid "Duplicating folder:"
+msgstr "Duplicando Cartafol:"
+
+#: editor/filesystem_dock.cpp
+msgid "New Inherited Scene"
+msgstr "Nova Escena Herdada"
+
+#: editor/filesystem_dock.cpp
+msgid "Set As Main Scene"
+msgstr "Establecer coma Escena Principal"
+
+#: editor/filesystem_dock.cpp
+msgid "Open Scenes"
+msgstr "Abrir Escenas"
+
+#: editor/filesystem_dock.cpp
+msgid "Instance"
+msgstr "Instanciar"
+
+#: editor/filesystem_dock.cpp
+msgid "Add to Favorites"
+msgstr "Engadir a Favoritos"
+
+#: editor/filesystem_dock.cpp
+msgid "Remove from Favorites"
+msgstr "Eliminar de Favoritos"
+
+#: editor/filesystem_dock.cpp
+msgid "Edit Dependencies..."
+msgstr "Editar Dependencias..."
+
+#: editor/filesystem_dock.cpp
+msgid "View Owners..."
+msgstr "Ver Donos..."
+
+#: editor/filesystem_dock.cpp
+msgid "Move To..."
+msgstr "Mover a..."
+
+#: editor/filesystem_dock.cpp
+msgid "New Scene..."
+msgstr "Nova Escena..."
+
+#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
+msgid "New Script..."
+msgstr "Novo Script..."
+
+#: editor/filesystem_dock.cpp
+msgid "New Resource..."
+msgstr "Novo Recurso..."
+
+#: editor/filesystem_dock.cpp editor/plugins/visual_shader_editor_plugin.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Expand All"
+msgstr "Expandir Todo"
+
+#: editor/filesystem_dock.cpp editor/plugins/visual_shader_editor_plugin.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Collapse All"
+msgstr "Colapsar Todo"
+
+#: editor/filesystem_dock.cpp
+msgid "Duplicate..."
+msgstr "Duplicar..."
+
+#: editor/filesystem_dock.cpp
+msgid "Move to Trash"
+msgstr "Mover á Papeleira"
+
+#: editor/filesystem_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
+msgid "Rename..."
+msgstr "Renomear..."
+
+#: editor/filesystem_dock.cpp
+msgid "Previous Folder/File"
+msgstr "Anterior Cartafol/Arquivo"
+
+#: editor/filesystem_dock.cpp
+msgid "Next Folder/File"
+msgstr "Seguinte Cartafol/Arquivo"
+
+#: editor/filesystem_dock.cpp
+msgid "Re-Scan Filesystem"
+msgstr "Reexaminar Sistema de Arquivos"
+
+#: editor/filesystem_dock.cpp
+msgid "Toggle Split Mode"
+msgstr "Act./Desact. Modo Dividido"
+
+#: editor/filesystem_dock.cpp
+msgid "Search files"
+msgstr "Buscar arquivos"
+
+#: editor/filesystem_dock.cpp
+msgid ""
+"Scanning Files,\n"
+"Please Wait..."
+msgstr ""
+"Examinando arquivos,\n"
+"Por favor, espere..."
+
+#: editor/filesystem_dock.cpp
+msgid "Move"
+msgstr "Mover"
+
+#: editor/filesystem_dock.cpp
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+#: editor/project_manager.cpp editor/rename_dialog.cpp
+#: editor/scene_tree_dock.cpp
+msgid "Rename"
+msgstr "Renomear"
+
+#: editor/filesystem_dock.cpp
+msgid "Overwrite"
+msgstr "Sobreescribir"
+
+#: editor/filesystem_dock.cpp
+msgid "Create Scene"
+msgstr "Crear Escena"
+
+#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
+msgid "Create Script"
+msgstr "Crear Script"
+
+#: editor/find_in_files.cpp editor/plugins/script_editor_plugin.cpp
+msgid "Find in Files"
+msgstr "Buscar en Arquivos"
+
+#: editor/find_in_files.cpp
+msgid "Find:"
+msgstr "Buscar:"
+
+#: editor/find_in_files.cpp
+msgid "Folder:"
+msgstr "Cartafol:"
+
+#: editor/find_in_files.cpp
+msgid "Filters:"
+msgstr "Filtros:"
+
+#: editor/find_in_files.cpp
+msgid ""
+"Include the files with the following extensions. Add or remove them in "
+"ProjectSettings."
+msgstr ""
+"Inclúe os arquivos coas seguintes extensións. Engádeos ou elimínaos na "
+"Configuración do proxecto."
+
+#: editor/find_in_files.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+msgid "Find..."
+msgstr "Buscar..."
+
+#: editor/find_in_files.cpp editor/plugins/script_text_editor.cpp
+msgid "Replace..."
+msgstr "Substituír..."
+
+#: editor/find_in_files.cpp editor/progress_dialog.cpp scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: editor/find_in_files.cpp
+msgid "Find: "
+msgstr "Buscar: "
+
+#: editor/find_in_files.cpp
+msgid "Replace: "
+msgstr "Substituír: "
+
+#: editor/find_in_files.cpp
+msgid "Replace all (no undo)"
+msgstr "Substituír todo (non se pode defacer)"
+
+#: editor/find_in_files.cpp
+msgid "Searching..."
+msgstr "Procurando..."
+
+#: editor/find_in_files.cpp
+msgid "%d match in %d file."
+msgstr "%d coincidencia en %d arquivo."
+
+#: editor/find_in_files.cpp
+msgid "%d matches in %d file."
+msgstr "%d coincidencias en %d arquivo."
+
+#: editor/find_in_files.cpp
+msgid "%d matches in %d files."
+msgstr "%d coincidencias en %d arquivos."
+
+#: editor/groups_editor.cpp
+msgid "Add to Group"
+msgstr "Engadir ao Grupo"
+
+#: editor/groups_editor.cpp
+msgid "Remove from Group"
+msgstr "Eliminar do Grupo"
+
+#: editor/groups_editor.cpp
+msgid "Group name already exists."
+msgstr "Este nome de grupo xa existe."
+
+#: editor/groups_editor.cpp
+msgid "Invalid group name."
+msgstr "Nome de grupo inválido."
+
+#: editor/groups_editor.cpp
+msgid "Rename Group"
+msgstr "Renomear Grupo"
+
+#: editor/groups_editor.cpp
+msgid "Delete Group"
+msgstr "Eliminar Grupo"
+
+#: editor/groups_editor.cpp editor/node_dock.cpp
+msgid "Groups"
+msgstr "Grupos"
+
+#: editor/groups_editor.cpp
+msgid "Nodes Not in Group"
+msgstr "Nodos Fora do Grupo"
+
+#: editor/groups_editor.cpp editor/scene_tree_dock.cpp
+#: editor/scene_tree_editor.cpp
+msgid "Filter nodes"
+msgstr "Filtrar nodos"
+
+#: editor/groups_editor.cpp
+msgid "Nodes in Group"
+msgstr "Nodos no Grupo"
+
+#: editor/groups_editor.cpp
+msgid "Empty groups will be automatically removed."
+msgstr "Os grupos baleiros serán automaticamente eliminados."
+
+#: editor/groups_editor.cpp
+msgid "Group Editor"
+msgstr "Editor de Grupos"
+
+#: editor/groups_editor.cpp
+msgid "Manage Groups"
+msgstr "Administrar Grupos"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import as Single Scene"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr "Importar con Animacións Separadas"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials"
+msgstr "Importar con Materiais Separados"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects"
+msgstr "Importar con Obxectos Separados"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials"
+msgstr "Importar con Obxectos e Materiais Separados"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr "Importar con Obxectos e Animacións Separadas"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr "Importar con Materiais e Animacións Separadas"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr "Importar con Obxectos, Materiais, e Animacións Separados"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import as Multiple Scenes"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import as Multiple Scenes+Materials"
+msgstr "Importar como Escenas e Materiales Múltiples"
+
+#: editor/import/resource_importer_scene.cpp
+#: editor/plugins/mesh_library_editor_plugin.cpp
+msgid "Import Scene"
+msgstr "Importar Escena"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Importing Scene..."
+msgstr "Importando Escena..."
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Generating Lightmaps"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Generating for Mesh: "
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Running Custom Script..."
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Couldn't load post-import script:"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Invalid/broken script for post-import (check console):"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Error running post-import script:"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Did you return a Node-derived object in the `post_import()` method?"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Saving..."
+msgstr "Gardando..."
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Elixir Modo"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importación"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Cargar Valores por Defecto"
+
+#: editor/import_dock.cpp
+msgid "%d Files"
+msgstr "%d Arquivos"
+
+#: editor/import_dock.cpp
+msgid "Set as Default for '%s'"
+msgstr ""
+
+#: editor/import_dock.cpp
+msgid "Clear Default for '%s'"
+msgstr ""
+
+#: editor/import_dock.cpp
+msgid "Import As:"
+msgstr "Importar Como:"
+
+#: editor/import_dock.cpp
+msgid "Preset"
+msgstr "Axustes de Importación"
+
+#: editor/import_dock.cpp
+msgid "Reimport"
+msgstr "Reimportar"
+
+#: editor/import_dock.cpp
+msgid "Save Scenes, Re-Import, and Restart"
+msgstr ""
+
+#: editor/import_dock.cpp
+msgid "Changing the type of an imported file requires editor restart."
+msgstr ""
+
+#: editor/import_dock.cpp
+msgid ""
+"WARNING: Assets exist that use this resource, they may stop loading properly."
+msgstr ""
+
+#: editor/inspector_dock.cpp
+msgid "Failed to load resource."
+msgstr "Fallou a carga do Recurso."
+
+#: editor/inspector_dock.cpp
+msgid "Expand All Properties"
+msgstr "Expandir Tódalas Propiedades"
+
+#: editor/inspector_dock.cpp
+msgid "Collapse All Properties"
+msgstr "Colapsar Tódalas Propiedades"
+
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Save As..."
+msgstr "Gardar Como..."
+
+#: editor/inspector_dock.cpp
+msgid "Copy Params"
+msgstr "Copiar Parámetros"
+
+#: editor/inspector_dock.cpp
+msgid "Edit Resource Clipboard"
+msgstr ""
+
+#: editor/inspector_dock.cpp
+msgid "Copy Resource"
+msgstr "Copiar Recurso"
+
+#: editor/inspector_dock.cpp
+msgid "Make Built-In"
+msgstr ""
+
+#: editor/inspector_dock.cpp
+msgid "Make Sub-Resources Unique"
+msgstr ""
+
+#: editor/inspector_dock.cpp
+msgid "Open in Help"
+msgstr "Abrir na Axuda"
+
+#: editor/inspector_dock.cpp
+msgid "Create a new resource in memory and edit it."
+msgstr ""
+
+#: editor/inspector_dock.cpp
+msgid "Load an existing resource from disk and edit it."
+msgstr ""
+
+#: editor/inspector_dock.cpp
+msgid "Save the currently edited resource."
+msgstr ""
+
+#: editor/inspector_dock.cpp
+msgid "Go to the previous edited object in history."
+msgstr ""
+
+#: editor/inspector_dock.cpp
+msgid "Go to the next edited object in history."
+msgstr ""
+
+#: editor/inspector_dock.cpp
+msgid "History of recently edited objects."
+msgstr ""
+
+#: editor/inspector_dock.cpp
+msgid "Object properties."
+msgstr "Propiedade de Obxectos."
+
+#: editor/inspector_dock.cpp
+msgid "Filter properties"
+msgstr "Filtrar propiedades"
+
+#: editor/inspector_dock.cpp
+msgid "Changes may be lost!"
+msgstr "Os cambios poderían perderse!"
+
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
+msgstr ""
+
+#: editor/node_dock.cpp
+msgid "Select a single node to edit its signals and groups."
+msgstr "Seleccione un nodo para editar as súas sinais e grupos."
+
+#: editor/plugin_config_dialog.cpp
+msgid "Edit a Plugin"
+msgstr "Editar unha Característica Adicional (Plugin)"
+
+#: editor/plugin_config_dialog.cpp
+msgid "Create a Plugin"
+msgstr "Crear unha Característica Adicional (Plugin)"
+
+#: editor/plugin_config_dialog.cpp
+msgid "Plugin Name:"
+msgstr "Nome do Plugin:"
+
+#: editor/plugin_config_dialog.cpp
+msgid "Subfolder:"
+msgstr "Subcartafol:"
+
+#: editor/plugin_config_dialog.cpp editor/script_create_dialog.cpp
+msgid "Language:"
+msgstr "Linguaxe:"
+
+#: editor/plugin_config_dialog.cpp
+msgid "Script Name:"
+msgstr "Nome do Script:"
+
+#: editor/plugin_config_dialog.cpp
+msgid "Activate now?"
+msgstr "Activar agora?"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Create Polygon"
+msgstr "Crear Polígono"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Create points."
+msgstr "Crear puntos."
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit points.\n"
+"LMB: Move Point\n"
+"RMB: Erase Point"
+msgstr ""
+"Editar puntos.\n"
+"Clic Izq: Mover Punto\n"
+"Clic Der: Eliminar Punto"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+msgid "Erase points."
+msgstr "Borrar puntos."
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Edit Polygon"
+msgstr "Editar Polígono"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
+msgstr "Inserir Punto"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Edit Polygon (Remove Point)"
+msgstr "Editar Polígono (Eliminar Punto)"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Polygon And Point"
+msgstr "Eliminar Polígono e Punto"
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/animation_state_machine_editor.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Add Animation"
+msgstr "Engadir Animación"
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Load..."
+msgstr "Cargar..."
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Move Node Point"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+msgid "Change BlendSpace1D Limits"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+msgid "Change BlendSpace1D Labels"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "This type of node can't be used. Only root nodes are allowed."
+msgstr "Non se pode usar este tipo de nodo. Só nodos raíz están permitidos."
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Add Node Point"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Add Animation Point"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+msgid "Remove BlendSpace1D Point"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+msgid "Move BlendSpace1D Node Point"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid ""
+"AnimationTree is inactive.\n"
+"Activate to enable playback, check node warnings if activation fails."
+msgstr ""
+"O AnimationTree está inactivo.\n"
+"Actívao para permitir a reprodución; e comproba os avisos do nodo se hai un "
+"erro na activación."
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Set the blending position within the space"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Select and move points, create points with RMB."
+msgstr ""
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp scene/gui/graph_edit.cpp
+msgid "Enable snap and show grid."
+msgstr "Activar axuste de cuadrícula e amosar cuadrícula."
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Point"
+msgstr "Punto"
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Open Editor"
+msgstr "Abrir Editor"
+
+#: editor/plugins/animation_blend_space_1d_editor.cpp
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Open Animation Node"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Triangle already exists."
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Add Triangle"
+msgstr "Engadir Triángulo"
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Change BlendSpace2D Limits"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Change BlendSpace2D Labels"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Remove BlendSpace2D Point"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Remove BlendSpace2D Triangle"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "BlendSpace2D does not belong to an AnimationTree node."
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "No triangles exist, so no blending can take place."
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Toggle Auto Triangles"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Create triangles by connecting points."
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Erase points and triangles."
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+msgid "Generate blend triangles automatically (instead of manually)"
+msgstr ""
+
+#: editor/plugins/animation_blend_space_2d_editor.cpp
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Blend:"
+msgstr "Mezcla:"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Parameter Changed"
+msgstr "Parámetro Cambiado"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Edit Filters"
+msgstr "Editar Flitros"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Output node can't be added to the blend tree."
+msgstr ""
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Add Node to BlendTree"
+msgstr ""
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Node Moved"
+msgstr "Nodo Movido"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Unable to connect, port may be in use or connection may be invalid."
+msgstr ""
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Nodes Connected"
+msgstr "Nodos Conectado"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Nodes Disconnected"
+msgstr "Nodos Desconectados"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Set Animation"
+msgstr "Establecer Animación"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Delete Node"
+msgstr "Eliminar Nodo"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/scene_tree_dock.cpp
+msgid "Delete Node(s)"
+msgstr "Eliminar Nodo(s)"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Toggle Filter On/Off"
+msgstr ""
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Change Filter"
+msgstr "Cambiar Filtro"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "No animation player set, so unable to retrieve track names."
+msgstr ""
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Player path set is invalid, so unable to retrieve track names."
+msgstr ""
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/root_motion_editor_plugin.cpp
+msgid ""
+"Animation player has no valid root node path, so unable to retrieve track "
+"names."
+msgstr ""
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Anim Clips"
+msgstr "Clips de Animación"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Audio Clips"
+msgstr "Clips de Audio"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Functions"
+msgstr "Funcións"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Node Renamed"
+msgstr "Nodo Renomeado"
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Add Node..."
+msgstr "Engadir Nodo..."
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+#: editor/plugins/root_motion_editor_plugin.cpp
+msgid "Edit Filtered Tracks:"
+msgstr ""
+
+#: editor/plugins/animation_blend_tree_editor_plugin.cpp
+msgid "Enable Filtering"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Toggle Autoplay"
+msgstr "Act./Desact. Auto-reproducción"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "New Animation Name:"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "New Anim"
+msgstr "Nova Animación"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Change Animation Name:"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Delete Animation?"
+msgstr "Eliminar Animación?"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Remove Animation"
+msgstr "Eliminar Animación"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Invalid animation name!"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Animation name already exists!"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Rename Animation"
+msgstr "Renomear Animación"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Blend Next Changed"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Change Blend Time"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Load Animation"
+msgstr "Cargar Animación"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Duplicate Animation"
+msgstr "Duplicar Animación"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "No animation to copy!"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "No animation resource on clipboard!"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Pasted Animation"
+msgstr "Animación Pegada"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Paste Animation"
+msgstr "Pegar Animación"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "No animation to edit!"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Play selected animation backwards from current pos. (A)"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Play selected animation backwards from end. (Shift+A)"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Stop animation playback. (S)"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Play selected animation from start. (Shift+D)"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Play selected animation from current pos. (D)"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Animation position (in seconds)."
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Scale animation playback globally for the node."
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Animation Tools"
+msgstr "Ferramentas de Animación"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Animation"
+msgstr "Animación"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Edit Transitions..."
+msgstr "Editar Transicións..."
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Open in Inspector"
+msgstr "Abrir no Inspector"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Display list of animations in player."
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Autoplay on Load"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Enable Onion Skinning"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Onion Skinning Options"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Directions"
+msgstr "Direccións"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Past"
+msgstr "Pasado"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Future"
+msgstr "Futuro"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Depth"
+msgstr "Profundidad"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "1 step"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "2 steps"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "3 steps"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Differences Only"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Force White Modulate"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Include Gizmos (3D)"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Pin AnimationPlayer"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Create New Animation"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Animation Name:"
+msgstr "Nome da Animación:"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+msgid "Error!"
+msgstr "Erro!"
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Blend Times:"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Next (Auto Queue):"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Cross-Animation Blend Times"
+msgstr ""
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Move Node"
+msgstr "Mover Nodo"
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Transition exists!"
+msgstr "Existe transición!"
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Add Transition"
+msgstr "Engadir Transición"
+
+#: editor/plugins/animation_state_machine_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Node"
+msgstr "Engadir Nodo"
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "End"
+msgstr "Fin"
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Immediate"
+msgstr "Inmediata"
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Sync"
+msgstr "Sincronizar"
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "At End"
+msgstr "Ao Final"
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Travel"
+msgstr "Viaxe"
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Start and end nodes are needed for a sub-transition."
+msgstr ""
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "No playback resource set at path: %s."
+msgstr ""
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Node Removed"
+msgstr "Nodo Eliminado"
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Transition Removed"
+msgstr "Transición Eliminada"
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Set Start Node (Autoplay)"
+msgstr ""
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid ""
+"Select and move nodes.\n"
+"RMB to add new nodes.\n"
+"Shift+LMB to create connections."
+msgstr ""
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Create new nodes."
+msgstr "Crear novos nodos."
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Connect nodes."
+msgstr "Conectar nodos."
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Remove selected node or transition."
+msgstr ""
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Toggle autoplay this animation on start, restart or seek to zero."
+msgstr ""
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Set the end animation. This is useful for sub-transitions."
+msgstr ""
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Transition: "
+msgstr "Transición: "
+
+#: editor/plugins/animation_state_machine_editor.cpp
+msgid "Play Mode:"
+msgstr "Modo de Reprodución:"
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "AnimationTree"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "New name:"
+msgstr "Novo nome:"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Scale:"
+msgstr "Escala:"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Fade In (s):"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Fade Out (s):"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Blend"
+msgstr "Mezcla"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Mix"
+msgstr "Mezcla"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Auto Restart:"
+msgstr "Auto Reinicio:"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Restart (s):"
+msgstr "Reiniciar (s):"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Random Restart (s):"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Start!"
+msgstr "Comezar!"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Amount:"
+msgstr "Cantidade:"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Blend 0:"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Blend 1:"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "X-Fade Time (s):"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Current:"
+msgstr "Actual:"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Input"
+msgstr "Engadir Entrada"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Clear Auto-Advance"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Set Auto-Advance"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Delete Input"
+msgstr "Eliminar Entrada"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Animation tree is valid."
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Animation tree is invalid."
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Animation Node"
+msgstr "Nodo de Animación"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "OneShot Node"
+msgstr "Nodo de Execución Única (Oneshot)"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Mix Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Blend2 Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Blend3 Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Blend4 Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "TimeScale Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "TimeSeek Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Transition Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Import Animations..."
+msgstr "Importar Animacións..."
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Edit Node Filters"
+msgstr "Editar Filtros do Nodo"
+
+#: editor/plugins/animation_tree_player_editor_plugin.cpp
+msgid "Filters..."
+msgstr "Filtros..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "Contidos:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "Ver Arquivos"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "Houbo un erro na conexión; por favor, inténtao de novo."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "Non houbo respota por parte do host:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed."
+msgstr "A petición fallou."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Cannot save response to:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Write error."
+msgstr "Erro de escritura."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect loop."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, timeout"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Timeout."
+msgstr "Timeout."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "Esperado:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "Recibido:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed SHA-256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Downloading (%s / %s)..."
+msgstr "Descargando (%s / %s)..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Downloading..."
+msgstr "Descargando..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving..."
+msgstr "Resolvendo..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "Ocioso"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Install..."
+msgstr "Instalar..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "Reintentar"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "Erro na Descarga"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Recently Updated"
+msgstr "Actualizado Recentemente"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Least Recently Updated"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Name (A-Z)"
+msgstr "Nome (A-Z)"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Name (Z-A)"
+msgstr "Nome (Z-A)"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "License (A-Z)"
+msgstr "Licenza (A-Z)"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "License (Z-A)"
+msgstr "Licenza (Z-A)"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "First"
+msgstr "Primeiro"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Previous"
+msgstr "Anterior"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Next"
+msgstr "Seguinte"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Last"
+msgstr "Derradeiro"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Todos"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No results for \"%s\"."
+msgstr "Non houbo resultado para \"%s\"."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Import..."
+msgstr "Importar..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Plugins..."
+msgstr "Características Adicionais (Plugins)..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Sort:"
+msgstr "Ordenar:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Category:"
+msgstr "Categoría:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Sitio:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support"
+msgstr "Soporte"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Oficial"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Probas"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Loading..."
+msgstr "Cargando..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr ""
+
+#: editor/plugins/baked_lightmap_editor_plugin.cpp
+msgid ""
+"Can't determine a save path for lightmap images.\n"
+"Save your scene and try again."
+msgstr ""
+
+#: editor/plugins/baked_lightmap_editor_plugin.cpp
+msgid ""
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
+"Light' flag is on."
+msgstr ""
+
+#: editor/plugins/baked_lightmap_editor_plugin.cpp
+msgid "Failed creating lightmap images, make sure path is writable."
+msgstr ""
+
+#: editor/plugins/baked_lightmap_editor_plugin.cpp
+msgid "Failed determining lightmap size. Maximum lightmap size too small?"
+msgstr ""
+
+#: editor/plugins/baked_lightmap_editor_plugin.cpp
+msgid ""
+"Some mesh is invalid. Make sure the UV2 channel values are contained within "
+"the [0.0,1.0] square region."
+msgstr ""
+"Algunha malla é inválida. Asegúrese de que o os valores do canle UV2 están "
+"contidos dentro da rexión cadrada ([0.0,1.0], [0.0,1.0])."
+
+#: editor/plugins/baked_lightmap_editor_plugin.cpp
+msgid ""
+"Godot editor was built without ray tracing support, lightmaps can't be baked."
+msgstr ""
+
+#: editor/plugins/baked_lightmap_editor_plugin.cpp
+msgid "Bake Lightmaps"
+msgstr ""
+
+#: editor/plugins/baked_lightmap_editor_plugin.cpp
+msgid "Select lightmap bake file:"
+msgstr ""
+
+#: editor/plugins/camera_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Preview"
+msgstr "Vista Previa"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Configure Snap"
+msgstr "Configurar Axuste de Cuadrícula"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Grid Offset:"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Grid Step:"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Primary Line Every:"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "steps"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Rotation Offset:"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Rotation Step:"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Scale Step:"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Move Vertical Guide"
+msgstr "Mover Guía Vertical"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Create Vertical Guide"
+msgstr "Crear Guía Vertical"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Remove Vertical Guide"
+msgstr "Eliminar Guía Vertical"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Move Horizontal Guide"
+msgstr "Mover Guía Horizontal"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Create Horizontal Guide"
+msgstr "Crear Guía Horizontal"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Remove Horizontal Guide"
+msgstr "Eliminar Guía Horizontal"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Create Horizontal and Vertical Guides"
+msgstr "Crear Guías Horizontais e Verticais"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Set CanvasItem \"%s\" Pivot Offset to (%d, %d)"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Rotate %d CanvasItems"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Rotate CanvasItem \"%s\" to %d degrees"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Move CanvasItem \"%s\" Anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Scale Node2D \"%s\" to (%s, %s)"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Resize Control \"%s\" to (%d, %d)"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Scale %d CanvasItems"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Scale CanvasItem \"%s\" to (%s, %s)"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Move %d CanvasItems"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Move CanvasItem \"%s\" to (%d, %d)"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid ""
+"Children of containers have their anchors and margins values overridden by "
+"their parent."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Presets for the anchors and margins values of a Control node."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid ""
+"When active, moving Control nodes changes their anchors instead of their "
+"margins."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Top Left"
+msgstr "Arriba á Esquerda"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Top Right"
+msgstr "Arriba á Dereita"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Bottom Right"
+msgstr "Abaixo á Dereita"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Bottom Left"
+msgstr "Abaixo á Esquerda"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Center Left"
+msgstr "Centro á Esquerda"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Center Top"
+msgstr "Centro Arriba"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Center Right"
+msgstr "Centro á Dereita"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Center Bottom"
+msgstr "Centro Abaixo"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Center"
+msgstr "Centro"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Left Wide"
+msgstr "Esquerdo Alto"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Top Wide"
+msgstr "Arriba Ancho"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Right Wide"
+msgstr "Dereito Alto"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Bottom Wide"
+msgstr "Abaixo Ancho"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "VCenter Wide"
+msgstr "CentradoV Alto"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "HCenter Wide"
+msgstr "CentradoH Ancho"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Full Rect"
+msgstr "Recta Completa"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Keep Ratio"
+msgstr "Manter Relación de Aspecto"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Anchors only"
+msgstr "Só Áncoras"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
+msgstr "Cambiar Áncoras e Marxes"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
+msgstr "Cambiar Áncoras"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid ""
+"Game Camera Override\n"
+"Overrides game camera with editor viewport camera."
+msgstr ""
+"Substituír a Cámara do Xogo\n"
+"Substitue a cámara do xogo pola cámara da Mini-ventá (Viewport) do editor."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid ""
+"Game Camera Override\n"
+"No game instance running."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Lock Selected"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Unlock Selected"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Group Selected"
+msgstr "Agrupar Selección"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Ungroup Selected"
+msgstr "Desagrupar Selección"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Paste Pose"
+msgstr "Pegar Pose"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Clear Guides"
+msgstr "Limpar Guías"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Create Custom Bone(s) from Node(s)"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Clear Bones"
+msgstr "Limpar Ósos"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Make IK Chain"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Clear IK Chain"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid ""
+"Warning: Children of a container get their position and size determined only "
+"by their parent."
+msgstr ""
+"Aviso: Os nodos fillos dun contedor (Container) teñen determinada a súa "
+"posición e tamaño unicamente polo seu padre."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/texture_region_editor_plugin.cpp
+#: editor/plugins/tile_set_editor_plugin.cpp scene/gui/graph_edit.cpp
+msgid "Zoom Reset"
+msgstr "Restablecer Zoom"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Select Mode"
+msgstr "Elixir Modo"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Drag: Rotate"
+msgstr "Arrastrar: Rotar"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Alt+Drag: Move"
+msgstr "Alt+Arrastrar: Mover"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Alt+RMB: Depth list selection"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Move Mode"
+msgstr "Mover Modo"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rotate Mode"
+msgstr "Modo Rotación"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Scale Mode"
+msgstr "Modo Escalado"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid ""
+"Show a list of all objects at the position clicked\n"
+"(same as Alt+RMB in select mode)."
+msgstr ""
+"Amosa unha lista de obxectos na posición na que se fixo clic\n"
+"(O mesmo que usar Alt+Clic Dereito en modo selección)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Click to change object's rotation pivot."
+msgstr "Faga clic para cambiar o pivote de rotación do obxecto."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Pan Mode"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Ruler Mode"
+msgstr "Modo Regra"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Toggle smart snapping."
+msgstr "Act./Desact. axuste intelixente."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Use Smart Snap"
+msgstr "Usar Axuste Intelixente"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Toggle grid snapping."
+msgstr "Act./Desact. axuste de cuadrícula."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Use Grid Snap"
+msgstr "Usar Axuste de Cuadrícula"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snapping Options"
+msgstr "Opcións de Axuste de Cuadrícula"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Use Rotation Snap"
+msgstr "Empregar Axuste de Rotación"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Use Scale Snap"
+msgstr "Empregar Axuste de Escalado"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap Relative"
+msgstr "Axuste Relativo"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Use Pixel Snap"
+msgstr "Empregar Axuste aos Píxeles"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Smart Snapping"
+msgstr "Axuste Intelixente"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap..."
+msgstr "Configurar Axuste de Cuadrícula..."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to Parent"
+msgstr "Axustar ao Pai"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to Node Anchor"
+msgstr "Axustar á Áncora do Nodo"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to Node Sides"
+msgstr "Axustar aos Laterais do Nodo"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to Node Center"
+msgstr "Axustar ao Centro do Nodo"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to Other Nodes"
+msgstr "Axustar a Outros Nodos"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to Guides"
+msgstr "Axustar as Guías"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "Fixar o obxecto no sitio (non se poderá mover)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Liberar o obxecto seleccionado (pode moverse)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr "Asegúrase de que os fillos do obxecto non sexan seleccionables."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "Volve a permitir seleccionar os fillos do obxecto."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Skeleton Options"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show Bones"
+msgstr "Amosar Ósos"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Make Custom Bone(s) from Node(s)"
+msgstr "Crear Óso(s) Personalizados a partir de Nodo(s)"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Clear Custom Bones"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View"
+msgstr "Ver"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Always Show Grid"
+msgstr "Sempre Amosar a Cuadrícula"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show Helpers"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show Rulers"
+msgstr "Amosar Regras"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show Guides"
+msgstr "Amosar Guías"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show Origin"
+msgstr "Amosar Orixe"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show Viewport"
+msgstr "Amosar Mini-Ventá (Viewport)"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show Group And Lock Icons"
+msgstr "Amosar Grupo e Bloquear Iconas"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Center Selection"
+msgstr "Centrar Selección"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Frame Selection"
+msgstr "Encadrar Selección"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Preview Canvas Scale"
+msgstr "Vista Previa da Escala do Lenzo (Canvas)"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Translation mask for inserting keys."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Rotation mask for inserting keys."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Scale mask for inserting keys."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Insert keys (based on mask)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid ""
+"Auto insert keys when objects are translated, rotated or scaled (based on "
+"mask).\n"
+"Keys are only added to existing tracks, no new tracks will be created.\n"
+"Keys must be inserted manually for the first time."
+msgstr ""
+"Inserción automática de claves cando os obxectos son trasladados, rotados, "
+"ou escalados (depenendo da Máscara).\n"
+"As chaves só engádense a pistas xa existentes; nunca se crean novas pistas.\n"
+"As chaves teñen que insertarse manualmente cando se utiliza por primeira vez."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Auto Insert Key"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Animation Key and Pose Options"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Insert Key (Existing Tracks)"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Copy Pose"
+msgstr "Copiar Pose"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Clear Pose"
+msgstr "Restablecer Pose"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr "Multiplicar Dimensión da Cuadrícula por 2"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
+msgstr "Dividir Dimensión da Cuadrícula por 2"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Pan View"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Add %s"
+msgstr "Engadir %s"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Adding %s..."
+msgstr "Engadindo %s..."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Cannot instantiate multiple nodes without root."
+msgstr "Non se pode instanciar varios nodos sen un nodo raíz."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "Create Node"
+msgstr "Crear Nodo"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "Error instancing scene from %s"
+msgstr "Erro instanciado escena desde %s"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Default Type"
+msgstr "Cambiar Tipo por Defecto"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid ""
+"Drag & drop + Shift : Add node as sibling\n"
+"Drag & drop + Alt : Change node type"
+msgstr ""
+"Arrastrar e Soltar + Shift : Engade nodo como irmán\n"
+"Arrastrar e Soltar + Alt : Cambiar tipo de nodo"
+
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+msgid "Create Polygon3D"
+msgstr ""
+
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "Editar Polígono"
+
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "Editar Polígono (Eliminar Punto)"
+
+#: editor/plugins/collision_shape_2d_editor_plugin.cpp
+msgid "Set Handle"
+msgstr ""
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Load Emission Mask"
+msgstr ""
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/cpu_particles_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Restart"
+msgstr "Reiniciar"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Clear Emission Mask"
+msgstr ""
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Particles"
+msgstr "Partículas"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Generated Point Count:"
+msgstr "Número de Puntos Xerados:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Emission Mask"
+msgstr ""
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Solid Pixels"
+msgstr ""
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Border Pixels"
+msgstr ""
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Directed Border Pixels"
+msgstr ""
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Capture from Pixel"
+msgstr ""
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Emission Colors"
+msgstr ""
+
+#: editor/plugins/cpu_particles_editor_plugin.cpp
+msgid "CPUParticles"
+msgstr "CPUParticles"
+
+#: editor/plugins/cpu_particles_editor_plugin.cpp
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Create Emission Points From Mesh"
+msgstr ""
+
+#: editor/plugins/cpu_particles_editor_plugin.cpp
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Create Emission Points From Node"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat 0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat 1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp
+msgid "Ease In"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp
+msgid "Ease Out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Modify Curve Point"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Modify Curve Tangent"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Load Curve Preset"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Add Point"
+msgstr "Engadir Punto"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Remove Point"
+msgstr "Eliminar Punto"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Left Linear"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Right Linear"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Load Preset"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Remove Curve Point"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Toggle Curve Linear Tangent"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Hold Shift to edit tangents individually"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Right click to add point"
+msgstr ""
+
+#: editor/plugins/gi_probe_editor_plugin.cpp
+msgid "Bake GI Probe"
+msgstr ""
+
+#: editor/plugins/gradient_editor_plugin.cpp
+msgid "Gradient Edited"
+msgstr ""
+
+#: editor/plugins/item_list_editor_plugin.cpp
+msgid "Item %d"
+msgstr "Elemento %d"
+
+#: editor/plugins/item_list_editor_plugin.cpp
+msgid "Items"
+msgstr "Elementos"
+
+#: editor/plugins/item_list_editor_plugin.cpp
+msgid "Item List Editor"
+msgstr ""
+
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Occluder Polygon"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh is empty!"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Couldn't create a Trimesh collision shape."
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Static Trimesh Body"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "This doesn't work on scene root!"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Trimesh Static Shape"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Can't create a single convex collision shape for the scene root."
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Couldn't create a single convex collision shape."
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Single Convex Shape"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Can't create multiple convex collision shapes for the scene root."
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Couldn't create any collision shapes."
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Multiple Convex Shapes"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Navigation Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Contained Mesh is not of type ArrayMesh."
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "UV Unwrap failed, mesh may not be manifold?"
+msgstr ""
+"Fallo no Unwrap de UV. Posiblemente a malla non é unha variedade (é dicir, "
+"que a malla non forma unha superficie conexa, contínua, e con dous caras "
+"diferenciables). En programas de modelaxe 3D pódese eliminar xeometría que "
+"non sexa unha variedade (\"Non Manifold\") fácilmente."
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "No mesh to debug."
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Model has no UV in this layer"
+msgstr "O modelo non ten UVs nesta capa"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "MeshInstance lacks a Mesh!"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh has not surface to create outlines from!"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh primitive type is not PRIMITIVE_TRIANGLES!"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Could not create outline!"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Outline"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Malla"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Trimesh Static Body"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid ""
+"Creates a StaticBody and assigns a polygon-based collision shape to it "
+"automatically.\n"
+"This is the most accurate (but slowest) option for collision detection."
+msgstr ""
+"Crear un nodo StaticBody e asígnalle automáticamente unha forma física "
+"baseada en polígonos.\n"
+"Esta é a forma máis precisa (e máis lenta) de detección de colisións."
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Trimesh Collision Sibling"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid ""
+"Creates a polygon-based collision shape.\n"
+"This is the most accurate (but slowest) option for collision detection."
+msgstr ""
+"Crea unha formá física baseada en polígonos.\n"
+"Esta é a forma máis precisa (pero máis lenta) de detectar colisións."
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Single Convex Collision Sibling"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid ""
+"Creates a single convex collision shape.\n"
+"This is the fastest (but least accurate) option for collision detection."
+msgstr ""
+"Crea unha única forma física convexa.\n"
+"Esta é a maneira más eficiente (pero menos precisa) de detectar colisións."
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Multiple Convex Collision Siblings"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid ""
+"Creates a polygon-based collision shape.\n"
+"This is a performance middle-ground between the two above options."
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Outline Mesh..."
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid ""
+"Creates a static outline mesh. The outline mesh will have its normals "
+"flipped automatically.\n"
+"This can be used instead of the SpatialMaterial Grow property when using "
+"that property isn't possible."
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "View UV1"
+msgstr "Amosar UV1"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "View UV2"
+msgstr "Amosar UV2"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Unwrap UV2 for Lightmap/AO"
+msgstr "Facer Unwrap do UV2 para Lightmap/AO"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Outline Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Outline Size:"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "UV Channel Debug"
+msgstr "Depuración do Canle UV"
+
+#: editor/plugins/mesh_library_editor_plugin.cpp
+msgid "Remove item %d?"
+msgstr ""
+
+#: editor/plugins/mesh_library_editor_plugin.cpp
+msgid ""
+"Update from existing scene?:\n"
+"%s"
+msgstr ""
+
+#: editor/plugins/mesh_library_editor_plugin.cpp
+msgid "Mesh Library"
+msgstr ""
+
+#: editor/plugins/mesh_library_editor_plugin.cpp
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Add Item"
+msgstr "Engadir Elemento"
+
+#: editor/plugins/mesh_library_editor_plugin.cpp
+msgid "Remove Selected Item"
+msgstr ""
+
+#: editor/plugins/mesh_library_editor_plugin.cpp
+msgid "Import from Scene"
+msgstr ""
+
+#: editor/plugins/mesh_library_editor_plugin.cpp
+msgid "Update from Scene"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "No mesh source specified (and no MultiMesh set in node)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "No mesh source specified (and MultiMesh contains no Mesh)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Mesh source is invalid (invalid path)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Mesh source is invalid (not a MeshInstance)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Mesh source is invalid (contains no Mesh resource)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "No surface source specified."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Surface source is invalid (invalid path)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Surface source is invalid (no geometry)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Surface source is invalid (no faces)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Select a Source Mesh:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Select a Target Surface:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Populate Surface"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Populate MultiMesh"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Target Surface:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Source Mesh:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "X-Axis"
+msgstr "Eixe X"
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Y-Axis"
+msgstr "Eixe Y"
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Z-Axis"
+msgstr "Eixe Z"
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Mesh Up Axis:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Random Rotation:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Random Tilt:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Random Scale:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Populate"
+msgstr "Encher"
+
+#: editor/plugins/navigation_polygon_editor_plugin.cpp
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Create Navigation Polygon"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Convert to CPUParticles"
+msgstr "Converter a CPUParticles"
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Generating Visibility Rect"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Generate Visibility Rect"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Can only set point into a ParticlesMaterial process material"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Convert to CPUParticles2D"
+msgstr "Converter a CPUParticles2D"
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Generation Time (sec):"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "The geometry's faces don't contain any area."
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "The geometry doesn't contain any faces."
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "\"%s\" doesn't inherit from Spatial."
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "\"%s\" doesn't contain geometry."
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "\"%s\" doesn't contain face geometry."
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Create Emitter"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Emission Points:"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Surface Points"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Surface Points+Normal (Directed)"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Volume"
+msgstr "Volume"
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Emission Source: "
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "A processor material of type 'ParticlesMaterial' is required."
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Generating AABB"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Generate Visibility AABB"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Remove Point from Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Remove Out-Control from Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Remove In-Control from Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Add Point to Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Split Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Move Point in Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Move In-Control in Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Move Out-Control in Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Select Points"
+msgstr "Seleccionar Puntos"
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Shift+Drag: Select Control Points"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Click: Add Point"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Left Click: Split Segment (in curve)"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Right Click: Delete Point"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Select Control Points (Shift+Drag)"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Add Point (in empty space)"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Delete Point"
+msgstr "Eliminar Puntos"
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Close Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp editor/plugins/theme_editor_plugin.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_export.cpp
+msgid "Options"
+msgstr "Opcións"
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Mirror Handle Angles"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Mirror Handle Lengths"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Curve Point #"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Set Curve Point Position"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Set Curve In Position"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Set Curve Out Position"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Split Path"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Remove Path Point"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Remove Out-Control Point"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Remove In-Control Point"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Split Segment (in curve)"
+msgstr ""
+
+#: editor/plugins/physical_bone_plugin.cpp
+msgid "Move Joint"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid ""
+"The skeleton property of the Polygon2D does not point to a Skeleton2D node"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Sync Bones"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid ""
+"No texture in this polygon.\n"
+"Set a texture to be able to edit UV."
+msgstr ""
+"Non hai unha textura neste polígono.\n"
+"Engada unha textura para editar o UV."
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Create UV Map"
+msgstr "Crear Mapa UV"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid ""
+"Polygon 2D has internal vertices, so it can no longer be edited in the "
+"viewport."
+msgstr ""
+"O polígono 2D ten vértices internos, polo que xa non se pode editar na Mini-"
+"Ventá (Viewport)."
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Create Polygon & UV"
+msgstr "Crear Polígono e UV"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Create Internal Vertex"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Remove Internal Vertex"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Invalid Polygon (need 3 different vertices)"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Add Custom Polygon"
+msgstr "Engadir Polígono Personalizado"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Remove Custom Polygon"
+msgstr "Eliminar Polígono Personalizado"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Transform UV Map"
+msgstr "Transformar Mapa UV"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Transform Polygon"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Paint Bone Weights"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Open Polygon 2D UV editor."
+msgstr "Abrir Editor UV de Polígonos 2D."
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Polygon 2D UV Editor"
+msgstr "Editor UV de Polígonos 2D"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "UV"
+msgstr "UV"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Points"
+msgstr "Puntos"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Polygons"
+msgstr "Polígonos"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Bones"
+msgstr "Ósos"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Move Points"
+msgstr "Mover Puntos"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Command: Rotate"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Shift: Move All"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Shift+Command: Scale"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Ctrl: Rotate"
+msgstr "Ctrl: Rotar"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Shift+Ctrl: Scale"
+msgstr "Shift+Ctrl: Escalar"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Move Polygon"
+msgstr "Mover Polígono"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Rotate Polygon"
+msgstr "Rotar Polígono"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Scale Polygon"
+msgstr "Escalar Polígono"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Create a custom polygon. Enables custom polygon rendering."
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid ""
+"Remove a custom polygon. If none remain, custom polygon rendering is "
+"disabled."
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Paint weights with specified intensity."
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Unpaint weights with specified intensity."
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Radius:"
+msgstr "Radio:"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Copy Polygon to UV"
+msgstr "Copiar Polígono a UV"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Copy UV to Polygon"
+msgstr "Copiar UV a Polígono"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Clear UV"
+msgstr "Limpar UV"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Grid Settings"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Snap"
+msgstr "Axuste de Cuadrícula"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Enable Snap"
+msgstr "Activar Axuste"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Grid"
+msgstr "Cuadrícula"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Amosar Cuadrícula"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Configure Grid:"
+msgstr "Configurar Cuadrícula:"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Grid Offset X:"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Grid Offset Y:"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Grid Step X:"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Grid Step Y:"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Sync Bones to Polygon"
+msgstr ""
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "ERROR: Couldn't load resource!"
+msgstr ""
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "Add Resource"
+msgstr "Engadir Recurso"
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "Rename Resource"
+msgstr "Renomear Recurso"
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Delete Resource"
+msgstr "Eliminar Recurso"
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "Resource clipboard is empty!"
+msgstr ""
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "Paste Resource"
+msgstr "Pegar Recurso"
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/scene_tree_editor.cpp
+msgid "Instance:"
+msgstr "Instancia:"
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp
+#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Type:"
+msgstr "Tipo:"
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp
+msgid "Open in Editor"
+msgstr ""
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "Load Resource"
+msgstr "Cargar Recurso"
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "ResourcePreloader"
+msgstr ""
+
+#: editor/plugins/root_motion_editor_plugin.cpp
+msgid "AnimationTree has no path set to an AnimationPlayer"
+msgstr ""
+
+#: editor/plugins/root_motion_editor_plugin.cpp
+msgid "Path to AnimationPlayer is invalid"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Clear Recent Files"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Close and save changes?"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error writing TextFile:"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Could not load file at:"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error saving file!"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error while saving theme."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error Saving"
+msgstr "Erro ao Gardar"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error importing theme."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error Importing"
+msgstr "Erro ao Importar"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "New Text File..."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Open File"
+msgstr "Abrir Arquivo"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Save File As..."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Can't obtain the script for running."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Script failed reloading, check console for errors."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Script is not in tool mode, will not be able to run."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid ""
+"To run this script, it must inherit EditorScript and be set to tool mode."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Import Theme"
+msgstr "Importar Tema"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error while saving theme"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error saving"
+msgstr "Erro ao gardar"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Save Theme As..."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "%s Class Reference"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+msgid "Find Next"
+msgstr "Atopar Seguinte"
+
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+msgid "Find Previous"
+msgstr "Atopar Anterior"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Filter scripts"
+msgstr "Filtrar scripts"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Toggle alphabetical sorting of the method list."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Filter methods"
+msgstr "Filtrar métodos"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Sort"
+msgstr "Ordenar"
+
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "Move Up"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "Move Down"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Next script"
+msgstr "Seguinte script"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Previous script"
+msgstr "Anterior script"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "File"
+msgstr "Arquivo"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Open..."
+msgstr "Abrir..."
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Reopen Closed Script"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Save All"
+msgstr "Gardar Todo"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Soft Reload Script"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Copy Script Path"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "History Previous"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "History Next"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme"
+msgstr "Tema"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Import Theme..."
+msgstr "Importar Tema..."
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Reload Theme"
+msgstr "Volver a Cargar Tema"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Save Theme"
+msgstr "Gardar Tema"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Close All"
+msgstr "Pechar Todo"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Close Docs"
+msgstr "Pechar Documentación"
+
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Executar"
+
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Buscar"
+
+#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+msgid "Step Into"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+msgid "Step Over"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+msgid "Break"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Continue"
+msgstr "Continuar"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Keep Debugger Open"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Debug with External Editor"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Open Godot online documentation."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Search the reference documentation."
+msgstr "Buscar na documentación de referencia."
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Go to previous edited document."
+msgstr "Ir ao anterior documento editado."
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Go to next edited document."
+msgstr "Ir ao seguinte documento editado."
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Discard"
+msgstr "Descartar"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?:"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+msgid "Debugger"
+msgstr "Depurador"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Search Results"
+msgstr "Resultados de Búsqueda"
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Clear Recent Scripts"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Connections to method:"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp editor/script_editor_debugger.cpp
+msgid "Source"
+msgstr "Fonte"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Target"
+msgstr "Obxectivo"
+
+#: editor/plugins/script_text_editor.cpp
+msgid ""
+"Missing connected method '%s' for signal '%s' from node '%s' to node '%s'."
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "[Ignore]"
+msgstr "[Ignorar]"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Line"
+msgstr "Liña"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Go to Function"
+msgstr "Ir a Función"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Only resources from filesystem can be dropped."
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Can't drop nodes because script '%s' is not used in this scene."
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Lookup Symbol"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Pick Color"
+msgstr "Elexir Cor"
+
+#: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp
+msgid "Convert Case"
+msgstr "Converter Maiús./Minús."
+
+#: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp
+msgid "Uppercase"
+msgstr "Maiúscula"
+
+#: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp
+msgid "Lowercase"
+msgstr "Minúscula"
+
+#: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp
+msgid "Capitalize"
+msgstr "Capitalizar"
+
+#: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp
+msgid "Syntax Highlighter"
+msgstr "Marcador de Sintaxe"
+
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+msgid "Bookmarks"
+msgstr "Marcadores"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Breakpoints"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+msgid "Go To"
+msgstr "Ir a"
+
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+msgid "Cut"
+msgstr "Cortar"
+
+#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
+#: scene/gui/text_edit.cpp
+msgid "Select All"
+msgstr "Seleccionar Todo"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Delete Line"
+msgstr "Eliminar Liña"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Indent Left"
+msgstr "Sangrado á Esquerda"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Indent Right"
+msgstr "Sangrado á Dereita"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Toggle Comment"
+msgstr "Comentar/Descomentar"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Fold/Unfold Line"
+msgstr "Expandir/Colapsar Liña"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Fold All Lines"
+msgstr "Colapsar Tódalas Liñas"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Unfold All Lines"
+msgstr "Expandir Tódalas Liñas"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Clone Down"
+msgstr "Clonar Liña"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Complete Symbol"
+msgstr "Completar Símbolo"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Evaluate Selection"
+msgstr "Evaluar Selección"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Trim Trailing Whitespace"
+msgstr "Eliminar Espazos ao Final da Liña"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Convert Indent to Spaces"
+msgstr "Convertir Indentación a Espazos"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Convert Indent to Tabs"
+msgstr "Convertir Identación a Tabulacións"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Auto Indent"
+msgstr "Auto Indentar"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Find in Files..."
+msgstr "Buscar en Arquivos.."
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Contextual Help"
+msgstr "Axuda Contextual"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Toggle Bookmark"
+msgstr "Act./Desact. Marcapáxinas"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Go to Next Bookmark"
+msgstr "Ir ao Seguinte Marcapáxinas"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Go to Previous Bookmark"
+msgstr "Ir ao Anterior Marcapáxinas"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Remove All Bookmarks"
+msgstr "Eliminar Tódolos Marcapáxinas"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Go to Function..."
+msgstr "Ir a Función..."
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Go to Line..."
+msgstr "Ir a Liña..."
+
+#: editor/plugins/script_text_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Toggle Breakpoint"
+msgstr "Act./Desact. Punto de Interrupción (Breakpoint)"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Remove All Breakpoints"
+msgstr "Eliminar Tódolos Puntos de Interrupción (Breakpoints)"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Go to Next Breakpoint"
+msgstr "Ir ao Seguinte Punto de Interrupción"
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Go to Previous Breakpoint"
+msgstr "Ir ao Anterior Punto de Interrupción"
+
+#: editor/plugins/shader_editor_plugin.cpp
+msgid ""
+"This shader has been modified on on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Este shader foi modificado en disco.\n"
+"Que acción deberían de tomarse?"
+
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Shader"
+msgstr "Shader"
+
+#: editor/plugins/skeleton_2d_editor_plugin.cpp
+msgid "This skeleton has no bones, create some children Bone2D nodes."
+msgstr "Este esqueleto non ten ósos; crea uns nodos fillo Bone2D."
+
+#: editor/plugins/skeleton_2d_editor_plugin.cpp
+msgid "Create Rest Pose from Bones"
+msgstr "Crear Pose de Repouso a partir dos Ósos"
+
+#: editor/plugins/skeleton_2d_editor_plugin.cpp
+msgid "Set Rest Pose to Bones"
+msgstr "Asignar Pose de Repouso aos Ósos"
+
+#: editor/plugins/skeleton_2d_editor_plugin.cpp
+msgid "Skeleton2D"
+msgstr "Skeleton2D"
+
+#: editor/plugins/skeleton_2d_editor_plugin.cpp
+msgid "Make Rest Pose (From Bones)"
+msgstr "Crear Pose de Repouso (a partir dos Ósos)"
+
+#: editor/plugins/skeleton_2d_editor_plugin.cpp
+msgid "Set Bones to Rest Pose"
+msgstr "Asignar Pose de Repouso aos Ósos"
+
+#: editor/plugins/skeleton_editor_plugin.cpp
+msgid "Create physical bones"
+msgstr "Crear ósos físicos"
+
+#: editor/plugins/skeleton_editor_plugin.cpp
+msgid "Skeleton"
+msgstr "Esqueleto"
+
+#: editor/plugins/skeleton_editor_plugin.cpp
+msgid "Create physical skeleton"
+msgstr "Crear esqueleto físico"
+
+#: editor/plugins/skeleton_ik_editor_plugin.cpp
+msgid "Play IK"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Orthogonal"
+msgstr "Ortogonal"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Perspective"
+msgstr "Perspetiva"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Transform Aborted."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "X-Axis Transform."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Y-Axis Transform."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Z-Axis Transform."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Plane Transform."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Scaling: "
+msgstr "Escalado: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Translating: "
+msgstr "Trasladando: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rotating %s degrees."
+msgstr "Rotando % graos."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Keying is disabled (no key inserted)."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Animation Key Inserted."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Pitch"
+msgstr "Cabeceo"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Yaw"
+msgstr "Guiñada"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Tamaño"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Objects Drawn"
+msgstr "Obxectos Debuxados"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Material Changes"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Shader Changes"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Surface Changes"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Draw Calls"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Vertices"
+msgstr "Vértices"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Top View."
+msgstr "Vista Superior."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Bottom View."
+msgstr "Vista Inferior."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Bottom"
+msgstr "Inferior"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Left View."
+msgstr "Vista Esquerda."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Left"
+msgstr "Esquerda"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Right View."
+msgstr "Vista Dereita."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Right"
+msgstr "Dereita"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Front View."
+msgstr "Vista Frontal."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Front"
+msgstr "Frontal"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rear View."
+msgstr "Vista Traseria."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rear"
+msgstr "Traseira"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Align Transform with View"
+msgstr "Aliñar Transformación con Perspectiva"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Align Rotation with View"
+msgstr "Aliñar Rotación con Perspectiva"
+
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "No parent to instance a child at."
+msgstr "Non hai un pai ao que instanciarlle un fillo."
+
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "This operation requires a single selected node."
+msgstr "Esta operación precisa un único nodo seleccionado."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Auto Orthogonal Enabled"
+msgstr "Auto Ortogonal Activado"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Lock View Rotation"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Display Normal"
+msgstr "Mostrar de Forma Normal"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Display Wireframe"
+msgstr "Mostrar Malla"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Display Overdraw"
+msgstr "Mostrar Zonas Redebuxadas (Overdraw)"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Display Unshaded"
+msgstr "Mostrar Sen Sombreado"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Environment"
+msgstr "Amosar Entorno"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Gizmos"
+msgstr "Amosar Gizmos"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Information"
+msgstr "Amosar Información"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View FPS"
+msgstr "Ver FPS"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Half Resolution"
+msgstr "Resolución á Metade"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Audio Listener"
+msgstr "Oínte de Son"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Enable Doppler"
+msgstr "Activar Efecto Doppler"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Cinematic Preview"
+msgstr "Vista Previa Cinemática"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Not available when using the GLES2 renderer."
+msgstr "Non dispoñible cando se está usando o renderizador GLES2."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Left"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Right"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Forward"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Backwards"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Up"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Down"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Speed Modifier"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Slow Modifier"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Rotation Locked"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid ""
+"Note: The FPS value displayed is the editor's framerate.\n"
+"It cannot be used as a reliable indication of in-game performance."
+msgstr ""
+"Nota: o valor dos FPS corresponde aos fotogramas por segundo do editor.\n"
+"Non pode usarse como unha forma fiable de medir o rendemento do xogo."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "XForm Dialog"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid ""
+"Click to toggle between visibility states.\n"
+"\n"
+"Open eye: Gizmo is visible.\n"
+"Closed eye: Gizmo is hidden.\n"
+"Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")."
+msgstr ""
+"Faga clic para cambiar entre estados de visibilidade.\n"
+"\n"
+"Ollo aberto: Gizmo visible.\n"
+"Ollo pechado: Gizmo oculto.\n"
+"Ollo medio aberto, medio pechado: Gizmo visible ao través de superficies "
+"opacas (\"raios x\")."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Snap Nodes To Floor"
+msgstr "Axustar Nodos ao Chan"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Couldn't find a solid floor to snap the selection to."
+msgstr "Non se puido encontrar chan sólido no que poder axustar a selección."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid ""
+"Drag: Rotate\n"
+"Alt+Drag: Move\n"
+"Alt+RMB: Depth list selection"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Local Space"
+msgstr "Usar Espazo Local"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "Usar Axuste de Cuadrícula"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Bottom View"
+msgstr "Vista Inferior"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Top View"
+msgstr "Vista Superior"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rear View"
+msgstr "Vista Traseira"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Front View"
+msgstr "Vista Frontal"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Left View"
+msgstr "Vista Esquerda"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Right View"
+msgstr "Vista Dereita"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Switch Perspective/Orthogonal View"
+msgstr "Vista Perspectiva/Ortogonal"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Insert Animation Key"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Focus Origin"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Focus Selection"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Toggle Freelook"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Transform"
+msgstr "Transformación"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Snap Object to Floor"
+msgstr "Axustar Obxecto ao Chan"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Transform Dialog..."
+msgstr "Aplicar Transformación..."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "1 Viewport"
+msgstr "1 Ventá"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "2 Viewports"
+msgstr "2 Ventás"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "2 Viewports (Alt)"
+msgstr "2 Ventás (Alt)"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "3 Viewports"
+msgstr "3 Ventás"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "3 Viewports (Alt)"
+msgstr "3 Ventás (Alt)"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "4 Viewports"
+msgstr "4 Ventás"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Gizmos"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Origin"
+msgstr "Amosar Orixe"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Grid"
+msgstr "Amosar Cuadrícula"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Settings..."
+msgstr "Axustes..."
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Snap Settings"
+msgstr "Configuración de Axuste"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Translate Snap:"
+msgstr "Axuste de Translación:"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rotate Snap (deg.):"
+msgstr "Axuste de Rotación (graos):"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Scale Snap (%):"
+msgstr "Axuste de Escalado (%):"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Viewport Settings"
+msgstr "Axustes de Visión"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Perspective FOV (deg.):"
+msgstr "Campo de Visión (graos):"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Z-Near:"
+msgstr "Plano Próximo:"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Z-Far:"
+msgstr "Plano Afastado:"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Transform Change"
+msgstr "Cambio de Transformación"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Translate:"
+msgstr "Trasladar:"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rotate (deg.):"
+msgstr "Rotar (graos):"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Scale (ratio):"
+msgstr "Escalar (Razón):"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Transform Type"
+msgstr "Tipo de Transformación"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Pre"
+msgstr "Anterior (Pre)"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Post"
+msgstr "Posterior (Post)"
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Nameless gizmo"
+msgstr "Gizmo sen nome"
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Create Mesh2D"
+msgstr "Crear Mesh2D"
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Mesh2D Preview"
+msgstr "Vista Previa de Mesh2D"
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Create Polygon2D"
+msgstr "Crear Polygon2D"
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Polygon2D Preview"
+msgstr "Vista Previa Polygon2D"
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Create CollisionPolygon2D"
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "CollisionPolygon2D Preview"
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Create LightOccluder2D"
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "LightOccluder2D Preview"
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Sprite is empty!"
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Can't convert a sprite using animation frames to mesh."
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Invalid geometry, can't replace by mesh."
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Convert to Mesh2D"
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Invalid geometry, can't create polygon."
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Convert to Polygon2D"
+msgstr "Convertir a Polygon2D"
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Invalid geometry, can't create collision polygon."
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Create CollisionPolygon2D Sibling"
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Invalid geometry, can't create light occluder."
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Create LightOccluder2D Sibling"
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Sprite"
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Simplification: "
+msgstr "Simplificación: "
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Shrink (Pixels): "
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Grow (Pixels): "
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Update Preview"
+msgstr ""
+
+#: editor/plugins/sprite_editor_plugin.cpp
+msgid "Settings:"
+msgstr "Axustes:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "No Frames Selected"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Add %d Frame(s)"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Add Frame"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Unable to load images"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "ERROR: Couldn't load frame resource!"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Resource clipboard is empty or not a texture!"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Paste Frame"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Add Empty"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Change Animation FPS"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "(empty)"
+msgstr "(baleiro)"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Move Frame"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Animations:"
+msgstr "Animacións:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "New Animation"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Speed:"
+msgstr "Velocidade:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Bucle"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Animation Frames:"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Add a Texture from File"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Add Frames from a Sprite Sheet"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Insert Empty (Before)"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Insert Empty (After)"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Move (Before)"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Move (After)"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Select Frames"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Horizontal:"
+msgstr "Horizontal:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Vertical:"
+msgstr "Vertical:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Select/Clear All Frames"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Create Frames from Sprite Sheet"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "SpriteFrames"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Set Region Rect"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Set Margin"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Snap Mode:"
+msgstr "Modo de Axuste:"
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+#: scene/resources/visual_shader.cpp
+msgid "None"
+msgstr "Ningún"
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Pixel Snap"
+msgstr "Axustar aos Píxeles"
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Grid Snap"
+msgstr "Axuste de Cuadrícula"
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Auto Slice"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Offset:"
+msgstr "Offset:"
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Step:"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Sep.:"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "TextureRegion"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Add All Items"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Add All"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Remove All Items"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp editor/project_manager.cpp
+msgid "Remove All"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Edit Theme"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Add Class Items"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Remove Class Items"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Create Empty Template"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Create Empty Editor Template"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Create From Current Editor Theme"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Toggle Button"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Disabled Button"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Item"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Disabled Item"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Check Item"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Checked Item"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Radio Item"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Checked Radio Item"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Named Sep."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Submenu"
+msgstr "Submenú"
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Subitem 1"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Subitem 2"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Has"
+msgstr "Ten"
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Many"
+msgstr "Moitas"
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Disabled LineEdit"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Tab 1"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Tab 2"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Tab 3"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Editable Item"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Subtree"
+msgstr "Subárbore"
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Has,Many,Options"
+msgstr "Ten,Moitas,Opcións"
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Data Type:"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Icon"
+msgstr "Icona"
+
+#: editor/plugins/theme_editor_plugin.cpp editor/rename_dialog.cpp
+msgid "Style"
+msgstr "Estilo"
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Fonte"
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Color"
+msgstr "Cor"
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme File"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Erase Selection"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Fix Invalid Tiles"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cut Selection"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Paint TileMap"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Line Draw"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Rectangle Paint"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Bucket Fill"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Erase TileMap"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Find Tile"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Transpose"
+msgstr "Transpoñer"
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Disable Autotile"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Enable Priority"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Filter tiles"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Give a TileSet resource to this TileMap to use its tiles."
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Paint Tile"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid ""
+"Shift+LMB: Line Draw\n"
+"Shift+Command+LMB: Rectangle Paint"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid ""
+"Shift+LMB: Line Draw\n"
+"Shift+Ctrl+LMB: Rectangle Paint"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Pick Tile"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Rotate Left"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Rotate Right"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Flip Horizontally"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Flip Vertically"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Clear Transform"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Add Texture(s) to TileSet."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Remove selected Texture from TileSet."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Create from Scene"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Merge from Scene"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "New Single Tile"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "New Autotile"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "New Atlas"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Next Coordinate"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Select the next shape, subtile, or Tile."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Previous Coordinate"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Select the previous shape, subtile, or Tile."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Region"
+msgstr "Rexión"
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Collision"
+msgstr "Colisión"
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Occlusion"
+msgstr "Oclusión"
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Navigation"
+msgstr "Navegación"
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Bitmask"
+msgstr "Máscara de Bits"
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Priority"
+msgstr "Prioridade"
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Z Index"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Region Mode"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Collision Mode"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Occlusion Mode"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Navigation Mode"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Bitmask Mode"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Priority Mode"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Icon Mode"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Z Index Mode"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Copy bitmask."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Paste bitmask."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Erase bitmask."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Create a new rectangle."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "New Rectangle"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Create a new polygon."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "New Polygon"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Delete Selected Shape"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Keep polygon inside region Rect."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Enable snap and show grid (configurable via the Inspector)."
+msgstr ""
+"Activar axuste de cuadrícula e amosar cuadrícula (configurable no inspector)."
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Display Tile Names (Hold Alt Key)"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid ""
+"Add or select a texture on the left panel to edit the tiles bound to it."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Remove selected texture? This will remove all tiles which use it."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "You haven't selected a texture to remove."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Create from scene? This will overwrite all current tiles."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Merge from scene?"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Remove Texture"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "%s file(s) were not added because was already on the list."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid ""
+"Drag handles to edit Rect.\n"
+"Click on another Tile to edit it."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Delete selected Rect."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid ""
+"Select current edited sub-tile.\n"
+"Click on another Tile to edit it."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Delete polygon."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid ""
+"LMB: Set bit on.\n"
+"RMB: Set bit off.\n"
+"Shift+LMB: Set wildcard bit.\n"
+"Click on another Tile to edit it."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid ""
+"Select sub-tile to use as icon, this will be also used on invalid autotile "
+"bindings.\n"
+"Click on another Tile to edit it."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid ""
+"Select sub-tile to change its priority.\n"
+"Click on another Tile to edit it."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid ""
+"Select sub-tile to change its z index.\n"
+"Click on another Tile to edit it."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Set Tile Region"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Create Tile"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Set Tile Icon"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Edit Tile Bitmask"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Edit Collision Polygon"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Edit Occlusion Polygon"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Edit Navigation Polygon"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Paste Tile Bitmask"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Clear Tile Bitmask"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Make Polygon Concave"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Make Polygon Convex"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Remove Tile"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Remove Collision Polygon"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Remove Occlusion Polygon"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Remove Navigation Polygon"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Edit Tile Priority"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Edit Tile Z Index"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Make Convex"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Make Concave"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Create Collision Polygon"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Create Occlusion Polygon"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "This property can't be changed."
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "TileSet"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "No VCS addons are available."
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Error"
+msgstr "Erro"
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "No files added to stage"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Commit"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "VCS Addon is not initialized"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Version Control System"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Initialize"
+msgstr "Inicializar"
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Staging area"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Detect new changes"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Changes"
+msgstr "Cambios"
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Modified"
+msgstr "Modificado"
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Renamed"
+msgstr "Renomeado"
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Deleted"
+msgstr "Eliminado"
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Typechange"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Stage Selected"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Stage All"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Commit Changes"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+#: modules/gdnative/gdnative_library_singleton_editor.cpp
+msgid "Status"
+msgstr "Estado"
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "View file diffs before committing them to the latest version"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "No file diff is active"
+msgstr ""
+
+#: editor/plugins/version_control_editor_plugin.cpp
+msgid "Detect changes in file diff"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "(GLES3 only)"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Add Output"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Scalar"
+msgstr "Escalar"
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Vector"
+msgstr "Vector"
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Boolean"
+msgstr "Booleano"
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Sampler"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Add input port"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Add output port"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Change input port type"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Change output port type"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Change input port name"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Change output port name"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Remove input port"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Remove output port"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Set expression"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Resize VisualShader node"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Set Uniform Name"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Set Input Default Port"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Add Node to Visual Shader"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Node(s) Moved"
+msgstr "Nodo(s) Movido(s)"
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Duplicate Nodes"
+msgstr "Duplicar Nodos"
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Paste Nodes"
+msgstr "Pegar Nodos"
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Delete Nodes"
+msgstr "Eliminar Nodos"
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Visual Shader Input Type Changed"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "UniformRef Name Changed"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Vertex"
+msgstr "Vertex"
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Fragment"
+msgstr "Fragment"
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Light"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Show resulted shader code."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Create Shader Node"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Color function."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Color operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Grayscale function."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Converts HSV vector to RGB equivalent."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Converts RGB vector to HSV equivalent."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Sepia function."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Burn operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Darken operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Difference operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Dodge operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "HardLight operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Lighten operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Overlay operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Screen operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "SoftLight operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Color constant."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Color uniform."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the boolean result of the %s comparison between two parameters."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Equal (==)"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Greater Than (>)"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Greater Than or Equal (>=)"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Returns an associated vector if the provided scalars are equal, greater or "
+"less."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Returns the boolean result of the comparison between INF and a scalar "
+"parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Returns the boolean result of the comparison between NaN and a scalar "
+"parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Less Than (<)"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Less Than or Equal (<=)"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Not Equal (!=)"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Returns an associated vector if the provided boolean value is true or false."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Returns an associated scalar if the provided boolean value is true or false."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the boolean result of the comparison between two parameters."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Returns the boolean result of the comparison between INF (or NaN) and a "
+"scalar parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Boolean constant."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Boolean uniform."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "'%s' input parameter for all shader modes."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Input parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "'%s' input parameter for vertex and fragment shader modes."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "'%s' input parameter for fragment and light shader modes."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "'%s' input parameter for fragment shader mode."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "'%s' input parameter for light shader mode."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "'%s' input parameter for vertex shader mode."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "'%s' input parameter for vertex and fragment shader mode."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Scalar function."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Scalar operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "E constant (2.718282). Represents the base of the natural logarithm."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Epsilon constant (0.00001). Smallest possible scalar number."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Phi constant (1.618034). Golden ratio."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Pi/4 constant (0.785398) or 45 degrees."
+msgstr "Constante Pi/4 (0.785398), ou 45 graos."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Pi/2 constant (1.570796) or 90 degrees."
+msgstr "Constante Pi/2 (1.570796), ou 90 graos."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Pi constant (3.141593) or 180 degrees."
+msgstr "Constante Pi (3.141593), ou 180 graos."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Tau constant (6.283185) or 360 degrees."
+msgstr "Constante Tau (6.283185), ou 360 graos."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Sqrt2 constant (1.414214). Square root of 2."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the absolute value of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the arc-cosine of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the inverse hyperbolic cosine of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the arc-sine of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the inverse hyperbolic sine of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the arc-tangent of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the arc-tangent of the parameters."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the inverse hyperbolic tangent of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Finds the nearest integer that is greater than or equal to the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Constrains a value to lie between two further values."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the cosine of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the hyperbolic cosine of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Converts a quantity in radians to degrees."
+msgstr "Converte unha cantidade de radiáns a graos."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Base-e Exponential."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Base-2 Exponential."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Finds the nearest integer less than or equal to the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Computes the fractional part of the argument."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the inverse of the square root of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Natural logarithm."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Base-2 logarithm."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the greater of two values."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the lesser of two values."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Linear interpolation between two scalars."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the opposite value of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "1.0 - scalar"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Returns the value of the first parameter raised to the power of the second."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Converts a quantity in degrees to radians."
+msgstr "Converte unha cantidade de graos a radiáns."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "1.0 / scalar"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Finds the nearest integer to the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Finds the nearest even integer to the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Clamps the value between 0.0 and 1.0."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Extracts the sign of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the sine of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the hyperbolic sine of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the square root of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"SmoothStep function( scalar(edge0), scalar(edge1), scalar(x) ).\n"
+"\n"
+"Returns 0.0 if 'x' is smaller than 'edge0' and 1.0 if x is larger than "
+"'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 "
+"using Hermite polynomials."
+msgstr ""
+"SmoothStep function( scalar(edge0), scalar(edge1), scalar(x) ).\n"
+"\n"
+"Devolve 0.0 se 'x' é menor que 'edge0' e 1.0 se x é maior que 'edge1'. En "
+"caso contrario devólvese un valor interpolado entre 0.0 e 1.0 usando "
+"polinomios de Hermite."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Step function( scalar(edge), scalar(x) ).\n"
+"\n"
+"Returns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."
+msgstr ""
+"Step function( scalar(edge), scalar(x) ).\n"
+"\n"
+"Devolve 0.0 se 'x' e menor que 'edge'; e 1.0 en caso contrario."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the tangent of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the hyperbolic tangent of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Finds the truncated value of the parameter."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Adds scalar to scalar."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Divides scalar by scalar."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Multiplies scalar by scalar."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the remainder of the two scalars."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Subtracts scalar from scalar."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Scalar constant."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Scalar uniform."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Perform the cubic texture lookup."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Perform the texture lookup."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Cubic texture uniform lookup."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "2D texture uniform lookup."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "2D texture uniform lookup with triplanar."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Transform function."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Calculate the outer product of a pair of vectors.\n"
+"\n"
+"OuterProduct treats the first parameter 'c' as a column vector (matrix with "
+"one column) and the second parameter 'r' as a row vector (matrix with one "
+"row) and does a linear algebraic matrix multiply 'c * r', yielding a matrix "
+"whose number of rows is the number of components in 'c' and whose number of "
+"columns is the number of components in 'r'."
+msgstr ""
+"Calcula o produto exterior dun par de vectores.\n"
+"\n"
+"OuterProduct trata o primeiro parámetro 'c' coma un vector columna (matriz "
+"con unha soa columna), e o segundo parámetro 'r' coma un vector fila (matriz "
+"con unha soa fila), e fai a multiplicación alxebráica 'c * r'. Esto devolve "
+"unha matriz cun número de filas igual ao número de compoñentes en 'c', e cun "
+"número de columnas igual ao número de compoñentes en 'r'."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Composes transform from four vectors."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Decomposes transform to four vectors."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Calculates the determinant of a transform."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Calculates the inverse of a transform."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Calculates the transpose of a transform."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Multiplies transform by transform."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Multiplies vector by transform."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Transform constant."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Transform uniform."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Vector function."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Vector operator."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Composes vector from three scalars."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Decomposes vector to three scalars."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Calculates the cross product of two vectors."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the distance between two points."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Calculates the dot product of two vectors."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Returns the vector that points in the same direction as a reference vector. "
+"The function has three vector parameters : N, the vector to orient, I, the "
+"incident vector, and Nref, the reference vector. If the dot product of I and "
+"Nref is smaller than zero the return value is N. Otherwise -N is returned."
+msgstr ""
+"Devolve o vector que ten a mesma dirección que o vector de referencia. A "
+"función ten tres vector como parámetros: N, o vector a orientar; I, o vector "
+"incidente; e Nref, o vector de referencia. Se o produto escalar de I e Nref "
+"é menor que cero (forman un ángulo maior que 90 graos) entón devolve N. En "
+"caso contrario devolve -N."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Calculates the length of a vector."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Linear interpolation between two vectors."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Linear interpolation between two vectors using scalar."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Calculates the normalize product of vector."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "1.0 - vector"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "1.0 / vector"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Returns the vector that points in the direction of reflection ( a : incident "
+"vector, b : normal vector )."
+msgstr ""
+"Devolve o vector que apunta na dirección de reflexo ( a : vector incidente, "
+"b : vector normal)."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the vector that points in the direction of refraction."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n"
+"\n"
+"Returns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than "
+"'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 "
+"using Hermite polynomials."
+msgstr ""
+"SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n"
+"\n"
+"Devolve 0.0 se 'x' é menor que 'edge0' e 1.0 se x é maior que 'edge1'. En "
+"caso contrario devólvese un valor interpolado entre 0.0 e 1.0 usando "
+"polinomios de Hermite."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n"
+"\n"
+"Returns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than "
+"'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 "
+"using Hermite polynomials."
+msgstr ""
+"SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n"
+"\n"
+"Devolve 0.0 se 'x' é menor que 'edge0' e 1.0 se x é maior que 'edge1'. En "
+"caso contrario devólvese un valor interpolado entre 0.0 e 1.0 usando "
+"polinomios de Hermite."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Step function( vector(edge), vector(x) ).\n"
+"\n"
+"Returns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."
+msgstr ""
+"Step function( vector(edge), vector(x) ).\n"
+"\n"
+"Devolve 0.0 se 'x' e menor que 'edge'; e 1.0 en caso contrario."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Step function( scalar(edge), vector(x) ).\n"
+"\n"
+"Returns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."
+msgstr ""
+"Step function( scalar(edge), vector(x) ).\n"
+"\n"
+"Devolve 0.0 se 'x' e menor que 'edge'; e 1.0 en caso contrario."
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Adds vector to vector."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Divides vector by vector."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Multiplies vector by vector."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Returns the remainder of the two vectors."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Subtracts vector from vector."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Vector constant."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Vector uniform."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Custom Godot Shader Language expression, with custom amount of input and "
+"output ports. This is a direct injection of code into the vertex/fragment/"
+"light function, do not use it to write the function declarations inside."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Returns falloff based on the dot product of surface normal and view "
+"direction of camera (pass associated inputs to it)."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"Custom Godot Shader Language expression, which is placed on top of the "
+"resulted shader. You can place various function definitions inside and call "
+"it later in the Expressions. You can also declare varyings, uniforms and "
+"constants."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "A reference to an existing uniform."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "(Fragment/Light mode only) Scalar derivative function."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "(Fragment/Light mode only) Vector derivative function."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"(Fragment/Light mode only) (Vector) Derivative in 'x' using local "
+"differencing."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"(Fragment/Light mode only) (Scalar) Derivative in 'x' using local "
+"differencing."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"(Fragment/Light mode only) (Vector) Derivative in 'y' using local "
+"differencing."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"(Fragment/Light mode only) (Scalar) Derivative in 'y' using local "
+"differencing."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and "
+"'y'."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid ""
+"(Fragment/Light mode only) (Scalar) Sum of absolute derivative in 'x' and "
+"'y'."
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "VisualShader"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Edit Visual Property"
+msgstr ""
+
+#: editor/plugins/visual_shader_editor_plugin.cpp
+msgid "Visual Shader Mode Changed"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Runnable"
+msgstr "Executable"
+
+#: editor/project_export.cpp
+msgid "Delete preset '%s'?"
+msgstr "Eliminar axustes de exportación '%s'?"
+
+#: editor/project_export.cpp
+msgid ""
+"Failed to export the project for platform '%s'.\n"
+"Export templates seem to be missing or invalid."
+msgstr ""
+
+#: editor/project_export.cpp
+msgid ""
+"Failed to export the project for platform '%s'.\n"
+"This might be due to a configuration issue in the export preset or your "
+"export settings."
+msgstr ""
+"Fallou a exportación do proxecto á plataforma '%s'.\n"
+"Esto pode deberse a un problema cos axustes de exportación."
+
+#: editor/project_export.cpp
+msgid "Release"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Exporting All"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "The given export path doesn't exist:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Presets"
+msgstr "Axustes de Exportación"
+
+#: editor/project_export.cpp editor/project_settings_editor.cpp
+msgid "Add..."
+msgstr "Engadir..."
+
+#: editor/project_export.cpp
+msgid ""
+"If checked, the preset will be available for use in one-click deploy.\n"
+"Only one preset per platform may be marked as runnable."
+msgstr ""
+"Ao estar activado, estes axustes de exportación estarán dispoñibles para o "
+"usar co despregue dun só clic.\n"
+"Só uns axustes de exportación por plataforma poden marcarse como executables."
+
+#: editor/project_export.cpp
+msgid "Export Path"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Resources"
+msgstr "Recursos"
+
+#: editor/project_export.cpp
+msgid "Export all resources in the project"
+msgstr "Exportar tódolos recursos no proxecto"
+
+#: editor/project_export.cpp
+msgid "Export selected scenes (and dependencies)"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export selected resources (and dependencies)"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export Mode:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Resources to export:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid ""
+"Filters to export non-resource files/folders\n"
+"(comma-separated, e.g: *.json, *.txt, docs/*)"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid ""
+"Filters to exclude files/folders from project\n"
+"(comma-separated, e.g: *.json, *.txt, docs/*)"
+msgstr ""
+"Filtros para excluír arquivos/cartafois de proxectos\n"
+"(separados por coma; exemplo: *json, *.txt, docs*)"
+
+#: editor/project_export.cpp
+msgid "Features"
+msgstr "Características"
+
+#: editor/project_export.cpp
+msgid "Custom (comma-separated):"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Feature List:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Script"
+msgstr "Script"
+
+#: editor/project_export.cpp
+msgid "Script Export Mode:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Text"
+msgstr "Texto"
+
+#: editor/project_export.cpp
+msgid "Compiled"
+msgstr "Compilado"
+
+#: editor/project_export.cpp
+msgid "Encrypted (Provide Key Below)"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Invalid Encryption Key (must be 64 characters long)"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Script Encryption Key (256-bits as hex):"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export PCK/Zip"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Exportar Proxecto"
+
+#: editor/project_export.cpp
+msgid "Export mode?"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export All"
+msgstr ""
+
+#: editor/project_export.cpp editor/project_manager.cpp
+msgid "ZIP File"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Godot Game Pack"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export templates for this platform are missing:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Manage Export Templates"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export With Debug"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "The path specified doesn't exist."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Error opening package file (it's not in ZIP format)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
+"Invalid \".zip\" project file; it doesn't contain a \"project.godot\" file."
+msgstr ""
+"O arquivo de proxecto '.zip' non é válido; non conteñe ningún arquivo de "
+"configuración 'project.godot'."
+
+#: editor/project_manager.cpp
+msgid "Please choose an empty folder."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a \"project.godot\" or \".zip\" file."
+msgstr "Por favor, elixa un arquivo de tipo 'project.godot' ou '.zip'."
+
+#: editor/project_manager.cpp
+msgid "This directory already contains a Godot project."
+msgstr "O directorio xa contén un proxecto Godot."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Novo Proxecto de Xogo"
+
+#: editor/project_manager.cpp
+msgid "Imported Project"
+msgstr "Proxecto Importado"
+
+#: editor/project_manager.cpp
+msgid "Invalid Project Name."
+msgstr "Nome de Proxecto Inválido."
+
+#: editor/project_manager.cpp
+msgid "Couldn't create folder."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "There is already a folder in this path with the specified name."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr "Sería unha boa idea nomear o teu proxecto."
+
+#: editor/project_manager.cpp
+msgid "Invalid project path (changed anything?)."
+msgstr "A ruta ao proxecto non é valida. Cambiaches algo?"
+
+#: editor/project_manager.cpp
+msgid ""
+"Couldn't load project.godot in project path (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."
+
+#: editor/project_manager.cpp
+msgid "Couldn't create project.godot in project path."
+msgstr "Non se pudo crear o arquivo 'project.godot' na ruta do proxecto."
+
+#: editor/project_manager.cpp
+msgid "Rename Project"
+msgstr "Renomear Proxecto"
+
+#: editor/project_manager.cpp
+msgid "Import Existing Project"
+msgstr "Importar Proxecto Existente"
+
+#: editor/project_manager.cpp
+msgid "Import & Edit"
+msgstr "Importar e Editar"
+
+#: editor/project_manager.cpp
+msgid "Create New Project"
+msgstr "Crear Novo Proxecto"
+
+#: editor/project_manager.cpp
+msgid "Create & Edit"
+msgstr "Crear e Editar"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "Instalar Proxecto:"
+
+#: editor/project_manager.cpp
+msgid "Install & Edit"
+msgstr "Instalar e Editar"
+
+#: editor/project_manager.cpp
+msgid "Project Name:"
+msgstr "Nome do Proxecto:"
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
+msgstr "Ruta do Proxecto:"
+
+#: editor/project_manager.cpp
+msgid "Project Installation Path:"
+msgstr "Ruta de Instalación do Proxecto:"
+
+#: editor/project_manager.cpp
+msgid "Renderer:"
+msgstr "Renderizador:"
+
+#: editor/project_manager.cpp
+msgid "OpenGL ES 3.0"
+msgstr "OpenGL ES 3.0"
+
+#: editor/project_manager.cpp
+msgid "Not supported by your GPU drivers."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
+"Higher visual quality\n"
+"All features available\n"
+"Incompatible with older hardware\n"
+"Not recommended for web games"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "OpenGL ES 2.0"
+msgstr "OpenGL ES 2.0"
+
+#: editor/project_manager.cpp
+msgid ""
+"Lower visual quality\n"
+"Some features not available\n"
+"Works on most hardware\n"
+"Recommended for web games"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Renderer can be changed later, but scenes may need to be adjusted."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Unnamed Project"
+msgstr "Proxecto Sen Nome"
+
+#: editor/project_manager.cpp
+msgid "Missing Project"
+msgstr "Proxecto Faltante"
+
+#: editor/project_manager.cpp
+msgid "Error: Project is missing on the filesystem."
+msgstr "Erro: O proxecto non se pode encontrar no sistema de arquivos."
+
+#: editor/project_manager.cpp
+msgid "Can't open project at '%s'."
+msgstr "Non se pode abrir proxecto en '%s'."
+
+#: editor/project_manager.cpp
+msgid "Are you sure to open more than one project?"
+msgstr "Está seguro de que quere abrir máis dun proxecto?"
+
+#: editor/project_manager.cpp
+msgid ""
+"The following project settings file does not specify the version of Godot "
+"through which it was created.\n"
+"\n"
+"%s\n"
+"\n"
+"If you proceed with opening it, it will be converted to Godot's current "
+"configuration file format.\n"
+"Warning: You won't be able to open the project with previous versions of the "
+"engine anymore."
+msgstr ""
+"O arquivo de configuración do seguinte proxecto non especifica a versión de "
+"Godot ca cal foi creado.\n"
+"\n"
+"%s\n"
+"\n"
+"Se o abres o arquivo de configuración será convertido ao formato utilizado "
+"na versión actual de Godot.\n"
+"Aviso: Xa non poderás volver a abrir este proxecto con versións anteriores "
+"de Godot."
+
+#: editor/project_manager.cpp
+msgid ""
+"The following project settings file was generated by an older engine "
+"version, and needs to be converted for this version:\n"
+"\n"
+"%s\n"
+"\n"
+"Do you want to convert it?\n"
+"Warning: You won't be able to open the project with previous versions of the "
+"engine anymore."
+msgstr ""
+"O arquivo de configuración do seguinte proxecto foi xerado por unha versión "
+"antiga de Godot, e é necesario convertelo á versión actual:\n"
+"\n"
+"%s\n"
+"\n"
+"Queres convertelo?\n"
+"Aviso: Xa non poderás abrir o proxecto con versións anteriores de Godot."
+
+#: editor/project_manager.cpp
+msgid ""
+"The project settings were created by a newer engine version, whose settings "
+"are not compatible with this version."
+msgstr ""
+"A configuración do proxecto foi creada por versións máis novas de Godot; "
+"facéndoa incompatible con esta versión."
+
+#: editor/project_manager.cpp
+msgid ""
+"Can't run project: no main scene defined.\n"
+"Please edit the project and set the main scene in the Project Settings under "
+"the \"Application\" category."
+msgstr ""
+"Non se pode executar o proxecto: non hai unha escena principal definida.\n"
+"Por favor, selecciona unha escena principal en \"Configuración do Proxecto"
+"\", na categoría \"Aplicación\"."
+
+#: editor/project_manager.cpp
+msgid ""
+"Can't run project: Assets need to be imported.\n"
+"Please edit the project to trigger the initial import."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Are you sure to run %d projects at once?"
+msgstr "Seguro que queres executar %d proxectos ao mesmo tempo?"
+
+#: editor/project_manager.cpp
+msgid ""
+"Remove %d projects from the list?\n"
+"The project folders' contents won't be modified."
+msgstr ""
+"Eliminar %d proxectos da lista?\n"
+"Os contidos da carpeta de proxectos non serán modificados."
+
+#: editor/project_manager.cpp
+msgid ""
+"Remove this project from the list?\n"
+"The project folder's contents won't be modified."
+msgstr ""
+"Eliminar este proxecto da lista?\n"
+"Os contidos da carpeta de proxectos non serán modificados."
+
+#: editor/project_manager.cpp
+msgid ""
+"Remove all missing projects from the list?\n"
+"The project folders' contents won't be modified."
+msgstr ""
+"Eliminar todos os proxectos faltantes da lista?\n"
+"Os contidos da carpeta de proxectos non serán modificados."
+
+#: editor/project_manager.cpp
+msgid ""
+"Language changed.\n"
+"The interface will update after restarting the editor or project manager."
+msgstr ""
+"Linguaxe cambiada.\n"
+"A interface actualizarase despois de reiniciar o editor ou administrador de "
+"proxectos."
+
+#: editor/project_manager.cpp
+msgid ""
+"Are you sure to scan %s folders for existing Godot projects?\n"
+"This could take a while."
+msgstr ""
+"Seguro que quere escanear proxectos de Godot en %s cartafois?\n"
+"Esto podería demorarse un tempo."
+
+#. TRANSLATORS: This refers to the application where users manage their Godot projects.
+#: editor/project_manager.cpp
+msgid "Project Manager"
+msgstr "Administrador de Proxectos"
+
+#: editor/project_manager.cpp
+msgid "Projects"
+msgstr "Proxectos"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr ""
+"Examinando arquivos,\n"
+"Por favor, espere..."
+
+#: editor/project_manager.cpp
+msgid "Last Modified"
+msgstr "Derradeira Modificación"
+
+#: editor/project_manager.cpp
+msgid "Scan"
+msgstr "Escanear"
+
+#: editor/project_manager.cpp
+msgid "Select a Folder to Scan"
+msgstr "Seleccionar un Cartafol para Escanear"
+
+#: editor/project_manager.cpp
+msgid "New Project"
+msgstr "Novo Proxecto"
+
+#: editor/project_manager.cpp
+msgid "Remove Missing"
+msgstr "Eliminar Faltantes"
+
+#: editor/project_manager.cpp
+msgid "Templates"
+msgstr "Proxectos Modelo"
+
+#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr "Reiniciar Agora"
+
+#: editor/project_manager.cpp
+msgid "Can't run project"
+msgstr "Non se pode executar proxecto"
+
+#: editor/project_manager.cpp
+msgid ""
+"You currently don't have any projects.\n"
+"Would you like to explore official example projects in the Asset Library?"
+msgstr ""
+"Actualmente non tes ningún proxecto.\n"
+"Gustaríalle buscar proxectos de exemplo oficiais na biblioteca de Assets?"
+
+#: editor/project_manager.cpp
+msgid ""
+"The search box filters projects by name and last path component.\n"
+"To filter projects by name and full path, the query must contain at least "
+"one `/` character."
+msgstr ""
+"A barra de búsqueda filtra os proxectos por nome e último compoñente da súa "
+"ruta.\n"
+"Se quere filtrar proxectos por nome e ruta completa, a consulta debe conter "
+"polo menos un carácter '/'."
+
+#: editor/project_settings_editor.cpp
+msgid "Key "
+msgstr "Botón: "
+
+#: editor/project_settings_editor.cpp
+msgid "Joy Button"
+msgstr "Botón Joystick"
+
+#: editor/project_settings_editor.cpp
+msgid "Joy Axis"
+msgstr "Eixe Joystick"
+
+#: editor/project_settings_editor.cpp
+msgid "Mouse Button"
+msgstr "Botón do Rato"
+
+#: editor/project_settings_editor.cpp
+msgid ""
+"Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or "
+"'\"'"
+msgstr ""
+"Nome de acción inválido. O nome non pode estar baleiro, nin conter '/', ':', "
+"'=', '\\' ou '\"'"
+
+#: editor/project_settings_editor.cpp
+msgid "An action with the name '%s' already exists."
+msgstr "Xa existe unha acción co nome '%s'."
+
+#: editor/project_settings_editor.cpp
+msgid "Rename Input Action Event"
+msgstr "Renomear Evento de Entrada"
+
+#: editor/project_settings_editor.cpp
+msgid "Change Action deadzone"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Add Input Action Event"
+msgstr "Engadir Evento de Entrada"
+
+#: editor/project_settings_editor.cpp
+msgid "All Devices"
+msgstr "Tódolos Dispositivos"
+
+#: editor/project_settings_editor.cpp
+msgid "Device"
+msgstr "Dispositivo"
+
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Press a Key..."
+msgstr "Pulse algún botón..."
+
+#: editor/project_settings_editor.cpp
+msgid "Mouse Button Index:"
+msgstr "Índice do Botón do Rato:"
+
+#: editor/project_settings_editor.cpp
+msgid "Left Button"
+msgstr "Botón Esquerdo"
+
+#: editor/project_settings_editor.cpp
+msgid "Right Button"
+msgstr "Botón Dereito"
+
+#: editor/project_settings_editor.cpp
+msgid "Middle Button"
+msgstr "Botón Central"
+
+#: editor/project_settings_editor.cpp
+msgid "Wheel Up Button"
+msgstr "Mover Roda cara Arriba"
+
+#: editor/project_settings_editor.cpp
+msgid "Wheel Down Button"
+msgstr "Mover Roda cara Abaixo"
+
+#: editor/project_settings_editor.cpp
+msgid "Wheel Left Button"
+msgstr "Mover Roda cara a Esquerda"
+
+#: editor/project_settings_editor.cpp
+msgid "Wheel Right Button"
+msgstr "Mover Roda cara a Dereita"
+
+#: editor/project_settings_editor.cpp
+msgid "X Button 1"
+msgstr "Botón X 1"
+
+#: editor/project_settings_editor.cpp
+msgid "X Button 2"
+msgstr "Botón X 2"
+
+#: editor/project_settings_editor.cpp
+msgid "Joypad Axis Index:"
+msgstr "Índice do Eixe do Joystick:"
+
+#: editor/project_settings_editor.cpp
+msgid "Axis"
+msgstr "Eixe"
+
+#: editor/project_settings_editor.cpp
+msgid "Joypad Button Index:"
+msgstr "Índice do Botón do Joystick:"
+
+#: editor/project_settings_editor.cpp
+msgid "Erase Input Action"
+msgstr "Eliminar Acción de Entrada"
+
+#: editor/project_settings_editor.cpp
+msgid "Erase Input Action Event"
+msgstr "Eliminar Evento de Entrada"
+
+#: editor/project_settings_editor.cpp
+msgid "Add Event"
+msgstr "Engadir Evento"
+
+#: editor/project_settings_editor.cpp
+msgid "Button"
+msgstr "Botón"
+
+#: editor/project_settings_editor.cpp
+msgid "Left Button."
+msgstr "Botón Esquerdo."
+
+#: editor/project_settings_editor.cpp
+msgid "Right Button."
+msgstr "Botón Dereito."
+
+#: editor/project_settings_editor.cpp
+msgid "Middle Button."
+msgstr "Botón Central."
+
+#: editor/project_settings_editor.cpp
+msgid "Wheel Up."
+msgstr "Roda cara Arriba."
+
+#: editor/project_settings_editor.cpp
+msgid "Wheel Down."
+msgstr "Roda cara Abaixo."
+
+#: editor/project_settings_editor.cpp
+msgid "Add Global Property"
+msgstr "Engadir Propiedade Global"
+
+#: editor/project_settings_editor.cpp
+msgid "Select a setting item first!"
+msgstr "Primeiro seleccione un elemento!"
+
+#: editor/project_settings_editor.cpp
+msgid "No property '%s' exists."
+msgstr "Non existe a propiedade '%s'."
+
+#: editor/project_settings_editor.cpp
+msgid "Setting '%s' is internal, and it can't be deleted."
+msgstr "A propiedade '%s' é interna, e non pode ser eliminada."
+
+#: editor/project_settings_editor.cpp
+msgid "Delete Item"
+msgstr "Eliminar Elemento"
+
+#: editor/project_settings_editor.cpp
+msgid ""
+"Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or "
+"'\"'."
+msgstr ""
+"Nome de acción inválido. Non pode estar baleiro, nin pode conter '/', ':', "
+"'=', '\\' ou '\"'."
+
+#: editor/project_settings_editor.cpp
+msgid "Add Input Action"
+msgstr "Engadir Acción de Entrada"
+
+#: editor/project_settings_editor.cpp
+msgid "Error saving settings."
+msgstr "Erro gardando os axustes."
+
+#: editor/project_settings_editor.cpp
+msgid "Settings saved OK."
+msgstr "Axustes gardados correctamente."
+
+#: editor/project_settings_editor.cpp
+msgid "Moved Input Action Event"
+msgstr "Evento de Entrada Movido"
+
+#: editor/project_settings_editor.cpp
+msgid "Override for Feature"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Add Translation"
+msgstr "Engadir Tradución"
+
+#: editor/project_settings_editor.cpp
+msgid "Remove Translation"
+msgstr "Eliminar Tradución"
+
+#: editor/project_settings_editor.cpp
+msgid "Add Remapped Path"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Resource Remap Add Remap"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Change Resource Remap Language"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Remove Resource Remap"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Remove Resource Remap Option"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Project Settings (project.godot)"
+msgstr "Configuración do Proxecto (project.godot)"
+
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "General"
+msgstr "Xeral"
+
+#: editor/project_settings_editor.cpp
+msgid "Override For..."
+msgstr ""
+
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "The editor must be restarted for changes to take effect."
+msgstr "O editor ten que reiniciarse para que os cambios teñan efecto."
+
+#: editor/project_settings_editor.cpp
+msgid "Input Map"
+msgstr "Mapeado de Entradas"
+
+#: editor/project_settings_editor.cpp
+msgid "Action:"
+msgstr "Acción:"
+
+#: editor/project_settings_editor.cpp
+msgid "Action"
+msgstr "Acción"
+
+#: editor/project_settings_editor.cpp
+msgid "Deadzone"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Device:"
+msgstr "Dispositivo:"
+
+#: editor/project_settings_editor.cpp
+msgid "Index:"
+msgstr "Índice:"
+
+#: editor/project_settings_editor.cpp
+msgid "Localization"
+msgstr "Linguaxe"
+
+#: editor/project_settings_editor.cpp
+msgid "Translations"
+msgstr "Traducións"
+
+#: editor/project_settings_editor.cpp
+msgid "Translations:"
+msgstr "Traducións:"
+
+#: editor/project_settings_editor.cpp
+msgid "Remaps"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Resources:"
+msgstr "Recursos:"
+
+#: editor/project_settings_editor.cpp
+msgid "Remaps by Locale:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Locale"
+msgstr "Linguaxe"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr "Filtrar Linguaxes"
+
+#: editor/project_settings_editor.cpp
+msgid "Show All Locales"
+msgstr "Amosar Tódolos Linguaxes"
+
+#: editor/project_settings_editor.cpp
+msgid "Show Selected Locales Only"
+msgstr "Amosar só os Linguaxes Seleccionados"
+
+#: editor/project_settings_editor.cpp
+msgid "Filter mode:"
+msgstr "Modo de Filtrado:"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr "Linguaxes:"
+
+#: editor/project_settings_editor.cpp
+msgid "AutoLoad"
+msgstr "AutoCargador"
+
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "Características Adicionais (Plugins)"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Cargar Valores por Defecto"
+
+#: editor/property_editor.cpp
+msgid "Preset..."
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Zero"
+msgstr "Cero"
+
+#: editor/property_editor.cpp
+msgid "Easing In-Out"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Easing Out-In"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "File..."
+msgstr "Arquivo..."
+
+#: editor/property_editor.cpp
+msgid "Dir..."
+msgstr "Directorio..."
+
+#: editor/property_editor.cpp
+msgid "Assign"
+msgstr "Asignar"
+
+#: editor/property_editor.cpp
+msgid "Select Node"
+msgstr "Seleccionar Nodos"
+
+#: editor/property_editor.cpp
+msgid "Error loading file: Not a resource!"
+msgstr "Erro cargando arquivo: Non é un recurso!"
+
+#: editor/property_editor.cpp
+msgid "Pick a Node"
+msgstr "Elixe un Nodo"
+
+#: editor/property_editor.cpp
+msgid "Bit %d, val %d."
+msgstr ""
+
+#: editor/property_selector.cpp
+msgid "Select Property"
+msgstr ""
+
+#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
+msgid "Select Method"
+msgstr ""
+
+#: editor/rename_dialog.cpp editor/scene_tree_dock.cpp
+msgid "Batch Rename"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Replace:"
+msgstr "Substituír:"
+
+#: editor/rename_dialog.cpp
+msgid "Prefix:"
+msgstr "Prefixo:"
+
+#: editor/rename_dialog.cpp
+msgid "Suffix:"
+msgstr "Sufixo:"
+
+#: editor/rename_dialog.cpp
+msgid "Use Regular Expressions"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Advanced Options"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Substitute"
+msgstr "Substituír"
+
+#: editor/rename_dialog.cpp
+msgid "Node name"
+msgstr "Nome do nodo"
+
+#: editor/rename_dialog.cpp
+msgid "Node's parent name, if available"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Node type"
+msgstr "Tipo de nodo"
+
+#: editor/rename_dialog.cpp
+msgid "Current scene name"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Root node name"
+msgstr "Nome do nodo raíz"
+
+#: editor/rename_dialog.cpp
+msgid ""
+"Sequential integer counter.\n"
+"Compare counter options."
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Per-level Counter"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "If set, the counter restarts for each group of child nodes."
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Initial value for the counter"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Step"
+msgstr "Paso"
+
+#: editor/rename_dialog.cpp
+msgid "Amount by which counter is incremented for each node"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Padding"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid ""
+"Minimum number of digits for the counter.\n"
+"Missing digits are padded with leading zeros."
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Post-Process"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Keep"
+msgstr "Manter"
+
+#: editor/rename_dialog.cpp
+msgid "PascalCase to snake_case"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "snake_case to PascalCase"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Case"
+msgstr "Maiús./Minús."
+
+#: editor/rename_dialog.cpp
+msgid "To Lowercase"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "To Uppercase"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "Reset"
+msgstr "Restablecer"
+
+#: editor/rename_dialog.cpp
+msgid "Regular Expression Error:"
+msgstr ""
+
+#: editor/rename_dialog.cpp
+msgid "At character %s"
+msgstr ""
+
+#: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp
+msgid "Reparent Node"
+msgstr "Remparentar Nodo"
+
+#: editor/reparent_dialog.cpp
+msgid "Reparent Location (Select new Parent):"
+msgstr ""
+
+#: editor/reparent_dialog.cpp
+msgid "Keep Global Transform"
+msgstr ""
+
+#: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp
+msgid "Reparent"
+msgstr "Remparentar"
+
+#: editor/run_settings_dialog.cpp
+msgid "Run Mode:"
+msgstr ""
+
+#: editor/run_settings_dialog.cpp
+msgid "Current Scene"
+msgstr ""
+
+#: editor/run_settings_dialog.cpp
+msgid "Main Scene"
+msgstr ""
+
+#: editor/run_settings_dialog.cpp
+msgid "Main Scene Arguments:"
+msgstr ""
+
+#: editor/run_settings_dialog.cpp
+msgid "Scene Run Settings"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "No parent to instance the scenes at."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Error loading scene from %s"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid ""
+"Cannot instance the scene '%s' because the current scene exists within one "
+"of its nodes."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Instance Scene(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Replace with Branch Scene"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Instance Child Scene"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Pegar Nodos"
+
+#: editor/scene_tree_dock.cpp
+msgid "Detach Script"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "This operation can't be done on the tree root."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Move Node In Parent"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Move Nodes In Parent"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Duplicate Node(s)"
+msgstr "Duplicar Nodo(s)"
+
+#: editor/scene_tree_dock.cpp
+msgid "Can't reparent nodes in inherited scenes, order of nodes can't change."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Node must belong to the edited scene to become root."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Instantiated scenes can't become root"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Make node as Root"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Delete %d nodes and any children?"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Delete %d nodes?"
+msgstr "Eliminar %d nodos?"
+
+#: editor/scene_tree_dock.cpp
+msgid "Delete the root node \"%s\"?"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Delete node \"%s\" and its children?"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Delete node \"%s\"?"
+msgstr "Eliminar nodo \"%s\"?"
+
+#: editor/scene_tree_dock.cpp
+msgid "Can not perform with the root node."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "This operation can't be done on instanced scenes."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Save New Scene As..."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid ""
+"Disabling \"editable_instance\" will cause all properties of the node to be "
+"reverted to their default."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid ""
+"Enabling \"Load As Placeholder\" will disable \"Editable Children\" and "
+"cause all properties of the node to be reverted to their default."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Make Local"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "New Scene Root"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Create Root Node:"
+msgstr "Crear nodo raíz:"
+
+#: editor/scene_tree_dock.cpp
+msgid "2D Scene"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "3D Scene"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "User Interface"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Other Node"
+msgstr "Outro Nodo"
+
+#: editor/scene_tree_dock.cpp
+msgid "Can't operate on nodes from a foreign scene!"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Can't operate on nodes the current scene inherits from!"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Attach Script"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Cortar Nodos"
+
+#: editor/scene_tree_dock.cpp
+msgid "Remove Node(s)"
+msgstr "Eliminar Nodo(s)"
+
+#: editor/scene_tree_dock.cpp
+msgid "Change type of node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid ""
+"Couldn't save new scene. Likely dependencies (instances) couldn't be "
+"satisfied."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Error saving scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Error duplicating scene to save it."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Sub-Resources"
+msgstr "Sub-Recursos"
+
+#: editor/scene_tree_dock.cpp
+msgid "Clear Inheritance"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Editable Children"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Load As Placeholder"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Open Documentation"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid ""
+"Cannot attach a script: there are no languages registered.\n"
+"This is probably because this editor was built with all language modules "
+"disabled."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Add Child Node"
+msgstr "Engadir Nodo Fillo"
+
+#: editor/scene_tree_dock.cpp
+msgid "Expand/Collapse All"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Change Type"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Reparent to New Node"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Make Scene Root"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Merge From Scene"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp
+msgid "Save Branch as Scene"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp
+msgid "Copy Node Path"
+msgstr "Copiar Ruta do Nodo"
+
+#: editor/scene_tree_dock.cpp
+msgid "Delete (No Confirm)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Add/Create a New Node."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid ""
+"Instance a scene file as a Node. Creates an inherited scene if no root node "
+"exists."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Attach a new or existing script to the selected node."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Detach the script from the selected node."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Remote"
+msgstr "Remoto"
+
+#: editor/scene_tree_dock.cpp
+msgid "Local"
+msgstr "Local"
+
+#: editor/scene_tree_dock.cpp
+msgid "Clear Inheritance? (No Undo!)"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Toggle Visible"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Unlock Node"
+msgstr "Desbloquear Nodo"
+
+#: editor/scene_tree_editor.cpp
+msgid "Button Group"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "(Connecting From)"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Node configuration warning:"
+msgstr "Aviso sobre a configuración do nodo:"
+
+#: editor/scene_tree_editor.cpp
+msgid ""
+"Node has %s connection(s) and %s group(s).\n"
+"Click to show signals dock."
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid ""
+"Node has %s connection(s).\n"
+"Click to show signals dock."
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid ""
+"Node is in %s group(s).\n"
+"Click to show groups dock."
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Open Script:"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid ""
+"Node is locked.\n"
+"Click to unlock it."
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid ""
+"Children are not selectable.\n"
+"Click to make selectable."
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Toggle Visibility"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid ""
+"AnimationPlayer is pinned.\n"
+"Click to unpin."
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Invalid node name, the following characters are not allowed:"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Rename Node"
+msgstr "Renomear Nodo"
+
+#: editor/scene_tree_editor.cpp
+msgid "Scene Tree (Nodes):"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Node Configuration Warning!"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Select a Node"
+msgstr "Seleccione un Nodo"
+
+#: editor/script_create_dialog.cpp
+msgid "Path is empty."
+msgstr "A ruta está baleira."
+
+#: editor/script_create_dialog.cpp
+msgid "Filename is empty."
+msgstr "O nome de arquivo está baleiro."
+
+#: editor/script_create_dialog.cpp
+msgid "Path is not local."
+msgstr "A ruta non é local."
+
+#: editor/script_create_dialog.cpp
+msgid "Invalid base path."
+msgstr "Ruta base inválida."
+
+#: editor/script_create_dialog.cpp
+msgid "A directory with the same name exists."
+msgstr "Xa existe un directorio co mesmo nome."
+
+#: editor/script_create_dialog.cpp
+msgid "File does not exist."
+msgstr "O arquivo non existe."
+
+#: editor/script_create_dialog.cpp
+msgid "Invalid extension."
+msgstr "Extensión inválida."
+
+#: editor/script_create_dialog.cpp
+msgid "Wrong extension chosen."
+msgstr "Extensión incorrecta elixida."
+
+#: editor/script_create_dialog.cpp
+msgid "Error loading template '%s'"
+msgstr "Erro cargando o modelo '%s'"
+
+#: editor/script_create_dialog.cpp
+msgid "Error - Could not create script in filesystem."
+msgstr "Erro - Non se puido gardar o Script no sistema de arquivos."
+
+#: editor/script_create_dialog.cpp
+msgid "Error loading script from %s"
+msgstr "Erro cargando script desde %s"
+
+#: editor/script_create_dialog.cpp
+msgid "Overrides"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "N/A"
+msgstr "N/A"
+
+#: editor/script_create_dialog.cpp
+msgid "Open Script / Choose Location"
+msgstr "Abrir Script / Elixir Ubicación"
+
+#: editor/script_create_dialog.cpp
+msgid "Open Script"
+msgstr "Abrir Script"
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, it will be reused."
+msgstr "O arquivo xa existe; será reutilizado."
+
+#: editor/script_create_dialog.cpp
+msgid "Invalid path."
+msgstr "Ruta inválida."
+
+#: editor/script_create_dialog.cpp
+msgid "Invalid class name."
+msgstr "Nome de clase inválido."
+
+#: editor/script_create_dialog.cpp
+msgid "Invalid inherited parent name or path."
+msgstr "A ruta ou o nome do pai herdado é inválido."
+
+#: editor/script_create_dialog.cpp
+msgid "Script path/name is valid."
+msgstr "A ruta e nome do script son válidos."
+
+#: editor/script_create_dialog.cpp
+msgid "Allowed: a-z, A-Z, 0-9, _ and ."
+msgstr "Permitido: a-z, A-Z, 0-9,_ e ."
+
+#: editor/script_create_dialog.cpp
+msgid "Built-in script (into scene file)."
+msgstr "Script integrada na escena."
+
+#: editor/script_create_dialog.cpp
+msgid "Will create a new script file."
+msgstr "Crearase un novo arquivo de script."
+
+#: editor/script_create_dialog.cpp
+msgid "Will load an existing script file."
+msgstr "Cargarase un arquivo de script xa existente."
+
+#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr "Xa existe un arquivo script na mesma ruta."
+
+#: editor/script_create_dialog.cpp
+msgid ""
+"Note: Built-in scripts have some limitations and can't be edited using an "
+"external editor."
+msgstr ""
+"Nota: Os scripts integrados teñen algunhas limitacións, e non poden editarse "
+"usando editores externos."
+
+#: editor/script_create_dialog.cpp
+msgid "Class Name:"
+msgstr "Nome da Clase:"
+
+#: editor/script_create_dialog.cpp
+msgid "Template:"
+msgstr "Modelo:"
+
+#: editor/script_create_dialog.cpp
+msgid "Built-in Script:"
+msgstr "Script Integrado:"
+
+#: editor/script_create_dialog.cpp
+msgid "Attach Node Script"
+msgstr "Adxuntar Script de Nodo"
+
+#: editor/script_editor_debugger.cpp
+msgid "Remote "
+msgstr "Remoto "
+
+#: editor/script_editor_debugger.cpp
+msgid "Bytes:"
+msgstr "Bytes:"
+
+#: editor/script_editor_debugger.cpp
+msgid "Warning:"
+msgstr "Aviso:"
+
+#: editor/script_editor_debugger.cpp
+msgid "Error:"
+msgstr "Erro:"
+
+#: editor/script_editor_debugger.cpp
+msgid "C++ Error"
+msgstr "Erro de C++"
+
+#: editor/script_editor_debugger.cpp
+msgid "C++ Error:"
+msgstr "Erro de C++:"
+
+#: editor/script_editor_debugger.cpp
+msgid "C++ Source"
+msgstr "Fonte C++"
+
+#: editor/script_editor_debugger.cpp
+msgid "Source:"
+msgstr "Fonte:"
+
+#: editor/script_editor_debugger.cpp
+msgid "C++ Source:"
+msgstr "Fonte C++:"
+
+#: editor/script_editor_debugger.cpp
+msgid "Stack Trace"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Errors"
+msgstr "Erros"
+
+#: editor/script_editor_debugger.cpp
+msgid "Child process connected."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Copy Error"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Video RAM"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Skip Breakpoints"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Inspect Previous Instance"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Inspect Next Instance"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Stack Frames"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Profiler"
+msgstr "Analítica de Rendemento"
+
+#: editor/script_editor_debugger.cpp
+msgid "Network Profiler"
+msgstr "Analítica de Rendemento de Rede"
+
+#: editor/script_editor_debugger.cpp
+msgid "Monitor"
+msgstr "Monitor"
+
+#: editor/script_editor_debugger.cpp
+msgid "Value"
+msgstr "Valor"
+
+#: editor/script_editor_debugger.cpp
+msgid "Monitors"
+msgstr "Monitores"
+
+#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "List of Video Memory Usage by Resource:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Total:"
+msgstr "Total:"
+
+#: editor/script_editor_debugger.cpp
+msgid "Export list to a CSV file"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Resource Path"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Type"
+msgstr "Tipo"
+
+#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "Formato"
+
+#: editor/script_editor_debugger.cpp
+msgid "Usage"
+msgstr "Uso"
+
+#: editor/script_editor_debugger.cpp
+msgid "Misc"
+msgstr "Outros"
+
+#: editor/script_editor_debugger.cpp
+msgid "Clicked Control:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Clicked Control Type:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Live Edit Root:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Set From Tree"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Export measures as CSV"
+msgstr ""
+
+#: editor/settings_config_dialog.cpp
+msgid "Erase Shortcut"
+msgstr ""
+
+#: editor/settings_config_dialog.cpp
+msgid "Restore Shortcut"
+msgstr ""
+
+#: editor/settings_config_dialog.cpp
+msgid "Change Shortcut"
+msgstr ""
+
+#: editor/settings_config_dialog.cpp
+msgid "Editor Settings"
+msgstr ""
+
+#: editor/settings_config_dialog.cpp
+msgid "Shortcuts"
+msgstr "Atallos"
+
+#: editor/settings_config_dialog.cpp
+msgid "Binding"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Light Radius"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change AudioStreamPlayer3D Emission Angle"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Camera FOV"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Camera Size"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Notifier AABB"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Particles AABB"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Probe Extents"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
+msgid "Change Sphere Shape Radius"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
+msgid "Change Box Shape Extents"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Capsule Shape Radius"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Capsule Shape Height"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Cylinder Shape Radius"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Cylinder Shape Height"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Ray Shape Length"
+msgstr ""
+
+#: modules/csg/csg_gizmos.cpp
+msgid "Change Cylinder Radius"
+msgstr ""
+
+#: modules/csg/csg_gizmos.cpp
+msgid "Change Cylinder Height"
+msgstr ""
+
+#: modules/csg/csg_gizmos.cpp
+msgid "Change Torus Inner Radius"
+msgstr ""
+
+#: modules/csg/csg_gizmos.cpp
+msgid "Change Torus Outer Radius"
+msgstr ""
+
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "Select the dynamic library for this entry"
+msgstr ""
+
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "Select dependencies of the library for this entry"
+msgstr ""
+
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "Remove current entry"
+msgstr ""
+
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "Double click to create a new entry"
+msgstr ""
+
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "Platform:"
+msgstr "Plataforma:"
+
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "Platform"
+msgstr "Plataforma"
+
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "Dynamic Library"
+msgstr ""
+
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "Add an architecture entry"
+msgstr ""
+
+#: modules/gdnative/gdnative_library_editor_plugin.cpp
+msgid "GDNativeLibrary"
+msgstr ""
+
+#: modules/gdnative/gdnative_library_singleton_editor.cpp
+msgid "Enabled GDNative Singleton"
+msgstr ""
+
+#: modules/gdnative/gdnative_library_singleton_editor.cpp
+msgid "Disabled GDNative Singleton"
+msgstr ""
+
+#: modules/gdnative/gdnative_library_singleton_editor.cpp
+msgid "Library"
+msgstr "Biblioteca"
+
+#: modules/gdnative/gdnative_library_singleton_editor.cpp
+msgid "Libraries: "
+msgstr "Bibliotecas: "
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr "GDNative"
+
+#: modules/gdscript/gdscript_functions.cpp
+msgid "Step argument is zero!"
+msgstr ""
+
+#: modules/gdscript/gdscript_functions.cpp
+msgid "Not a script with an instance"
+msgstr ""
+
+#: modules/gdscript/gdscript_functions.cpp
+msgid "Not based on a script"
+msgstr ""
+
+#: modules/gdscript/gdscript_functions.cpp
+msgid "Not based on a resource file"
+msgstr ""
+
+#: modules/gdscript/gdscript_functions.cpp
+msgid "Invalid instance dictionary format (missing @path)"
+msgstr ""
+
+#: modules/gdscript/gdscript_functions.cpp
+msgid "Invalid instance dictionary format (can't load script at @path)"
+msgstr ""
+
+#: modules/gdscript/gdscript_functions.cpp
+msgid "Invalid instance dictionary format (invalid script at @path)"
+msgstr ""
+
+#: modules/gdscript/gdscript_functions.cpp
+msgid "Invalid instance dictionary (invalid subclasses)"
+msgstr ""
+
+#: modules/gdscript/gdscript_functions.cpp
+msgid "Object can't provide a length."
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Next Plane"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Previous Plane"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Plane:"
+msgstr "Plano:"
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Next Floor"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Previous Floor"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Floor:"
+msgstr "Chan:"
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "GridMap Delete Selection"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "GridMap Fill Selection"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "GridMap Paste Selection"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "GridMap Paint"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Grid Map"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Snap View"
+msgstr "Axustar Vista"
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Clip Disabled"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Clip Above"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Clip Below"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Edit X Axis"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Edit Y Axis"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Edit Z Axis"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Rotate X"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Rotate Y"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Rotate Z"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Back Rotate X"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Back Rotate Y"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Back Rotate Z"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Clear Rotation"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Paste Selects"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Clear Selection"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Fill Selection"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "GridMap Settings"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Pick Distance:"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Filter meshes"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Give a MeshLibrary resource to this GridMap to use its meshes."
+msgstr ""
+
+#: modules/lightmapper_cpu/lightmapper_cpu.cpp
+msgid "Begin Bake"
+msgstr ""
+
+#: modules/lightmapper_cpu/lightmapper_cpu.cpp
+msgid "Preparing data structures"
+msgstr ""
+
+#: modules/lightmapper_cpu/lightmapper_cpu.cpp
+msgid "Generate buffers"
+msgstr ""
+
+#: modules/lightmapper_cpu/lightmapper_cpu.cpp
+msgid "Direct lighting"
+msgstr ""
+
+#: modules/lightmapper_cpu/lightmapper_cpu.cpp
+msgid "Indirect lighting"
+msgstr ""
+
+#: modules/lightmapper_cpu/lightmapper_cpu.cpp
+msgid "Post processing"
+msgstr ""
+
+#: modules/lightmapper_cpu/lightmapper_cpu.cpp
+msgid "Plotting lightmaps"
+msgstr ""
+
+#: modules/mono/csharp_script.cpp
+msgid "Class name can't be a reserved keyword"
+msgstr ""
+
+#: modules/mono/mono_gd/gd_mono_utils.cpp
+msgid "End of inner exception stack trace"
+msgstr ""
+
+#: modules/recast/navigation_mesh_editor_plugin.cpp
+msgid "Bake NavMesh"
+msgstr ""
+
+#: modules/recast/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr "Particionando..."
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: modules/recast/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr "Feito!"
+
+#: modules/visual_script/visual_script.cpp
+msgid ""
+"A node yielded without working memory, please read the docs on how to yield "
+"properly!"
+msgstr ""
+
+#: modules/visual_script/visual_script.cpp
+msgid ""
+"Node yielded, but did not return a function state in the first working "
+"memory."
+msgstr ""
+
+#: modules/visual_script/visual_script.cpp
+msgid ""
+"Return value must be assigned to first element of node working memory! Fix "
+"your node please."
+msgstr ""
+
+#: modules/visual_script/visual_script.cpp
+msgid "Node returned an invalid sequence output: "
+msgstr ""
+
+#: modules/visual_script/visual_script.cpp
+msgid "Found sequence bit but not the node in the stack, report bug!"
+msgstr ""
+
+#: modules/visual_script/visual_script.cpp
+msgid "Stack overflow with stack depth: "
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Signal Arguments"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Argument Type"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Argument name"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Set Variable Default Value"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Set Variable Type"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Input Port"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Output Port"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Override an existing built-in function."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Create a new function."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Variables:"
+msgstr "Variables:"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Create a new variable."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Signals:"
+msgstr "Sinais:"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Create a new signal."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Name is not a valid identifier:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Name already in use by another func/var/signal:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Rename Function"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Rename Variable"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Rename Signal"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Function"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Delete input port"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Variable"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Signal"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove Input Port"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove Output Port"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Expression"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove VisualScript Nodes"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Duplicate VisualScript Nodes"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold %s to drop a Getter. Hold Shift to drop a generic signature."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold %s to drop a simple reference to the node."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold Ctrl to drop a simple reference to the node."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold %s to drop a Variable Setter."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold Ctrl to drop a Variable Setter."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Preload Node"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Node(s) From Tree"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid ""
+"Can't drop properties because script '%s' is not used in this scene.\n"
+"Drop holding 'Shift' to just copy the signature."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Getter Property"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Setter Property"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Base Type"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Move Node(s)"
+msgstr "Mover Nodo(s)"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove VisualScript Node"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Connect Nodes"
+msgstr "Conectar Nodos"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Disconnect Nodes"
+msgstr "Desconectar Nodos"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Connect Node Data"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Connect Node Sequence"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr "O script xa ten unha función chamada '%s'"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Input Value"
+msgstr "Cambiar Valor de Entrada"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Resize Comment"
+msgstr "Cambiar Tamaño do Comentario"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Can't copy the function node."
+msgstr "Non se pode copiar o nodo función."
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr "O portapapeis está baleiro!"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Paste VisualScript Nodes"
+msgstr "Pegar Nodos VisualScript"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Can't create function with a function node."
+msgstr "Non se pode crear unha función cun nodo función."
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Can't create function of nodes from nodes of multiple functions."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Select at least one node with sequence port."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Try to only have one sequence input in selection."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Create Function"
+msgstr "Crear Función"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove Function"
+msgstr "Eliminar Función"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove Variable"
+msgstr "Eliminar Variable"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Editing Variable:"
+msgstr "Editando Variable:"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove Signal"
+msgstr "Eliminar Sinal"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Editing Signal:"
+msgstr "Editando Sinal:"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Make Tool:"
+msgstr "Ferramenta:"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Members:"
+msgstr "Membros:"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Base Type:"
+msgstr "Cambiar Tipo Base:"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Nodes..."
+msgstr "Engadir Nodos..."
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Function..."
+msgstr "Engadir Función..."
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "function_name"
+msgstr "nome_da_funcion"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Select or create a function to edit its graph."
+msgstr "Seleccione ou cree unha función para editar a sua gráfica."
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Delete Selected"
+msgstr "Eliminar Selección"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Find Node Type"
+msgstr "Encontrar Tipo de Nodo"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Copy Nodes"
+msgstr "Copiar Nodos"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Cut Nodes"
+msgstr "Cortar Nodos"
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Make Function"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Refresh Graph"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit Member"
+msgstr "Editar Membro"
+
+#: modules/visual_script/visual_script_flow_control.cpp
+msgid "Input type not iterable: "
+msgstr ""
+
+#: modules/visual_script/visual_script_flow_control.cpp
+msgid "Iterator became invalid"
+msgstr ""
+
+#: modules/visual_script/visual_script_flow_control.cpp
+msgid "Iterator became invalid: "
+msgstr ""
+
+#: modules/visual_script/visual_script_func_nodes.cpp
+msgid "Invalid index property name."
+msgstr ""
+
+#: modules/visual_script/visual_script_func_nodes.cpp
+msgid "Base object is not a Node!"
+msgstr ""
+
+#: modules/visual_script/visual_script_func_nodes.cpp
+msgid "Path does not lead Node!"
+msgstr ""
+
+#: modules/visual_script/visual_script_func_nodes.cpp
+msgid "Invalid index property name '%s' in node %s."
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid ": Invalid argument of type: "
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid ": Invalid arguments: "
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid "VariableGet not found in script: "
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid "VariableSet not found in script: "
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid "Custom node has no _step() method, can't process graph."
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid ""
+"Invalid return value from _step(), must be integer (seq out), or string "
+"(error)."
+msgstr ""
+
+#: modules/visual_script/visual_script_property_selector.cpp
+msgid "Search VisualScript"
+msgstr "Buscar en VisualScript"
+
+#: modules/visual_script/visual_script_property_selector.cpp
+msgid "Get %s"
+msgstr ""
+
+#: modules/visual_script/visual_script_property_selector.cpp
+msgid "Set %s"
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Package name is missing."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Package segments must be of non-zero length."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "The character '%s' is not allowed in Android application package names."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "A digit cannot be the first character in a package segment."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "The character '%s' cannot be the first character in a package segment."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "The package must have at least one '.' separator."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Select device from the list"
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Unable to find the 'apksigner' tool."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid ""
+"Android build template not installed in the project. Install it from the "
+"Project menu."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Debug keystore not configured in the Editor Settings nor in the preset."
+msgstr ""
+"Non está configurado o Keystore de depuración nin na configuración do "
+"editor, nin nos axustes de exportación."
+
+#: platform/android/export/export.cpp
+msgid "Release keystore incorrectly configured in the export preset."
+msgstr ""
+"O Keystore Release non está configurado correctamente nos axustes de "
+"exportación."
+
+#: platform/android/export/export.cpp
+msgid "A valid Android SDK path is required in Editor Settings."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Invalid Android SDK path in Editor Settings."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Missing 'platform-tools' directory!"
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Unable to find Android SDK platform-tools' adb command."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Please check in the Android SDK directory specified in Editor Settings."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Missing 'build-tools' directory!"
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Unable to find Android SDK build-tools' apksigner command."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Invalid public key for APK expansion."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Invalid package name:"
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid ""
+"Invalid \"GodotPaymentV3\" module included in the \"android/modules\" "
+"project setting (changed in Godot 3.2.2).\n"
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "\"Use Custom Build\" must be enabled to use the plugins."
+msgstr ""
+"\"Use Custom Build\" debe estar activado para usar estas características "
+"adicionais (plugins)."
+
+#: platform/android/export/export.cpp
+msgid ""
+"\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR"
+"\"."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid ""
+"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid ""
+"\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Invalid filename! Android App Bundle requires the *.aab extension."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "APK Expansion not compatible with Android App Bundle."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Invalid filename! Android APK requires the *.apk extension."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid ""
+"Trying to build from a custom built template, but no version info for it "
+"exists. Please reinstall from the 'Project' menu."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid ""
+"Android build version mismatch:\n"
+" Template installed: %s\n"
+" Godot Version: %s\n"
+"Please reinstall Android build template from 'Project' menu."
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid "Building Android Project (gradle)"
+msgstr "Construir Proxecto Android (gradle)"
+
+#: platform/android/export/export.cpp
+msgid ""
+"Building of Android project failed, check output for the error.\n"
+"Alternatively visit docs.godotengine.org for Android build documentation."
+msgstr ""
+"A creación do proxecto para Android fallou; comproba a saída para encontrar "
+"o erro.\n"
+"Ou visita docs.godotengine.org para ver a documentación sobre compilación "
+"para Android."
+
+#: platform/android/export/export.cpp
+msgid "Moving output"
+msgstr ""
+
+#: platform/android/export/export.cpp
+msgid ""
+"Unable to copy and rename export file, check gradle project directory for "
+"outputs."
+msgstr ""
+
+#: platform/iphone/export/export.cpp
+msgid "Identifier is missing."
+msgstr ""
+
+#: platform/iphone/export/export.cpp
+msgid "The character '%s' is not allowed in Identifier."
+msgstr ""
+
+#: platform/iphone/export/export.cpp
+msgid "App Store Team ID not specified - cannot configure the project."
+msgstr ""
+"ID de App Store Team non especificado - non se pode configurar o proxecto."
+
+#: platform/iphone/export/export.cpp
+msgid "Invalid Identifier:"
+msgstr ""
+
+#: platform/iphone/export/export.cpp
+msgid "Required icon is not specified in the preset."
+msgstr ""
+"As iconas requeridas non están especificadas nos axustes de exportación."
+
+#: platform/javascript/export/export.cpp
+msgid "Stop HTTP Server"
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Run in Browser"
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Run exported HTML in the system's default browser."
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Could not write file:"
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Could not open template for export:"
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Invalid export template:"
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Could not read custom HTML shell:"
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Could not read boot splash image file:"
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Using default boot splash image."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid package short name."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid package unique name."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid package publisher display name."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid product GUID."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid publisher GUID."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid background color."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid Store Logo image dimensions (should be 50x50)."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid square 44x44 logo image dimensions (should be 44x44)."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid square 71x71 logo image dimensions (should be 71x71)."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid square 150x150 logo image dimensions (should be 150x150)."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid square 310x310 logo image dimensions (should be 310x310)."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)."
+msgstr ""
+
+#: platform/uwp/export/export.cpp
+msgid "Invalid splash screen image dimensions (should be 620x300)."
+msgstr ""
+
+#: scene/2d/animated_sprite.cpp
+msgid ""
+"A SpriteFrames resource must be created or set in the \"Frames\" property in "
+"order for AnimatedSprite to display frames."
+msgstr ""
+
+#: scene/2d/canvas_modulate.cpp
+msgid ""
+"Only one visible CanvasModulate is allowed per scene (or set of instanced "
+"scenes). The first created one will work, while the rest will be ignored."
+msgstr ""
+
+#: scene/2d/collision_object_2d.cpp
+msgid ""
+"This node has no shape, so it can't collide or interact with other objects.\n"
+"Consider adding a CollisionShape2D or CollisionPolygon2D as a child to "
+"define its shape."
+msgstr ""
+"Este nodo non ten unha forma física definida, polo que non pode colisionar "
+"ou interactuar con outros obxectos.\n"
+"Engade un nodo CollisionShape2D ou CollisionPolygon2D como fillo para "
+"definir a sua forma."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid ""
+"CollisionPolygon2D only serves to provide a collision shape to a "
+"CollisionObject2D derived node. Please only use it as a child of Area2D, "
+"StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."
+msgstr ""
+"O nodo CollisionPolygon2D só serve para darlle unha forma física a nodos "
+"derivados de CollisionObject2D. É decir, do tipo Area2D, StaticBody2D, "
+"RigidBody2D, KinematicBody2D, etc."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "An empty CollisionPolygon2D has no effect on collision."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
+#: scene/2d/collision_shape_2d.cpp
+msgid ""
+"CollisionShape2D only serves to provide a collision shape to a "
+"CollisionObject2D derived node. Please only use it as a child of Area2D, "
+"StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."
+msgstr ""
+"O nodo CollisionShape2D só serve para darlle unha forma física a nodos "
+"derivados de CollisionObject2D. É decir, do tipo Area2D, StaticBody2D, "
+"RigidBody2D, KinematicBody2D, etc."
+
+#: scene/2d/collision_shape_2d.cpp
+msgid ""
+"A shape must be provided for CollisionShape2D to function. Please create a "
+"shape resource for it!"
+msgstr ""
+
+#: scene/2d/collision_shape_2d.cpp
+msgid ""
+"Polygon-based shapes are not meant be used nor edited directly through the "
+"CollisionShape2D node. Please use the CollisionPolygon2D node instead."
+msgstr ""
+"As formas físicas baseadas en polígonos non están pensadas para editarse "
+"directamente mediante o nodo CollisionShape2D. Por favor, usa o nodo "
+"CollisionPolygon2D no seu lugar."
+
+#: scene/2d/cpu_particles_2d.cpp
+msgid ""
+"CPUParticles2D animation requires the usage of a CanvasItemMaterial with "
+"\"Particles Animation\" enabled."
+msgstr ""
+
+#: scene/2d/joints_2d.cpp
+msgid "Node A and Node B must be PhysicsBody2Ds"
+msgstr "Os nodo A e B teñen que ser do tipo PhysicsBody2D"
+
+#: scene/2d/joints_2d.cpp
+msgid "Node A must be a PhysicsBody2D"
+msgstr "O nodo A ten que ser un nodo PhysicsBody2D"
+
+#: scene/2d/joints_2d.cpp
+msgid "Node B must be a PhysicsBody2D"
+msgstr "O nodo B ten que ser un nodo PhysicsBody2D"
+
+#: scene/2d/joints_2d.cpp
+msgid "Joint is not connected to two PhysicsBody2Ds"
+msgstr "A articulación non está conectada a dous nodos PhysicsBody2D"
+
+#: scene/2d/joints_2d.cpp
+msgid "Node A and Node B must be different PhysicsBody2Ds"
+msgstr "Os nodos A e B teñen que ser nodos PhysicsBody2D distintos"
+
+#: scene/2d/light_2d.cpp
+msgid ""
+"A texture with the shape of the light must be supplied to the \"Texture\" "
+"property."
+msgstr ""
+
+#: scene/2d/light_occluder_2d.cpp
+msgid ""
+"An occluder polygon must be set (or drawn) for this occluder to take effect."
+msgstr ""
+
+#: scene/2d/light_occluder_2d.cpp
+msgid "The occluder polygon for this occluder is empty. Please draw a polygon."
+msgstr ""
+
+#: scene/2d/navigation_polygon.cpp
+msgid ""
+"A NavigationPolygon resource must be set or created for this node to work. "
+"Please set a property or draw a polygon."
+msgstr ""
+
+#: scene/2d/navigation_polygon.cpp
+msgid ""
+"NavigationPolygonInstance must be a child or grandchild to a Navigation2D "
+"node. It only provides navigation data."
+msgstr ""
+
+#: scene/2d/parallax_layer.cpp
+msgid ""
+"ParallaxLayer node only works when set as child of a ParallaxBackground node."
+msgstr ""
+
+#: scene/2d/particles_2d.cpp
+msgid ""
+"GPU-based particles are not supported by the GLES2 video driver.\n"
+"Use the CPUParticles2D node instead. You can use the \"Convert to "
+"CPUParticles\" option for this purpose."
+msgstr ""
+"As partículas baseadas na GPU non están soportas por o controlador de vídeo "
+"de GLES2.\n"
+"Usa o nodo CPUParticles2D no seu lugar. Podes usar a opción \"Converter a "
+"CPUParticles\" con tal motivo."
+
+#: scene/2d/particles_2d.cpp scene/3d/particles.cpp
+msgid ""
+"A material to process the particles is not assigned, so no behavior is "
+"imprinted."
+msgstr ""
+
+#: scene/2d/particles_2d.cpp
+msgid ""
+"Particles2D animation requires the usage of a CanvasItemMaterial with "
+"\"Particles Animation\" enabled."
+msgstr ""
+
+#: scene/2d/path_2d.cpp
+msgid "PathFollow2D only works when set as a child of a Path2D node."
+msgstr ""
+
+#: scene/2d/physics_body_2d.cpp
+msgid ""
+"Size changes to RigidBody2D (in character or rigid modes) will be overridden "
+"by the physics engine when running.\n"
+"Change the size in children collision shapes instead."
+msgstr ""
+"Os cambios ao tamaño do RigidBody2D (en modo ríxido ou modo personaxe) serán "
+"sobreescritos por o motor físico cando a aplicación estea executándose.\n"
+"Cambia o tamaño dos nodos fillos (CollisionShape2D e CollisionPolygon2D) no "
+"seu lugar."
+
+#: scene/2d/remote_transform_2d.cpp
+msgid "Path property must point to a valid Node2D node to work."
+msgstr ""
+
+#: scene/2d/skeleton_2d.cpp
+msgid "This Bone2D chain should end at a Skeleton2D node."
+msgstr ""
+
+#: scene/2d/skeleton_2d.cpp
+msgid "A Bone2D only works with a Skeleton2D or another Bone2D as parent node."
+msgstr ""
+
+#: scene/2d/skeleton_2d.cpp
+msgid ""
+"This bone lacks a proper REST pose. Go to the Skeleton2D node and set one."
+msgstr ""
+
+#: scene/2d/tile_map.cpp
+msgid ""
+"TileMap with Use Parent on needs a parent CollisionObject2D to give shapes "
+"to. Please use it as a child of Area2D, StaticBody2D, RigidBody2D, "
+"KinematicBody2D, etc. to give them a shape."
+msgstr ""
+
+#: scene/2d/visibility_notifier_2d.cpp
+msgid ""
+"VisibilityEnabler2D works best when used with the edited scene root directly "
+"as parent."
+msgstr ""
+
+#: scene/3d/arvr_nodes.cpp
+msgid "ARVRCamera must have an ARVROrigin node as its parent."
+msgstr ""
+
+#: scene/3d/arvr_nodes.cpp
+msgid "ARVRController must have an ARVROrigin node as its parent."
+msgstr ""
+
+#: scene/3d/arvr_nodes.cpp
+msgid ""
+"The controller ID must not be 0 or this controller won't be bound to an "
+"actual controller."
+msgstr ""
+"O ID do controlador non pode ser 0, ou o controlador non estará asociado a "
+"ningún controlador real."
+
+#: scene/3d/arvr_nodes.cpp
+msgid "ARVRAnchor must have an ARVROrigin node as its parent."
+msgstr ""
+
+#: scene/3d/arvr_nodes.cpp
+msgid ""
+"The anchor ID must not be 0 or this anchor won't be bound to an actual "
+"anchor."
+msgstr ""
+"O ID da áncora non pode ser 0, ou esta áncora non estará asociada a ningunha "
+"áncora real."
+
+#: scene/3d/arvr_nodes.cpp
+msgid "ARVROrigin requires an ARVRCamera child node."
+msgstr ""
+
+#: scene/3d/baked_lightmap.cpp
+msgid "Finding meshes and lights"
+msgstr ""
+
+#: scene/3d/baked_lightmap.cpp
+msgid "Preparing geometry (%d/%d)"
+msgstr ""
+
+#: scene/3d/baked_lightmap.cpp
+msgid "Preparing environment"
+msgstr ""
+
+#: scene/3d/baked_lightmap.cpp
+msgid "Generating capture"
+msgstr ""
+
+#: scene/3d/baked_lightmap.cpp
+msgid "Saving lightmaps"
+msgstr ""
+
+#: scene/3d/baked_lightmap.cpp
+msgid "Done"
+msgstr "Feito"
+
+#: scene/3d/collision_object.cpp
+msgid ""
+"This node has no shape, so it can't collide or interact with other objects.\n"
+"Consider adding a CollisionShape or CollisionPolygon as a child to define "
+"its shape."
+msgstr ""
+"Este nodo non ten unha forma física definida, polo que non pode colisionar "
+"ou interactuar con outros obxectos.\n"
+"Engade un nodo CollisionShape ou CollisionPolygon como fillo para definir a "
+"sua forma."
+
+#: scene/3d/collision_polygon.cpp
+msgid ""
+"CollisionPolygon only serves to provide a collision shape to a "
+"CollisionObject derived node. Please only use it as a child of Area, "
+"StaticBody, RigidBody, KinematicBody, etc. to give them a shape."
+msgstr ""
+"O nodo CollisionPolygon só serve para darlle unha forma física a nodos "
+"derivados de CollisionObject. É decir, do tipo Area, StaticBody, RigidBody, "
+"KinematicBody, etc."
+
+#: scene/3d/collision_polygon.cpp
+msgid "An empty CollisionPolygon has no effect on collision."
+msgstr ""
+
+#: scene/3d/collision_shape.cpp
+msgid ""
+"CollisionShape only serves to provide a collision shape to a CollisionObject "
+"derived node. Please only use it as a child of Area, StaticBody, RigidBody, "
+"KinematicBody, etc. to give them a shape."
+msgstr ""
+"O nodo CollisionShape só serve para darlle unha forma física a nodos "
+"derivados de CollisionObject. É decir, do tipo Area, StaticBody, RigidBody, "
+"KinematicBody, etc."
+
+#: scene/3d/collision_shape.cpp
+msgid ""
+"A shape must be provided for CollisionShape to function. Please create a "
+"shape resource for it."
+msgstr ""
+
+#: scene/3d/collision_shape.cpp
+msgid ""
+"Plane shapes don't work well and will be removed in future versions. Please "
+"don't use them."
+msgstr ""
+
+#: scene/3d/collision_shape.cpp
+msgid ""
+"ConcavePolygonShape doesn't support RigidBody in another mode than static."
+msgstr ""
+"A forma física ConcavePolygonShape non está soportada en nodos RigidBody en "
+"ningún outro modo que non sexa o estático."
+
+#: scene/3d/cpu_particles.cpp
+msgid "Nothing is visible because no mesh has been assigned."
+msgstr ""
+
+#: scene/3d/cpu_particles.cpp
+msgid ""
+"CPUParticles animation requires the usage of a SpatialMaterial whose "
+"Billboard Mode is set to \"Particle Billboard\"."
+msgstr ""
+
+#: scene/3d/gi_probe.cpp
+msgid "Plotting Meshes"
+msgstr ""
+
+#: scene/3d/gi_probe.cpp
+msgid "Finishing Plot"
+msgstr ""
+
+#: scene/3d/gi_probe.cpp
+msgid ""
+"GIProbes are not supported by the GLES2 video driver.\n"
+"Use a BakedLightmap instead."
+msgstr ""
+
+#: scene/3d/light.cpp
+msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
+msgstr ""
+
+#: scene/3d/navigation_mesh.cpp
+msgid "A NavigationMesh resource must be set or created for this node to work."
+msgstr ""
+
+#: scene/3d/navigation_mesh.cpp
+msgid ""
+"NavigationMeshInstance must be a child or grandchild to a Navigation node. "
+"It only provides navigation data."
+msgstr ""
+
+#: scene/3d/particles.cpp
+msgid ""
+"GPU-based particles are not supported by the GLES2 video driver.\n"
+"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles"
+"\" option for this purpose."
+msgstr ""
+"As partículas baseadas na GPU non están soportas por o controlador de vídeo "
+"de GLES2.\n"
+"Usa o nodo CPUParticles no seu lugar. Podes usar a opción \"Converter a "
+"CPUParticles\" con tal motivo."
+
+#: scene/3d/particles.cpp
+msgid ""
+"Nothing is visible because meshes have not been assigned to draw passes."
+msgstr ""
+
+#: scene/3d/particles.cpp
+msgid ""
+"Particles animation requires the usage of a SpatialMaterial whose Billboard "
+"Mode is set to \"Particle Billboard\"."
+msgstr ""
+
+#: scene/3d/path.cpp
+msgid "PathFollow only works when set as a child of a Path node."
+msgstr ""
+
+#: scene/3d/path.cpp
+msgid ""
+"PathFollow's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its "
+"parent Path's Curve resource."
+msgstr ""
+
+#: scene/3d/physics_body.cpp
+msgid ""
+"Size changes to RigidBody (in character or rigid modes) will be overridden "
+"by the physics engine when running.\n"
+"Change the size in children collision shapes instead."
+msgstr ""
+"Os cambios ao tamaño do RigidBody (en modo ríxido ou modo personaxe) serán "
+"sobreescritos por o motor físico cando a aplicación estea executándose.\n"
+"Cambia o tamaño dos nodos fillos (CollisionShape e CollisionPolygon) no seu "
+"lugar."
+
+#: scene/3d/physics_joint.cpp
+msgid "Node A and Node B must be PhysicsBodies"
+msgstr ""
+
+#: scene/3d/physics_joint.cpp
+msgid "Node A must be a PhysicsBody"
+msgstr "O nodo A ten que ser un nodo PhysicsBody"
+
+#: scene/3d/physics_joint.cpp
+msgid "Node B must be a PhysicsBody"
+msgstr "O nodo B ten que ser un nodo PhysicsBody"
+
+#: scene/3d/physics_joint.cpp
+msgid "Joint is not connected to any PhysicsBodies"
+msgstr ""
+
+#: scene/3d/physics_joint.cpp
+msgid "Node A and Node B must be different PhysicsBodies"
+msgstr ""
+
+#: scene/3d/remote_transform.cpp
+msgid ""
+"The \"Remote Path\" property must point to a valid Spatial or Spatial-"
+"derived node to work."
+msgstr ""
+
+#: scene/3d/soft_body.cpp
+msgid "This body will be ignored until you set a mesh."
+msgstr "Este corpo será ignorado ata que se lle sea asignado unha malla."
+
+#: scene/3d/soft_body.cpp
+msgid ""
+"Size changes to SoftBody will be overridden by the physics engine when "
+"running.\n"
+"Change the size in children collision shapes instead."
+msgstr ""
+"Os cambios ao tamaño do SoftBody serán sobreescritos por o motor físico "
+"cando a aplicación estea executándose.\n"
+"Cambia o tamaño dos nodos fillos (CollisionShape e CollisionPolygon) no seu "
+"lugar."
+
+#: scene/3d/sprite_3d.cpp
+msgid ""
+"A SpriteFrames resource must be created or set in the \"Frames\" property in "
+"order for AnimatedSprite3D to display frames."
+msgstr ""
+
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+"O nodo VehicleWheel (Roda de Vehículo) serve para proporcionar un sistema de "
+"rodas a un nodo VehicleBody. Por favor; úsao como fillo dun nodo VehicleBody."
+
+#: scene/3d/world_environment.cpp
+msgid ""
+"WorldEnvironment requires its \"Environment\" property to contain an "
+"Environment to have a visible effect."
+msgstr ""
+
+#: scene/3d/world_environment.cpp
+msgid ""
+"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)."
+msgstr ""
+
+#: scene/3d/world_environment.cpp
+msgid ""
+"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set "
+"this environment's Background Mode to Canvas (for 2D scenes)."
+msgstr ""
+
+#: scene/animation/animation_blend_tree.cpp
+msgid "On BlendTree node '%s', animation not found: '%s'"
+msgstr ""
+
+#: scene/animation/animation_blend_tree.cpp
+msgid "Animation not found: '%s'"
+msgstr ""
+
+#: scene/animation/animation_tree.cpp
+msgid "In node '%s', invalid animation: '%s'."
+msgstr ""
+
+#: scene/animation/animation_tree.cpp
+msgid "Invalid animation: '%s'."
+msgstr ""
+
+#: scene/animation/animation_tree.cpp
+msgid "Nothing connected to input '%s' of node '%s'."
+msgstr ""
+
+#: scene/animation/animation_tree.cpp
+msgid "No root AnimationNode for the graph is set."
+msgstr ""
+
+#: scene/animation/animation_tree.cpp
+msgid "Path to an AnimationPlayer node containing animations is not set."
+msgstr ""
+
+#: scene/animation/animation_tree.cpp
+msgid "Path set for AnimationPlayer does not lead to an AnimationPlayer node."
+msgstr ""
+
+#: scene/animation/animation_tree.cpp
+msgid "The AnimationPlayer root node is not a valid node."
+msgstr ""
+
+#: scene/animation/animation_tree_player.cpp
+msgid "This node has been deprecated. Use AnimationTree instead."
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+msgid "Pick a color from the editor window."
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+msgid "HSV"
+msgstr "HSV"
+
+#: scene/gui/color_picker.cpp
+msgid "Raw"
+msgstr "Sen Procesar (Raw)"
+
+#: scene/gui/color_picker.cpp
+msgid "Switch between hexadecimal and code values."
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+msgid "Add current color as a preset."
+msgstr ""
+
+#: scene/gui/container.cpp
+msgid ""
+"Container by itself serves no purpose unless a script configures its "
+"children placement behavior.\n"
+"If you don't intend to add a script, use a plain Control node instead."
+msgstr ""
+"Un nodo contedor (Container) por sí mesmo non ten ningunha utilidade, salvo "
+"que se lle engada algún Script que configure a colocación dos seus nodos "
+"fillos.\n"
+"Se non tes pensado engadir un Script, utilizada un nodo Control no seu lugar."
+
+#: scene/gui/control.cpp
+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\"."
+msgstr ""
+
+#: scene/gui/dialogs.cpp
+msgid "Alert!"
+msgstr "Alerta!"
+
+#: scene/gui/dialogs.cpp
+msgid "Please Confirm..."
+msgstr "Por favor, confirma..."
+
+#: scene/gui/file_dialog.cpp
+msgid "Must use a valid extension."
+msgstr ""
+
+#: scene/gui/graph_edit.cpp
+msgid "Enable grid minimap."
+msgstr ""
+
+#: scene/gui/popup.cpp
+msgid ""
+"Popups will hide by default unless you call popup() or any of the popup*() "
+"functions. Making them visible for editing is fine, but they will hide upon "
+"running."
+msgstr ""
+"As ventás emerxentes (Popups) están ocultas por defecto, a non ser que "
+"chames a popup() ou calquera das funcións popup*(). Podes facelas visibles "
+"para editalas, pero ocultarasen ao iniciar a execución."
+
+#: scene/gui/range.cpp
+msgid "If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0."
+msgstr ""
+
+#: scene/gui/scroll_container.cpp
+msgid ""
+"ScrollContainer is intended to work with a single child control.\n"
+"Use a container as child (VBox, HBox, etc.), or a Control and set the custom "
+"minimum size manually."
+msgstr ""
+
+#: scene/gui/tree.cpp
+msgid "(Other)"
+msgstr "(Outros)"
+
+#: scene/main/scene_tree.cpp
+msgid ""
+"Default Environment as specified in Project Settings (Rendering -> "
+"Environment -> Default Environment) could not be loaded."
+msgstr ""
+
+#: scene/main/viewport.cpp
+msgid ""
+"This viewport is not set as render target. If you intend for it to display "
+"its contents directly to the screen, make it a child of a Control so it can "
+"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
+"texture to some node for display."
+msgstr ""
+"Esta Mini-Ventá (Viewport) no está configurada como obxectivo de "
+"renderizado. Se quere que o seu contido se mostre directamente na pantalla, "
+"convértao nun nodo fillo dun nodo Control para que poida recibir dimensións. "
+"Ou ben, fágao un RenderTarget e asigne a súa textura a algún nodo."
+
+#: scene/main/viewport.cpp
+msgid "Viewport size must be greater than 0 to render anything."
+msgstr ""
+"As dimensións da Mini-Ventá (Viewport) deben de ser maior que 0 para poder "
+"renderizar nada."
+
+#: scene/resources/visual_shader_nodes.cpp
+msgid ""
+"The sampler port is connected but not used. Consider changing the source to "
+"'SamplerPort'."
+msgstr ""
+
+#: scene/resources/visual_shader_nodes.cpp
+msgid "Invalid source for preview."
+msgstr ""
+
+#: scene/resources/visual_shader_nodes.cpp
+msgid "Invalid source for shader."
+msgstr ""
+
+#: scene/resources/visual_shader_nodes.cpp
+msgid "Invalid comparison function for that type."
+msgstr ""
+
+#: servers/visual/shader_language.cpp
+msgid "Assignment to function."
+msgstr ""
+
+#: servers/visual/shader_language.cpp
+msgid "Assignment to uniform."
+msgstr ""
+
+#: servers/visual/shader_language.cpp
+msgid "Varyings can only be assigned in vertex function."
+msgstr ""
+
+#: servers/visual/shader_language.cpp
+msgid "Constants cannot be modified."
+msgstr ""
diff --git a/editor/translations/he.po b/editor/translations/he.po
index c179d06c24..ab97d97c0a 100644
--- a/editor/translations/he.po
+++ b/editor/translations/he.po
@@ -18,12 +18,13 @@
# yariv benj <yariv4400@gmail.com>, 2020.
# Guy Dadon <guydadon14@gmail.com>, 2020.
# bruvzg <bruvzg13@gmail.com>, 2020.
+# Omer I.S. <omeritzicschwartz@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-12-03 19:28+0000\n"
-"Last-Translator: Ziv D <wizdavid@gmail.com>\n"
+"PO-Revision-Date: 2021-02-21 10:51+0000\n"
+"Last-Translator: Omer I.S. <omeritzicschwartz@gmail.com>\n"
"Language-Team: Hebrew <https://hosted.weblate.org/projects/godot-engine/"
"godot/he/>\n"
"Language: he\n"
@@ -32,7 +33,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.4-dev\n"
+"X-Generator: Weblate 4.5\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -379,9 +380,8 @@ msgid "Anim Insert"
msgstr "הוסף הנפשה"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "AnimationPlayer can't animate itself, only other players."
-msgstr "נגן הנפשות לא יכול להנפיש את עצמו, רק שחקנים אחרים."
+msgstr "נגן ההנפשות לא יכול להנפיש את עצמו, רק שחקנים אחרים."
#: editor/animation_track_editor.cpp
msgid "Anim Create & Insert"
@@ -662,7 +662,7 @@ msgstr "בחירת רצועות להעתקה"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "העתקה"
@@ -900,9 +900,8 @@ msgid "Connect a Signal to a Method"
msgstr "שגיאת חיבור"
#: editor/connections_dialog.cpp
-#, fuzzy
msgid "Edit Connection:"
-msgstr "שגיאת חיבור"
+msgstr "עריכת חיבור:"
#: editor/connections_dialog.cpp
msgid "Are you sure you want to remove all connections from the \"%s\" signal?"
@@ -1102,7 +1101,7 @@ msgstr "דפדפן משאבים יתומים"
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp
msgid "Delete"
-msgstr "למחוק"
+msgstr "מחיקה"
#: editor/dependency_editor.cpp
msgid "Owns"
@@ -1194,9 +1193,8 @@ msgid "License"
msgstr "רישיון"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Third-party Licenses"
-msgstr "רישיון צד שלישי"
+msgstr "רשיונות צד שלישי"
#: editor/editor_about.cpp
msgid ""
@@ -1657,9 +1655,8 @@ msgid "Script Editor"
msgstr "פתיחת עורך סקריפטים"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Asset Library"
-msgstr "ייצוא ספריה"
+msgstr "ספריית משאבים"
#: editor/editor_feature_profile.cpp
msgid "Scene Tree Editing"
@@ -1874,8 +1871,8 @@ msgid "Open a File or Directory"
msgstr "פתיחת קובץ או תיקייה"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "שמירה"
@@ -2532,7 +2529,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr "לא ניתן לפתוח את תוסף ההרחבות בנתיב: '%s' פענוח ההגדרות נכשל."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr "לא ניתן למצוא שדה סקריפט עבור תוסף הרחבה בנתיב 'res://addons/%s'."
#: editor/editor_node.cpp
@@ -2952,14 +2950,6 @@ msgid "Help"
msgstr "עזרה"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "חיפוש"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "מסמכים מקוונים"
@@ -3120,6 +3110,24 @@ msgid "Open & Run a Script"
msgstr "פתיחה והרצה של סקריפט"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"הקבצים הבאים הם חדשים בכונן.\n"
+"באילו פעולות לנקוט?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "רענון"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "שמירה מחדש"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "חדש בירושה"
@@ -3328,7 +3336,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "הדבקה"
@@ -4047,6 +4055,21 @@ msgstr ""
msgid "Saving..."
msgstr "שמירה…"
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "נא לבחור מפרקים לייצוא"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "ייבוא"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "טעינת בררת המחדל"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d קבצים"
@@ -5030,7 +5053,8 @@ msgid "Got:"
msgstr "התקבל:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "בדיקת האש sha256 נכשלה"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5134,7 +5158,6 @@ msgid "Sort:"
msgstr "מיון:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "קטגוריה:"
@@ -5498,9 +5521,8 @@ msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/texture_region_editor_plugin.cpp
#: editor/plugins/tile_set_editor_plugin.cpp scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Zoom Reset"
-msgstr "להתרחק"
+msgstr "איפוס התקריב"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -6987,6 +7009,14 @@ msgstr "סגירת מסמכים"
msgid "Run"
msgstr "הרצה"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "חיפוש"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "לצעוד לתוך"
@@ -7042,16 +7072,6 @@ msgstr ""
"הקבצים הבאים הם חדשים בכונן.\n"
"באילו פעולות לנקוט?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "רענון"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "שמירה מחדש"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "ניפוי שגיאות"
@@ -7150,8 +7170,8 @@ msgstr "מחיקת נקודות"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "גזירה"
@@ -7278,13 +7298,12 @@ msgid "Go to Previous Breakpoint"
msgstr "מעבר לנקודת העצירה הקודמת"
#: editor/plugins/shader_editor_plugin.cpp
-#, fuzzy
msgid ""
"This shader has been modified on on disk.\n"
"What action should be taken?"
msgstr ""
"הקבצים הבאים הם חדשים בכונן.\n"
-"באילו פעולות לנקוט?:"
+"באילו פעולות לנקוט?"
#: editor/plugins/shader_editor_plugin.cpp
msgid "Shader"
@@ -7392,6 +7411,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -10053,6 +10076,13 @@ msgid "Projects"
msgstr "מיזם"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr ""
+"הקבצים נסרקים,\n"
+"נא להמתין…"
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10423,6 +10453,11 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "טעינת בררת המחדל"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "ערכה מוגדרת…"
@@ -10682,6 +10717,16 @@ msgid "Instance Child Scene"
msgstr "יצירת מופע לסצנה הצאצאית"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Can't paste root node into the same scene."
+msgstr "לא יכול לפעול על מפרקים מסצנה זרה!"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "הדבקת מפרקים"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "ניתוק סקריפט"
@@ -10805,6 +10850,11 @@ msgid "Attach Script"
msgstr "חיבור סקריפט"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "גזירת מפרקים"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "הסרת מפרק(ים)"
@@ -12439,6 +12489,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "ל־CollisionPolygon2D ריק אין השפעה על התנגשות."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12736,11 +12794,6 @@ msgstr ""
"מנהל הווידאו GLES2 אינו תומך ב- GIProbes.\n"
"השתמש ב-BakedLightmap במקום."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "SpotLight עם זווית רחבה מ-90 מעלות אינו יכול להטיל צללים."
diff --git a/editor/translations/hi.po b/editor/translations/hi.po
index fbf1352eff..034451542b 100644
--- a/editor/translations/hi.po
+++ b/editor/translations/hi.po
@@ -649,7 +649,7 @@ msgstr "कॉपी करने के लिए ट्रैक का चय
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "कॉपी"
@@ -1852,8 +1852,8 @@ msgid "Open a File or Directory"
msgstr "फ़ाइल या डायरेक्टरी खोलिये"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "सेव कीजिये"
@@ -2518,7 +2518,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr "ऐडऑन प्लगइन को सक्षम करने में असमर्थ: '%' कॉन्फिग का पार्सिंग विफल रहा।"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr "ऐडऑन प्लगइन के लिए स्क्रिप्ट फ़ील्ड खोजने में असमर्थ: 'res://addons/% s'।"
#: editor/editor_node.cpp
@@ -2946,14 +2947,6 @@ msgid "Help"
msgstr "मदद"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "ढूंढें"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "ऑनलाइन डॉक्स"
@@ -3117,6 +3110,23 @@ msgid "Open & Run a Script"
msgstr "ओपन एंड रन एक स्क्रिप्ट"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr "निम्न फ़ाइलों का निस्सारण नहीं हो पाया:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "नई विरासत में मिली"
@@ -3324,7 +3334,7 @@ msgstr "अद्वितीय बनाओ"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "चिपकाएँ"
@@ -4025,6 +4035,21 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "आयात करने के लिए नोड (एस) का चयन करें"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "इंपोर्ट"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "प्रायिक लोड कीजिये"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4972,7 +4997,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5076,7 +5101,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6863,6 +6887,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "ढूंढें"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6914,16 +6946,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7020,8 +7042,8 @@ msgstr "एक नया बनाएं"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7244,6 +7266,11 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "आकार: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9834,6 +9861,11 @@ msgid "Projects"
msgstr "परियोजना के संस्थापक"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "दर्पण को पुनः प्राप्त करना, कृपया प्रतीक्षा करें ..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10196,6 +10228,11 @@ msgstr ""
msgid "Plugins"
msgstr "प्लगइन्स"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "प्रायिक लोड कीजिये"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10441,6 +10478,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "प्रतिलिपि"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "नई स्क्रिप्ट"
@@ -10567,6 +10613,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "प्रतिलिपि"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12185,6 +12236,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12442,11 +12501,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/hr.po b/editor/translations/hr.po
index 9826f61488..047363db63 100644
--- a/editor/translations/hr.po
+++ b/editor/translations/hr.po
@@ -631,7 +631,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopiraj"
@@ -1812,8 +1812,8 @@ msgid "Open a File or Directory"
msgstr "Otvori datoteku ili direktorij"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Spremi"
@@ -2447,7 +2447,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2837,14 +2837,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2998,6 +2990,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3200,7 +3208,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3885,6 +3893,21 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Odaberi Sve/Ništa"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Uvoz"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Učitaj Zadano"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Fajlovi"
@@ -4832,7 +4855,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4936,7 +4959,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6703,6 +6725,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6754,16 +6784,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6856,8 +6876,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7078,6 +7098,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9611,6 +9635,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9971,6 +9999,11 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Učitaj Zadano"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10214,6 +10247,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Brisati odabrani ključ/odabrane ključeve"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Odspoji Skriptu"
@@ -10334,6 +10376,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11917,6 +11963,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12172,11 +12226,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/hu.po b/editor/translations/hu.po
index 78db184f7d..3966959f91 100644
--- a/editor/translations/hu.po
+++ b/editor/translations/hu.po
@@ -663,7 +663,7 @@ msgstr "Másolandó nyomvonalak kiválasztása"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Másolás"
@@ -1855,8 +1855,8 @@ msgid "Open a File or Directory"
msgstr "Fájl vagy Könyvtár Megnyitása"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Mentés"
@@ -2530,7 +2530,8 @@ msgstr ""
"megbukott."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"Nem található szkript mező az addon pluginnak a következő helyen: 'res://"
"addons/%s'."
@@ -2970,14 +2971,6 @@ msgid "Help"
msgstr "Súgó"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Keresés"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Online Dokumentáció"
@@ -3133,6 +3126,25 @@ msgid "Open & Run a Script"
msgstr "Szkriptet Megnyit és Futtat"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"A alábbi fájlok újabbak a lemezen.\n"
+"Mit szeretne lépni?:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Újratöltés"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Újramentés"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Új Örökölt"
@@ -3335,7 +3347,7 @@ msgstr "Egyedivé tétel"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Beillesztés"
@@ -4035,6 +4047,21 @@ msgstr ""
msgid "Saving..."
msgstr "Mentés..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Kiválasztó Mód"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importálás"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Alapértelmezett Betöltése"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d fájl"
@@ -4993,7 +5020,8 @@ msgid "Got:"
msgstr "Kapott:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "sha256 hash ellenőrzés megbukott"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5097,7 +5125,6 @@ msgid "Sort:"
msgstr "Rendezés:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategória:"
@@ -6904,6 +6931,14 @@ msgstr "Dokumentációs Lapok Bezárása"
msgid "Run"
msgstr "Futtatás"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Keresés"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Belépés"
@@ -6957,16 +6992,6 @@ msgstr ""
"A alábbi fájlok újabbak a lemezen.\n"
"Mit szeretne lépni?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Újratöltés"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Újramentés"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Hibakereső"
@@ -7059,8 +7084,8 @@ msgstr "Töréspontok"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Kivágás"
@@ -7282,6 +7307,11 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "Méret: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Rajzolt objektumok"
@@ -9831,6 +9861,11 @@ msgid "Projects"
msgstr "Projektek"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Tükrök letöltése, kérjük várjon..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10194,6 +10229,11 @@ msgstr ""
msgid "Plugins"
msgstr "Bővítmények"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Alapértelmezett Betöltése"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Beépített Beállítások..."
@@ -10438,6 +10478,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Node-ok beillesztése"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Szkript leválasztása"
@@ -10558,6 +10607,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Node-ok kivágása"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12152,6 +12206,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12412,11 +12474,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/id.po b/editor/translations/id.po
index b7dc29eb20..5dc5b9751a 100644
--- a/editor/translations/id.po
+++ b/editor/translations/id.po
@@ -28,12 +28,13 @@
# Richard Urban <redasuio1@gmail.com>, 2020.
# yusuf afandi <afandi.yusuf.04@gmail.com>, 2020.
# Habib Rohman <revolusi147id@gmail.com>, 2020.
+# Hanz <hanzhaxors@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-11-13 22:59+0000\n"
-"Last-Translator: Habib Rohman <revolusi147id@gmail.com>\n"
+"PO-Revision-Date: 2021-03-08 15:33+0000\n"
+"Last-Translator: Hanz <hanzhaxors@gmail.com>\n"
"Language-Team: Indonesian <https://hosted.weblate.org/projects/godot-engine/"
"godot/id/>\n"
"Language: id\n"
@@ -41,7 +42,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.4-dev\n"
+"X-Generator: Weblate 4.5.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -57,7 +58,8 @@ msgstr "String dengan panjang 1 (karakter) yang diharapkan."
#: 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 "Tidak cukup bytes untuk mendekode bytes, atau format tidak valid."
+msgstr ""
+"Tidak cukup bytes untuk merubah bytes ke nilai asal, atau format tidak valid."
#: core/math/expression.cpp
msgid "Invalid input %i (not passed) in expression"
@@ -65,8 +67,7 @@ msgstr "Masukkan tidak sah %i (tidak diberikan) dalam ekspresi"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
-msgstr ""
-"self tidak dapat digunakan karena tidak memiliki instance (tidak lolos)"
+msgstr "self tidak dapat digunakan karena instance adalah null"
#: core/math/expression.cpp
msgid "Invalid operands to operator %s, %s and %s."
@@ -74,7 +75,7 @@ msgstr "operan salah untuk operator %s, %s dan %s."
#: core/math/expression.cpp
msgid "Invalid index of type %s for base type %s"
-msgstr "Tipe index %s tidak valid untuk tipe dasar %s"
+msgstr "Tipe indeks %s tidak valid untuk tipe dasar %s"
#: core/math/expression.cpp
msgid "Invalid named index '%s' for base type %s"
@@ -671,7 +672,7 @@ msgstr "Pilih Trek untuk Disalin"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopy"
@@ -1052,14 +1053,14 @@ msgid "Owners Of:"
msgstr "Pemilik Dari:"
#: editor/dependency_editor.cpp
-#, fuzzy
msgid ""
"Remove selected files from the project? (no undo)\n"
"You can find the removed files in the system trash to restore them."
-msgstr "Hapus berkas yang dipilih dari proyek? (tidak bisa dibatalkan)"
+msgstr ""
+"Hapus berkas yang dipilih dari proyek? (tidak bisa dibatalkan)\n"
+"Anda bisa menemukan berkas yang telah dihapus di tong sampah."
#: editor/dependency_editor.cpp
-#, fuzzy
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -1068,7 +1069,8 @@ msgid ""
msgstr ""
"File-file yang telah dihapus diperlukan oleh resource lain agar mereka dapat "
"bekerja.\n"
-"Hapus saja? (tidak bisa dibatalkan/undo)"
+"Hapus saja? (tidak bisa dibatalkan)\n"
+"Anda bisa menemukan berkas yang telah dihapus di tong sampah."
#: editor/dependency_editor.cpp
msgid "Cannot remove:"
@@ -1621,34 +1623,31 @@ msgstr ""
"Enabled'."
#: editor/editor_export.cpp
-#, fuzzy
msgid ""
"Target platform requires 'PVRTC' texture compression for GLES2. Enable "
"'Import Pvrtc' in Project Settings."
msgstr ""
-"Platform target membutuhkan kompresi tekstur 'ETC' untuk GLES2. Aktifkan "
-"'Impor Lainnya' di Pengaturan Proyek."
+"Platform target membutuhkan kompresi tekstur 'PVRTC' untuk GLES2. Aktifkan "
+"'Impor Pvrtc' di Pengaturan Proyek."
#: editor/editor_export.cpp
-#, fuzzy
msgid ""
"Target platform requires 'ETC2' or 'PVRTC' texture compression for GLES3. "
"Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings."
msgstr ""
-"Platform target membutuhkan kompresi tekstur 'ETC2' untuk GLES3. Aktifkan "
-"'Impor Lainnya 2' di Pengaturan Proyek."
+"Platform target membutuhkan kompresi tekstur 'ETC2' atau 'PVRTC' untuk "
+"GLES3. Aktifkan 'Impor Lainnya 2' atau 'Import Pvrtc' di Pengaturan Proyek."
#: editor/editor_export.cpp
-#, fuzzy
msgid ""
"Target platform requires 'PVRTC' texture compression for the driver fallback "
"to GLES2.\n"
"Enable 'Import Pvrtc' in Project Settings, or disable 'Driver Fallback "
"Enabled'."
msgstr ""
-"Platform target membutuhkan kompressi tekstur 'ETC' untuk mengembalikan "
+"Platform target membutuhkan kompressi tekstur 'PVRTC' untuk mengembalikan "
"driver ke GLES2. \n"
-"Aktifkan 'Impor Lainnya' di Pengaturan Proyek, atau matikan 'Driver Fallback "
+"Aktifkan 'Impor Pvrtc' di Pengaturan Proyek, atau matikan 'Driver Fallback "
"Enabled'."
#: editor/editor_export.cpp platform/android/export/export.cpp
@@ -1877,8 +1876,8 @@ msgid "Open a File or Directory"
msgstr "Buka sebuah File atau Direktori"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Simpan"
@@ -2330,6 +2329,8 @@ msgid ""
"An error occurred while trying to save the editor layout.\n"
"Make sure the editor's user data path is writable."
msgstr ""
+"Terjadi kesalahan ketika mencoba menyimpan layout editor.\n"
+"Pastikan jalur data pengguna editor dapat ditulis."
#: editor/editor_node.cpp
msgid ""
@@ -2337,13 +2338,15 @@ msgid ""
"To restore the Default layout to its base settings, use the Delete Layout "
"option and delete the Default layout."
msgstr ""
+"Penataan editor default telah dirubah.\n"
+"Untuk mengembalikan penataan editor default ke asalnya, gunakan opsi Hapus "
+"Penataan dan hapus Penataan Default."
#: editor/editor_node.cpp
msgid "Layout name not found!"
msgstr "Nama layout tidak ditemukan!"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Restored the Default layout to its base settings."
msgstr "Mengembalikan semula layout default ke pengaturan-pengaturan awal."
@@ -2402,7 +2405,7 @@ msgstr "Tidak ada skena yang didefinisikan untuk dijalankan."
#: editor/editor_node.cpp
msgid "Save scene before running..."
-msgstr ""
+msgstr "Simpan skena sebelum menjalankan..."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -2481,7 +2484,6 @@ msgid "Reload Saved Scene"
msgstr "Muat ulang scene yang sudah disimpan"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"The current scene has unsaved changes.\n"
"Reload the saved scene anyway? This action cannot be undone."
@@ -2548,9 +2550,9 @@ msgstr ""
"gagal."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
-"Tidak dapat mencari bidang script untuk addon plugin pada: 'res://addons/%s'."
+"Tidak dapat mencari bidang skrip untuk addon plugin pada: 'res://addons/%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2854,12 +2856,10 @@ msgstr ""
"lokal."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Small Deploy with Network Filesystem"
-msgstr "Deploy Kecil dengan Jaringan FS"
+msgstr "Deploy Kecil dengan Jaringan Berkas"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, using one-click deploy for Android will only "
"export an executable without the project data.\n"
@@ -2868,9 +2868,9 @@ msgid ""
"On Android, deploying will use the USB cable for faster performance. This "
"option speeds up testing for projects with large assets."
msgstr ""
-"Ketika opsi ini aktif, ekspor atau deploy akan menghasilkan minimal "
-"executable.\n"
-"Berkas sistem akan tersedia dari proyek dari editor melalui jaringan.\n"
+"Ketika opsi ini aktif, menggunakan 'one-click deploy' hanya akan mengekspor "
+"executable tanpa data proyek.\n"
+"Berkas sistem akan tersedia dari proyek oleh editor melalui jaringan.\n"
"Pada Android, deploy akan menggunakan kabel USB untuk performa yang lebih "
"cepat. Opsi ini mempercepat pengujian dengan jejak kaki yang besar."
@@ -2879,34 +2879,29 @@ msgid "Visible Collision Shapes"
msgstr "Collision Shapes Terlihat"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, collision shapes and raycast nodes (for 2D and "
"3D) will be visible in the running project."
msgstr ""
"Collision shapes dan raycast nodes (untuk 2D dan 3D) akan terlihat pada saat "
-"permainan berjalan jika opsi ini aktif."
+"proyek berjalan jika opsi ini aktif."
#: editor/editor_node.cpp
msgid "Visible Navigation"
msgstr "Navigasi Terlihat"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, navigation meshes and polygons will be visible "
"in the running project."
msgstr ""
-"Navigasi meshes dan poligon akan terlihat saat game berjalan jika opsi ini "
-"aktif."
+"Navigasi dan poligon akan terlihat saat game berjalan jika opsi ini aktif."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Synchronize Scene Changes"
msgstr "Sinkronkan Perubahan Skena"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, any changes made to the scene in the editor "
"will be replicated in the running project.\n"
@@ -2914,17 +2909,15 @@ msgid ""
"filesystem option is enabled."
msgstr ""
"Ketika opsi ini aktif, perubahan yang dibuat pada skena melalui editor akan "
-"direplika pada gim yang sedang berjalan.\n"
+"direplika pada proyek yang sedang berjalan.\n"
"Ketika penggunaan remote pada sebuah perangkat, akan lebih efisien dengan "
-"berkas sistem jaringan."
+"opsi berkas sistem jaringan."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Synchronize Script Changes"
-msgstr "Sinkronkan Perubahan Script"
+msgstr "Sinkronkan Perubahan skrip"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, any script that is saved will be reloaded in "
"the running project.\n"
@@ -2933,8 +2926,8 @@ msgid ""
msgstr ""
"Ketika opsi ini aktif, perubahan script yang tersimpan akan di muat kembali "
"pada permainan yang sedang berjalan.\n"
-"Ketika penggunaan remote pada sebuah perngakat, akan lebih efisien jika "
-"jaringan filesystem."
+"Ketika penggunaan remote pada sebuah perangakat, akan lebih efisien dengan "
+"opsi jaringan berkas-berkas."
#: editor/editor_node.cpp editor/script_create_dialog.cpp
msgid "Editor"
@@ -2989,14 +2982,6 @@ msgid "Help"
msgstr "Bantuan"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Cari"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Online Dokumentasi"
@@ -3161,6 +3146,24 @@ msgid "Open & Run a Script"
msgstr "Buka & Jalankan Skrip"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Berkas berikut lebih baru dalam disk.\n"
+"Aksi apa yang ingin diambil?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Muat Ulang"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Simpan Ulang"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Turunan Baru"
@@ -3372,7 +3375,7 @@ msgstr "Jadikan Unik"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Tempel"
@@ -3410,7 +3413,6 @@ msgid "Add Key/Value Pair"
msgstr "Tambahkan pasangan Key/Value"
#: editor/editor_run_native.cpp
-#, fuzzy
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the Export menu or define an existing preset "
@@ -3444,11 +3446,10 @@ msgid "Did you forget the '_run' method?"
msgstr "Apakah anda lupa dengan fungsi '_run' ?"
#: editor/editor_spin_slider.cpp
-#, fuzzy
msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes."
msgstr ""
-"Tahan Ctrl untuk meletakkan Getter. Tahan Shift untuk meletakkan generic "
-"signature."
+"Tahan Ctrl untuk membulatkan bilangan. Tahan Shift untuk meletakkan bilangan "
+"yang lebih presisi."
#: editor/editor_sub_scene.cpp
msgid "Select Node(s) to Import"
@@ -3732,6 +3733,11 @@ msgid ""
"\n"
"Do you wish to overwrite them?"
msgstr ""
+"file dan/atau berkas-berkas berikut mempunyai konflik di '%s':\n"
+"\n"
+"%s\n"
+"\n"
+"Apakah Anda ingin melanjutkan (overwrite)?"
#: editor/filesystem_dock.cpp
msgid "Renaming file:"
@@ -3763,7 +3769,7 @@ msgstr "Buka Skena"
#: editor/filesystem_dock.cpp
msgid "Instance"
-msgstr "Instansi"
+msgstr "hal"
#: editor/filesystem_dock.cpp
msgid "Add to Favorites"
@@ -3812,9 +3818,8 @@ msgid "Duplicate..."
msgstr "Gandakan..."
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "Move to Trash"
-msgstr "Pindahkan Autoload"
+msgstr "Pindahkan ke tong sampah"
#: editor/filesystem_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
msgid "Rename..."
@@ -3925,12 +3930,10 @@ msgid "Searching..."
msgstr "Mencari..."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d match in %d file."
msgstr "Ditemukan %d kecocokan."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d matches in %d file."
msgstr "Ditemukan %d kecocokan."
@@ -4073,6 +4076,21 @@ msgstr ""
msgid "Saving..."
msgstr "Menyimpan..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Mode Seleksi"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Impor"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Muat Default"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Berkas"
@@ -5036,7 +5054,8 @@ msgid "Got:"
msgstr "Yang Didapat:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "Gagal mengecek hash sha256"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5140,7 +5159,6 @@ msgid "Sort:"
msgstr "Sortir:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategori:"
@@ -6975,6 +6993,14 @@ msgstr "Tutup Dokumentasi"
msgid "Run"
msgstr "Jalankan"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Cari"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Masuki"
@@ -7028,16 +7054,6 @@ msgstr ""
"Berkas berikut lebih baru dalam diska.\n"
"Aksi apa yang ingin diambil?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Muat Ulang"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Simpan Ulang"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Pengawakutu"
@@ -7135,8 +7151,8 @@ msgstr "Breakpoint"
msgid "Go To"
msgstr "Pergi Ke"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Potong"
@@ -7360,6 +7376,11 @@ msgid "Yaw"
msgstr "Oleng"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "Ukuran: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Objek Digambar"
@@ -10053,6 +10074,11 @@ msgid "Projects"
msgstr "Proyek"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Mendapatkan informasi cermin, silakan tunggu..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Terakhir Diubah"
@@ -10423,6 +10449,11 @@ msgstr "Muat Otomatis"
msgid "Plugins"
msgstr "Pengaya"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Muat Default"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Prasetel..."
@@ -10678,6 +10709,16 @@ msgstr "Instansi Skena Anak"
#: editor/scene_tree_dock.cpp
#, fuzzy
+msgid "Can't paste root node into the same scene."
+msgstr "Tidak dapat bekerja pada node dari skena luar!"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Rekatkan Node"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
msgid "Detach Script"
msgstr "Lampirkan Skrip"
@@ -10808,6 +10849,11 @@ msgid "Attach Script"
msgstr "Lampirkan Skrip"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Potong Node"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Hapus Node"
@@ -12468,6 +12514,14 @@ msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
"Sebuah CollisionPolygon2D yang kosong tidak memiliki efek pada collision."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12788,11 +12842,6 @@ msgstr ""
"GIProbes tidak didukung oleh driver video GLES2.\n"
"Gunakan BakedLightmap sebagai gantinya."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/is.po b/editor/translations/is.po
index 88dbd92927..8d36556c04 100644
--- a/editor/translations/is.po
+++ b/editor/translations/is.po
@@ -659,7 +659,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1835,8 +1835,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2472,7 +2472,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2865,14 +2865,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -3027,6 +3019,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3230,7 +3238,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3915,6 +3923,19 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Afrita val"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4876,7 +4897,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4980,7 +5001,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6763,6 +6783,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6814,16 +6842,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6916,8 +6934,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7139,6 +7157,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9703,6 +9725,10 @@ msgid "Projects"
msgstr "Verkefna Stjóri"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10065,6 +10091,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10309,6 +10339,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Tvíteknir lyklar"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10433,6 +10472,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Tvíteknir lyklar"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12022,6 +12066,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12277,11 +12329,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/it.po b/editor/translations/it.po
index f322366f4f..67b524937c 100644
--- a/editor/translations/it.po
+++ b/editor/translations/it.po
@@ -50,17 +50,18 @@
# J. Lavoie <j.lavoie@net-c.ca>, 2020.
# Andrea Terenziani <andrea.terenziani.at@gmail.com>, 2020.
# Anonymous <noreply@weblate.org>, 2020.
-# riccardo boffelli <riccardo.boffelli.96@gmail.com>, 2020.
+# riccardo boffelli <riccardo.boffelli.96@gmail.com>, 2020, 2021.
# Lorenzo Asolan <brixiumx@gmail.com>, 2020.
-# Lorenzo Cerqua <lorenzocerqua@tutanota.com>, 2020.
+# Lorenzo Cerqua <lorenzocerqua@tutanota.com>, 2020, 2021.
# Federico Manzella <ferdiu.manzella@gmail.com>, 2020.
# Ziv D <wizdavid@gmail.com>, 2020.
+# Riteo Siuga <lorenzocerqua@tutanota.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-22 10:21+0000\n"
-"Last-Translator: Micila Micillotto <micillotto@gmail.com>\n"
+"PO-Revision-Date: 2021-03-10 22:14+0000\n"
+"Last-Translator: riccardo boffelli <riccardo.boffelli.96@gmail.com>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/"
"godot/it/>\n"
"Language: it\n"
@@ -68,7 +69,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.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -191,7 +192,7 @@ msgstr "Elimina delle chiavi d'animazione"
#: editor/animation_track_editor.cpp
msgid "Anim Change Keyframe Time"
-msgstr "Cambia Intervallo Fotogramma Principale Animazione"
+msgstr "Cambia il tempo di un fotogramma chiave"
#: editor/animation_track_editor.cpp
msgid "Anim Change Transition"
@@ -203,7 +204,7 @@ msgstr "Cambia la trasformazione di un'animazione"
#: editor/animation_track_editor.cpp
msgid "Anim Change Keyframe Value"
-msgstr "Cambia Valore Fotogramma Principale Animazione"
+msgstr "Cambia il valore del fotogramma chiave di un'animazione"
#: editor/animation_track_editor.cpp
msgid "Anim Change Call"
@@ -211,32 +212,32 @@ msgstr "Cambia la chiamata di un'animazione"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Time"
-msgstr "Cambia Multipli Intervalli Fotogramma Principale Animazione"
+msgstr "Cambia il tempo di più fotogrammi chiave"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Transition"
-msgstr "Cambi Multipli Transizione Animazione"
+msgstr "Cambia la transizione di più animazioni"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Transform"
-msgstr "Cambi Multipli Trasformazione Animazione"
+msgstr "Cambia le trasformazioni di più animazioni"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Value"
-msgstr "Cambia Multipli Valori Fotogramma Principale Animazione"
+msgstr "Cambia il valore di più fotogrammi chiave di un'Animazione"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Call"
-msgstr "Cambi Multipli Chiamata Animazione"
+msgstr "Cambia la chiamata di metodo di più animazioni"
#: editor/animation_track_editor.cpp
msgid "Change Animation Length"
-msgstr "Cambia Lunghezza Animazione"
+msgstr "Cambia la durata dell'animazione"
#: editor/animation_track_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Change Animation Loop"
-msgstr "Cambia Loop Animazione"
+msgstr "Commuta ciclicità animazione"
#: editor/animation_track_editor.cpp
msgid "Property Track"
@@ -293,7 +294,7 @@ msgstr "Clip animazione:"
#: editor/animation_track_editor.cpp
msgid "Change Track Path"
-msgstr "Cambia il percorso della traccia"
+msgstr "Cambia Percorso Traccia"
#: editor/animation_track_editor.cpp
msgid "Toggle this track on/off."
@@ -309,7 +310,7 @@ msgstr "Modalità d'interpolazione"
#: editor/animation_track_editor.cpp
msgid "Loop Wrap Mode (Interpolate end with beginning on loop)"
-msgstr "Modalità Ciclo ad Anello (interpola la fine con l'inizio a ciclo)"
+msgstr "Modalità ciclo ad anello (interpola la fine con l'inizio del ciclo)"
#: editor/animation_track_editor.cpp
msgid "Remove this track."
@@ -333,7 +334,7 @@ msgstr "Discreta"
#: editor/animation_track_editor.cpp
msgid "Trigger"
-msgstr "Attivatore"
+msgstr "Attivazione"
#: editor/animation_track_editor.cpp
msgid "Capture"
@@ -354,24 +355,24 @@ msgstr "Cubica"
#: editor/animation_track_editor.cpp
msgid "Clamp Loop Interp"
-msgstr "Blocca Interpolazione Ciclo"
+msgstr "Blocca l'interpolazione d'un ciclo"
#: editor/animation_track_editor.cpp
msgid "Wrap Loop Interp"
-msgstr "Avvolgi Interpolazione Ciclo"
+msgstr "Continua l'interpolazione d'un ciclo"
#: editor/animation_track_editor.cpp
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Key"
-msgstr "Inserisci Fotogramma Chiave"
+msgstr "Inserisci un fotogramma chiave"
#: editor/animation_track_editor.cpp
msgid "Duplicate Key(s)"
-msgstr "Duplica Fotogrammi Chiave Selezionati"
+msgstr "Duplica i fotogrammi chiave selezionati"
#: editor/animation_track_editor.cpp
msgid "Delete Key(s)"
-msgstr "Elimina Fotogrammi Chiave Selezionati"
+msgstr "Elimina i fotogrammi chiave selezionati"
#: editor/animation_track_editor.cpp
msgid "Change Animation Update Mode"
@@ -383,15 +384,16 @@ msgstr "Cambia la modalità d'interpolazione di un'animazione"
#: editor/animation_track_editor.cpp
msgid "Change Animation Loop Mode"
-msgstr "Cambia la modalità del ciclo di un'animazione"
+msgstr "Cambia Modalità Loop Animazione"
#: editor/animation_track_editor.cpp
msgid "Remove Anim Track"
-msgstr "Rimuovi la traccia di un'animazione"
+msgstr "Rimuovi una traccia d'animazione"
#: editor/animation_track_editor.cpp
+#, fuzzy
msgid "Create NEW track for %s and insert key?"
-msgstr "Crea NUOVA traccia per %s ed inserire fotogramma chiave?"
+msgstr "Creare una NUOVA traccia per %s e inserirci la chiave?"
#: editor/animation_track_editor.cpp
msgid "Create %d NEW tracks and insert keys?"
@@ -473,15 +475,15 @@ msgstr "Non è possibile aggiungere una nuova traccia senza un nodo radice"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr "Traccia non valida per la curva Bézier (nessuna sottoproprietà adatta)"
+msgstr "Traccia non valida per Bezier (nessuna sotto-proprietà valida)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
-msgstr "Aggiungi traccia Bézier"
+msgstr "Aggiungi una traccia di curve di Bézier"
#: editor/animation_track_editor.cpp
msgid "Track path is invalid, so can't add a key."
-msgstr "Il tracciato non è valido, non è possibile aggiungere una chiave."
+msgstr "La traccia non è valida, quindi è impossibile aggiungere una chiave."
#: editor/animation_track_editor.cpp
msgid "Track is not of type Spatial, can't insert key"
@@ -489,21 +491,21 @@ msgstr "La traccia non è di tipo Spatial, impossibile aggiungere la chiave"
#: editor/animation_track_editor.cpp
msgid "Add Transform Track Key"
-msgstr "Aggiungi chiave traccia Transform"
+msgstr "Aggiungi una chiave a una traccia di trasformazioni"
#: editor/animation_track_editor.cpp
msgid "Add Track Key"
-msgstr "Aggiungi chiave traccia"
+msgstr "Aggiungi una chiave a una traccia"
#: editor/animation_track_editor.cpp
msgid "Track path is invalid, so can't add a method key."
msgstr ""
-"Il tracciato non è valido, non è possibile aggiungere una chiave di chiamata "
-"di funzione."
+"La traccia non è valida, quindi, non è stato possibile aggiungere una chiave "
+"chiamata metodo."
#: editor/animation_track_editor.cpp
msgid "Add Method Track Key"
-msgstr "Aggiungi chiave alla traccia metodo"
+msgstr "Aggiungi una chiave a una traccia di chiamate di metodi"
#: editor/animation_track_editor.cpp
msgid "Method not found in object: "
@@ -511,7 +513,7 @@ msgstr "Metodo non trovato nell'oggetto: "
#: editor/animation_track_editor.cpp
msgid "Anim Move Keys"
-msgstr "Sposta chiavi animazione"
+msgstr "Sposta delle chiavi d'animazione"
#: editor/animation_track_editor.cpp
msgid "Clipboard is empty"
@@ -519,18 +521,18 @@ msgstr "Gli appunti sono vuoti"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
-msgstr "Incolla tracce"
+msgstr "Incolla Tracce"
#: editor/animation_track_editor.cpp
msgid "Anim Scale Keys"
-msgstr "Scala chiavi animazione"
+msgstr "Scala Chiavi Animazione"
#: editor/animation_track_editor.cpp
msgid ""
"This option does not work for Bezier editing, as it's only a single track."
msgstr ""
-"Questa opzione non funziona per modificare curve di Bézier, dato che si "
-"tratta di una traccia singola."
+"Questa opzione non funziona per modificare delle curve di Bézier, dato che "
+"si tratta di una singola traccia."
#: editor/animation_track_editor.cpp
msgid ""
@@ -544,14 +546,14 @@ msgid ""
"Alternatively, use an import preset that imports animations to separate "
"files."
msgstr ""
-"Questa animazione appartiene a una scena importata, eventuali modifiche alle "
-"tracce importate non saranno salvate.\n"
+"Questa animazione appartiene ad una scena importata, quindi i cambiamenti "
+"alle tracce importate non saranno salvate.\n"
"\n"
-"Per abilitare la possibilità di aggiungere ulteriori tracce, vai alle "
-"impostazioni di importazione della scena e imposta\n"
-"\"Animation > Storage\" su \"Files\", abilita \"Animation > Keep Custom "
-"Tracks\", e infine reimporta la scena.\n"
-"Altrimenti, usa un preset di importazione che importa le animazioni in file "
+"Per abilitare l'aggiunta di tracce personalizzate, naviga alle impostazioni "
+"d'importazione della scena ed imposta\n"
+"\"Animation > Storage\" a \"Files\", abilita \"Animation > Keep Custom Tracks"
+"\", e poi re-importa.\n"
+"In alternativa, usa un preset d'importo che importa le animazioni da file "
"separati."
#: editor/animation_track_editor.cpp
@@ -568,11 +570,11 @@ msgstr "Mostra solo le tracce dei nodi selezionati nell'albero."
#: editor/animation_track_editor.cpp
msgid "Group tracks by node or display them as plain list."
-msgstr "Raggruppa le tracce per nodo o mostra una lista semplice."
+msgstr "Raggruppa le tracce per nodo o le visualizza in una lista semplice."
#: editor/animation_track_editor.cpp
msgid "Snap:"
-msgstr "Snap:"
+msgstr "Scatto:"
#: editor/animation_track_editor.cpp
msgid "Animation step value."
@@ -599,27 +601,27 @@ msgstr "Modifica"
#: editor/animation_track_editor.cpp
msgid "Animation properties."
-msgstr "Proprietà animazione."
+msgstr "Proprietà dell'animazione."
#: editor/animation_track_editor.cpp
msgid "Copy Tracks"
-msgstr "Copia tracce"
+msgstr "Copia le tracce"
#: editor/animation_track_editor.cpp
msgid "Scale Selection"
-msgstr "Scala selezione"
+msgstr "Scala la selezione"
#: editor/animation_track_editor.cpp
msgid "Scale From Cursor"
-msgstr "Scala da cursore"
+msgstr "Scala a partire dal cursore"
#: editor/animation_track_editor.cpp modules/gridmap/grid_map_editor_plugin.cpp
msgid "Duplicate Selection"
-msgstr "Duplica selezione"
+msgstr "Duplica la selezione"
#: editor/animation_track_editor.cpp
msgid "Duplicate Transposed"
-msgstr "Duplica trasposto"
+msgstr "Duplica Trasposto"
#: editor/animation_track_editor.cpp
msgid "Delete Selection"
@@ -627,19 +629,19 @@ msgstr "Elimina la selezione"
#: editor/animation_track_editor.cpp
msgid "Go to Next Step"
-msgstr "Va' al passo successivo"
+msgstr "Vai allo Step Successivo"
#: editor/animation_track_editor.cpp
msgid "Go to Previous Step"
-msgstr "Va' al passo precedente"
+msgstr "Vai allo Step Precedente"
#: editor/animation_track_editor.cpp
msgid "Optimize Animation"
-msgstr "Ottimizza animazione"
+msgstr "Ottimizza l'animazione"
#: editor/animation_track_editor.cpp
msgid "Clean-Up Animation"
-msgstr "Pulisci animazione"
+msgstr "Pulisci l'animazione"
#: editor/animation_track_editor.cpp
msgid "Pick the node that will be animated:"
@@ -647,7 +649,7 @@ msgstr "Seleziona il nodo che verrà animato:"
#: editor/animation_track_editor.cpp
msgid "Use Bezier Curves"
-msgstr "Usa curve di Bézier"
+msgstr "Usa le curve di Bézier"
#: editor/animation_track_editor.cpp
msgid "Anim. Optimizer"
@@ -655,15 +657,15 @@ msgstr "Ottimizzatore anim."
#: editor/animation_track_editor.cpp
msgid "Max. Linear Error:"
-msgstr "Max. errore lineare:"
+msgstr "Max Errore Lineare:"
#: editor/animation_track_editor.cpp
msgid "Max. Angular Error:"
-msgstr "Max. errore angolare:"
+msgstr "Max Errore Angolare:"
#: editor/animation_track_editor.cpp
msgid "Max Optimizable Angle:"
-msgstr "Max. angolo ottimizzabile:"
+msgstr "Max Angolo Ottimizzabile:"
#: editor/animation_track_editor.cpp
msgid "Optimize"
@@ -671,11 +673,11 @@ msgstr "Ottimizza"
#: editor/animation_track_editor.cpp
msgid "Remove invalid keys"
-msgstr "Rimuovi chiavi non valide"
+msgstr "Rimuovi le chiavi non valide"
#: editor/animation_track_editor.cpp
msgid "Remove unresolved and empty tracks"
-msgstr "Rimuovi tracce irrisolte e vuote"
+msgstr "Rimuovi le tracce irrisolte e vuote"
#: editor/animation_track_editor.cpp
msgid "Clean-up all animations"
@@ -683,7 +685,7 @@ msgstr "Pulisci tutte le animazioni"
#: editor/animation_track_editor.cpp
msgid "Clean-Up Animation(s) (NO UNDO!)"
-msgstr "Pulisci animazione(i) (NON ANNULLABILE!)"
+msgstr "Pulisci le animazioni (NON ANNULLABILE!)"
#: editor/animation_track_editor.cpp
msgid "Clean-Up"
@@ -702,45 +704,45 @@ msgstr "Seleziona le tracce da copiare"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copia"
#: editor/animation_track_editor.cpp
msgid "Select All/None"
-msgstr "Seleziona Tutto/Nulla"
+msgstr "De/Seleziona Tutto"
#: editor/animation_track_editor_plugins.cpp
msgid "Add Audio Track Clip"
-msgstr "Aggiungi traccia clip audio"
+msgstr "Aggiungi audio in una traccia di riproduzione audio"
#: editor/animation_track_editor_plugins.cpp
msgid "Change Audio Track Clip Start Offset"
-msgstr "Cambia Offset di Inizio della Clip della Traccia Audio"
+msgstr "Cambia Offset Inizio Clip Traccia Audio"
#: editor/animation_track_editor_plugins.cpp
msgid "Change Audio Track Clip End Offset"
-msgstr "Cambia offset di fine della clip della traccia audio"
+msgstr "Cambia Offset Fine Clip Traccia Audio"
#: editor/array_property_edit.cpp
msgid "Resize Array"
-msgstr "Ridimensiona array"
+msgstr "Ridimensiona Array"
#: editor/array_property_edit.cpp
msgid "Change Array Value Type"
-msgstr "Cambia tipo del valore dell'array"
+msgstr "Cambia Tipo Valore Array"
#: editor/array_property_edit.cpp
msgid "Change Array Value"
-msgstr "Cambia valore array"
+msgstr "Cambia Valore Array"
#: editor/code_editor.cpp
msgid "Go to Line"
-msgstr "Vai alla linea"
+msgstr "Vai alla Linea"
#: editor/code_editor.cpp
msgid "Line Number:"
-msgstr "Numero linea:"
+msgstr "Numero Linea:"
#: editor/code_editor.cpp
msgid "%d replaced."
@@ -752,15 +754,15 @@ msgstr "%d corrispondenza."
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "%d matches."
-msgstr "%d corrispondenza/e."
+msgstr "%d corrispondenze."
#: editor/code_editor.cpp editor/find_in_files.cpp
msgid "Match Case"
-msgstr "Distingui maiuscole"
+msgstr "Distingui Maiuscole"
#: editor/code_editor.cpp editor/find_in_files.cpp
msgid "Whole Words"
-msgstr "Parole intere"
+msgstr "Parole Intere"
#: editor/code_editor.cpp
msgid "Replace"
@@ -768,11 +770,11 @@ msgstr "Sostituisci"
#: editor/code_editor.cpp
msgid "Replace All"
-msgstr "Rimpiazza tutti"
+msgstr "Rimpiazza Tutti"
#: editor/code_editor.cpp
msgid "Selection Only"
-msgstr "Solo selezione"
+msgstr "Solo Selezione"
#: editor/code_editor.cpp editor/plugins/script_text_editor.cpp
#: editor/plugins/text_editor.cpp
@@ -781,7 +783,7 @@ msgstr "Standard"
#: editor/code_editor.cpp editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
-msgstr "Commuta pannello degli script"
+msgstr "Toggle Pannello Script"
#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/texture_region_editor_plugin.cpp
@@ -797,23 +799,23 @@ msgstr "Rimpicciolisci"
#: editor/code_editor.cpp
msgid "Reset Zoom"
-msgstr "Resetta ingrandimento"
+msgstr "Reimposta ingrandimento"
#: editor/code_editor.cpp
msgid "Warnings"
-msgstr "Avvertenze"
+msgstr "Avvisi"
#: editor/code_editor.cpp
msgid "Line and column numbers."
-msgstr "Numeri di riga e colonna."
+msgstr "Numeri di riga e di colonna."
#: editor/connections_dialog.cpp
msgid "Method in target node must be specified."
-msgstr "Il metodo del nodo designato deve essere specificato."
+msgstr "Il metodo del nodo selezionato deve essere specificato."
#: editor/connections_dialog.cpp
msgid "Method name must be a valid identifier."
-msgstr "Il nome del metodo dev'essere un identificatore valido."
+msgstr "Il nome del metodo deve essere un identificatore valido."
#: editor/connections_dialog.cpp
msgid ""
@@ -1911,8 +1913,8 @@ msgid "Open a File or Directory"
msgstr "Apri un file o una cartella"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Salva"
@@ -2592,10 +2594,9 @@ msgstr ""
"configurazione fallita."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
-"Impossibile trovare il campo dello script per il componente aggiuntivo in: "
-"'res://addons/%s'."
+"Impossibile trovare il campo script per il plugin addon in posizione: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -3031,14 +3032,6 @@ msgid "Help"
msgstr "Aiuto"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Cerca"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Documentazione online"
@@ -3164,13 +3157,13 @@ msgid ""
"the \"Use Custom Build\" option should be enabled in the Android export "
"preset."
msgstr ""
-"Questo imposterà il tuo progetto per le build custom per Android, "
-"installando i source templates in \"res://android/build\".\n"
-"Puoi, allora, applicare le modifiche e costruire il tuo APK custom durante "
-"l'esportazione (aggiungere moduli, cambiare il AndroidManifest.xml, ed "
-"altro).\n"
-"Nota che, in ordine per creare le build custom invece di usare gli APK pre-"
-"costruiti, l'opzione \"Use Custom Build\" sarà abilitata nel preset "
+"Questo predisporrà il progetto per le build personalizzate per Android "
+"installando i template sorgente in \"res://android/build\".\n"
+"Potrai allora applicare le modifiche e costruire il tuo APK personalizzato "
+"durante l'esportazione (aggiungere moduli, cambiare l'AndroidManifest.xml, "
+"eccetera).\n"
+"Nota che per creare delle build personalizzate, invece di usare gli APK pre-"
+"costruiti, l'opzione \"Use Custom Build\" va attivata nella preimpostazione "
"d'esportazione per Android."
#: editor/editor_node.cpp
@@ -3180,30 +3173,48 @@ msgid ""
"Remove the \"res://android/build\" directory manually before attempting this "
"operation again."
msgstr ""
-"Il modello della build Android è già installato in questo progetto e non "
-"sarà sovrascritto.\n"
-"Rimuovi la cartella \"res://android/build\" manualmente prima di ritentare "
+"Il template della build Android è già installato in questo progetto e non "
+"verrà sovrascritto.\n"
+"Rimuovi manualmente la cartella \"res://android/build\" prima di ritentare "
"questa operazione."
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
-msgstr "Importa template da un file ZIP"
+msgstr "Importa Template Da File ZIP"
#: editor/editor_node.cpp
msgid "Template Package"
-msgstr "Pacchetto Modello"
+msgstr "Pacchetto Template"
#: editor/editor_node.cpp
msgid "Export Library"
-msgstr "Esporta libreria"
+msgstr "Esporta Libreria"
#: editor/editor_node.cpp
msgid "Merge With Existing"
-msgstr "Unisci con esistente"
+msgstr "Unisci Con Esistente"
#: editor/editor_node.cpp
msgid "Open & Run a Script"
-msgstr "Apri ed esegui uno script"
+msgstr "Apri ed Esegui uno Script"
+
+#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"I seguenti file sono più recenti sul disco.\n"
+"Quale azione dovrebbe essere presa?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Ricarica"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Risalva"
#: editor/editor_node.cpp
msgid "New Inherited"
@@ -3416,7 +3427,7 @@ msgstr "Rendi Unico"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Incolla"
@@ -4123,6 +4134,20 @@ msgstr ""
msgid "Saving..."
msgstr "Salvataggio..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Modalità di selezione"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importare"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Ripristinare le impostazioni predefinite"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d File"
@@ -5095,8 +5120,8 @@ msgid "Got:"
msgstr "Ottenuto:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Check hash sha256 fallito"
+msgid "Failed SHA-256 hash check"
+msgstr "Check has SHA-256 fallito"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5199,7 +5224,6 @@ msgid "Sort:"
msgstr "Ordina:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Categoria:"
@@ -7039,6 +7063,14 @@ msgstr "Chiudi la documentazione"
msgid "Run"
msgstr "Esegui"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Cerca"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Passo dentro all'istruzione"
@@ -7092,16 +7124,6 @@ msgstr ""
"I file seguenti sono più recenti su disco.\n"
"Che azione deve essere intrapresa?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Ricarica"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Risalva"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Debugger"
@@ -7197,8 +7219,8 @@ msgstr "Punti di interruzione"
msgid "Go To"
msgstr "Vai a"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Taglia"
@@ -7421,6 +7443,10 @@ msgid "Yaw"
msgstr "Imbardata"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Dimensione"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Oggetti disegnati"
@@ -10121,6 +10147,10 @@ msgid "Projects"
msgstr "Progetti"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Caricamento, per favore attendere..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Ultima Modifica"
@@ -10491,6 +10521,10 @@ msgstr "AutoLoad"
msgid "Plugins"
msgstr "Plugins"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "Carica Predefiniti"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Preset…"
@@ -10741,6 +10775,14 @@ msgid "Instance Child Scene"
msgstr "Istanzia Scena Figlia"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "Non si può incollare il noto root nella stessa scena."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Incolla Nodo(i)"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Rimuovi Script"
@@ -10867,6 +10909,10 @@ msgid "Attach Script"
msgstr "Allega Script"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Taglia Nodo(i)"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Rimuovi nodo(i)"
@@ -12545,6 +12591,18 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Un CollisionPolygon2D vuoto non ha effetti sulla collisione."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+"Poligono non valido. Sono necessari almeno 3 punti nella modalità di "
+"costruzione 'Solidi'."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+"Poligono non valido. Sono necessari almeno 2 punti nella modalità di "
+"costruzione 'Segmenti'."
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12869,11 +12927,6 @@ msgstr ""
"Le GIProbes non sono supportate dal driver video GLES2.\n"
"In alternativa, usa una BakedLightmap."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "\"InterpolatedCamera\" è stata deprecata e sarà rimossa in Godot 4.0."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13132,9 +13185,9 @@ msgid ""
"functions. Making them visible for editing is fine, but they will hide upon "
"running."
msgstr ""
-"I popup saranno nascosti di predefinita finchè non chiami popup() o una "
-"delle qualsiasi funzioni popup*(). Farli diventare visibili per modificarli "
-"va bene, ma scompariranno all'esecuzione."
+"I popup saranno nascosti di default finchè non chiami popup(), o una delle "
+"qualsiasi funzioni popup*(). Farli diventare visibili per modificarli va "
+"bene, ma scompariranno durante l'esecuzione."
#: scene/gui/range.cpp
msgid "If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0."
@@ -13217,6 +13270,11 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Le constanti non possono essere modificate."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr ""
+#~ "\"InterpolatedCamera\" è stata deprecata e sarà rimossa in Godot 4.0."
+
#~ msgid "No"
#~ msgstr "No"
@@ -14880,9 +14938,6 @@ msgstr "Le constanti non possono essere modificate."
#~ msgid "Use Default Light"
#~ msgstr "Usa Luce Default"
-#~ msgid "Use Default sRGB"
-#~ msgstr "Usa sRGB Default"
-
#~ msgid "Default Light Normal:"
#~ msgstr "Normale Luce di Default:"
diff --git a/editor/translations/ja.po b/editor/translations/ja.po
index 917587952a..8afa2de349 100644
--- a/editor/translations/ja.po
+++ b/editor/translations/ja.po
@@ -31,12 +31,12 @@
# Akihiro Ogoshi <technical@palsystem-game.com>, 2019, 2020.
# Wataru Onuki <bettawat@yahoo.co.jp>, 2020, 2021.
# sporeball <sporeballdev@gmail.com>, 2020.
-# BinotaLIU <me@binota.org>, 2020.
+# BinotaLIU <me@binota.org>, 2020, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-22 10:21+0000\n"
+"PO-Revision-Date: 2021-03-08 15:33+0000\n"
"Last-Translator: Wataru Onuki <bettawat@yahoo.co.jp>\n"
"Language-Team: Japanese <https://hosted.weblate.org/projects/godot-engine/"
"godot/ja/>\n"
@@ -45,12 +45,12 @@ 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.5-dev\n"
+"X-Generator: Weblate 4.5.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
-msgstr "convert() の引数の型が無効です。TYPE_* 定数を使ってください。"
+msgstr "convert() の引数の型が無効です。TYPE_* 定数を使用してください。"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
msgid "Expected a string of length 1 (a character)."
@@ -676,7 +676,7 @@ msgstr "コピーするトラックを選択"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "コピー"
@@ -1590,7 +1590,7 @@ msgstr "ファイルの保存:"
#: editor/editor_export.cpp
msgid "No export template found at the expected path:"
-msgstr "エクスポート テンプレートが予想されたパスに見つかりません:"
+msgstr "エクスポート テンプレートが予期されたパスに見つかりません:"
#: editor/editor_export.cpp
msgid "Packing"
@@ -1881,8 +1881,8 @@ msgid "Open a File or Directory"
msgstr "ファイルまたはディレクトリを開く"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "保存"
@@ -2554,10 +2554,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr "アドオンプラグインを有効にできません: '%s' 設定の解析に失敗しました。"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr ""
-"アドオンプラグインのスクリプトフィールドが 'res://addons/%s' から見つかりませ"
-"ん。"
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "アドオンプラグインのスクリプトフィールドが '%s' で見つかりません。"
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2988,14 +2986,6 @@ msgid "Help"
msgstr "ヘルプ"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "検索"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "オンラインドキュメント"
@@ -3161,6 +3151,24 @@ msgid "Open & Run a Script"
msgstr "スクリプトを開いて実行"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"以下のファイルより新しいものがディスク上に存在します。\n"
+"どうしますか?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "再読込"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "再保存"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "新規の継承"
@@ -3371,7 +3379,7 @@ msgstr "ユニーク化"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "貼り付け"
@@ -4071,6 +4079,21 @@ msgstr ""
msgid "Saving..."
msgstr "保存中..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "選択モード"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "インポート"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "デフォルトを読込む"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d ファイル"
@@ -5035,8 +5058,8 @@ msgid "Got:"
msgstr "取得:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "sha256 ハッシュチェック失敗"
+msgid "Failed SHA-256 hash check"
+msgstr "SHA-256 ハッシュチェック失敗"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5139,7 +5162,6 @@ msgid "Sort:"
msgstr "ソート:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "カテゴリー:"
@@ -6962,6 +6984,14 @@ msgstr "ドキュメントを閉じる"
msgid "Run"
msgstr "実行"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "検索"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "ステップイン"
@@ -7015,16 +7045,6 @@ msgstr ""
"以下のファイルより新しいものがディスク上に存在します。\n"
"どうしますか?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "再読込"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "再保存"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "デバッガ"
@@ -7121,8 +7141,8 @@ msgstr "ブレークポイント"
msgid "Go To"
msgstr "参照"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "切り取り"
@@ -7345,6 +7365,10 @@ msgid "Yaw"
msgstr "ヨー"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "サイズ"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "描画されたオブジェクト"
@@ -10021,6 +10045,10 @@ msgid "Projects"
msgstr "プロジェクト"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "読み込み中、しばらくお待ちください..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "最終更新"
@@ -10391,6 +10419,11 @@ msgstr "自動読み込み"
msgid "Plugins"
msgstr "プラグイン"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "デフォルトを読込む"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "プリセット..."
@@ -10640,6 +10673,14 @@ msgid "Instance Child Scene"
msgstr "子シーンをインスタンス化"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "ルートノードは同じシーンに貼り付けできません。"
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "ノードを貼り付け"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "スクリプトをデタッチ"
@@ -10765,6 +10806,10 @@ msgid "Attach Script"
msgstr "スクリプトをアタッチ"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "ノードを切り取り"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "ノードを除去"
@@ -10836,7 +10881,7 @@ msgstr "親ノードを新規ノードに変更"
#: editor/scene_tree_dock.cpp
msgid "Make Scene Root"
-msgstr "シーンをルートにする"
+msgstr "シーンのルートにする"
#: editor/scene_tree_dock.cpp
msgid "Merge From Scene"
@@ -11581,24 +11626,20 @@ msgid "Preparing data structures"
msgstr "データ構造の準備"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Generate buffers"
-msgstr "AABBを生成"
+msgstr "バッファを生成"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Direct lighting"
-msgstr "方向"
+msgstr "直接光"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Indirect lighting"
-msgstr "右インデント"
+msgstr "間接光"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Post processing"
-msgstr "ポストプロセス"
+msgstr "後処理"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
#, fuzzy
@@ -12119,9 +12160,8 @@ msgid "Select device from the list"
msgstr "一覧からデバイスを選択"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Unable to find the 'apksigner' tool."
-msgstr "zipalign ツールが見つかりません。"
+msgstr "'apksigner' ツールが見つかりません。"
#: platform/android/export/export.cpp
msgid ""
@@ -12140,14 +12180,12 @@ msgid "Release keystore incorrectly configured in the export preset."
msgstr "エクスポート設定にてリリース キーストアが誤って設定されています。"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "A valid Android SDK path is required in Editor Settings."
-msgstr "エディタ設定のカスタムビルドのAndroid SDKパスが無効です。"
+msgstr "エディタ設定でAndroid SDKパスの指定が必要です。"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Invalid Android SDK path in Editor Settings."
-msgstr "エディタ設定のカスタムビルドのAndroid SDKパスが無効です。"
+msgstr "エディタ設定のAndroid SDKパスが無効です。"
#: platform/android/export/export.cpp
msgid "Missing 'platform-tools' directory!"
@@ -12155,12 +12193,11 @@ msgstr "'platform-tools' ディレクトリがありません!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK platform-tools' adb command."
-msgstr ""
+msgstr "Android SDK platform-toolsのadbコマンドが見つかりません。"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Please check in the Android SDK directory specified in Editor Settings."
-msgstr "エディタ設定のカスタムビルドのAndroid SDKパスが無効です。"
+msgstr "エディタ設定で指定されたAndroid SDKのディレクトリを確認してください。"
#: platform/android/export/export.cpp
msgid "Missing 'build-tools' directory!"
@@ -12168,7 +12205,7 @@ msgstr "'build-tools' ディレクトリがありません!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK build-tools' apksigner command."
-msgstr ""
+msgstr "Android SDK build-toolsのapksignerコマンドが見つかりません。"
#: platform/android/export/export.cpp
msgid "Invalid public key for APK expansion."
@@ -12432,6 +12469,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "空の CollisionPolygon2D は、衝突判定を持ちません。"
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12645,9 +12690,8 @@ msgid "Finding meshes and lights"
msgstr ""
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing geometry (%d/%d)"
-msgstr "ジオメトリを解析しています..."
+msgstr "ジオメトリを解析しています (%d/%d)"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -12754,11 +12798,6 @@ msgstr ""
"GIProbesはGLES2ビデオドライバではサポートされていません。\n"
"代わりにBakedLightmapを使用してください。"
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamera は廃止予定であり、Godot 4.0で除去されます。"
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "90度を超える角度のスポットライトは、シャドウを投影できません。"
@@ -13097,6 +13136,10 @@ msgstr "Varying変数は頂点関数にのみ割り当てることができま
msgid "Constants cannot be modified."
msgstr "定数は変更できません。"
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr "InterpolatedCamera は廃止予定であり、Godot 4.0で除去されます。"
+
#~ msgid "No"
#~ msgstr "いいえ"
diff --git a/editor/translations/ka.po b/editor/translations/ka.po
index c35aebac02..6828baf211 100644
--- a/editor/translations/ka.po
+++ b/editor/translations/ka.po
@@ -675,7 +675,7 @@ msgstr "დაყენდეს გადასვლები შემდე
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1900,8 +1900,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2552,7 +2552,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2949,14 +2949,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -3111,6 +3103,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3316,7 +3324,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -4020,6 +4028,19 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "წავშალოთ მონიშნული ფაილები?"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4998,7 +5019,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5105,7 +5126,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6918,6 +6938,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6969,16 +6997,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7078,8 +7096,8 @@ msgstr "შექმნა"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7307,6 +7325,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9908,6 +9930,11 @@ msgid "Projects"
msgstr "პროექტის დამფუძნებლები"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "ძებნა:"
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10272,6 +10299,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10519,6 +10550,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "ანიმაციის გასაღებების ასლის შექმნა"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "დამოკიდებულებების შემსწორებელი"
@@ -10645,6 +10685,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "ანიმაციის გასაღებების ასლის შექმნა"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12266,6 +12311,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12521,11 +12574,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/ko.po b/editor/translations/ko.po
index 8c15195d24..693b726ebf 100644
--- a/editor/translations/ko.po
+++ b/editor/translations/ko.po
@@ -16,7 +16,7 @@
# Jiyoon Kim <kimjiy@dickinson.edu>, 2019.
# Ervin <zetsmart@gmail.com>, 2019.
# Tilto_ <tilto0822@develable.xyz>, 2020.
-# Myeongjin Lee <aranet100@gmail.com>, 2020.
+# Myeongjin Lee <aranet100@gmail.com>, 2020, 2021.
# Doyun Kwon <caen4516@gmail.com>, 2020.
# Jun Hyung Shin <shmishmi79@gmail.com>, 2020.
# Yongjin Jo <wnrhd114@gmail.com>, 2020.
@@ -25,8 +25,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-10-31 23:15+0000\n"
-"Last-Translator: Yungjoong Song <yungjoong.song@gmail.com>\n"
+"PO-Revision-Date: 2021-03-12 09:17+0000\n"
+"Last-Translator: Myeongjin Lee <aranet100@gmail.com>\n"
"Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/"
"godot/ko/>\n"
"Language: ko\n"
@@ -34,7 +34,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.3.2-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -662,7 +662,7 @@ msgstr "복사할 트랙 선택"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "복사"
@@ -704,7 +704,7 @@ msgstr "행 번호:"
#: editor/code_editor.cpp
msgid "%d replaced."
-msgstr "%d개가 바뀌었습니다."
+msgstr "%d개 찾아 바꿈."
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "%d match."
@@ -1044,22 +1044,23 @@ msgid "Owners Of:"
msgstr "소유자:"
#: editor/dependency_editor.cpp
-#, fuzzy
msgid ""
"Remove selected files from the project? (no undo)\n"
"You can find the removed files in the system trash to restore them."
-msgstr "프로젝트에서 선택한 파일을 삭제할까요? (되돌릴 수 없습니다)"
+msgstr ""
+"프로젝트에서 선택된 파일을 제거하시겠습니다? (되돌릴 수 없음)\n"
+"시스템 휴지통에서 제거된 파일을 찾고 복원할 수 있습니다."
#: editor/dependency_editor.cpp
-#, fuzzy
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
"Remove them anyway? (no undo)\n"
"You can find the removed files in the system trash to restore them."
msgstr ""
-"삭제하려는 파일은 다른 리소스가 동작하기 위해 필요한 파일입니다.\n"
-"무시하고 삭제할까요? (되돌릴 수 없습니다)"
+"제거하려는 파일은 다른 리소스가 동작하기 위해 필요합니다.\n"
+"무시하고 제거하시겠습니까? (되돌릴 수 없음)\n"
+"시스템 휴지통에서 제거된 파일을 찾고 복원할 수 있습니다."
#: editor/dependency_editor.cpp
msgid "Cannot remove:"
@@ -1864,8 +1865,8 @@ msgid "Open a File or Directory"
msgstr "디렉토리 또는 파일 열기"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "저장"
@@ -2314,6 +2315,8 @@ msgid ""
"An error occurred while trying to save the editor layout.\n"
"Make sure the editor's user data path is writable."
msgstr ""
+"편집기 레이아웃의 저장을 하려는 동안 오류가 발생했습니다.\n"
+"편집기의 사용자 데이터 경로가 쓰기 가능한지 확인해주세요."
#: editor/editor_node.cpp
msgid ""
@@ -2321,15 +2324,17 @@ msgid ""
"To restore the Default layout to its base settings, use the Delete Layout "
"option and delete the Default layout."
msgstr ""
+"기본 편집기 레이아웃이 덮어 쓰여져 있습니디.\n"
+"기본 레이아웃을 원래 설정으로 복구하려면, 레이아웃 삭제 옵션을 사용하여 기본 "
+"레이아웃을 삭제하세요."
#: editor/editor_node.cpp
msgid "Layout name not found!"
msgstr "레이아웃 이름을 찾을 수 없습니다!"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Restored the Default layout to its base settings."
-msgstr "기본 레이아웃을 초기화하였습니다."
+msgstr "기본 레이아웃을 원래 설정으로 복구하였습니다."
#: editor/editor_node.cpp
msgid ""
@@ -2384,7 +2389,7 @@ msgstr "실행할 씬이 설정되지 않았습니다."
#: editor/editor_node.cpp
msgid "Save scene before running..."
-msgstr ""
+msgstr "씬을 실행하기 전에 저장..."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -2507,8 +2512,8 @@ msgid ""
"This option is deprecated. Situations where refresh must be forced are now "
"considered a bug. Please report."
msgstr ""
-"이 설정은 제거되었습니다. 강제로 새로고침해야 하는 상황은 이제 버그입니다. 신"
-"고해주세요."
+"이 옵션은 사용되지 않습니다. 강제로 새로 고침해야 하는 상황은 이제 버그로 간"
+"주됩니다. 신고해주세요."
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
@@ -2529,8 +2534,9 @@ msgstr ""
"실패했습니다."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr "다음 경로에서 애드온 플러그인을 찾을 수 없음: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr ""
+"다음 경로에서 애드온 플러그인을 위한 스크립트 필드를 찾을 수 없습니다: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2893,17 +2899,16 @@ msgid "Synchronize Script Changes"
msgstr "스크립트 변경사항 동기화"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, any script that is saved will be reloaded in "
"the running project.\n"
"When used remotely on a device, this is more efficient when the network "
"filesystem option is enabled."
msgstr ""
-"이 설정이 활성화된 경우, 어떤 스크립트든 저장하면 실행중인 게임에도 새로고침"
-"되어 반영됩니다.\n"
-"원격 장치에서 사용중인 경우 네트워크 파일 시스템 기능을 활성화하면 더욱 효율"
-"적입니다."
+"이 옵션이 활성화된 경우, 어떤 스크립트든지 저장되면 실행 중인 프로젝트를 다"
+"시 불러오게 됩니다.\n"
+"기기에서 원격으로 사용 중인 경우, 네트워크 파일 시스템 옵션이 활성화되어 있다"
+"면 더욱 효율적입니다."
#: editor/editor_node.cpp editor/script_create_dialog.cpp
msgid "Editor"
@@ -2958,14 +2963,6 @@ msgid "Help"
msgstr "도움말"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "검색"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "온라인 문서"
@@ -3127,6 +3124,24 @@ msgid "Open & Run a Script"
msgstr "스크립트 열기 & 실행"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"다음 파일은 디스크에 있는 게 더 최신입니다.\n"
+"조치을 어떻게 취해야 합니까?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "새로고침"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "다시 저장"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "새 상속 씬"
@@ -3335,7 +3350,7 @@ msgstr "유일하게 만들기"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "붙여넣기"
@@ -3373,14 +3388,14 @@ msgid "Add Key/Value Pair"
msgstr "키/값 쌍 추가"
#: editor/editor_run_native.cpp
-#, fuzzy
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the Export menu or define an existing preset "
"as runnable."
msgstr ""
-"이 플랫폼으로 실행할 수 있는 내보내기 프리셋이 없습니다.\n"
-"내보내기 메뉴에서 실행할 수 있는 프리셋을 추가해주세요."
+"이 플랫폼을 위한 실행할 수 있는 내보내기 프리셋이 없습니다.\n"
+"내보내기 메뉴에서 실행할 수 있는 프리셋을 추가하거나 기존 프리셋을 실행할 수 "
+"있도록 지정해주세요."
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -3693,6 +3708,11 @@ msgid ""
"\n"
"Do you wish to overwrite them?"
msgstr ""
+"다음 파일이나 폴더가 대상 위치 '%s'의 항목과 충돌합니다:\n"
+"\n"
+"%s\n"
+"\n"
+"이를 덮어쓰시겠습니까?"
#: editor/filesystem_dock.cpp
msgid "Renaming file:"
@@ -3773,9 +3793,8 @@ msgid "Duplicate..."
msgstr "복제..."
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "Move to Trash"
-msgstr "오토로드 이동"
+msgstr "휴지통으로 이동"
#: editor/filesystem_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
msgid "Rename..."
@@ -3886,19 +3905,16 @@ msgid "Searching..."
msgstr "검색 중..."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d match in %d file."
-msgstr "%d개 일치."
+msgstr "파일 %d$2개 중 %d$1개 일치."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d matches in %d file."
-msgstr "%d개 일치."
+msgstr "파일 %d$2개 중 %d$1개 일치."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d matches in %d files."
-msgstr "%d개 일치."
+msgstr "파일 %d$2개 중 %d$1개 일치."
#: editor/groups_editor.cpp
msgid "Add to Group"
@@ -4034,6 +4050,18 @@ msgstr "`post_import()` 메소드에서 Node에서 상속받은 객체를 반환
msgid "Saving..."
msgstr "저장 중..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "임포터 선택"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "임포터:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "기본값으로 재설정"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "파일 %d개"
@@ -4997,8 +5025,8 @@ msgid "Got:"
msgstr "받음:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "sha256 해시 확인 실패"
+msgid "Failed SHA-256 hash check"
+msgstr "SHA-256 해시 확인 실패"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5101,7 +5129,6 @@ msgid "Sort:"
msgstr "정렬:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "카테고리:"
@@ -5130,14 +5157,12 @@ msgid "Assets ZIP File"
msgstr "애셋 ZIP 파일"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid ""
"Can't determine a save path for lightmap images.\n"
"Save your scene and try again."
msgstr ""
-"라이트맵 이미지의 저장 경로를 파악할 수 없습니다.\n"
-"(같은 경로에 이미지를 저장할 수 있도록) 씬을 저장하거나, BakedLightmap 속성에"
-"서 저장 경로를 지정하세요."
+"라이트맵 이미지를 위한 저장 경로를 결정할 수 없습니다.\n"
+"당신의 씬을 저장하고 다시 시도하세요."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
@@ -5154,26 +5179,30 @@ msgstr "라이트맵 이미지 생성 실패. 작성 가능한 경로인지 확
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Failed determining lightmap size. Maximum lightmap size too small?"
msgstr ""
+"라이트맵 크기를 결정하는 데 실패했습니다. 최대 라이트맵 크기가 너무 작나요?"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
"Some mesh is invalid. Make sure the UV2 channel values are contained within "
"the [0.0,1.0] square region."
msgstr ""
+"일부 메시가 잘못되었습니다. UV2 채널 값이 [0.0,1.0] 정사각형 영역 안에 포함되"
+"어 있는지 확인해주세요."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
+"Godot 편집기가 레이 트레이싱 지원 없이 빌드되어 있어, 라이트맵이 구워질 수 없"
+"습니다."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
msgstr "라이트맵 굽기"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid "Select lightmap bake file:"
-msgstr "템플릿 파일 선택"
+msgstr "라이트맵을 구울 파일 선택:"
#: editor/plugins/camera_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -5242,50 +5271,43 @@ msgstr "수평 및 수직 가이드 만들기"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Set CanvasItem \"%s\" Pivot Offset to (%d, %d)"
-msgstr "CanvasItem \"%s\" Pivot Offset (%d, %d)로 설정"
+msgstr "CanvasItem \"%s\"의 피벗 오프셋을 (%d, %d)로 설정"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Rotate %d CanvasItems"
-msgstr "CanvasItem 회전"
+msgstr "CanvasItem %d개 회전"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Rotate CanvasItem \"%s\" to %d degrees"
-msgstr "CanvasItem 회전"
+msgstr "CanvasItem \"%s\"를 %d도로 회전"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Move CanvasItem \"%s\" Anchor"
-msgstr "CanvasItem 이동"
+msgstr "CanvasItem \"%s\" 앵커 이동"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Scale Node2D \"%s\" to (%s, %s)"
-msgstr ""
+msgstr "Node2D \"%s\"를 (%s, %s)로 크기 조절"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Resize Control \"%s\" to (%d, %d)"
-msgstr ""
+msgstr "컨트롤 \"%s\"를 (%d, %d)로 크기 조절"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Scale %d CanvasItems"
-msgstr "CanvasItem 규모"
+msgstr "CanvasItem %d개 크기 조절"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Scale CanvasItem \"%s\" to (%s, %s)"
-msgstr "CanvasItem 규모"
+msgstr "CanvasItem \"%s\"를 (%s, %s)로 크기 조절"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Move %d CanvasItems"
-msgstr "CanvasItem 이동"
+msgstr "CanvasItem %d개 이동"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Move CanvasItem \"%s\" to (%d, %d)"
-msgstr "CanvasItem 이동"
+msgstr "CanvasItem \"%s\"를 (%d, %d)로 이동"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid ""
@@ -5491,7 +5513,7 @@ msgstr "회전모드"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Scale Mode"
-msgstr "크기조절 모드"
+msgstr "크기 조절 모드"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -5540,7 +5562,7 @@ msgstr "회전 스냅 사용"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Use Scale Snap"
-msgstr "스마트 스냅 사용"
+msgstr "크기 조절 스냅 사용"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap Relative"
@@ -5658,11 +5680,11 @@ msgstr "선택 항목 중앙으로"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Frame Selection"
-msgstr "선택 항목 전체 화면으로"
+msgstr "프레임 선택"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Preview Canvas Scale"
-msgstr "캔버스 규모 미리 보기"
+msgstr "캔버스 크기 조절 미리 보기"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Translation mask for inserting keys."
@@ -5924,7 +5946,7 @@ msgstr "기울기 편집됨"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "Item %d"
-msgstr "항목 %d"
+msgstr "항목 %d개"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "Items"
@@ -6264,9 +6286,8 @@ msgid "Can only set point into a ParticlesMaterial process material"
msgstr "ParticlesMaterial 프로세스 머티리얼 안에만 점을 설정할 수 있습니다"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Convert to CPUParticles2D"
-msgstr "CPU파티클로 변환"
+msgstr "CPUParticles2D로 변환"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
@@ -6554,18 +6575,16 @@ msgid "Move Points"
msgstr "점 이동"
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Command: Rotate"
-msgstr "드래그: 회전"
+msgstr "Command: 회전"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Shift: Move All"
msgstr "Shift: 모두 이동"
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Shift+Command: Scale"
-msgstr "Shift+Ctrl: 크기 조절"
+msgstr "Shift+Command: 크기 조절"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Ctrl: Rotate"
@@ -6612,14 +6631,12 @@ msgid "Radius:"
msgstr "반지름:"
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Copy Polygon to UV"
-msgstr "폴리곤 & UV 만들기"
+msgstr "폴리곤을 UV로 복사"
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Copy UV to Polygon"
-msgstr "Polygon2D로 변환"
+msgstr "UV를 폴리곤으로 복사"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Clear UV"
@@ -6878,7 +6895,7 @@ msgstr "모두 저장"
#: editor/plugins/script_editor_plugin.cpp
msgid "Soft Reload Script"
-msgstr "스크립트 새로고침"
+msgstr "스크립트 일반 새로고침"
#: editor/plugins/script_editor_plugin.cpp
msgid "Copy Script Path"
@@ -6921,6 +6938,14 @@ msgstr "문서 닫기"
msgid "Run"
msgstr "실행"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "검색"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "프로시저 단위 실행"
@@ -6974,16 +6999,6 @@ msgstr ""
"해당 파일은 디스크에 있는 게 더 최신입니다.\n"
"어떻게 할 건가요?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "새로고침"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "다시 저장"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "디버거"
@@ -7079,8 +7094,8 @@ msgstr "중단점"
msgid "Go To"
msgstr "이동"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "잘라내기"
@@ -7107,7 +7122,7 @@ msgstr "주석 토글"
#: editor/plugins/script_text_editor.cpp
msgid "Fold/Unfold Line"
-msgstr "행 펼치기/접기"
+msgstr "행 접기/펼치기"
#: editor/plugins/script_text_editor.cpp
msgid "Fold All Lines"
@@ -7151,7 +7166,7 @@ msgstr "파일에서 찾기..."
#: editor/plugins/script_text_editor.cpp
msgid "Contextual Help"
-msgstr "상황에 맞는 도움"
+msgstr "상황에 맞는 도움말"
#: editor/plugins/script_text_editor.cpp
msgid "Toggle Bookmark"
@@ -7167,7 +7182,7 @@ msgstr "이전 북마크로 이동"
#: editor/plugins/script_text_editor.cpp
msgid "Remove All Bookmarks"
-msgstr "모든 북마크 삭제"
+msgstr "모든 북마크 제거"
#: editor/plugins/script_text_editor.cpp
msgid "Go to Function..."
@@ -7184,7 +7199,7 @@ msgstr "중단점 토글"
#: editor/plugins/script_text_editor.cpp
msgid "Remove All Breakpoints"
-msgstr "중단점 모두 삭제"
+msgstr "중단점 모두 제거"
#: editor/plugins/script_text_editor.cpp
msgid "Go to Next Breakpoint"
@@ -7303,6 +7318,10 @@ msgid "Yaw"
msgstr "요"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "크기"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "그려진 객체"
@@ -7528,7 +7547,7 @@ msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Use Local Space"
-msgstr "로컬 스페이스 사용"
+msgstr "로컬 공간 사용"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Use Snap"
@@ -7585,7 +7604,7 @@ msgstr "변형"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Snap Object to Floor"
-msgstr "객체를 바닥에 스냅"
+msgstr "개체를 바닥에 스냅"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform Dialog..."
@@ -7798,7 +7817,7 @@ msgstr "선택한 프레임 없음"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Add %d Frame(s)"
-msgstr "%d개의 프레임 추가"
+msgstr "프레임 %d개 추가"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Add Frame"
@@ -7845,9 +7864,8 @@ msgid "New Animation"
msgstr "새 애니메이션"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Speed:"
-msgstr "속도 (FPS):"
+msgstr "속도:"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Loop"
@@ -8105,7 +8123,7 @@ msgstr "테마 파일"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Erase Selection"
-msgstr "선택 지우기"
+msgstr "선택 항목 지우기"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Fix Invalid Tiles"
@@ -8165,13 +8183,12 @@ msgid "Paint Tile"
msgstr "타일 칠하기"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid ""
"Shift+LMB: Line Draw\n"
"Shift+Command+LMB: Rectangle Paint"
msgstr ""
-"Shift+우클릭: 선 그리기\n"
-"Shift+Ctrl+우클릭: 사각 영역 페인트"
+"Shift+좌클릭: 선 그리기\n"
+"Shift+Command+좌클릭: 사각 영역 페인트"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid ""
@@ -8211,7 +8228,7 @@ msgstr "TileSet에 텍스처를 추가합니다."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Remove selected Texture from TileSet."
-msgstr "선택한 텍스처를 TileSet에서 삭제."
+msgstr "선택한 텍스처를 TileSet에서 제거합니다."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create from Scene"
@@ -8326,23 +8343,20 @@ msgid "Create a new rectangle."
msgstr "새로운 사각형을 만듭니다."
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "New Rectangle"
-msgstr "사각 영역 칠하기"
+msgstr "새 사각 영역"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create a new polygon."
msgstr "새로운 폴리곤을 만듭니다."
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "New Polygon"
-msgstr "폴리곤 이동"
+msgstr "새 폴리곤"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Delete Selected Shape"
-msgstr "선택 항목 삭제"
+msgstr "선택된 모양 삭제"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Keep polygon inside region Rect."
@@ -8703,7 +8717,6 @@ msgid "Add Node to Visual Shader"
msgstr "노드를 비주얼 셰이더에 추가"
#: editor/plugins/visual_shader_editor_plugin.cpp
-#, fuzzy
msgid "Node(s) Moved"
msgstr "노드 이동됨"
@@ -8725,9 +8738,8 @@ msgid "Visual Shader Input Type Changed"
msgstr "비주얼 셰이더 입력 유형 변경됨"
#: editor/plugins/visual_shader_editor_plugin.cpp
-#, fuzzy
msgid "UniformRef Name Changed"
-msgstr "Uniform 이름 설정"
+msgstr "UniformRef 이름 변경됨"
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Vertex"
@@ -8908,7 +8920,7 @@ msgstr "꼭짓점과 프래그먼트 셰이더 모드에 대한 '%s' 입력 매
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "'%s' input parameter for fragment and light shader modes."
-msgstr "꼭짓점과 프래그먼트 셰이더 모드에 대한 '%s' 입력 매개변수."
+msgstr "프래그먼트과 조명 셰이더 모드에 대한 '%s' 입력 매개변수."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "'%s' input parameter for fragment shader mode."
@@ -9001,7 +9013,7 @@ msgstr "매개변수의 역쌍곡탄젠트 값을 반환합니다."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid ""
"Finds the nearest integer that is greater than or equal to the parameter."
-msgstr "매개변수보다 크거나 같은 가장 가까운 정수를 찾아요."
+msgstr "매개변수보다 크거나 같은 가장 가까운 정수를 찾습니다."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Constrains a value to lie between two further values."
@@ -9029,7 +9041,7 @@ msgstr "2가 밑인 지수 함수."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Finds the nearest integer less than or equal to the parameter."
-msgstr "매개변수보다 적거나 같은 가장 가까운 정수를 찾아요."
+msgstr "매개변수보다 적거나 같은 가장 가까운 정수를 찾습니다."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Computes the fractional part of the argument."
@@ -9082,11 +9094,11 @@ msgstr "1.0 / 스칼라"
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Finds the nearest integer to the parameter."
-msgstr "매개변수에서 가장 가까운 정수를 찾아요."
+msgstr "매개변수에서 가장 가까운 정수를 찾습니다."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Finds the nearest even integer to the parameter."
-msgstr "매개변수에서 가장 가까운 짝수 정수를 찾아요."
+msgstr "매개변수에서 가장 가까운 짝수 정수를 찾습니다."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Clamps the value between 0.0 and 1.0."
@@ -9725,8 +9737,8 @@ msgid ""
"Couldn't load project.godot in project path (error %d). It may be missing or "
"corrupted."
msgstr ""
-"프로젝트 경로에서 project.godot을 불러올 수 없습니다 (error %d). 누락되거나 "
-"손상된 모양입니다."
+"프로젝트 경로에서 project.godot을 불러올 수 없습니다 (오류 %d). 누락되거나 손"
+"상된 모양입니다."
#: editor/project_manager.cpp
msgid "Couldn't edit project.godot in project path."
@@ -9786,7 +9798,7 @@ msgstr "OpenGL ES 3.0"
#: editor/project_manager.cpp
msgid "Not supported by your GPU drivers."
-msgstr ""
+msgstr "당신의 GPU 드라이버에 의해 지원되지 않습니다."
#: editor/project_manager.cpp
msgid ""
@@ -9958,6 +9970,10 @@ msgid "Projects"
msgstr "프로젝트"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "로드 중, 기다려 주세요..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "마지막으로 수정됨"
@@ -10327,6 +10343,10 @@ msgstr "오토로드"
msgid "Plugins"
msgstr "플러그인(Plugin)"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "기본값 가져오기"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "프리셋..."
@@ -10405,7 +10425,7 @@ msgstr "정규 표현식 사용"
#: editor/rename_dialog.cpp
msgid "Advanced Options"
-msgstr "고급 설정"
+msgstr "고급 옵션"
#: editor/rename_dialog.cpp
msgid "Substitute"
@@ -10437,7 +10457,7 @@ msgid ""
"Compare counter options."
msgstr ""
"순차 정수 카운터.\n"
-"카운터 설정과 비교합니다."
+"카운터 옵션과 비교합니다."
#: editor/rename_dialog.cpp
msgid "Per-level Counter"
@@ -10574,6 +10594,14 @@ msgid "Instance Child Scene"
msgstr "자식 씬 인스턴스화"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "루트 노드를 같은 씬 안으로 붙여넣을 수 없습니다."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "노드 붙여넣기"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "스크립트 떼기"
@@ -10699,6 +10727,10 @@ msgid "Attach Script"
msgstr "스크립트 붙이기"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "노드 잘라내기"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "노드 삭제"
@@ -11503,36 +11535,31 @@ msgstr "메시를 사용하려면 이 GridMap에 MeshLibrary 리소스를 주세
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Begin Bake"
-msgstr ""
+msgstr "굽기 시작"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Preparing data structures"
-msgstr ""
+msgstr "데이터 구조 준비 중"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Generate buffers"
-msgstr "AABB 만들기"
+msgstr "버퍼 생성"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Direct lighting"
-msgstr "방향"
+msgstr "조명 방향"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Indirect lighting"
-msgstr "들여쓰기"
+msgstr "간접 조명"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Post processing"
msgstr "후처리"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Plotting lightmaps"
-msgstr "구분하는 조명:"
+msgstr "구분하는 조명"
#: modules/mono/csharp_script.cpp
msgid "Class name can't be a reserved keyword"
@@ -11544,11 +11571,11 @@ msgstr "내부 예외 스택 추적의 끝"
#: modules/recast/navigation_mesh_editor_plugin.cpp
msgid "Bake NavMesh"
-msgstr "NavMesh 베이크"
+msgstr "NavMesh 굽기"
#: modules/recast/navigation_mesh_editor_plugin.cpp
msgid "Clear the navigation mesh."
-msgstr "내비게이션 메시 지우기."
+msgstr "내비게이션 메시를 지웁니다."
#: modules/recast/navigation_mesh_generator.cpp
msgid "Setting up Configuration..."
@@ -12046,15 +12073,15 @@ msgstr "목록에서 기기 선택"
#: platform/android/export/export.cpp
msgid "Unable to find the 'apksigner' tool."
-msgstr ""
+msgstr "'apksigner' 도구를 찾을 수 없습니다."
#: platform/android/export/export.cpp
msgid ""
"Android build template not installed in the project. Install it from the "
"Project menu."
msgstr ""
-"프로젝트에 안드로이드 빌드 템플릿을 설치하지 않았습니다. 프로젝트 메뉴에서 설"
-"치하세요."
+"프로젝트에 Android 빌드 템플릿을 설치하지 않았습니다. 프로젝트 메뉴에서 설치"
+"하세요."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -12065,35 +12092,32 @@ msgid "Release keystore incorrectly configured in the export preset."
msgstr "내보내기 프리셋에 배포 keystorke가 잘못 설정되어 있습니다."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "A valid Android SDK path is required in Editor Settings."
-msgstr "편집기 설정에서 맞춤 빌드에 잘못된 안드로이드 SDK 경로입니다."
+msgstr "편집기 설정에서 올바른 Android SDK 경로가 필요합니다."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Invalid Android SDK path in Editor Settings."
-msgstr "편집기 설정에서 맞춤 빌드에 잘못된 안드로이드 SDK 경로입니다."
+msgstr "편집기 설정에서 잘못된 Android SDK 경로입니다."
#: platform/android/export/export.cpp
msgid "Missing 'platform-tools' directory!"
-msgstr ""
+msgstr "'platform-tools' 디렉터리가 없습니다!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK platform-tools' adb command."
-msgstr ""
+msgstr "Android SDK platform-tools의 adb 명령을 찾을 수 없습니다."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Please check in the Android SDK directory specified in Editor Settings."
-msgstr "편집기 설정에서 맞춤 빌드에 잘못된 안드로이드 SDK 경로입니다."
+msgstr "편집기 설정에서 지정된 Android SDK 디렉터리를 확인해주세요."
#: platform/android/export/export.cpp
msgid "Missing 'build-tools' directory!"
-msgstr ""
+msgstr "'build-tools' 디렉터리가 없습니다!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK build-tools' apksigner command."
-msgstr ""
+msgstr "Android SDK build-tools의 apksigner 명령을 찾을 수 없습니다."
#: platform/android/export/export.cpp
msgid "Invalid public key for APK expansion."
@@ -12157,8 +12181,8 @@ msgid ""
"Trying to build from a custom built template, but no version info for it "
"exists. Please reinstall from the 'Project' menu."
msgstr ""
-"맞춤 빌드 템플릿으로 빌드하려 했으나, 버전 정보가가 없습니다. '프로젝트' 메뉴"
-"에서 다시 설치해주세요."
+"맞춤 빌드 템플릿으로 빌드하려 했으나, 버전 정보가 없습니다. '프로젝트' 메뉴에"
+"서 다시 설치해주세요."
#: platform/android/export/export.cpp
msgid ""
@@ -12167,32 +12191,34 @@ msgid ""
" Godot Version: %s\n"
"Please reinstall Android build template from 'Project' menu."
msgstr ""
-"안드로이드 빌드 버전이 맞지 않음:\n"
-" 설치한 템플릿: %s\n"
+"Android 빌드 버전이 맞지 않음:\n"
+" 설치된 템플릿: %s\n"
" Godot 버전: %s\n"
-"'프로젝트' 메뉴에서 안드로이드 빌드 템플릿을 다시 설치해주세요."
+"'프로젝트' 메뉴에서 Android 빌드 템플릿을 다시 설치해주세요."
#: platform/android/export/export.cpp
msgid "Building Android Project (gradle)"
-msgstr "안드로이드 프로젝트 빌드 중 (gradle)"
+msgstr "Android 프로젝트 빌드 중 (gradle)"
#: platform/android/export/export.cpp
msgid ""
"Building of Android project failed, check output for the error.\n"
"Alternatively visit docs.godotengine.org for Android build documentation."
msgstr ""
-"안드로이드 프로젝트의 빌드에 실패했, 출력한 오류를 확인하세요.\n"
-"또는 docs.godotengine.org에서 안드로이드 빌드 문서를 찾아 보세요."
+"Android 프로젝트의 빌드에 실패했습니다, 출력된 오류를 확인하세요.\n"
+"또는 docs.godotengine.org에서 Andoid 빌드 문서를 찾아보세요."
#: platform/android/export/export.cpp
msgid "Moving output"
-msgstr ""
+msgstr "출력 이동 중"
#: platform/android/export/export.cpp
msgid ""
"Unable to copy and rename export file, check gradle project directory for "
"outputs."
msgstr ""
+"내보내기 파일을 복사하고 이름을 바꿀 수 없습니다, 출력에 대한 gradle 프로젝"
+"트 디렉터리를 확인하세요."
#: platform/iphone/export/export.cpp
msgid "Identifier is missing."
@@ -12342,6 +12368,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "빈 CollisionPolygon2D는 충돌에 영향을 주지 않습니다."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr "잘못된 폴리곤. 적어도 '솔리드' 빌드 모드에서 점 3개가 필요합니다."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr "잘못된 폴리곤. 적어도 '세그먼트' 빌드 모드에서 점 2개가 필요합니다."
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12378,23 +12412,23 @@ msgstr ""
#: scene/2d/joints_2d.cpp
msgid "Node A and Node B must be PhysicsBody2Ds"
-msgstr ""
+msgstr "노드 A와 노드 B는 PhysicsBody2D여야 합니다"
#: scene/2d/joints_2d.cpp
msgid "Node A must be a PhysicsBody2D"
-msgstr ""
+msgstr "노드 A는 PhysicsBody2D여야 합니다"
#: scene/2d/joints_2d.cpp
msgid "Node B must be a PhysicsBody2D"
-msgstr ""
+msgstr "노드 B는 PhysicsBody2D여야 합니다"
#: scene/2d/joints_2d.cpp
msgid "Joint is not connected to two PhysicsBody2Ds"
-msgstr ""
+msgstr "관절이 PhysicsBody2D 두 곳과 연결되어 있지 않습니다"
#: scene/2d/joints_2d.cpp
msgid "Node A and Node B must be different PhysicsBody2Ds"
-msgstr ""
+msgstr "노드 A와 노드 B는 서로 다른 PhysicsBody2D여야 합니다"
#: scene/2d/light_2d.cpp
msgid ""
@@ -12543,27 +12577,23 @@ msgstr "ARVROrigin은 자식으로 ARVRCamera 노드가 필요합니다."
#: scene/3d/baked_lightmap.cpp
msgid "Finding meshes and lights"
-msgstr ""
+msgstr "메시 및 조명 찾는 중"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing geometry (%d/%d)"
-msgstr "형태 분석 중..."
+msgstr "형태 준비 중 (%d/%d)"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing environment"
-msgstr "환경 보기"
+msgstr "환경 준비 중"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Generating capture"
-msgstr "라이트맵 생성 중"
+msgstr "캡처 생성 중"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Saving lightmaps"
-msgstr "라이트맵 생성 중"
+msgstr "라이트맵 저장 중"
#: scene/3d/baked_lightmap.cpp
msgid "Done"
@@ -12654,11 +12684,6 @@ msgstr ""
"GIProbe는 GLES2 비디오 드라이버에서 지원하지 않습니다.\n"
"대신 BakedLightmap을 사용하세요."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamera는 더 이상 사용되지 않으며 Godot 4.0에서 제거됩니다."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "SpotLight의 각도를 90도 이상으로 잡게되면 그림자를 투영할 수 없습니다."
@@ -12723,23 +12748,23 @@ msgstr ""
#: scene/3d/physics_joint.cpp
msgid "Node A and Node B must be PhysicsBodies"
-msgstr ""
+msgstr "노드 A와 노드 B는 PhysicsBody여야 합니다"
#: scene/3d/physics_joint.cpp
msgid "Node A must be a PhysicsBody"
-msgstr ""
+msgstr "노드 A는 PhysicsBody여야 합니다"
#: scene/3d/physics_joint.cpp
msgid "Node B must be a PhysicsBody"
-msgstr ""
+msgstr "노드 B는 PhysicsBodies여야 합니다"
#: scene/3d/physics_joint.cpp
msgid "Joint is not connected to any PhysicsBodies"
-msgstr ""
+msgstr "관절이 어떠한 PhysicsBody에도 연결되어 있지 않습니다"
#: scene/3d/physics_joint.cpp
msgid "Node A and Node B must be different PhysicsBodies"
-msgstr ""
+msgstr "노드 A와 노드 B는 서로 다른 PhysicsBody여야 합니다"
#: scene/3d/remote_transform.cpp
msgid ""
@@ -12904,9 +12929,8 @@ msgid "Must use a valid extension."
msgstr "올바른 확장자를 사용해야 합니다."
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Enable grid minimap."
-msgstr "스냅 켜기"
+msgstr "그리드 미니맵을 활성화합니다."
#: scene/gui/popup.cpp
msgid ""
@@ -12964,6 +12988,8 @@ msgid ""
"The sampler port is connected but not used. Consider changing the source to "
"'SamplerPort'."
msgstr ""
+"샘플러 포트가 연결되어 있지만 사용되지 않습이다. 소스를 'SamplerPort'로 변경"
+"하는 것을 고려해주세요."
#: scene/resources/visual_shader_nodes.cpp
msgid "Invalid source for preview."
@@ -12993,6 +13019,11 @@ msgstr "Varying은 꼭짓점 함수에만 지정할 수 있습니다."
msgid "Constants cannot be modified."
msgstr "상수는 수정할 수 없습니다."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr ""
+#~ "InterpolatedCamera는 더 이상 사용되지 않으며 Godot 4.0에서 제거됩니다."
+
#~ msgid "No"
#~ msgstr "아니오"
@@ -14779,9 +14810,6 @@ msgstr "상수는 수정할 수 없습니다."
#~ msgid "Use Default Light"
#~ msgstr "기본 Light 사용"
-#~ msgid "Use Default sRGB"
-#~ msgstr "기본 sRGB 사용"
-
#~ msgid "Default Light Normal:"
#~ msgstr "기본 라이트 노말:"
diff --git a/editor/translations/lt.po b/editor/translations/lt.po
index f8c6d6acc9..585e4d4447 100644
--- a/editor/translations/lt.po
+++ b/editor/translations/lt.po
@@ -5,12 +5,12 @@
# Ignas Kiela <ignaskiela@super.lt>, 2017.
# Kornelijus <kornelijus.github@gmail.com>, 2017, 2018.
# Ignotas Gražys <ignotas.gr@gmail.com>, 2020.
-# Kornelijus Tvarijanavičius <kornelitvari@protonmail.com>, 2020.
+# Kornelijus Tvarijanavičius <kornelitvari@protonmail.com>, 2020, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-09-28 11:18+0000\n"
+"PO-Revision-Date: 2021-02-21 10:51+0000\n"
"Last-Translator: Kornelijus Tvarijanavičius <kornelitvari@protonmail.com>\n"
"Language-Team: Lithuanian <https://hosted.weblate.org/projects/godot-engine/"
"godot/lt/>\n"
@@ -20,7 +20,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1 ? 0 : n%10>=2 && (n%100<10 || n"
"%100>=20) ? 1 : n%10==0 || (n%100>10 && n%100<20) ? 2 : 3;\n"
-"X-Generator: Weblate 4.3-dev\n"
+"X-Generator: Weblate 4.5\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -650,7 +650,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1854,8 +1854,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2504,7 +2504,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2901,14 +2901,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -3062,6 +3054,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3271,7 +3279,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3978,6 +3986,20 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Pasirinkite Nodus, kuriuos norite importuoti"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importuoti Animacijas..."
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -4762,7 +4784,6 @@ msgstr "Naujas pavadinimas:"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
#: editor/plugins/multimesh_editor_plugin.cpp
-#, fuzzy
msgid "Scale:"
msgstr "Skalė:"
@@ -4964,7 +4985,7 @@ msgid "Got:"
msgstr "Gauta:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5073,7 +5094,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategorija:"
@@ -6888,6 +6908,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6939,16 +6967,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7045,8 +7063,8 @@ msgstr "Sukurti"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7269,6 +7287,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9881,6 +9903,11 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Atsiųsti"
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10243,6 +10270,10 @@ msgstr ""
msgid "Plugins"
msgstr "Priedai"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10490,6 +10521,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Duplikuoti"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Atidaryti Skriptų Editorių"
@@ -10614,6 +10654,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Transition Nodas"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12235,6 +12280,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12490,11 +12543,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -12833,10 +12881,6 @@ msgstr ""
#~ msgid "Path to Node:"
#~ msgstr "Kelias iki Nodo:"
-#, fuzzy
-#~ msgid "Custom Node"
-#~ msgstr "Transition Nodas"
-
#~ msgid "Line:"
#~ msgstr "Linija:"
diff --git a/editor/translations/lv.po b/editor/translations/lv.po
index e7abc2a6e7..5512d59238 100644
--- a/editor/translations/lv.po
+++ b/editor/translations/lv.po
@@ -649,7 +649,7 @@ msgstr "Izvēlēties Celiņus ko Kopēt"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopēt"
@@ -1841,8 +1841,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2477,7 +2477,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2867,14 +2867,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -3028,6 +3020,23 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr "Sekojošie faili netika izvilkti no paketes:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3230,7 +3239,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3914,6 +3923,20 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Izvēlēties Šablona Failu"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Ielādēt Noklusējumu"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Failā"
@@ -4861,7 +4884,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4965,7 +4988,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6742,6 +6764,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6793,16 +6823,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6899,8 +6919,8 @@ msgstr "Izveidot"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7126,6 +7146,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9704,6 +9728,11 @@ msgid "Projects"
msgstr "Projekta Dibinātāji"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Ielādēt..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10066,6 +10095,11 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Ielādēt Noklusējumu"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10311,6 +10345,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Dublicēt atslēgvietnes"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Galvenais Skripts:"
@@ -10434,6 +10477,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Dublicēt atslēgvietnes"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12035,6 +12083,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12290,11 +12346,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/mi.po b/editor/translations/mi.po
index 33153ba3a5..260543a475 100644
--- a/editor/translations/mi.po
+++ b/editor/translations/mi.po
@@ -619,7 +619,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1788,8 +1788,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2423,7 +2423,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2813,14 +2813,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2974,6 +2966,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3176,7 +3184,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3857,6 +3865,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4804,7 +4824,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4908,7 +4928,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6675,6 +6694,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6726,16 +6753,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6828,8 +6845,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7050,6 +7067,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9570,6 +9591,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9930,6 +9955,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10173,6 +10202,14 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10293,6 +10330,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11867,6 +11908,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12122,11 +12171,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/mk.po b/editor/translations/mk.po
index 71da151591..cd72ecd259 100644
--- a/editor/translations/mk.po
+++ b/editor/translations/mk.po
@@ -626,7 +626,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Копирај"
@@ -1795,8 +1795,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2430,7 +2430,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2820,14 +2820,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2981,6 +2973,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3183,7 +3191,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3864,6 +3872,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4811,7 +4831,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4915,7 +4935,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6682,6 +6701,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6733,16 +6760,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6835,8 +6852,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7057,6 +7074,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9577,6 +9598,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9937,6 +9962,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10180,6 +10209,14 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10300,6 +10337,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11874,6 +11915,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12129,11 +12178,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/ml.po b/editor/translations/ml.po
index a72cd78ca2..fb9de4a419 100644
--- a/editor/translations/ml.po
+++ b/editor/translations/ml.po
@@ -629,7 +629,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1798,8 +1798,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2435,7 +2435,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2825,14 +2825,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2986,6 +2978,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3188,7 +3196,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3869,6 +3877,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4819,7 +4839,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4923,7 +4943,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6691,6 +6710,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6742,16 +6769,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6844,8 +6861,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7066,6 +7083,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9587,6 +9608,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9947,6 +9972,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10190,6 +10219,14 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10310,6 +10347,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11885,6 +11926,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12140,11 +12189,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/mr.po b/editor/translations/mr.po
index 6f019300ff..cf3a24a739 100644
--- a/editor/translations/mr.po
+++ b/editor/translations/mr.po
@@ -626,7 +626,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1795,8 +1795,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2430,7 +2430,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2820,14 +2820,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2981,6 +2973,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3183,7 +3191,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3864,6 +3872,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4811,7 +4831,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4915,7 +4935,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6682,6 +6701,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6733,16 +6760,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6835,8 +6852,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7057,6 +7074,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9578,6 +9599,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9938,6 +9963,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10181,6 +10210,14 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10301,6 +10338,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11875,6 +11916,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12130,11 +12179,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/ms.po b/editor/translations/ms.po
index 2f3e1481a2..c0a7f7cea2 100644
--- a/editor/translations/ms.po
+++ b/editor/translations/ms.po
@@ -649,7 +649,7 @@ msgstr "Pilih Trek untuk Disalin"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Salin"
@@ -1865,8 +1865,8 @@ msgid "Open a File or Directory"
msgstr "Buka Fail atau Direktori"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Simpan"
@@ -2542,7 +2542,8 @@ msgstr ""
"gagal."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"Tidak dapat mencari medan skrip untuk pemalam addon di: 'res://addons/%s'."
@@ -3022,15 +3023,6 @@ msgid "Help"
msgstr "Bantuan"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#, fuzzy
-msgid "Search"
-msgstr "Cari"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
#, fuzzy
msgid "Online Docs"
@@ -3214,6 +3206,23 @@ msgstr "Buka & Jalankan Skrip"
#: editor/editor_node.cpp
#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr "Fail berikut gagal diekstrak dari pakej:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
msgid "New Inherited"
msgstr "Baru Diwarisi"
@@ -3458,7 +3467,7 @@ msgstr "Buat Unik"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
#, fuzzy
msgid "Paste"
msgstr "Tampal"
@@ -4183,6 +4192,21 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Pilih Nod(Nod-nod) untuk Diimport"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Import"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Muatkan Lalai"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -5133,7 +5157,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5239,7 +5263,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -7012,6 +7035,15 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+#, fuzzy
+msgid "Search"
+msgstr "Cari"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -7063,16 +7095,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7165,8 +7187,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7388,6 +7410,11 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "Saiz: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9924,6 +9951,11 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Mengambil maklumat cermin, sila tunggu..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10284,6 +10316,11 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Muatkan Lalai"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10528,6 +10565,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Anim Menduakan Kunci"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10649,6 +10695,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Anim Menduakan Kunci"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12231,6 +12282,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12486,11 +12545,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/nb.po b/editor/translations/nb.po
index 90f033ad39..9e69510739 100644
--- a/editor/translations/nb.po
+++ b/editor/translations/nb.po
@@ -3,24 +3,25 @@
# Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
# This file is distributed under the same license as the Godot source code.
# Allan Nordhøy <epost@anotheragency.no>, 2017-2018, 2019, 2020, 2021.
-# Anonymous <GentleSaucepan@protonmail.com>, 2017.
+# Anonymous <GentleSaucepan@protonmail.com>, 2017, 2021.
# Elias <eliasnykrem@gmail.com>, 2018.
# flesk <eivindkn@gmail.com>, 2017, 2019.
-# Frank T. Rambol <frank@d-fect.com>, 2018.
+# Frank T. Rambol <frank@d-fect.com>, 2018, 2021.
# Jørgen Aarmo Lund <jorgen.aarmo@gmail.com>, 2016, 2019.
-# NicolaiF <nico-fre@hotmail.com>, 2017-2018, 2019.
+# NicolaiF <nico-fre@hotmail.com>, 2017-2018, 2019, 2021.
# Norwegian Disaster <stian.furu.overbye@gmail.com>, 2017.
# passeride <lukas@passeride.com>, 2017.
# Byzantin <kasper-hoel@hotmail.com>, 2018.
# Hans-Marius Øverås <hansmariusoveras@gmail.com>, 2019.
# Revolution <revosw@gmail.com>, 2019.
# Petter Reinholdtsen <pere-weblate@hungry.com>, 2019, 2020.
+# Patrick Sletvold <patricksletvold@hotmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-12 13:32+0000\n"
-"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n"
+"PO-Revision-Date: 2021-02-27 00:47+0000\n"
+"Last-Translator: Anonymous <GentleSaucepan@protonmail.com>\n"
"Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/godot-"
"engine/godot/nb_NO/>\n"
"Language: nb\n"
@@ -28,7 +29,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.4.1-dev\n"
+"X-Generator: Weblate 4.5\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -200,7 +201,6 @@ msgid "Change Animation Loop"
msgstr "Endre Animasjonssløyfe"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Property Track"
msgstr "Egenskapsspor"
@@ -209,24 +209,20 @@ msgid "3D Transform Track"
msgstr "3D transformasjonsspor"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Call Method Track"
msgstr "Kall metode-spor"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Bezier Curve Track"
-msgstr "Bezier-kurvespor"
+msgstr "Bézier-kurvespor"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Audio Playback Track"
msgstr "Lydavspillingsspor"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Animation Playback Track"
-msgstr "Stopp avspilling av animasjon. (S)"
+msgstr "Animasjonavspillingspor"
#: editor/animation_track_editor.cpp
msgid "Animation length (frames)"
@@ -241,7 +237,6 @@ msgid "Add Track"
msgstr "Legg til Spor"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Animation Looping"
msgstr "Animasjonsløkke"
@@ -260,23 +255,20 @@ msgid "Anim Clips:"
msgstr "Anim-klipp:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Change Track Path"
-msgstr "Endre Array-verdi"
+msgstr "Endre sporsti"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Toggle this track on/off."
-msgstr "Vis/skjul distraksjonsfri modus."
+msgstr "Slå spor på/av."
#: editor/animation_track_editor.cpp
msgid "Update Mode (How this property is set)"
msgstr "Oppdateringsmodus (Hvordan denne egenskapen settes)"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Interpolation Mode"
-msgstr "Animasjonsnode"
+msgstr "Interpolasjonsmodus"
#: editor/animation_track_editor.cpp
msgid "Loop Wrap Mode (Interpolate end with beginning on loop)"
@@ -334,7 +326,7 @@ msgstr "Pakk Inn Sløyfeinterp"
#: editor/animation_track_editor.cpp
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Key"
-msgstr "Sett inn Nøkkel"
+msgstr "Sett inn nøkkel"
#: editor/animation_track_editor.cpp
msgid "Duplicate Key(s)"
@@ -345,19 +337,16 @@ msgid "Delete Key(s)"
msgstr "Fjern Nøkler"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Change Animation Update Mode"
-msgstr "Endre Animasjonsnavn:"
+msgstr "Endre oppdateringsmetode for animasjon"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Change Animation Interpolation Mode"
-msgstr "Animasjonsnode"
+msgstr "Endre interpolasjonsmodus for animasjon"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Change Animation Loop Mode"
-msgstr "Endre Anim-Løkke"
+msgstr "Endre løkkemodus for animasjon"
#: editor/animation_track_editor.cpp
msgid "Remove Anim Track"
@@ -412,9 +401,8 @@ msgid "Rearrange Tracks"
msgstr "Omorganiser Spor"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Transform tracks only apply to Spatial-based nodes."
-msgstr "Transformasjonsspor kan kun brukes på Spatial-baserte noder."
+msgstr "Transformeringsspor virker kun på Spatial-baserte noder."
#: editor/animation_track_editor.cpp
msgid ""
@@ -438,47 +426,40 @@ msgstr ""
"En animansjonsavspiller kan ikke animere seg selv, kun andre avspillere."
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Not possible to add a new track without a root"
msgstr "Ikke mulig å legge til et nytt spor uten en rot"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Ugyldig spor for Bézier (ingen passende underegenskaper)"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Add Bezier Track"
-msgstr "Anim Legg til Spor"
+msgstr "Legg til Bézier-spor"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Track path is invalid, so can't add a key."
msgstr "Sporsti er ugyldig, så kan ikke legge til en nøkkel."
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Track is not of type Spatial, can't insert key"
-msgstr "Spor er ikke av type Spatial, kan ikke legge til nøkkel"
+msgstr "Spor er ikke av typen Spatial, kan ikke sette inn nøkkel"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Add Transform Track Key"
-msgstr "3D transformasjonsspor"
+msgstr "Legg til transformasjons-spornøkkel"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Add Track Key"
-msgstr "Anim Legg til Spor"
+msgstr "Legg til spornøkkel"
#: editor/animation_track_editor.cpp
msgid "Track path is invalid, so can't add a method key."
msgstr "Sporsti er ugyldig, så kan ikke legge til en metodenøkkel."
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Add Method Track Key"
-msgstr "Kall metode-spor"
+msgstr "Legg til metode-spornøkkel"
#: editor/animation_track_editor.cpp
msgid "Method not found in object: "
@@ -489,26 +470,22 @@ msgid "Anim Move Keys"
msgstr "Anim Flytt Nøkler"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Clipboard is empty"
-msgstr "Ressurs-utklippstavle er tom!"
+msgstr "Utklippstavlen er tom"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Paste Tracks"
-msgstr "Lim inn Parametre"
+msgstr "Sett in spor"
#: editor/animation_track_editor.cpp
msgid "Anim Scale Keys"
msgstr "Anim Skalér Nøkler"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid ""
"This option does not work for Bezier editing, as it's only a single track."
msgstr ""
-"Dette valget virker ikke på Bezier-redigering, siden det kun er ett enkelt "
-"spor."
+"Dette valget virker ikke på Bézier-redigering, da det kun er ett enkelt spor."
#: editor/animation_track_editor.cpp
msgid ""
@@ -522,10 +499,19 @@ msgid ""
"Alternatively, use an import preset that imports animations to separate "
"files."
msgstr ""
+"Denne animasjonen hører til en importert scene, så endringer på importerte "
+"spor vil ikke bli lagret.\n"
+"\n"
+"For å legge til egendefinerte spor, gå til scenens importinstillinger og "
+"sett\n"
+"\"Animasjon > Lagring\" til \"Filer\", aktiver \"Animasjon > Behold egne spor"
+"\", og importer på nytt.\n"
+"Alternativt, bruk et importoppsett som importerer animasjonen som separate "
+"filer."
#: editor/animation_track_editor.cpp
msgid "Warning: Editing imported animation"
-msgstr ""
+msgstr "Advarsel: Redigerer importert animasjon"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -570,9 +556,8 @@ msgid "Edit"
msgstr "Rediger"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Animation properties."
-msgstr "Animasjon"
+msgstr "Animasjon egenskaper."
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -589,26 +574,23 @@ msgstr "Skaler Fra Peker"
#: editor/animation_track_editor.cpp modules/gridmap/grid_map_editor_plugin.cpp
msgid "Duplicate Selection"
-msgstr "Dupliser Utvalg"
+msgstr "Dupliser utvalg"
#: editor/animation_track_editor.cpp
msgid "Duplicate Transposed"
-msgstr "Dupliser Transponert"
+msgstr "Dupliser transponert"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Delete Selection"
-msgstr "Slett Valgte"
+msgstr "Slett valgte"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Go to Next Step"
-msgstr "Gå til Neste Steg"
+msgstr "Gå til neste steg"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Go to Previous Step"
-msgstr "Gå til Forrige Steg"
+msgstr "Gå til forrige steg"
#: editor/animation_track_editor.cpp
msgid "Optimize Animation"
@@ -671,16 +653,15 @@ msgid "Scale Ratio:"
msgstr "Skaler Størrelsesforhold:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Select Tracks to Copy"
-msgstr "Velg spor å kopiere:"
+msgstr "Velg spor å kopiere"
#: editor/animation_track_editor.cpp editor/editor_log.cpp
#: editor/editor_properties.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Lim inn"
@@ -690,9 +671,8 @@ msgid "Select All/None"
msgstr "Kutt Noder"
#: editor/animation_track_editor_plugins.cpp
-#, fuzzy
msgid "Add Audio Track Clip"
-msgstr "Lydklipp:"
+msgstr "Legg til lyd-spor klipp"
#: editor/animation_track_editor_plugins.cpp
msgid "Change Audio Track Clip Start Offset"
@@ -723,19 +703,16 @@ msgid "Line Number:"
msgstr "Linjenummer:"
#: editor/code_editor.cpp
-#, fuzzy
msgid "%d replaced."
-msgstr "Erstatt..."
+msgstr "%d erstattet."
#: editor/code_editor.cpp editor/editor_help.cpp
-#, fuzzy
msgid "%d match."
-msgstr "%d samsvar."
+msgstr "%d samsvarer."
#: editor/code_editor.cpp editor/editor_help.cpp
-#, fuzzy
msgid "%d matches."
-msgstr "Ingen Treff"
+msgstr "%d sammsvarer."
#: editor/code_editor.cpp editor/find_in_files.cpp
msgid "Match Case"
@@ -760,7 +737,7 @@ msgstr "Kun Valgte"
#: editor/code_editor.cpp editor/plugins/script_text_editor.cpp
#: editor/plugins/text_editor.cpp
msgid "Standard"
-msgstr ""
+msgstr "Standard"
#: editor/code_editor.cpp editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
@@ -791,9 +768,8 @@ msgid "Line and column numbers."
msgstr "Linje- og kolonnenummer."
#: editor/connections_dialog.cpp
-#, fuzzy
msgid "Method in target node must be specified."
-msgstr "Metode i mål-Node må spesifiseres!"
+msgstr "Metode i målnoden må spesifiseres."
#: editor/connections_dialog.cpp
#, fuzzy
@@ -820,13 +796,12 @@ msgid "Connect to Script:"
msgstr "Kan ikke koble til tjener:"
#: editor/connections_dialog.cpp
-#, fuzzy
msgid "From Signal:"
-msgstr "Signaler:"
+msgstr "Fra signal:"
#: editor/connections_dialog.cpp
msgid "Scene does not contain any script."
-msgstr ""
+msgstr "Scenen inneholder ikke noen skript."
#: editor/connections_dialog.cpp editor/editor_autoload_settings.cpp
#: editor/groups_editor.cpp editor/plugins/item_list_editor_plugin.cpp
@@ -854,14 +829,12 @@ msgid "Extra Call Arguments:"
msgstr "Ekstra Call Argumenter:"
#: editor/connections_dialog.cpp
-#, fuzzy
msgid "Receiver Method:"
-msgstr "Lim inn Noder"
+msgstr "Mottakermetode:"
#: editor/connections_dialog.cpp
-#, fuzzy
msgid "Advanced"
-msgstr "Snapping innstillinger"
+msgstr "Avansert"
#: editor/connections_dialog.cpp
msgid "Deferred"
@@ -1064,9 +1037,8 @@ msgid "Fix Broken"
msgstr "Reparer Ødelagt"
#: editor/dependency_editor.cpp
-#, fuzzy
msgid "Dependency Editor"
-msgstr "Avhengighetsredigeringsverktøy"
+msgstr "Redigeringsverktøy for avhengigheter"
#: editor/dependency_editor.cpp
msgid "Search Replacement Resource:"
@@ -1087,14 +1059,15 @@ msgid "Owners Of:"
msgstr "Eiere Av:"
#: editor/dependency_editor.cpp
-#, fuzzy
msgid ""
"Remove selected files from the project? (no undo)\n"
"You can find the removed files in the system trash to restore them."
-msgstr "Fjerne valgte filer fra prosjektet? (kan ikke angres)"
+msgstr ""
+"Fjerne valgte filer fra prosjektet? (kan ikke angres)\n"
+"Du kan finne de fjernede filene i systemets papirkurv, og gjenopprette dem "
+"derfra."
#: editor/dependency_editor.cpp
-#, fuzzy
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -1102,7 +1075,9 @@ msgid ""
"You can find the removed files in the system trash to restore them."
msgstr ""
"Filene som fjernes kreves for at andre ressurser skal virke.\n"
-"Fjern dem likevel? (kan ikke angres)"
+"Fjerne dem likevel? (kan ikke angres)\n"
+"Du kan finne de fjernede filene i systemets papirkurv, og gjenopprette dem "
+"derfra."
#: editor/dependency_editor.cpp
msgid "Cannot remove:"
@@ -1163,14 +1138,12 @@ msgid "Resources Without Explicit Ownership:"
msgstr "Ressurser uten eksplisitt eierskap:"
#: editor/dictionary_property_edit.cpp
-#, fuzzy
msgid "Change Dictionary Key"
-msgstr "Endre Ordboksnøkkel"
+msgstr "Endre listenøkkel"
#: editor/dictionary_property_edit.cpp
-#, fuzzy
msgid "Change Dictionary Value"
-msgstr "Endre Ordboksverdi"
+msgstr "Endre listeverdi"
#: editor/editor_about.cpp
msgid "Thanks from the Godot community!"
@@ -1444,7 +1417,6 @@ msgid "There is no '%s' file."
msgstr "Det finnes ingen «%s»-fil"
#: editor/editor_audio_buses.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Layout"
msgstr "Layout"
@@ -1453,9 +1425,8 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Ugyldig fil, ikke et audio bus oppsett."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Error saving file: %s"
-msgstr "Error ved lagring av TileSet!"
+msgstr "Feil ved lagring av filen: %s"
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
@@ -1643,7 +1614,6 @@ msgid "Storing File:"
msgstr "Lagrer Fil:"
#: editor/editor_export.cpp
-#, fuzzy
msgid "No export template found at the expected path:"
msgstr "Ingen eksportmal funnet på forventet søkesti:"
@@ -1770,7 +1740,7 @@ msgstr "Erstatt Alle"
#: editor/editor_feature_profile.cpp
msgid "Profile must be a valid filename and must not contain '.'"
-msgstr ""
+msgstr "Profil må være et gyldig filnavn, og kan ikke inneholde '.'"
#: editor/editor_feature_profile.cpp
#, fuzzy
@@ -1797,9 +1767,8 @@ msgid "Class Options:"
msgstr "Beskrivelse:"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Enable Contextual Editor"
-msgstr "Åpne den neste Editoren"
+msgstr "Aktiver kontekstavhengig redigeringsverktøy"
#: editor/editor_feature_profile.cpp
#, fuzzy
@@ -1817,7 +1786,7 @@ msgstr "Søk i klasser"
#: editor/editor_feature_profile.cpp
msgid "File '%s' format is invalid, import aborted."
-msgstr ""
+msgstr "Filformatet til '%s' er ugyldig, importen ble avbrutt."
#: editor/editor_feature_profile.cpp
msgid ""
@@ -1826,9 +1795,8 @@ msgid ""
msgstr ""
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Error saving profile to path: '%s'."
-msgstr "Error ved lagring av TileSet!"
+msgstr "Feil ved lagring av profilen til stien: '%s'."
#: editor/editor_feature_profile.cpp
msgid "Unset"
@@ -1961,8 +1929,8 @@ msgid "Open a File or Directory"
msgstr "Åpne ei fil eller mappe"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Lagre"
@@ -2252,9 +2220,8 @@ msgid "Set"
msgstr "Sett"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Set Multiple:"
-msgstr "Sett Mange:"
+msgstr "Sett mange:"
#: editor/editor_log.cpp
msgid "Output:"
@@ -2286,9 +2253,8 @@ msgstr "Stopp"
#: editor/editor_network_profiler.cpp editor/editor_profiler.cpp
#: editor/plugins/animation_state_machine_editor.cpp editor/rename_dialog.cpp
-#, fuzzy
msgid "Start"
-msgstr "Start!"
+msgstr "Start"
#: editor/editor_network_profiler.cpp
msgid "%s/s"
@@ -2370,7 +2336,7 @@ msgstr "Kan ikke åpne '%s'. Filen kan ha blitt flyttet eller slettet."
#: editor/editor_node.cpp
msgid "Error while parsing '%s'."
-msgstr "Error ved parsing av '%s'."
+msgstr "Feil ved parsing av '%s'."
#: editor/editor_node.cpp
msgid "Unexpected end of file '%s'."
@@ -2401,7 +2367,6 @@ msgid "This operation can't be done without a tree root."
msgstr "Denne operasjonen kan ikke gjennomføres uten en trerot."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"This scene can't be saved because there is a cyclic instancing inclusion.\n"
"Please resolve it and then attempt to save again."
@@ -2428,7 +2393,7 @@ msgstr "Kan ikke laste MeshLibrary for sammenslåing!"
#: editor/editor_node.cpp
msgid "Error saving MeshLibrary!"
-msgstr "Error ved lagring av MeshLibrary!"
+msgstr "Feil ved lagring av MeshLibrary!"
#: editor/editor_node.cpp
msgid "Can't load TileSet for merging!"
@@ -2436,7 +2401,7 @@ msgstr "Kan ikke laste TileSet for sammenslåing!"
#: editor/editor_node.cpp
msgid "Error saving TileSet!"
-msgstr "Error ved lagring av TileSet!"
+msgstr "Feil ved lagring av TileSet!"
#: editor/editor_node.cpp
msgid ""
@@ -2619,7 +2584,7 @@ msgstr "Ja"
#: editor/editor_node.cpp
msgid "Exit the editor?"
-msgstr "Avslutt editoren?"
+msgstr "Avslutt redigeringsverktøyet?"
#: editor/editor_node.cpp
msgid "Open Project Manager?"
@@ -2666,7 +2631,8 @@ msgstr ""
"mislyktes."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr "Kunne ikke finne skriptfelt for addon-plugin i: 'res://addons/%s'."
#: editor/editor_node.cpp
@@ -2685,7 +2651,8 @@ msgstr ""
msgid ""
"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
-"Kan ikke laste addon skript fra bane: Basistype '%s' er ikke en EditorPlugin."
+"Kan ikke laste addon-skript fra stien: Basistypen '%s' er ikke en "
+"EditorPlugin."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
@@ -2923,7 +2890,7 @@ msgstr "Versjon:"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Set Up Version Control"
-msgstr ""
+msgstr "Sett opp versjonskontroll"
#: editor/editor_node.cpp
msgid "Shut Down Version Control"
@@ -2939,9 +2906,8 @@ msgid "Install Android Build Template..."
msgstr ""
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Project Data Folder"
-msgstr "Åpne ProsjektManager?"
+msgstr "Åpne prosjektdatamappe"
#: editor/editor_node.cpp editor/plugins/tile_set_editor_plugin.cpp
msgid "Tools"
@@ -3028,17 +2994,16 @@ msgid "Synchronize Scene Changes"
msgstr "Synkroniser Sceneendringer"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, any changes made to the scene in the editor "
"will be replicated in the running project.\n"
"When used remotely on a device, this is more efficient when the network "
"filesystem option is enabled."
msgstr ""
-"Når denne innstillingen er aktivert, alle endringer gjort til scenen i "
-"editoren vil bli replikert i det kjørende spillet.\n"
-"Når det brukes eksternt på en enhet, dette er mer effektivt med et "
-"nettverksfilsystem."
+"Når denne innstillingen er aktivert, vil alle endringer gjort i scenen i "
+"redigeringsverktøyet bli gjenspeilet i det kjørende spillet.\n"
+"Når det brukes eksternt på en enhet, er dette mer effektivt med et "
+"nettverksfilsystem aktivert."
#: editor/editor_node.cpp
#, fuzzy
@@ -3115,14 +3080,6 @@ msgid "Help"
msgstr "Hjelp"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Søk"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Online Dokumentasjon"
@@ -3196,9 +3153,8 @@ msgid "Save & Restart"
msgstr "Lagre & Avslutt"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Spins when the editor window redraws."
-msgstr "Snurrer når editorvinduet rendrer om!"
+msgstr "Snurrer når redigeringsvinduet tegner opp på nytt."
#: editor/editor_node.cpp
#, fuzzy
@@ -3286,13 +3242,31 @@ msgid "Open & Run a Script"
msgstr "Åpne & Kjør et Skript"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Følgende filer er nyere på disken.\n"
+"Hvilken handling skal utføres?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Gjeninnlat"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Lagre på nytt"
+
+#: editor/editor_node.cpp
#, fuzzy
msgid "New Inherited"
msgstr "Ny Arvet"
#: editor/editor_node.cpp
msgid "Load Errors"
-msgstr "Last Errors"
+msgstr "Last feil"
#: editor/editor_node.cpp editor/plugins/tile_map_editor_plugin.cpp
msgid "Select"
@@ -3300,11 +3274,11 @@ msgstr "Velg"
#: editor/editor_node.cpp
msgid "Open 2D Editor"
-msgstr "Åpne 2D Editor"
+msgstr "Åpne 2D-redigeringsverktøy"
#: editor/editor_node.cpp
msgid "Open 3D Editor"
-msgstr "Åpne 3D Editor"
+msgstr "Åpne 3D-redigeringsverktøy"
#: editor/editor_node.cpp
msgid "Open Script Editor"
@@ -3316,16 +3290,15 @@ msgstr "Åpne Assets-Bibliotek"
#: editor/editor_node.cpp
msgid "Open the next Editor"
-msgstr "Åpne den neste Editoren"
+msgstr "Åpne det neste redigeringsverktøyet"
#: editor/editor_node.cpp
msgid "Open the previous Editor"
-msgstr "Åpne den forrige Editoren"
+msgstr "Åpne det forrige redigeringsverktøy"
#: editor/editor_node.h
-#, fuzzy
msgid "Warning!"
-msgstr "Advarsler"
+msgstr "Advarsel!"
#: editor/editor_path.cpp
#, fuzzy
@@ -3389,9 +3362,8 @@ msgid "Average Time (sec)"
msgstr "Gjennomsnittstid (sek)"
#: editor/editor_profiler.cpp
-#, fuzzy
msgid "Frame %"
-msgstr "Frame %"
+msgstr "Bilde %"
#: editor/editor_profiler.cpp
msgid "Physics Frame %"
@@ -3406,9 +3378,8 @@ msgid "Self"
msgstr "Selv"
#: editor/editor_profiler.cpp
-#, fuzzy
msgid "Frame #:"
-msgstr "Frame #:"
+msgstr "Bilde #:"
#: editor/editor_profiler.cpp
#, fuzzy
@@ -3506,7 +3477,7 @@ msgstr "Gjør Unik"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Lim inn"
@@ -3585,7 +3556,7 @@ msgstr ""
#: editor/editor_sub_scene.cpp
msgid "Select Node(s) to Import"
-msgstr "Velg Node(r) for Importering"
+msgstr "Velg node(r) som skal importeres"
#: editor/editor_sub_scene.cpp editor/project_manager.cpp
#, fuzzy
@@ -3635,9 +3606,8 @@ msgid "Retrieving mirrors, please wait..."
msgstr "Henter fillager, vennligst vent..."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Remove template version '%s'?"
-msgstr "Fjern mal versjon '%s'?"
+msgstr "Fjern malversjon '%s'?"
#: editor/export_template_manager.cpp
msgid "Can't open export templates zip."
@@ -3653,9 +3623,8 @@ msgid "No version.txt found inside templates."
msgstr "Ingen version.txt funnet i mal."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error creating path for templates:"
-msgstr "Feil ved laging av sti for mal:\n"
+msgstr "Feil ved laging av sti for maler:"
#: editor/export_template_manager.cpp
msgid "Extracting Export Templates"
@@ -3840,14 +3809,12 @@ msgid "Cannot move/rename resources root."
msgstr "Kan ikke flytte/endre navn ressursrot"
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "Cannot move a folder into itself."
-msgstr "Kan ikke flytte mappe inn i seg selv.\n"
+msgstr "Kan ikke flytte en mappe inn i seg selv."
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "Error moving:"
-msgstr "Error ved flytting:\n"
+msgstr "Feil ved flytting:"
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -3855,9 +3822,8 @@ msgid "Error duplicating:"
msgstr "Feil ved innlasting:"
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "Unable to update dependencies:"
-msgstr "Kan ikke oppdatere av avhengigheter:\n"
+msgstr "Kan ikke oppdatere avhengigheter:"
#: editor/filesystem_dock.cpp editor/scene_tree_editor.cpp
msgid "No name provided."
@@ -4123,9 +4089,8 @@ msgid "Remove from Group"
msgstr "Fjern fra Gruppe"
#: editor/groups_editor.cpp
-#, fuzzy
msgid "Group name already exists."
-msgstr "ERROR: Animasjonsnavnet finnes allerede!"
+msgstr "Gruppenavnet finnes allerede."
#: editor/groups_editor.cpp
#, fuzzy
@@ -4167,9 +4132,8 @@ msgid "Empty groups will be automatically removed."
msgstr ""
#: editor/groups_editor.cpp
-#, fuzzy
msgid "Group Editor"
-msgstr "Åpne SkriptEditor"
+msgstr "Redigeringsverktøy for grupper"
#: editor/groups_editor.cpp
#, fuzzy
@@ -4227,7 +4191,7 @@ msgstr "Importerer Scene..."
#: editor/import/resource_importer_scene.cpp
msgid "Generating Lightmaps"
-msgstr "Genererer Lyskart"
+msgstr "Genererer lyskart"
#: editor/import/resource_importer_scene.cpp
msgid "Generating for Mesh: "
@@ -4248,7 +4212,7 @@ msgstr "Ugyldig/ødelagt skript for post-import (sjekk konsoll):"
#: editor/import/resource_importer_scene.cpp
msgid "Error running post-import script:"
-msgstr "Error ved kjøring av post-import script:"
+msgstr "Feil ved kjøring av post-import script:"
#: editor/import/resource_importer_scene.cpp
msgid "Did you return a Node-derived object in the `post_import()` method?"
@@ -4258,6 +4222,21 @@ msgstr ""
msgid "Saving..."
msgstr "Lagrer..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Velg Modus"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importer"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Last Standard"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Filer"
@@ -4324,9 +4303,8 @@ msgid "Copy Params"
msgstr "Kopier Parametre"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Edit Resource Clipboard"
-msgstr "Ressurs-utklippstavle er tom!"
+msgstr "Rediger ressurs-utklippstavlen"
#: editor/inspector_dock.cpp
msgid "Copy Resource"
@@ -4437,16 +4415,14 @@ msgid "Create points."
msgstr "Slett punkter"
#: editor/plugins/abstract_polygon_2d_editor.cpp
-#, fuzzy
msgid ""
"Edit points.\n"
"LMB: Move Point\n"
"RMB: Erase Point"
msgstr ""
-"Endre eksisterende polygon:\n"
-"Venstreklikk: Flytt Punkt.\n"
-"Ctrl+Venstreklikk: Splitt Segment.\n"
-"Høyreklikk: Fjern Punkt."
+"Rediger punkter.\n"
+"Venstreklikk: Flytt punkt\n"
+"Høyreklikk: Fjern punkt"
#: editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/animation_blend_space_1d_editor.cpp
@@ -4461,7 +4437,7 @@ msgstr "Rediger Poly"
#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid "Insert Point"
-msgstr "Sett inn Punkt"
+msgstr "Sett inn punkt"
#: editor/plugins/abstract_polygon_2d_editor.cpp
#, fuzzy
@@ -4578,9 +4554,8 @@ msgid "Open Animation Node"
msgstr "Animasjonsnode"
#: editor/plugins/animation_blend_space_2d_editor.cpp
-#, fuzzy
msgid "Triangle already exists."
-msgstr "ERROR: Animasjonsnavnet finnes allerede!"
+msgstr "Triangelet finnes allerede."
#: editor/plugins/animation_blend_space_2d_editor.cpp
#, fuzzy
@@ -4782,14 +4757,12 @@ msgid "Remove Animation"
msgstr "Fjern Animasjon"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Invalid animation name!"
-msgstr "ERROR: Ugyldig animasjonsnavn!"
+msgstr "Ugyldig animasjonsnavn!"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Animation name already exists!"
-msgstr "ERROR: Animasjonsnavnet finnes allerede!"
+msgstr "Animasjonsnavnet finnes allerede!"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
@@ -4814,14 +4787,12 @@ msgid "Duplicate Animation"
msgstr "Dupliser Animasjon"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "No animation to copy!"
-msgstr "ERROR: Ingen animasjon å kopiere!"
+msgstr "Ingen animasjon å kopiere!"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "No animation resource on clipboard!"
-msgstr "ERROR: Ingen animasjonsressurs på utklippstavlen!"
+msgstr "Ingen animasjonsressurs på utklippstavlen!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Pasted Animation"
@@ -4832,9 +4803,8 @@ msgid "Paste Animation"
msgstr "Lim inn Animasjon"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "No animation to edit!"
-msgstr "ERROR: Ingen animasjon å endre!"
+msgstr "Ingen animasjon å redigere!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation backwards from current pos. (A)"
@@ -4958,7 +4928,7 @@ msgstr "Animasjonsnavn:"
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
msgid "Error!"
-msgstr "Error!"
+msgstr "Feil!"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Blend Times:"
@@ -4980,9 +4950,8 @@ msgid "Move Node"
msgstr "Flytt Modus"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "Overgang"
+msgstr "Overgang eksisterer!"
#: editor/plugins/animation_state_machine_editor.cpp
#, fuzzy
@@ -4992,7 +4961,7 @@ msgstr "Overgang"
#: editor/plugins/animation_state_machine_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "Add Node"
-msgstr ""
+msgstr "Legg til node"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "End"
@@ -5298,10 +5267,12 @@ msgid "Got:"
msgstr "Fikk:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "Feilet sha256 hash-sjekk"
#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
msgid "Asset Download Error:"
msgstr "Asset Nedlasting Error:"
@@ -5339,7 +5310,7 @@ msgstr "Prøv på nytt"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Download Error"
-msgstr "Nedlastningserror"
+msgstr "Nedlastningsfeil"
#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
@@ -5413,7 +5384,6 @@ msgid "Sort:"
msgstr "Sorter:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategori:"
@@ -6015,7 +5985,7 @@ msgstr "Plasser Utvalg I Midten"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Frame Selection"
-msgstr ""
+msgstr "Bildeutvalg"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Preview Canvas Scale"
@@ -6101,7 +6071,7 @@ msgstr "Lag Node"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
-msgstr "Error ved instansiering av scene fra %s"
+msgstr "Feil ved instansiering av scene fra %s"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -6127,7 +6097,7 @@ msgstr "Rediger Poly"
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Edit Poly (Remove Point)"
-msgstr "Rediger Poly (Fjern Punkt)"
+msgstr "Rediger Poly (fjern punkt)"
#: editor/plugins/collision_shape_2d_editor_plugin.cpp
#, fuzzy
@@ -6487,11 +6457,12 @@ msgid "Remove item %d?"
msgstr "Fjern element %d?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "Oppdater fra Scene"
+msgstr ""
+"Oppdater fra eksisterende scene?:\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
#, fuzzy
@@ -6904,9 +6875,8 @@ msgid "Paint Bone Weights"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Open Polygon 2D UV editor."
-msgstr "Åpne 2D Editor"
+msgstr "Åpne 2D-redigeringsverktøy for polygon-UV"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon 2D UV Editor"
@@ -7058,7 +7028,7 @@ msgstr "Skaler Polygon"
#: editor/plugins/resource_preloader_editor_plugin.cpp
msgid "ERROR: Couldn't load resource!"
-msgstr "ERROR: Kunne ikke laste ressurs!"
+msgstr "FEIL: Kunne ikke laste ressurs!"
#: editor/plugins/resource_preloader_editor_plugin.cpp
msgid "Add Resource"
@@ -7121,16 +7091,12 @@ msgid "Clear Recent Files"
msgstr "Fjern Nylige Filer"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Close and save changes?"
-msgstr ""
-"Lukk og lagre endringer?\n"
-"\""
+msgstr "Lukke og lagre endringer?"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Error writing TextFile:"
-msgstr "Error ved lagring av TileSet!"
+msgstr "Feil ved lagring av TextFile:"
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
@@ -7138,29 +7104,24 @@ msgid "Could not load file at:"
msgstr "Kunne ikke opprette mappe."
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Error saving file!"
-msgstr "Error ved lagring av TileSet!"
+msgstr "Feil ved lagring av filen!"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Error while saving theme."
-msgstr "Error ved lasting av tema"
+msgstr "Feil ved lagring av tema"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Error Saving"
-msgstr "Error ved lagring"
+msgstr "Feil ved lagring"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Error importing theme."
-msgstr "Error ved importering av tema"
+msgstr "Feil ved importering av tema."
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Error Importing"
-msgstr "Error ved importering"
+msgstr "Feil ved importering"
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
@@ -7200,11 +7161,11 @@ msgstr "Importer Tema"
#: editor/plugins/script_editor_plugin.cpp
msgid "Error while saving theme"
-msgstr "Error ved lasting av tema"
+msgstr "Feil ved lagring av tema"
#: editor/plugins/script_editor_plugin.cpp
msgid "Error saving"
-msgstr "Error ved lagring"
+msgstr "Feil ved lagring"
#: editor/plugins/script_editor_plugin.cpp
msgid "Save Theme As..."
@@ -7328,6 +7289,14 @@ msgstr "Lukk Dokumentasjon"
msgid "Run"
msgstr "Kjør"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Søk"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Tre inn i"
@@ -7381,16 +7350,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Gjeninnlat"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Lagre på nytt"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Feilsøking"
@@ -7491,8 +7450,8 @@ msgstr "Slett punkter"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Klipp ut"
@@ -7732,6 +7691,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Størrelse"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -8890,11 +8853,12 @@ msgid "Delete selected Rect."
msgstr "Slett valgte filer?"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid ""
"Select current edited sub-tile.\n"
"Click on another Tile to edit it."
-msgstr "Velg Gjeldende Mappe"
+msgstr ""
+"Velg gjeldende redigerte underflis.\n"
+"Klikk på en annen flis for å redigere den."
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
@@ -8902,13 +8866,16 @@ msgid "Delete polygon."
msgstr "Slett punkter"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid ""
"LMB: Set bit on.\n"
"RMB: Set bit off.\n"
"Shift+LMB: Set wildcard bit.\n"
"Click on another Tile to edit it."
-msgstr "Velg Gjeldende Mappe"
+msgstr ""
+"Venstreklikk: Sett bit på.\n"
+"Høyreklikk: Sett bit av.\n"
+"Skift+venstreklikk: Sett jokertegn-bit.\n"
+"Klikk på en annen flis for å redigere den."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid ""
@@ -8924,11 +8891,12 @@ msgid ""
msgstr ""
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid ""
"Select sub-tile to change its z index.\n"
"Click on another Tile to edit it."
-msgstr "Velg Gjeldende Mappe"
+msgstr ""
+"Velg underflis for å endre z-indeksen.\n"
+"Klikk på en annen flis for å redigere den."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Set Tile Region"
@@ -10129,9 +10097,8 @@ msgid "Export Project"
msgstr "Eksporter Prosjekt"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export mode?"
-msgstr "Eksporter Prosjekt"
+msgstr "Eksportmodus?"
#: editor/project_export.cpp
#, fuzzy
@@ -10221,8 +10188,8 @@ msgid ""
"Couldn't load project.godot in project path (error %d). It may be missing or "
"corrupted."
msgstr ""
-"Kunne ikke laste project.godot i prosjekt sti (error %d). Den kan være "
-"manglet eller korruptert."
+"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."
@@ -10393,25 +10360,28 @@ msgid "Are you sure to run %d projects at once?"
msgstr "Er du sikker på at du vil kjøre mer enn ett prosjekt?"
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Remove %d projects from the list?\n"
"The project folders' contents won't be modified."
-msgstr "Fjern prosjekt fra listen? (Mappeinnhold vil ikke bli modifisert)"
+msgstr ""
+"Fjern %s prosjekter fra listen?\n"
+"Innhold i prosjektmappene vil ikke påvirkes."
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Remove this project from the list?\n"
"The project folder's contents won't be modified."
-msgstr "Fjern prosjekt fra listen? (Mappeinnhold vil ikke bli modifisert)"
+msgstr ""
+"Fjern dette prosjektet fra listen?\n"
+"Innhold i prosjektmappen vil ikke påvirkes."
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Remove all missing projects from the list?\n"
"The project folders' contents won't be modified."
-msgstr "Fjern prosjekt fra listen? (Mappeinnhold vil ikke bli modifisert)"
+msgstr ""
+"Fjern alle manglende prosjekter fra listen?\n"
+"Innhold i prosjektmappene vil ikke påvirkes."
#: editor/project_manager.cpp
msgid ""
@@ -10438,6 +10408,11 @@ msgid "Projects"
msgstr "Prosjekter"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Henter fillager, vennligst vent..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10506,9 +10481,8 @@ msgid ""
msgstr ""
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "An action with the name '%s' already exists."
-msgstr "ERROR: Animasjonsnavnet finnes allerede!"
+msgstr "En handling med navnet '%s' finnes allerede."
#: editor/project_settings_editor.cpp
msgid "Rename Input Action Event"
@@ -10809,10 +10783,14 @@ msgstr ""
msgid "Plugins"
msgstr "Innstikkmoduler"
-#: editor/property_editor.cpp
+#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Import Defaults"
+msgstr "Last Standard"
+
+#: editor/property_editor.cpp
msgid "Preset..."
-msgstr "Preset..."
+msgstr "Forhåndsinnstilt..."
#: editor/property_editor.cpp
msgid "Zero"
@@ -10873,9 +10851,8 @@ msgid "Batch Rename"
msgstr "Endre navn"
#: editor/rename_dialog.cpp
-#, fuzzy
msgid "Replace:"
-msgstr "Erstatt: "
+msgstr "Erstatt:"
#: editor/rename_dialog.cpp
msgid "Prefix:"
@@ -10914,9 +10891,8 @@ msgid "Node type"
msgstr "Finn Node Type"
#: editor/rename_dialog.cpp
-#, fuzzy
msgid "Current scene name"
-msgstr "Gjeldende scene er ikke lagret. Åpne likevel?"
+msgstr "Navn på gjeldende scene"
#: editor/rename_dialog.cpp
#, fuzzy
@@ -11068,6 +11044,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Lim inn Noder"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Nytt Skript"
@@ -11106,14 +11091,12 @@ msgid "Make node as Root"
msgstr "Lagre Scene"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Delete %d nodes and any children?"
-msgstr "Kutt Noder"
+msgstr "Slett %d noder og eventuelle barn?"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Delete %d nodes?"
-msgstr "Kutt Noder"
+msgstr "Slett %d noder?"
#: editor/scene_tree_dock.cpp
msgid "Delete the root node \"%s\"?"
@@ -11124,9 +11107,8 @@ msgid "Delete node \"%s\" and its children?"
msgstr ""
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Delete node \"%s\"?"
-msgstr "Kutt Noder"
+msgstr "Slett noden \"%s\"?"
#: editor/scene_tree_dock.cpp
msgid "Can not perform with the root node."
@@ -11197,6 +11179,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Kutt Noder"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11413,19 +11400,16 @@ msgid "Select a Node"
msgstr ""
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Path is empty."
-msgstr "Ressurs-utklippstavle er tom!"
+msgstr "Stien er tom."
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Filename is empty."
-msgstr "Ressurs-utklippstavle er tom!"
+msgstr "Filnavnet er tomt."
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Path is not local."
-msgstr "Sti leder ikke Node!"
+msgstr "Stien er ikke lokal."
#: editor/script_create_dialog.cpp
#, fuzzy
@@ -11472,9 +11456,8 @@ msgid "N/A"
msgstr ""
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Open Script / Choose Location"
-msgstr "Åpne SkriptEditor"
+msgstr "Åpne skript / Velg plassering"
#: editor/script_create_dialog.cpp
#, fuzzy
@@ -11569,19 +11552,16 @@ msgid "Warning:"
msgstr "Advarsler:"
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "Error:"
-msgstr "Error!"
+msgstr "Feil:"
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "C++ Error"
-msgstr "Last Errors"
+msgstr "C++-feil"
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "C++ Error:"
-msgstr "Last Errors"
+msgstr "C++-feil:"
#: editor/script_editor_debugger.cpp
#, fuzzy
@@ -11612,9 +11592,8 @@ msgid "Child process connected."
msgstr "Frakoblet"
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "Copy Error"
-msgstr "Last Errors"
+msgstr "Kopier feil"
#: editor/script_editor_debugger.cpp
msgid "Video RAM"
@@ -11879,7 +11858,7 @@ msgstr ""
#: modules/gdscript/gdscript_functions.cpp
msgid "Not a script with an instance"
-msgstr ""
+msgstr "Ikke et skript med en instans"
#: modules/gdscript/gdscript_functions.cpp
msgid "Not based on a script"
@@ -12245,25 +12224,24 @@ msgid "Name is not a valid identifier:"
msgstr "Navn er ikke en gyldig identifikator:"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Name already in use by another func/var/signal:"
-msgstr "Navn er allerede i bruk av en annen func/var/signal:"
+msgstr "Navnet er allerede i bruk av annen funk/var/signal:"
#: modules/visual_script/visual_script_editor.cpp
msgid "Rename Function"
-msgstr ""
+msgstr "Endre navn på funksjonen"
#: modules/visual_script/visual_script_editor.cpp
msgid "Rename Variable"
-msgstr ""
+msgstr "Endre navn på variabelen"
#: modules/visual_script/visual_script_editor.cpp
msgid "Rename Signal"
-msgstr ""
+msgstr "Endre navn på signalet"
#: modules/visual_script/visual_script_editor.cpp
msgid "Add Function"
-msgstr ""
+msgstr "Legg til funksjon"
#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
@@ -12272,11 +12250,11 @@ msgstr "Fjern punkt"
#: modules/visual_script/visual_script_editor.cpp
msgid "Add Variable"
-msgstr ""
+msgstr "Legg til variabel"
#: modules/visual_script/visual_script_editor.cpp
msgid "Add Signal"
-msgstr ""
+msgstr "Legg til signal"
#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
@@ -12290,7 +12268,7 @@ msgstr "Fjern punkt"
#: modules/visual_script/visual_script_editor.cpp
msgid "Change Expression"
-msgstr ""
+msgstr "Endre uttrykk"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove VisualScript Nodes"
@@ -12310,6 +12288,8 @@ msgstr ""
#: modules/visual_script/visual_script_editor.cpp
msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature."
msgstr ""
+"Hold Ctrl for å slippe en Getter. Hold Skift for å slippe en generisk "
+"signatur."
#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
@@ -12318,7 +12298,7 @@ msgstr "Hold Meta for å slippe en enkel referanse til noden."
#: modules/visual_script/visual_script_editor.cpp
msgid "Hold Ctrl to drop a simple reference to the node."
-msgstr "Hold Ctrl for å slippe en simpel referanse til noden."
+msgstr "Hold Ctrl for å slippe en enkel referanse til noden."
#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
@@ -12438,19 +12418,19 @@ msgstr "Fjern Funksjon"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Variable"
-msgstr ""
+msgstr "Fjern variabel"
#: modules/visual_script/visual_script_editor.cpp
msgid "Editing Variable:"
-msgstr ""
+msgstr "Redigerer variabel:"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Signal"
-msgstr ""
+msgstr "Fjern signal"
#: modules/visual_script/visual_script_editor.cpp
msgid "Editing Signal:"
-msgstr ""
+msgstr "Redigerer signal:"
#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
@@ -12544,7 +12524,7 @@ msgstr "Sti leder ikke Node!"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Invalid index property name '%s' in node %s."
-msgstr "Ugyldig indeks egenskap navn '%s' i node %s."
+msgstr "Ugyldig navn for indeksegenskap '%s' i noden %s."
#: modules/visual_script/visual_script_nodes.cpp
msgid ": Invalid argument of type: "
@@ -12894,6 +12874,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -13082,9 +13070,8 @@ msgid "Saving lightmaps"
msgstr "Genererer Lyskart"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Done"
-msgstr "Ferdig!"
+msgstr "Ferdig"
#: scene/3d/collision_object.cpp
msgid ""
@@ -13152,11 +13139,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13286,9 +13268,8 @@ msgid "In node '%s', invalid animation: '%s'."
msgstr ""
#: scene/animation/animation_tree.cpp
-#, fuzzy
msgid "Invalid animation: '%s'."
-msgstr "ERROR: Ugyldig animasjonsnavn!"
+msgstr "Ugyldig animasjon: '%s'."
#: scene/animation/animation_tree.cpp
#, fuzzy
diff --git a/editor/translations/nl.po b/editor/translations/nl.po
index 22b3202945..52c63ffa85 100644
--- a/editor/translations/nl.po
+++ b/editor/translations/nl.po
@@ -28,7 +28,7 @@
# rxadmin <r.van.eeghem@gmail.com>, 2018.
# Peter Goelst <muis24@gmail.com>, 2019.
# Wouter Buckens <wou.buc@gmail.com>, 2019.
-# Stijn Hinlopen <f.a.hinlopen@gmail.com>, 2019, 2020.
+# Stijn Hinlopen <f.a.hinlopen@gmail.com>, 2019, 2020, 2021.
# jef dered <themen098s@vivaldi.net>, 2019.
# Alex H. <sandertjeh13@hotmail.com>, 2019.
# edouardgr <edouard.gruyters@gmail.com>, 2019.
@@ -47,7 +47,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-12-25 12:29+0000\n"
+"PO-Revision-Date: 2021-02-05 23:44+0000\n"
"Last-Translator: Stijn Hinlopen <f.a.hinlopen@gmail.com>\n"
"Language-Team: Dutch <https://hosted.weblate.org/projects/godot-engine/godot/"
"nl/>\n"
@@ -56,7 +56,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.4.1-dev\n"
+"X-Generator: Weblate 4.5-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -686,7 +686,7 @@ msgstr "Selecteer sporen om te kopieren"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopiëren"
@@ -1703,7 +1703,7 @@ msgstr "Script Editor"
#: editor/editor_feature_profile.cpp
msgid "Asset Library"
-msgstr "Asset bibliotheek"
+msgstr "Materiaalbibliotheek"
#: editor/editor_feature_profile.cpp
msgid "Scene Tree Editing"
@@ -1899,8 +1899,8 @@ msgid "Open a File or Directory"
msgstr "Bestand of map openen"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Opslaan"
@@ -2430,7 +2430,7 @@ msgstr "Er is geen startscène ingesteld."
#: editor/editor_node.cpp
msgid "Save scene before running..."
-msgstr ""
+msgstr "Scène opslaan voor het afspelen..."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -2577,7 +2577,8 @@ msgstr ""
"mislukt."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"Onmogelijk om scriptveld te vinden voor de plugin op: 'res://addons/%s'."
@@ -2901,7 +2902,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Visible Collision Shapes"
-msgstr "Toon collision shapes"
+msgstr "Botsingsvormen tonen"
#: editor/editor_node.cpp
#, fuzzy
@@ -3011,14 +3012,6 @@ msgid "Help"
msgstr "Help"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Zoeken"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Online Documentatie"
@@ -3185,6 +3178,25 @@ msgid "Open & Run a Script"
msgstr "Voer Een Script Uit"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"De volgende bestanden zijn nieuwer op de schijf.\n"
+"Welke aktie moet worden genomen?:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Herladen"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Heropslaan"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Nieuw afgeleid type"
@@ -3210,7 +3222,7 @@ msgstr "Open Script Bewerker"
#: editor/editor_node.cpp editor/project_manager.cpp
msgid "Open Asset Library"
-msgstr "Open Asset Bibliotheek"
+msgstr "Open Materiaalbibliotheek"
#: editor/editor_node.cpp
msgid "Open the next Editor"
@@ -3396,7 +3408,7 @@ msgstr "Maak Uniek"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Plakken"
@@ -3758,6 +3770,11 @@ msgid ""
"\n"
"Do you wish to overwrite them?"
msgstr ""
+"De volgende bestanden of mappen conflicteren met elementen in '%s':\n"
+"\n"
+"%s\n"
+"\n"
+"Wil je deze overschrijven?"
#: editor/filesystem_dock.cpp
msgid "Renaming file:"
@@ -3950,19 +3967,16 @@ msgid "Searching..."
msgstr "Aan het zoeken..."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d match in %d file."
-msgstr "%d overeenkomst(en) gevonden."
+msgstr "%d overeenkomst in %d bestand."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d matches in %d file."
-msgstr "%d overeenkomst(en) gevonden."
+msgstr "%d overeenkomsten in %d bestand."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "%d matches in %d files."
-msgstr "%d overeenkomst(en) gevonden."
+msgstr "%d overeenkomsten in %d bestanden."
#: editor/groups_editor.cpp
msgid "Add to Group"
@@ -4099,6 +4113,21 @@ msgstr ""
msgid "Saving..."
msgstr "Opslaan..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Selecteermodus"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importeren"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Laad standaard"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Bestanden"
@@ -5066,7 +5095,8 @@ msgid "Got:"
msgstr "Gekregen:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "SHA256-proef mislukt"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5170,7 +5200,6 @@ msgid "Sort:"
msgstr "Sorteren op:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Categorie:"
@@ -5242,9 +5271,8 @@ msgid "Bake Lightmaps"
msgstr "Bak Lichtmappen"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid "Select lightmap bake file:"
-msgstr "Selecteer sjabloonbestand"
+msgstr "Selecteer lightmap bake-bestand"
#: editor/plugins/camera_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -5313,7 +5341,7 @@ msgstr "Maak nieuwe horizontale en verticale gidsen"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Set CanvasItem \"%s\" Pivot Offset to (%d, %d)"
-msgstr ""
+msgstr "Draaipuntverschuiving van het CanvasItem „%s“ op (%d, %d) zetten"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Rotate %d CanvasItems"
@@ -5336,24 +5364,20 @@ msgid "Resize Control \"%s\" to (%d, %d)"
msgstr "Control \"%s\" vergrootten tot (%d, %d)"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Scale %d CanvasItems"
-msgstr "Schaal CanvasItem"
+msgstr "Schaal %d CanvasItems"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Scale CanvasItem \"%s\" to (%s, %s)"
-msgstr "Schaal CanvasItem"
+msgstr "Schaal CanvasItem \"%s\" naar (%s, %s)"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Move %d CanvasItems"
-msgstr "Verplaats CanvasItem"
+msgstr "Verplaats %d CanvasItems"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Move CanvasItem \"%s\" to (%d, %d)"
-msgstr "Verplaats CanvasItem"
+msgstr "CanvasItem \"%s\" naar (%d, %d) verplaatsen"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid ""
@@ -6347,9 +6371,8 @@ msgid "Can only set point into a ParticlesMaterial process material"
msgstr "Kan punt alleen plaatsen in een PartikelsMateriaal proces materiaal"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Convert to CPUParticles2D"
-msgstr "Zet om in CPUParticles"
+msgstr "Omzetten naar CPUParticles2D"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
@@ -6640,9 +6663,8 @@ msgid "Move Points"
msgstr "Beweeg Punten"
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Command: Rotate"
-msgstr "Sleep: Roteer"
+msgstr "Ctrl: Roteer"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Shift: Move All"
@@ -6700,14 +6722,12 @@ msgid "Radius:"
msgstr "Radius:"
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Copy Polygon to UV"
-msgstr "Creëer Polygon & UV"
+msgstr "Kopieer Polygon naar UV"
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Copy UV to Polygon"
-msgstr "Naar Polygon2D omzetten"
+msgstr "Kopieer UV naar Polygon2D"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Clear UV"
@@ -7009,6 +7029,14 @@ msgstr "Sluit Docs"
msgid "Run"
msgstr "Uitvoeren"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Zoeken"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Stap In"
@@ -7062,16 +7090,6 @@ msgstr ""
"De volgende bestanden zijn nieuwer op de schijf.\n"
"Welke aktie moet worden genomen?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Herladen"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Heropslaan"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Debugger"
@@ -7165,8 +7183,8 @@ msgstr "Breekpunten"
msgid "Go To"
msgstr "Ga Naar"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Knippen"
@@ -7389,6 +7407,11 @@ msgid "Yaw"
msgstr "Yaw"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "Grootte: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Objecten Getekend"
@@ -7801,7 +7824,7 @@ msgstr "Polygon2D Voorbeeldweergave"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
-msgstr "Creëer CollisionPolygon2D"
+msgstr "CollisionPolygon2D aanmaken"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "CollisionPolygon2D Preview"
@@ -7843,11 +7866,11 @@ msgstr "Naar Polygon2D omzetten"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create collision polygon."
-msgstr "Ongeldige geometrie, kan geen collision polygoon creëren."
+msgstr "Ongeldige geometrie, kan geen botsingspolygoon aanmaken."
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D Sibling"
-msgstr "Creëer CollisionPolygon2D Sibling"
+msgstr "CollisionPolygon2D aanmaken"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create light occluder."
@@ -8253,13 +8276,12 @@ msgid "Paint Tile"
msgstr "Teken Tegel"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid ""
"Shift+LMB: Line Draw\n"
"Shift+Command+LMB: Rectangle Paint"
msgstr ""
-"Shift+LMB: Lijn Tekenen\n"
-"Shift+Ctrl+LMB: Vierkant Tekenen"
+"Shift+LMB: Lijn tekenen\n"
+"Shift+Ctrl+LMB: Vierkant tekenen"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid ""
@@ -8414,23 +8436,20 @@ msgid "Create a new rectangle."
msgstr "Creëer nieuwe driehoek."
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "New Rectangle"
-msgstr "Teken Driehoek"
+msgstr "Nieuwe rechthoek"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create a new polygon."
msgstr "Nieuwe veelhoek aanmaken."
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "New Polygon"
-msgstr "Beweeg Polygon"
+msgstr "Nieuwe veelhoek"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Delete Selected Shape"
-msgstr "Geselecteerde Verwijderen"
+msgstr "Geselecteerde vormen verwijderen"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Keep polygon inside region Rect."
@@ -8557,7 +8576,7 @@ msgstr "Tegelbitmasker bewerken"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Edit Collision Polygon"
-msgstr "Bewerk Collision Polygon"
+msgstr "Botsingspolygoon aanpassen"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Edit Occlusion Polygon"
@@ -8589,7 +8608,7 @@ msgstr "Verwijder Tile"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Remove Collision Polygon"
-msgstr "Verwijder Collision Polygon"
+msgstr "Botsingsvorm verwijderen"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Remove Occlusion Polygon"
@@ -8617,7 +8636,7 @@ msgstr "Maak concaaf"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
-msgstr "Creëer Collision Polygon"
+msgstr "Botsingsvorm aanmaken"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Occlusion Polygon"
@@ -8795,9 +8814,8 @@ msgid "Add Node to Visual Shader"
msgstr "VisualShader-knoop toevoegen"
#: editor/plugins/visual_shader_editor_plugin.cpp
-#, fuzzy
msgid "Node(s) Moved"
-msgstr "Knoop verplaatst"
+msgstr "Knoop/knopen verplaatst"
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Duplicate Nodes"
@@ -8817,9 +8835,8 @@ msgid "Visual Shader Input Type Changed"
msgstr "Visuele Shader Invoertype Gewijzigd"
#: editor/plugins/visual_shader_editor_plugin.cpp
-#, fuzzy
msgid "UniformRef Name Changed"
-msgstr "Uniforme naam instellen"
+msgstr "UniformRef naam veranderd"
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Vertex"
@@ -9547,7 +9564,7 @@ msgstr ""
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "A reference to an existing uniform."
-msgstr ""
+msgstr "Een verwijzing naar een bestaande uniform."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "(Fragment/Light mode only) Scalar derivative function."
@@ -9914,7 +9931,7 @@ msgstr "OpenGL ES 3.0"
#: editor/project_manager.cpp
msgid "Not supported by your GPU drivers."
-msgstr ""
+msgstr "Niet ondersteund door de GPU drivers op dit systeem."
#: editor/project_manager.cpp
msgid ""
@@ -10093,6 +10110,11 @@ msgid "Projects"
msgstr "Projecten"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Mirrors ophalen, even wachten a.u.b..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Laatst bewerkt"
@@ -10130,7 +10152,7 @@ msgid ""
"Would you like to explore official example projects in the Asset Library?"
msgstr ""
"U heeft momenteel geen projecten.\n"
-"Wilt u de officiële voorbeeldprojecten verkennen in de Asset Library?"
+"Wilt u officiële voorbeeldprojecten verkennen in de Materiaalbibliotheek?"
#: editor/project_manager.cpp
msgid ""
@@ -10463,6 +10485,11 @@ msgstr "Automatisch Laden"
msgid "Plugins"
msgstr "Plugins"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Laad standaard"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Voorinstelling..."
@@ -10524,19 +10551,16 @@ msgid "Batch Rename"
msgstr "Bulk hernoemen"
#: editor/rename_dialog.cpp
-#, fuzzy
msgid "Replace:"
-msgstr "Vervangen: "
+msgstr "Vervangen:"
#: editor/rename_dialog.cpp
-#, fuzzy
msgid "Prefix:"
-msgstr "Voorvoegsel"
+msgstr "Voorvoegsel:"
#: editor/rename_dialog.cpp
-#, fuzzy
msgid "Suffix:"
-msgstr "Achtervoegsel"
+msgstr "Achtervoegsel:"
#: editor/rename_dialog.cpp
msgid "Use Regular Expressions"
@@ -10583,11 +10607,10 @@ msgid "Per-level Counter"
msgstr "Per niveau teller"
#: editor/rename_dialog.cpp
-#, fuzzy
msgid "If set, the counter restarts for each group of child nodes."
msgstr ""
-"Indien ingesteld: herstart de teller voor iedere groep van onderliggende "
-"knopen"
+"Indien ingesteld, zal de teller voor iedere groep van onderliggende knopen "
+"opnieuw starten."
#: editor/rename_dialog.cpp
msgid "Initial value for the counter"
@@ -10646,9 +10669,8 @@ msgid "Reset"
msgstr "Resetten"
#: editor/rename_dialog.cpp
-#, fuzzy
msgid "Regular Expression Error:"
-msgstr "Fout in reguliere expressie"
+msgstr "Fout in reguliere expressie:"
#: editor/rename_dialog.cpp
msgid "At character %s"
@@ -10719,6 +10741,16 @@ msgid "Instance Child Scene"
msgstr "Scène instantiëren"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Can't paste root node into the same scene."
+msgstr "Kan deze operatie niet uitvoeren op knopen uit een vreemde scène!"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Knopen plakken"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Script losmaken"
@@ -10846,6 +10878,11 @@ msgid "Attach Script"
msgstr "Script toevoegen"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Knopen knippen"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Verwijder knoop/knopen"
@@ -11653,36 +11690,31 @@ msgstr "Voeg een MeshLibrary aan deze GridMap toe om meshes te gebruiken."
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Begin Bake"
-msgstr ""
+msgstr "Begin lichtberekening"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Preparing data structures"
-msgstr ""
+msgstr "Datastructuren worden voorbereid"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Generate buffers"
-msgstr "Genereer AABB"
+msgstr "Genereer buffers"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Direct lighting"
-msgstr "Richtingen"
+msgstr "Directe verlichting"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Indirect lighting"
-msgstr "Rechts Inspringen"
+msgstr "Indirecte verlichting"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Post processing"
-msgstr "Post-Process"
+msgstr "Nabewerking"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Plotting lightmaps"
-msgstr "Plotten Light:"
+msgstr "Lightmaps plotten"
#: modules/mono/csharp_script.cpp
msgid "Class name can't be a reserved keyword"
@@ -12202,7 +12234,7 @@ msgstr "Selecteer apparaat uit de lijst"
#: platform/android/export/export.cpp
msgid "Unable to find the 'apksigner' tool."
-msgstr ""
+msgstr "Het hulpmiddel 'apksigner' kon niet gevonden worden."
#: platform/android/export/export.cpp
msgid ""
@@ -12221,18 +12253,17 @@ msgid "Release keystore incorrectly configured in the export preset."
msgstr "Release-Keystore is verkeerd ingesteld in de exportinstelingen."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "A valid Android SDK path is required in Editor Settings."
-msgstr "Ongeldig Android SDK pad voor custom build in Editor Settings."
+msgstr ""
+"Een geldig Android SDK-pad moet in de Editorinstellingen ingesteld zijn."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Invalid Android SDK path in Editor Settings."
-msgstr "Ongeldig Android SDK pad voor custom build in Editor Settings."
+msgstr "Ongeldig Android SDK-pad in Editorinstellingen."
#: platform/android/export/export.cpp
msgid "Missing 'platform-tools' directory!"
-msgstr ""
+msgstr "'platform-tools' map ontbreekt!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK platform-tools' adb command."
@@ -12491,10 +12522,10 @@ msgid ""
"Consider adding a CollisionShape2D or CollisionPolygon2D as a child to "
"define its shape."
msgstr ""
-"Deze knoop heeft geen vorm (Shape), dus kan het niet met andere objecten "
-"botsen of interactie hebben.\n"
-"Overweeg om een CollisionShape2D of CollisionPolygon2D als kind toe te "
-"voegen om de vorm ervan vast te leggen."
+"Deze knoop heeft geen botsingsvorm als onderliggende knoop en kan dus niet "
+"met andere objecten botsen of interageren.\n"
+"Plaats hieronder een knoop als CollisionShape2D of CollisionPolygon2D om "
+"deze vorm vast te leggen."
#: scene/2d/collision_polygon_2d.cpp
msgid ""
@@ -12502,13 +12533,22 @@ msgid ""
"CollisionObject2D derived node. Please only use it as a child of Area2D, "
"StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."
msgstr ""
-"CollisionPolygon2D dient enkel om een botsingsvorm te koppelen aan een knoop "
-"afgeleid van CollisionObject2D. Plaats hem onder een Area2D-, StaticBody2D-, "
-"RigidBody2D- of KinematicBody2D-knoop."
+"Een knooppunt van het type CollisionPolygon2D kan alleen een botsingsvorm "
+"keveren aan knopen die zijn afgeleid van CollisionObject2D. Plaats het dus "
+"alleen onder een knoop als Area2D, StaticBody2D, RigidBody2D of "
+"KinematicBody2D."
#: scene/2d/collision_polygon_2d.cpp
msgid "An empty CollisionPolygon2D has no effect on collision."
-msgstr "Een lege CollisionPolygon2D heeft geen effect op botsingen."
+msgstr "Lege CollisionPolygon2D hebben geen botsingsfunctie."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
#: scene/2d/collision_shape_2d.cpp
msgid ""
@@ -12516,15 +12556,16 @@ msgid ""
"CollisionObject2D derived node. Please only use it as a child of Area2D, "
"StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."
msgstr ""
-"CollisionShape2D dient enkel om een botsingsvorm te koppelen aan een knoop "
-"afgeleid van CollisionObject2D. Plaats hem onder een Area2D-, StaticBody2D-, "
-"RigidBody2D- of KinematicBody2D-knoop."
+"Een knooppunt van het type CollisionShape2D kan alleen een botsingsvorm "
+"keveren aan knopen die zijn afgeleid van CollisionObject2D. Plaats het dus "
+"alleen onder een knoop als Area2D, StaticBody2D, RigidBody2D of "
+"KinematicBody2D."
#: scene/2d/collision_shape_2d.cpp
msgid ""
"A shape must be provided for CollisionShape2D to function. Please create a "
"shape resource for it!"
-msgstr "Een CollisionShape2D heeft een vorm nodig in de Shape-eigenschap!"
+msgstr "Een CollisionShape2D heeft een vorm nodig."
#: scene/2d/collision_shape_2d.cpp
msgid ""
@@ -12640,9 +12681,9 @@ msgid ""
"by the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
-"Grootteveranderingen van een RigidBody2D (in Character- of Rigidmodus) zal "
-"overschreven worden door de physics engine als het spel start.\n"
-"Verander in plaats daarvan de grootte van CollisionShapes in de kinderen."
+"De grootte van een RigidBody2D (in Character- of Rigidmodus) wordt "
+"overschreven wanneer het spel start.\n"
+"Verander in plaats daarvan de grootte van de onderliggende botsingsvormen."
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -12671,10 +12712,9 @@ msgid ""
"to. Please use it as a child of Area2D, StaticBody2D, RigidBody2D, "
"KinematicBody2D, etc. to give them a shape."
msgstr ""
-"TileMap met de optie \"Use Parent\" aan heeft een CollisionShape2D-ouder "
-"nodig om vormen aan te geven. De TileMap hoort een kind van een Area2D, "
-"StaticBody2D, RigidBody2D, KinematicBody2D enz. knoop te zijn om ze een vorm "
-"te geven."
+"Een TileMap met de optie \"Use Parent\" ingeschakeld moet knoop afgeleid van "
+"CollisionObject2D (Area2D, StaticBody2D, RigidBody2D of KinematicBody2D) als "
+"ouder hebben."
#: scene/2d/visibility_notifier_2d.cpp
msgid ""
@@ -12751,10 +12791,10 @@ msgid ""
"Consider adding a CollisionShape or CollisionPolygon as a child to define "
"its shape."
msgstr ""
-"Deze knoop heeft geen vorm (Shape), dus het kan niet met andere objecten "
-"botsen of interactie hebben.\n"
-"Overweeg om een CollisionShape of CollisionPolygon als kind toe te voegen om "
-"de vorm ervan vast te leggen."
+"Deze knoop heeft geen botsingsvorm als onderliggende knoop en kan dus niet "
+"met andere objecten botsen of interageren.\n"
+"Plaats hieronder een knoop als CollisionShape of CollisionPolygon om deze "
+"vorm vast te leggen."
#: scene/3d/collision_polygon.cpp
msgid ""
@@ -12762,13 +12802,13 @@ msgid ""
"CollisionObject derived node. Please only use it as a child of Area, "
"StaticBody, RigidBody, KinematicBody, etc. to give them a shape."
msgstr ""
-"CollisionPolygon dient enkel om een botsingsvorm te koppelen aan een knoop "
-"afgeleid van CollisionObject. Plaats hem onder een Area-, StaticBody-, "
-"RigidBody- of KinematicBody-knoop."
+"Een knooppunt van het type CollisionPolygon kan alleen een botsingsvorm "
+"keveren aan knopen die zijn afgeleid van CollisionObject. Plaats het dus "
+"alleen onder een knoop als Area, StaticBody, RigidBody of KinematicBody."
#: scene/3d/collision_polygon.cpp
msgid "An empty CollisionPolygon has no effect on collision."
-msgstr "Een lege CollisionPolygon heeft geen effect op botsingen."
+msgstr "Lege CollisionPolygon hebben geen botsingsfunctie."
#: scene/3d/collision_shape.cpp
msgid ""
@@ -12776,17 +12816,15 @@ msgid ""
"derived node. Please only use it as a child of Area, StaticBody, RigidBody, "
"KinematicBody, etc. to give them a shape."
msgstr ""
-"CollisionShape dient enkel om een botsingsvorm te koppelen aan een knoop "
-"afgeleid van CollisionObject. Plaats hem onder een Area-, StaticBody-, "
-"RigidBody- of KinematicBody-knoop."
+"Een knooppunt van het type CollisionShape kan alleen een botsingsvorm "
+"keveren aan knopen die zijn afgeleid van CollisionObject2D. Plaats het dus "
+"alleen onder een knoop als Area, StaticBody, RigidBody of KinematicBody."
#: scene/3d/collision_shape.cpp
msgid ""
"A shape must be provided for CollisionShape to function. Please create a "
"shape resource for it."
-msgstr ""
-"Om CollisionShape te laten werken, hoort het een Shape te hebben. Maak "
-"hiervoor alstublieft een Shape bron aan."
+msgstr "Een CollisionShape heeft een vorm nodig."
#: scene/3d/collision_shape.cpp
msgid ""
@@ -12829,11 +12867,6 @@ msgstr ""
"GIProbes worden niet ondersteund door het GLES2 grafische stuurprogramma.\n"
"Gebruik in plaats daarvan een BakedLightmap."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -12895,9 +12928,9 @@ msgid ""
"by the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
-"Grootteveranderingen van een RigidBody (in Character- of Rigidmodus) zal "
-"overschreven worden door de physics engine als het spel start.\n"
-"Verander in plaats daarvan de grootte van CollisionShapes in de kinderen."
+"De grootte van een RigidBody (in Character- of Rigidmodus) wordt "
+"overschreven wanneer het spel start.\n"
+"Verander in plaats daarvan de grootte van de onderliggende botsingsvormen."
#: scene/3d/physics_joint.cpp
msgid "Node A and Node B must be PhysicsBodies"
@@ -12937,9 +12970,8 @@ msgid ""
"running.\n"
"Change the size in children collision shapes instead."
msgstr ""
-"Grootteveranderingen van een SoftBody (in Character- of Rigidmodus) zal "
-"overschreven worden door de physics engine als het spel start.\n"
-"Verander de grootte van CollisionShapes in de kinderen."
+"De grootte van een SoftBody wordt overschreven wanneer het spel start.\n"
+"Verander in plaats daarvan de grootte van de onderliggende botsingsvormen."
#: scene/3d/sprite_3d.cpp
msgid ""
@@ -13084,9 +13116,8 @@ msgid "Must use a valid extension."
msgstr "Een geldige extensie moet gebruikt worden."
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Enable grid minimap."
-msgstr "Aan raster kleven"
+msgstr "Rasteroverzicht inschakelen."
#: scene/gui/popup.cpp
msgid ""
diff --git a/editor/translations/or.po b/editor/translations/or.po
index c1bc32d40f..19b87260d6 100644
--- a/editor/translations/or.po
+++ b/editor/translations/or.po
@@ -625,7 +625,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1794,8 +1794,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2429,7 +2429,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2819,14 +2819,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2980,6 +2972,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3182,7 +3190,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3863,6 +3871,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4810,7 +4830,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4914,7 +4934,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6681,6 +6700,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6732,16 +6759,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6834,8 +6851,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7056,6 +7073,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9576,6 +9597,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9936,6 +9961,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10179,6 +10208,14 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10299,6 +10336,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11873,6 +11914,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12128,11 +12177,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/pl.po b/editor/translations/pl.po
index 6372cedd0a..d55fee8b72 100644
--- a/editor/translations/pl.po
+++ b/editor/translations/pl.po
@@ -46,12 +46,13 @@
# Dzejkop <jakubtrad@gmail.com>, 2020.
# Mateusz Grzonka <alpinus4@gmail.com>, 2020.
# gnu-ewm <gnu.ewm@protonmail.com>, 2021.
+# vrid <patryksoon@live.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-26 03:28+0000\n"
-"Last-Translator: gnu-ewm <gnu.ewm@protonmail.com>\n"
+"PO-Revision-Date: 2021-03-10 22:14+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"
@@ -60,7 +61,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.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -688,7 +689,7 @@ msgstr "Wybierz ścieżki do skopiowania"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopiuj"
@@ -1890,8 +1891,8 @@ msgid "Open a File or Directory"
msgstr "Otwórz plik lub katalog"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Zapisz"
@@ -2562,8 +2563,8 @@ msgstr ""
"Nie można włączyć dodatku: \"%s\" - parsowanie konfiguracji nie powiodło się."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr "Nie można odnaleźć pola skryptu w dodatku: \"res://addons/%s\"."
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "Nie można odnaleźć pola skryptu w dodatku: \"%s\"."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2993,14 +2994,6 @@ msgid "Help"
msgstr "Pomoc"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Szukaj"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Dokumentacja online"
@@ -3164,6 +3157,24 @@ msgid "Open & Run a Script"
msgstr "Otwórz i Uruchom Skrypt"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Następujące pliki są nowsze na dysku.\n"
+"Jakie działanie powinno zostać podjęte?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Przeładuj"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Zapisz ponownie"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Nowa dziedzicząca scena"
@@ -3374,7 +3385,7 @@ msgstr "Zrób unikalny"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Wklej"
@@ -4080,6 +4091,18 @@ msgstr "Czy zwracasz obiekt dziedziczący po Node w metodzie `post_import()`?"
msgid "Saving..."
msgstr "Zapisywanie..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "Wybierz importer"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "Importer:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Resetuj do domyślnych"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d plików"
@@ -5048,8 +5071,8 @@ msgid "Got:"
msgstr "Otrzymano:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Nie udało się przeprowadzić testu integralności sha256"
+msgid "Failed SHA-256 hash check"
+msgstr "Test SHA-256 nieudany"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5152,7 +5175,6 @@ msgid "Sort:"
msgstr "Sortuj:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategoria:"
@@ -6979,6 +7001,14 @@ msgstr "Zamknij pliki pomocy"
msgid "Run"
msgstr "Uruchom"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Szukaj"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Krok w"
@@ -7032,16 +7062,6 @@ msgstr ""
"Następujące pliki są nowsze na dysku.\n"
"Jakie działania powinny zostać podjęte?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Przeładuj"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Zapisz ponownie"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Debugger"
@@ -7137,8 +7157,8 @@ msgstr "Punkty wstrzymania"
msgid "Go To"
msgstr "Idź do"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Wytnij"
@@ -7361,6 +7381,10 @@ msgid "Yaw"
msgstr "Odchylenie"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Rozmiar"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Narysowane obiekty"
@@ -8536,7 +8560,7 @@ msgstr "Edytuj wielokąt nawigacji"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Paste Tile Bitmask"
-msgstr "Wklej maskę bitową Kafelka"
+msgstr "Wklej maskę bitową kafelka"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Clear Tile Bitmask"
@@ -10046,6 +10070,10 @@ msgid "Projects"
msgstr "Projekty"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Wczytywanie, proszę czekać..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Data modyfikacji"
@@ -10154,15 +10182,15 @@ msgstr "Indeks przycisku myszy:"
#: editor/project_settings_editor.cpp
msgid "Left Button"
-msgstr "Lewy guzik"
+msgstr "Lewy przycisk"
#: editor/project_settings_editor.cpp
msgid "Right Button"
-msgstr "Prawy guzik"
+msgstr "Prawy przycisk"
#: editor/project_settings_editor.cpp
msgid "Middle Button"
-msgstr "Środkowy guzik"
+msgstr "Środkowy przycisk"
#: editor/project_settings_editor.cpp
msgid "Wheel Up Button"
@@ -10416,6 +10444,10 @@ msgstr "Autoładowanie"
msgid "Plugins"
msgstr "Wtyczki"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "Importuj domyślne"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Ustawienie predefiniowane..."
@@ -10665,6 +10697,14 @@ msgid "Instance Child Scene"
msgstr "Dodaj instancję sceny"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "Nie można wkleić korzenia do tej samej sceny."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Wklej węzeł/y"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Odłącz skrypt"
@@ -10791,6 +10831,10 @@ msgid "Attach Script"
msgstr "Dołącz skrypt"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Wytnij węzeł/y"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Usuń węzeł(y)"
@@ -12160,18 +12204,12 @@ msgstr ""
"Wydaniowy keystore jest niepoprawnie skonfigurowany w profilu eksportu."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "A valid Android SDK path is required in Editor Settings."
-msgstr ""
-"Niepoprawna ścieżka do SDK Androida dla własnego builda w Ustawieniach "
-"Edytora."
+msgstr "Wymagana jest poprawna ścieżka SDK Androida w Ustawieniach Edytora."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Invalid Android SDK path in Editor Settings."
-msgstr ""
-"Niepoprawna ścieżka do SDK Androida dla własnego builda w Ustawieniach "
-"Edytora."
+msgstr "Niepoprawna ścieżka do SDK Androida w Ustawieniach Edytora."
#: platform/android/export/export.cpp
msgid "Missing 'platform-tools' directory!"
@@ -12180,13 +12218,11 @@ msgstr "Folder \"platform-tools\" nie istnieje!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK platform-tools' adb command."
msgstr ""
+"Nie udało się znaleźć komendy adb z narzędzi platformowych SDK Androida."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Please check in the Android SDK directory specified in Editor Settings."
-msgstr ""
-"Niepoprawna ścieżka do SDK Androida dla własnego builda w Ustawieniach "
-"Edytora."
+msgstr "Sprawdź w folderze SDK Androida podanych w Ustawieniach Edytora."
#: platform/android/export/export.cpp
msgid "Missing 'build-tools' directory!"
@@ -12194,7 +12230,7 @@ msgstr "Brakuje folderu \"build-tools\"!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK build-tools' apksigner command."
-msgstr ""
+msgstr "Nie udało się znaleźć komendy apksigner z narzędzi SDK Androida."
#: platform/android/export/export.cpp
msgid "Invalid public key for APK expansion."
@@ -12460,6 +12496,18 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Pusty CollisionPolygon2D nie ma wpływu na kolizje."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+"Nieprawidłowy wielokąt. Co najmniej 3 punkty są potrzebne do trybu budowania "
+"\"Solids\"."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+"Nieprawidłowy wielokąt. Co najmniej 3 punkty są potrzebne do trybu budowania "
+"\"Segments\"."
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12672,27 +12720,23 @@ msgstr "ARVROrigin wymaga węzła potomnego typu ARVRCamera."
#: scene/3d/baked_lightmap.cpp
msgid "Finding meshes and lights"
-msgstr ""
+msgstr "Szukanie siatek i świateł"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing geometry (%d/%d)"
-msgstr "Parsowanie Geometrii..."
+msgstr "Przygotowywanie geometrii (%d/%d)"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing environment"
-msgstr "Wyświetlaj środowisko"
+msgstr "Przygotowywanie środowiska"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Generating capture"
-msgstr "Generowanie Lightmapy"
+msgstr "Generowanie przechwycenia"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Saving lightmaps"
-msgstr "Generowanie Lightmapy"
+msgstr "Zapisywanie map światła"
#: scene/3d/baked_lightmap.cpp
msgid "Done"
@@ -12785,12 +12829,6 @@ msgstr ""
"GIProbes nie są obsługiwane przez sterownik wideo GLES2.\n"
"Zamiast tego użyj BakedLightmap."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-"Węzeł InterpolatedCamera jest przestarzały i będzie usunięty w Godocie 4.0."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "SpotLight z kątem szerszym niż 90 stopni nie może rzucać cieni."
@@ -13099,6 +13137,8 @@ msgid ""
"The sampler port is connected but not used. Consider changing the source to "
"'SamplerPort'."
msgstr ""
+"Port samplera jest podłączony, ale nieużyty. Rozważ zmianę źródła na "
+"\"SamplerPort\"."
#: scene/resources/visual_shader_nodes.cpp
msgid "Invalid source for preview."
@@ -13128,6 +13168,12 @@ msgstr "Varying może być przypisane tylko w funkcji wierzchołków."
msgid "Constants cannot be modified."
msgstr "Stałe nie mogą być modyfikowane."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr ""
+#~ "Węzeł InterpolatedCamera jest przestarzały i będzie usunięty w Godocie "
+#~ "4.0."
+
#~ msgid "No"
#~ msgstr "Nie"
@@ -14748,9 +14794,6 @@ msgstr "Stałe nie mogą być modyfikowane."
#~ msgid "Use Default Light"
#~ msgstr "Użyj domyślnego światła"
-#~ msgid "Use Default sRGB"
-#~ msgstr "Użyj domyślnie sRGB"
-
#~ msgid "Ambient Light Color:"
#~ msgstr "Kolor światła otoczenia:"
diff --git a/editor/translations/pr.po b/editor/translations/pr.po
index 9f6933a077..09d967e01d 100644
--- a/editor/translations/pr.po
+++ b/editor/translations/pr.po
@@ -656,7 +656,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1862,8 +1862,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2510,7 +2510,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2911,14 +2911,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -3075,6 +3067,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3283,7 +3291,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3996,6 +4004,19 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Slit th' Node"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -4979,7 +5000,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5083,7 +5104,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6901,6 +6921,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6953,16 +6981,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7059,8 +7077,8 @@ msgstr "Yar, Blow th' Selected Down!"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7293,6 +7311,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9911,6 +9933,10 @@ msgid "Projects"
msgstr "Rename Function"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10277,6 +10303,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10525,6 +10555,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Paste yer Node"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Discharge ye' Variable"
@@ -10650,6 +10689,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Slit th' Node"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12318,6 +12362,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12573,11 +12625,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/pt.po b/editor/translations/pt.po
index 24cd684ee9..dd745d7c56 100644
--- a/editor/translations/pt.po
+++ b/editor/translations/pt.po
@@ -22,7 +22,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-26 03:28+0000\n"
+"PO-Revision-Date: 2021-03-10 22:14+0000\n"
"Last-Translator: João Lopes <linux-man@hotmail.com>\n"
"Language-Team: Portuguese <https://hosted.weblate.org/projects/godot-engine/"
"godot/pt/>\n"
@@ -31,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.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -661,7 +661,7 @@ msgstr "Selecionar Pistas a Copiar"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copiar"
@@ -1867,8 +1867,8 @@ msgid "Open a File or Directory"
msgstr "Abrir um Ficheiro ou Diretoria"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Guardar"
@@ -2542,8 +2542,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr "Incapaz de ativar plugin em: '%s' falha de análise ou configuração."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr "Incapaz de localizar campo Script para plugin em: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "Incapaz de localizar campo script para plugin em: '%s'."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2975,14 +2975,6 @@ msgid "Help"
msgstr "Ajuda"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Procurar"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Documentação Online"
@@ -3147,6 +3139,24 @@ msgid "Open & Run a Script"
msgstr "Abrir & Executar um Script"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Os seguintes ficheiros são mais recentes no disco.\n"
+"Que ação deve ser tomada?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Recarregar"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Guardar novamente"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Novo Herdado"
@@ -3357,7 +3367,7 @@ msgstr "Fazer único"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Colar"
@@ -4064,6 +4074,18 @@ msgstr "Devolveu um objeto derivado de Nó no método `post_import()`?"
msgid "Saving..."
msgstr "A guardar..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "Selecionar Importador"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "Importador:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Restaurar Predefinições"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Ficheiros"
@@ -5030,8 +5052,8 @@ msgid "Got:"
msgstr "Obtido:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Verificação hash sha256 falhada"
+msgid "Failed SHA-256 hash check"
+msgstr "Falhou a verificação hash SHA-256"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5134,7 +5156,6 @@ msgid "Sort:"
msgstr "Ordenar:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Categoria:"
@@ -6955,6 +6976,14 @@ msgstr "Fechar documentos"
msgid "Run"
msgstr "Executar"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Procurar"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Passar Dentro"
@@ -7008,16 +7037,6 @@ msgstr ""
"Os seguintes Ficheiros são mais recentes no disco.\n"
"Que ação deve ser tomada?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Recarregar"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Guardar novamente"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Depurador"
@@ -7110,8 +7129,8 @@ msgstr "Pontos de paragem"
msgid "Go To"
msgstr "Ir Para"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Cortar"
@@ -7334,6 +7353,10 @@ msgid "Yaw"
msgstr "Direção"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Tamanho"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Objetos desenhados"
@@ -10013,6 +10036,10 @@ msgid "Projects"
msgstr "Projetos"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "A carregar, espere por favor..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Última modificação"
@@ -10383,6 +10410,10 @@ msgstr "Carregamento automático"
msgid "Plugins"
msgstr "Plugins"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "Importar Predefinições"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Predefinição..."
@@ -10632,6 +10663,14 @@ msgid "Instance Child Scene"
msgstr "Instanciar Cena Filha"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "Não consigo colar o nó raiz na mesma cena."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Colar Nó(s)"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Separar Script"
@@ -10758,6 +10797,10 @@ msgid "Attach Script"
msgstr "Anexar Script"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Cortar Nó(s)"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Remover Nó(s)"
@@ -12423,6 +12466,18 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Um CollisionPolygon2D vazio não tem efeito na colisão."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+"Polígono inválido. São precisos pelo menos 3 pontos no modo de construção "
+"'Sólidos'."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+"Polígono inválido. São precisos pelo menos 2 pontos no modo de construção "
+"'Segmentos'."
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12736,11 +12791,6 @@ msgstr ""
"Sondas GI não são suportadas pelo driver vídeo GLES2.\n"
"Em vez disso, use um BakedLightmap."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamerda foi descontinuada e será removida no Godot 4.0."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "Uma SpotLight com ângulo superior a 90 graus não cria sombras."
@@ -13081,6 +13131,10 @@ msgstr "Variações só podem ser atribuídas na função vértice."
msgid "Constants cannot be modified."
msgstr "Constantes não podem ser modificadas."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr "InterpolatedCamerda foi descontinuada e será removida no Godot 4.0."
+
#~ msgid "No"
#~ msgstr "Não"
diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po
index 1e099e065c..c2e8116938 100644
--- a/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
@@ -20,7 +20,7 @@
# MalcomRF <malcomkbk@gmail.com>, 2017.
# Marcus Correia <marknokalt@live.com>, 2017-2018.
# Michael Alexsander Silva Dias <michaelalexsander@protonmail.com>, 2017-2018.
-# Renato Rotenberg <renato.rotenberg@gmail.com>, 2017, 2019.
+# Renato Rotenberg <renato.rotenberg@gmail.com>, 2017, 2019, 2021.
# Rodolfo R Gomes <rodolforg@gmail.com>, 2017-2018, 2019.
# Tiago Almeida <thyagoeap@gmail.com>, 2017.
# Mauricio Luan Carneiro deSouza <newmailmlcs@gmail.com>, 2018.
@@ -110,12 +110,14 @@
# Lucas Dantas <lucas.lucantas38@gmail.com>, 2021.
# Carlos Bonifacio <carlosboni.sa@gmail.com>, 2021.
# Lucas Castro <castroclucas@gmail.com>, 2021.
+# Ricardo Zamarrenho Carvalho Correa <ricardozcc17@gmail.com>, 2021.
+# Diego dos Reis Macedo <diego_dragon97@hotmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: 2016-05-30\n"
-"PO-Revision-Date: 2021-01-26 03:28+0000\n"
-"Last-Translator: Lucas Castro <castroclucas@gmail.com>\n"
+"PO-Revision-Date: 2021-03-10 22:14+0000\n"
+"Last-Translator: Renato Rotenberg <renato.rotenberg@gmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt_BR/>\n"
"Language: pt_BR\n"
@@ -123,7 +125,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.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -751,7 +753,7 @@ msgstr "Selecionar Trilhas para Copiar"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copiar"
@@ -1957,8 +1959,8 @@ msgid "Open a File or Directory"
msgstr "Abrir Arquivo ou Diretório"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Salvar"
@@ -2633,7 +2635,8 @@ msgstr ""
"falhou."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"Não foi possível encontrar o campo de script para o plugin em: 'res://addons/"
"%s'."
@@ -3068,14 +3071,6 @@ msgid "Help"
msgstr "Ajuda"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Pesquisar"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Documentação Online"
@@ -3241,6 +3236,24 @@ msgid "Open & Run a Script"
msgstr "Abrir e Rodar um Script"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Os seguintes arquivos são mais recentes no disco.\n"
+"Que ação deve ser tomada?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Recarregar"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Salve novamente"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Novo Herdado"
@@ -3452,7 +3465,7 @@ msgstr "Tornar Único"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Colar"
@@ -4159,6 +4172,21 @@ msgstr "Você retornou um objeto derivado de Nó no método `post_import()`?"
msgid "Saving..."
msgstr "Salvando..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Modo de Seleção"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importar"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Usar sRGB Padrão"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Arquivos"
@@ -5131,7 +5159,8 @@ msgid "Got:"
msgstr "Obtido:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "Falha na verificação da hash sha256"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5235,7 +5264,6 @@ msgid "Sort:"
msgstr "Ordenar:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Categoria:"
@@ -7063,6 +7091,14 @@ msgstr "Fechar Docs"
msgid "Run"
msgstr "Rodar"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Pesquisar"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Passo para dentro"
@@ -7116,16 +7152,6 @@ msgstr ""
"Os seguintes arquivos são mais recentes no disco.\n"
"Que ação deve ser tomada?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Recarregar"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Salve novamente"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Depurador"
@@ -7219,8 +7245,8 @@ msgstr "Breakpoints"
msgid "Go To"
msgstr "Ir Para"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Recortar"
@@ -7443,6 +7469,10 @@ msgid "Yaw"
msgstr "Guinada"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Tamanho"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Objetos Desenhados"
@@ -10126,6 +10156,10 @@ msgid "Projects"
msgstr "Projetos"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Carregando, por favor aguarde."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Ultima Modificação"
@@ -10496,6 +10530,11 @@ msgstr "O AutoLoad"
msgid "Plugins"
msgstr "Plugins"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Carregar Padrão"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Predefinição..."
@@ -10745,6 +10784,14 @@ msgid "Instance Child Scene"
msgstr "Instânciar Cena Filha"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "Não é possível colar o nó raiz na mesma cena."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Colar Nó(s)"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Remover Script"
@@ -10871,6 +10918,10 @@ msgid "Attach Script"
msgstr "Adicionar Script"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Recortar Nó(s)"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Remover Nó(s)"
@@ -11680,7 +11731,7 @@ msgstr "Atribua um recurso MeshLibrary a este GridMap para usar seus meshes."
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Begin Bake"
-msgstr ""
+msgstr "Iniciar pré-cálculo"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Preparing data structures"
@@ -11695,19 +11746,18 @@ msgid "Direct lighting"
msgstr "Direct lightning"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Indirect lighting"
-msgstr "Recuar Direita"
+msgstr "Iluminação indireta"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
#, fuzzy
msgid "Post processing"
-msgstr "Pós-Processamento"
+msgstr "Pós-processamento"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
#, fuzzy
msgid "Plotting lightmaps"
-msgstr "Planejando Luzes:"
+msgstr "Traçando mapas de luz"
#: modules/mono/csharp_script.cpp
msgid "Class name can't be a reserved keyword"
@@ -12249,18 +12299,12 @@ msgstr ""
"exportação."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "A valid Android SDK path is required in Editor Settings."
-msgstr ""
-"Caminho do Android SDK inválido para o build personalizado em Configurações "
-"do Editor."
+msgstr "Um caminho Android SDK é necessário nas Configurações do Editor."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Invalid Android SDK path in Editor Settings."
-msgstr ""
-"Caminho do Android SDK inválido para o build personalizado em Configurações "
-"do Editor."
+msgstr "Caminho do Android SDK está inválido para Configurações do Editor."
#: platform/android/export/export.cpp
msgid "Missing 'platform-tools' directory!"
@@ -12272,16 +12316,14 @@ msgstr ""
"Não foi possível encontrar o comando adb nas ferramentas do Android SDK."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Please check in the Android SDK directory specified in Editor Settings."
msgstr ""
-"Caminho do Android SDK inválido para o build personalizado em Configurações "
+"Por favor, verifique o caminho do Android SDK especificado nas Configurações "
"do Editor."
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Missing 'build-tools' directory!"
-msgstr "Diretório 'ferramentas-da-plataforma' ausente!"
+msgstr "Diretório 'ferramentas-da-plataforma' está faltando !"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK build-tools' apksigner command."
@@ -12547,6 +12589,18 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Um nó CollisionPolygon2D vazio não é efetivo para colisão."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+"Polígono inválido. Pelo menos 3 pontos são necessários no modo de construção "
+"\"Sólidos\"."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+"Polígono inválido. Pelo menos 2 pontos são necessários no modo de construção "
+"\"Segmentos\"."
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12760,24 +12814,21 @@ msgid "Finding meshes and lights"
msgstr "Encontrando malhas e luzes"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing geometry (%d/%d)"
-msgstr "Analisando Geometria..."
+msgstr "Preparando geometria (%d/%d)"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing environment"
-msgstr "Visualizar Ambiente"
+msgstr "Preparando ambiente"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Generating capture"
-msgstr "Generando Lightmaps"
+msgstr "Gerando captura"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
msgid "Saving lightmaps"
-msgstr "Generando Lightmaps"
+msgstr "Salvando mapas de luz"
#: scene/3d/baked_lightmap.cpp
msgid "Done"
@@ -12868,11 +12919,6 @@ msgstr ""
"GIProbes não são suportados pelo driver de vídeo GLES2.\n"
"Use um BakedLightmap em vez disso."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "IntepolatedCamera foi depreciada e será removida no Godot 4.0."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "Um SpotLight com um ângulo maior que 90 graus não pode criar sombras."
@@ -13123,9 +13169,8 @@ msgid "Must use a valid extension."
msgstr "Deve usar uma extensão válida."
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Enable grid minimap."
-msgstr "Ativar Snap"
+msgstr "Ativar minimapa de grade."
#: scene/gui/popup.cpp
msgid ""
@@ -13217,6 +13262,10 @@ msgstr "Variáveis só podem ser atribuídas na função de vértice."
msgid "Constants cannot be modified."
msgstr "Constantes não podem serem modificadas."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr "IntepolatedCamera foi depreciada e será removida no Godot 4.0."
+
#~ msgid "No"
#~ msgstr "Não"
@@ -14876,9 +14925,6 @@ msgstr "Constantes não podem serem modificadas."
#~ msgid "Use Default Light"
#~ msgstr "Usar Luz Padrão"
-#~ msgid "Use Default sRGB"
-#~ msgstr "Usar sRGB Padrão"
-
#~ msgid "Default Light Normal:"
#~ msgstr "Luz Normal Padrão:"
diff --git a/editor/translations/ro.po b/editor/translations/ro.po
index 8cdaef5b59..33f5264d71 100644
--- a/editor/translations/ro.po
+++ b/editor/translations/ro.po
@@ -661,7 +661,7 @@ msgstr "Selectează Pistele de Copiat"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copiază"
@@ -1874,8 +1874,8 @@ msgid "Open a File or Directory"
msgstr "Deschideți un Fişier sau Director"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Salvați"
@@ -2548,7 +2548,8 @@ msgstr ""
"Nu se poate inițializa plugin-ul la: '%s' analizarea configurației a eșuat."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"Nu a putut fi găsit câmpul scriptului pentru plugin la: 'res://addons/%s'."
@@ -2985,14 +2986,6 @@ msgid "Help"
msgstr "Ajutor"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Căutare"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Documentație Online"
@@ -3148,6 +3141,23 @@ msgid "Open & Run a Script"
msgstr "Deschide și Execută un Script"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr "Următoarele file au eșuat extragerea din pachet:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Derivare Nouă"
@@ -3350,7 +3360,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -4046,6 +4056,21 @@ msgstr ""
msgid "Saving..."
msgstr "Se Salvează..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Selectare mod"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importare"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Încărcați Implicit"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Fișiere"
@@ -5033,7 +5058,8 @@ msgid "Got:"
msgstr "Primit:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "Verificare hash sha256 eșuată"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5142,7 +5168,6 @@ msgid "Sort:"
msgstr "Sorare:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Categorie:"
@@ -7031,6 +7056,14 @@ msgstr ""
msgid "Run"
msgstr "Execută"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Căutare"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -7083,16 +7116,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7193,8 +7216,8 @@ msgstr "Șterge puncte"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7427,6 +7450,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -10065,6 +10092,11 @@ msgid "Projects"
msgstr "Proiect"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Se recuperează oglinzile, te rog așteaptă..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10433,6 +10465,11 @@ msgstr ""
msgid "Plugins"
msgstr "Plugin-uri"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Încărcați Implicit"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Presetare..."
@@ -10682,6 +10719,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Lipește Postura"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Curăță Scriptul"
@@ -10811,6 +10857,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Creează Nod"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12445,6 +12496,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12705,11 +12764,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13254,10 +13308,6 @@ msgstr ""
#~ msgstr "Creează un Corp Static Convex"
#, fuzzy
-#~ msgid "Custom Node"
-#~ msgstr "Creează Nod"
-
-#, fuzzy
#~ msgid "Snap (s): "
#~ msgstr "Pas (s):"
diff --git a/editor/translations/ru.po b/editor/translations/ru.po
index 122e75352d..5a443fd1e3 100644
--- a/editor/translations/ru.po
+++ b/editor/translations/ru.po
@@ -91,11 +91,12 @@
# Roman Tolkachyov <roman@tolkachyov.name>, 2020.
# Igor Grachev <igorecha.9999@gmail.com>, 2020.
# Dmytro Meleshko <dmytro.meleshko@gmail.com>, 2021.
+# narrnika <narr13niki@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-21 08:48+0000\n"
+"PO-Revision-Date: 2021-03-16 10:40+0000\n"
"Last-Translator: Danil Alexeev <danil@alexeev.xyz>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot/ru/>\n"
@@ -105,7 +106,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.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -733,7 +734,7 @@ msgstr "Выбрать треки для копирования"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Копировать"
@@ -1938,8 +1939,8 @@ msgid "Open a File or Directory"
msgstr "Открыть каталог или файл"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Сохранить"
@@ -2614,8 +2615,8 @@ msgstr ""
"конфигурации."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr "Не удаётся найти поле script для плагина: «res://addons/%s»."
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "Не удаётся найти поле script для плагина: «%s»."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -3045,14 +3046,6 @@ msgid "Help"
msgstr "Справка"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Поиск"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Онлайн документация"
@@ -3219,6 +3212,24 @@ msgid "Open & Run a Script"
msgstr "Открыть и запустить скрипт"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Следующие файлы изменены на диске.\n"
+"Какое действие следует выполнить?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Перезагрузить"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Пересохранить"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Новая унаследованная сцена"
@@ -3429,7 +3440,7 @@ msgstr "Сделать уникальным"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Вставить"
@@ -3553,7 +3564,7 @@ msgstr "(Текущий)"
#: editor/export_template_manager.cpp
msgid "Retrieving mirrors, please wait..."
-msgstr "Получение зеркал, пожалуйста подождите..."
+msgstr "Получение зеркал, пожалуйста, подождите..."
#: editor/export_template_manager.cpp
msgid "Remove template version '%s'?"
@@ -4132,6 +4143,18 @@ msgstr "Вы вернули производный от Node объект в м
msgid "Saving..."
msgstr "Сохранение..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "Выберите импортёр"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "Импортёр:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Сбросить настройки"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d файлов"
@@ -5088,7 +5111,7 @@ msgstr "Время ожидания."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Bad download hash, assuming file has been tampered with."
-msgstr "Несовпадение хэша загрузки, возможно файл был изменён."
+msgstr "Несовпадение хеша загрузки, возможно файл был изменён."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Expected:"
@@ -5099,8 +5122,8 @@ msgid "Got:"
msgstr "Получено:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Не удалось проверить sha256 хэш"
+msgid "Failed SHA-256 hash check"
+msgstr "Не удалось проверить хеш SHA-256"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5203,7 +5226,6 @@ msgid "Sort:"
msgstr "Сортировка:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Категория:"
@@ -5727,7 +5749,7 @@ msgstr "Очистить пользовательские кости"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View"
-msgstr "Обзор"
+msgstr "Вид"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Always Show Grid"
@@ -5767,7 +5789,7 @@ msgstr "Кадрировать выбранное"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Preview Canvas Scale"
-msgstr "Просмотреть Canvas Scale"
+msgstr "Предпросмотр Canvas Scale"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Translation mask for inserting keys."
@@ -7025,6 +7047,14 @@ msgstr "Закрыть документацию"
msgid "Run"
msgstr "Запустить"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Поиск"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Шаг в"
@@ -7078,16 +7108,6 @@ msgstr ""
"Следующие файлы новее на диске.\n"
"Какие меры должны быть приняты?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Перезагрузить"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Пересохранить"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Отладчик"
@@ -7184,8 +7204,8 @@ msgstr "Точки останова"
msgid "Go To"
msgstr "Перейти к"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Вырезать"
@@ -7408,8 +7428,12 @@ msgid "Yaw"
msgstr "Рыскание"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Размер"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
-msgstr "Нарисовано обьектов"
+msgstr "Нарисовано объектов"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Material Changes"
@@ -10091,6 +10115,10 @@ msgid "Projects"
msgstr "Проекты"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Загрузка, пожалуйста, ждите..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Последнее изменение"
@@ -10460,6 +10488,10 @@ msgstr "Автозагрузка"
msgid "Plugins"
msgstr "Плагины"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "Шаблоны импорта"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Предустановка..."
@@ -10711,6 +10743,14 @@ msgid "Instance Child Scene"
msgstr "Добавить дочернюю сцену"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "Невозможно вставить корневой узел в ту же сцену."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Вставить узел(узлы)"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Открепить скрипт"
@@ -10838,6 +10878,10 @@ msgid "Attach Script"
msgstr "Прикрепить скрипт"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Вырезать узел(узлы)"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Удалить узел(узлы)"
@@ -12492,6 +12536,16 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Пустой CollisionPolygon2D не влияет на столкновения."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+"Недопустимый полигон. В режиме «Solids» необходимо по крайней мере 3 точки."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+"Недопустимый полигон. В режиме «Segments» необходимо по крайней мере 2 точки."
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12814,11 +12868,6 @@ msgstr ""
"GIProbes не поддерживаются видеодрайвером GLES2.\n"
"Вместо этого используйте BakedLightmap."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamera устарела и будет удалена в Godot 4.0."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "SpotLight с углом более 90 градусов не может отбрасывать тени."
@@ -13159,6 +13208,10 @@ msgstr "Изменения могут быть назначены только
msgid "Constants cannot be modified."
msgstr "Константы не могут быть изменены."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr "InterpolatedCamera устарела и будет удалена в Godot 4.0."
+
#~ msgid "No"
#~ msgstr "Нет"
@@ -14822,9 +14875,6 @@ msgstr "Константы не могут быть изменены."
#~ msgid "Use Default Light"
#~ msgstr "Использовать стандартный свет"
-#~ msgid "Use Default sRGB"
-#~ msgstr "Использовать sRGB"
-
#~ msgid "Default Light Normal:"
#~ msgstr "Образец стандартного освещения:"
diff --git a/editor/translations/si.po b/editor/translations/si.po
index 46e606d935..0c3a01f0e4 100644
--- a/editor/translations/si.po
+++ b/editor/translations/si.po
@@ -3,12 +3,13 @@
# Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
# This file is distributed under the same license as the Godot source code.
# Yohan Sandun <Yohan99ysk@gmail.com>, 2018.
+# thushariii <thusharipahalage@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2018-12-13 14:42+0100\n"
-"Last-Translator: Yohan Sandun <Yohan99ysk@gmail.com>\n"
+"PO-Revision-Date: 2021-02-05 09:20+0000\n"
+"Last-Translator: thushariii <thusharipahalage@gmail.com>\n"
"Language-Team: Sinhala <https://hosted.weblate.org/projects/godot-engine/"
"godot/si/>\n"
"Language: si\n"
@@ -16,7 +17,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: Poedit 2.2\n"
+"X-Generator: Weblate 4.5-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -103,11 +104,11 @@ msgstr "කැඩපත"
#: editor/animation_bezier_editor.cpp editor/editor_profiler.cpp
msgid "Time:"
-msgstr ""
+msgstr "කාලය:"
#: editor/animation_bezier_editor.cpp
msgid "Value:"
-msgstr ""
+msgstr "වටිනාකම:"
#: editor/animation_bezier_editor.cpp
msgid "Insert Key Here"
@@ -190,7 +191,7 @@ msgstr "සජීවීකරණ පුනරාවර්ථනය"
#: editor/animation_track_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Change Animation Loop"
-msgstr ""
+msgstr "සජීවිකරණ ලූපය වෙනස් කරන්න"
#: editor/animation_track_editor.cpp
msgid "Property Track"
@@ -249,7 +250,7 @@ msgstr "Anim පසුරු:"
#: editor/animation_track_editor.cpp
msgid "Change Track Path"
-msgstr ""
+msgstr "පථය වෙනස් කරන්න"
#: editor/animation_track_editor.cpp
msgid "Toggle this track on/off."
@@ -331,7 +332,7 @@ msgstr "යතුරු මකා දමන්න"
#: editor/animation_track_editor.cpp
msgid "Change Animation Update Mode"
-msgstr ""
+msgstr "සජීවිකරණ යාවත්කාලීන ප්‍රකාරය වෙනස් කරන්න"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -435,7 +436,7 @@ msgstr "ලුහුබදින්නෙක් එක් කරන්න"
#: editor/animation_track_editor.cpp
msgid "Track path is invalid, so can't add a key."
-msgstr ""
+msgstr "පථය අවලංගු බැවින් යතුරක් එක් කළ නොහැක."
#: editor/animation_track_editor.cpp
msgid "Track is not of type Spatial, can't insert key"
@@ -646,7 +647,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1817,8 +1818,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2454,7 +2455,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2844,14 +2845,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -3006,6 +2999,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3208,7 +3217,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3891,6 +3900,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4849,7 +4870,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4953,7 +4974,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6733,6 +6753,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6784,16 +6812,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6887,8 +6905,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7109,6 +7127,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9654,6 +9676,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10014,6 +10040,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10257,6 +10287,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "යතුරු පිටපත් කරන්න"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10381,6 +10420,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "යතුරු පිටපත් කරන්න"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11968,6 +12012,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12223,11 +12275,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/sk.po b/editor/translations/sk.po
index c9133c8d7c..68da1b1221 100644
--- a/editor/translations/sk.po
+++ b/editor/translations/sk.po
@@ -647,7 +647,7 @@ msgstr "Vybrať Track-y na skopírovanie"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopírovať"
@@ -1851,8 +1851,8 @@ msgid "Open a File or Directory"
msgstr "Otvoriť súbor / priečinok"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Uložiť"
@@ -2519,7 +2519,8 @@ msgstr ""
"Addon plugin nie je možné povoliť pri: '% s' analýze konfigurácie zlyhalo."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"Nepodarilo sa nájsť script field pre addon plugin v: 'res://addons/%s'."
@@ -2950,14 +2951,6 @@ msgid "Help"
msgstr "Pomoc"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Vyhľadať"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Online Dokumentácie"
@@ -3122,6 +3115,23 @@ msgid "Open & Run a Script"
msgstr "Otvoriť a vykonať skript"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr "Nasledovné súbory sa nepodarilo extrahovať z balíka:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Novo Zdedené"
@@ -3331,7 +3341,7 @@ msgstr "Spraviť Jedinečným"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Vložiť"
@@ -4030,6 +4040,21 @@ msgstr "Vrátili ste Node-derived objekt v `post_import()` metóde?"
msgid "Saving..."
msgstr "Ukladám..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Vybrať Režim"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Import"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Načítať predvolené"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Súbory"
@@ -4994,7 +5019,8 @@ msgid "Got:"
msgstr "Má:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "Zlyhalo sha256 hash check"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5098,7 +5124,6 @@ msgid "Sort:"
msgstr "Zoradiť:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategória:"
@@ -6932,6 +6957,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Vyhľadať"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6984,16 +7017,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7092,8 +7115,8 @@ msgstr "Všetky vybrané"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7321,6 +7344,11 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "Veľkosť: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9958,6 +9986,11 @@ msgid "Projects"
msgstr "Zakladatelia Projektu"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Načítavanie zrkadiel, prosím čakajte..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10327,6 +10360,11 @@ msgstr ""
msgid "Plugins"
msgstr "Pluginy"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Načítať predvolené"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10572,6 +10610,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Vložiť"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Popis:"
@@ -10696,6 +10743,11 @@ msgid "Attach Script"
msgstr "Popis:"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Vložiť"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12338,6 +12390,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Prázdny CollisionPolygon2D nemá žiaden efekt na kolíziu."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12609,11 +12669,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13040,10 +13095,6 @@ msgstr ""
#~ msgstr "Vytvoriť adresár"
#, fuzzy
-#~ msgid "Custom Node"
-#~ msgstr "Vložiť"
-
-#, fuzzy
#~ msgid "Create Area"
#~ msgstr "Vytvoriť adresár"
diff --git a/editor/translations/sl.po b/editor/translations/sl.po
index a953258d3f..69819f0a36 100644
--- a/editor/translations/sl.po
+++ b/editor/translations/sl.po
@@ -12,12 +12,13 @@
# Arnold Marko <arnold.marko@gmail.com>, 2019.
# Alex <alexrixhardson@gmail.com>, 2019.
# Andrew Poženel <andrej.pozenel@outlook.com>, 2020.
+# Jakob Tadej Vrtačnik <minecraftalka2@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-07-15 02:42+0000\n"
-"Last-Translator: Andrew Poženel <andrej.pozenel@outlook.com>\n"
+"PO-Revision-Date: 2021-02-01 20:54+0000\n"
+"Last-Translator: Jakob Tadej Vrtačnik <minecraftalka2@gmail.com>\n"
"Language-Team: Slovenian <https://hosted.weblate.org/projects/godot-engine/"
"godot/sl/>\n"
"Language: sl\n"
@@ -26,7 +27,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n"
"%100==4 ? 2 : 3;\n"
-"X-Generator: Weblate 4.2-dev\n"
+"X-Generator: Weblate 4.5-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -370,7 +371,7 @@ msgstr "Odstrani animacijsko sled"
#: editor/animation_track_editor.cpp
msgid "Create NEW track for %s and insert key?"
-msgstr "Ustvarim NOVO sled za %s in vstavim ključ?"
+msgstr "Ustvarim NOVO sled za %s in vstavi ključ?"
#: editor/animation_track_editor.cpp
msgid "Create %d NEW tracks and insert keys?"
@@ -680,7 +681,7 @@ msgstr "Izberi Lastnost"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1935,8 +1936,8 @@ msgid "Open a File or Directory"
msgstr "Odpri Datoteko ali Mapo"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Shrani"
@@ -2633,7 +2634,8 @@ msgstr ""
"konfiguracije ni uspelo."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
"Ni mogoče najti polja skripte za dodatni vtičnik na: 'res://addons/%s'."
@@ -3085,14 +3087,6 @@ msgid "Help"
msgstr "Pomoč"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Iskanje"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Spletna Dokumentacija"
@@ -3255,6 +3249,22 @@ msgid "Open & Run a Script"
msgstr "Odpri & Zaženi Skripto"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Novo Podedovano"
@@ -3463,7 +3473,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -4199,6 +4209,21 @@ msgstr ""
msgid "Saving..."
msgstr "Shranjevanje..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Izberi Način"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Uvozi"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Naložite Prevzeto"
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -5224,7 +5249,8 @@ msgid "Got:"
msgstr "Dobil:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "Neuspešno preverjanje preizkusa sha256"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5338,7 +5364,6 @@ msgid "Sort:"
msgstr "Razvrsti:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategorija:"
@@ -7227,6 +7252,14 @@ msgstr ""
msgid "Run"
msgstr "Zaženi"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Iskanje"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -7280,16 +7313,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Razhroščevalnik"
@@ -7390,8 +7413,8 @@ msgstr "Izbriši točke"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7626,6 +7649,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -10301,6 +10328,11 @@ msgid "Projects"
msgstr "Projekt"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Pridobivanje virov, počakajte..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10669,6 +10701,11 @@ msgstr ""
msgid "Plugins"
msgstr "Vtičniki"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Naložite Prevzeto"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Prednastavitev..."
@@ -10924,6 +10961,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Prilepi Pozicijo"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Odstrani Gradnik VizualnaSkripta"
@@ -11054,6 +11100,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Gradnik Prehod"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12735,6 +12786,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Prazen CollisionPolygon2D nima vpliva na collision."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -13001,11 +13060,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13564,10 +13618,6 @@ msgstr "Konstante ni možno spreminjati."
#~ msgid "Create folder"
#~ msgstr "Ustvarite mapo"
-#, fuzzy
-#~ msgid "Custom Node"
-#~ msgstr "Gradnik Prehod"
-
#~ msgid "Invalid Path"
#~ msgstr "Neveljavna Pot"
diff --git a/editor/translations/sq.po b/editor/translations/sq.po
index 7dcc32735d..f53d0b630a 100644
--- a/editor/translations/sq.po
+++ b/editor/translations/sq.po
@@ -632,7 +632,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1887,8 +1887,8 @@ msgid "Open a File or Directory"
msgstr "Hap një Skedar ose Direktori"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Ruaj"
@@ -2577,7 +2577,8 @@ msgstr ""
"dështoi."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr "I paaftë te gjej fushën e shkrimit për shtojcën në: 'res://addons/%s'."
#: editor/editor_node.cpp
@@ -3023,14 +3024,6 @@ msgid "Help"
msgstr "Ndihmë"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Kërko"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Dokumentimi Online"
@@ -3191,6 +3184,22 @@ msgid "Open & Run a Script"
msgstr "Hap & Fillo një Shkrim"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "E Trashëguar e Re"
@@ -3404,7 +3413,7 @@ msgstr "Bëje Unik"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Ngjit"
@@ -4123,6 +4132,21 @@ msgstr ""
msgid "Saving..."
msgstr "Duke Ruajtur..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Zgjidh Nyjet Për ti Importuar"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importo"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Ngarko të Parazgjedhur"
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -5088,7 +5112,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5196,7 +5220,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6996,6 +7019,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Kërko"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -7047,16 +7078,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7153,8 +7174,8 @@ msgstr "Krijo pika."
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7380,6 +7401,11 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "Madhësia: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9958,6 +9984,11 @@ msgid "Projects"
msgstr "Projekti"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Duke marrë pasqyrat, ju lutem prisni..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10320,6 +10351,11 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Ngarko të Parazgjedhur"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10567,6 +10603,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Dyfisho Nyjet"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Shkrim i Ri"
@@ -10692,6 +10737,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Dyfisho Nyjet"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12319,6 +12369,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12576,11 +12634,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po
index b07bc4e1c9..4fe901f414 100644
--- a/editor/translations/sr_Cyrl.po
+++ b/editor/translations/sr_Cyrl.po
@@ -720,7 +720,7 @@ msgstr "Постави прелаз на:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Копирај"
@@ -2030,8 +2030,8 @@ msgid "Open a File or Directory"
msgstr "Отвори датотеку или директоријум"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Сачувај"
@@ -2752,7 +2752,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr "Неуспех при прикључивању додатка због конфигурационе датотеке: '%s'."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr "Неуспех при налажењу поља за скриптицу у додатку „res://addons/%s“."
#: editor/editor_node.cpp
@@ -3213,14 +3214,6 @@ msgid "Help"
msgstr "Помоћ"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Тражи"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Онлајн документација"
@@ -3400,6 +3393,25 @@ msgid "Open & Run a Script"
msgstr "Отвори и покрени скриптицу"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Следеће датотеке су нове на диску.\n"
+"Која акција се треба предузети?:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Освежи"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Поново сачувај"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Нова наслеђена"
@@ -3631,7 +3643,7 @@ msgstr "Учини Јединственим"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Налепи"
@@ -4403,6 +4415,21 @@ msgstr ""
msgid "Saving..."
msgstr "Чување..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Одабери режим"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Увоз"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Учитај уобичајено"
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -5480,7 +5507,8 @@ msgid "Got:"
msgstr "Добијено:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "Неуспела провера sha256 суме"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5599,7 +5627,6 @@ msgid "Sort:"
msgstr "Сортирање:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Категорија:"
@@ -7619,6 +7646,14 @@ msgstr "Затвори документацију"
msgid "Run"
msgstr "Покрени"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Тражи"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Корак у"
@@ -7674,16 +7709,6 @@ msgstr ""
"Следеће датотеке су нове на диску.\n"
"Која акција се треба предузети?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Освежи"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Поново сачувај"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Дебагер"
@@ -7791,8 +7816,8 @@ msgstr "Тачке прекида"
msgid "Go To"
msgstr "Иди На"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Исеци"
@@ -8041,6 +8066,11 @@ msgid "Yaw"
msgstr "Горе-Доле"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "Величина:"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Нацртани објекти"
@@ -11142,6 +11172,11 @@ msgstr "Пројекти"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Прихватам одредишта, молим сачекајте..."
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Last Modified"
msgstr "Задњи Измењен"
@@ -11596,6 +11631,11 @@ msgstr "Ауто-Учитавање"
msgid "Plugins"
msgstr "Прикључци"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Учитај уобичајено"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Поставке..."
@@ -11902,6 +11942,16 @@ msgstr "Инстанца Сцена Дете"
#: editor/scene_tree_dock.cpp
#, fuzzy
+msgid "Can't paste root node into the same scene."
+msgstr "Немогуће оперисати на чвору из стране сцене!"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Налепи Чворове"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
msgid "Detach Script"
msgstr "Припој Скрипту"
@@ -12057,6 +12107,11 @@ msgstr "Припој Скрипту"
#: editor/scene_tree_dock.cpp
#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Направи чвор"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
msgid "Remove Node(s)"
msgstr "Уклони Чвор/ове"
@@ -13977,6 +14032,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Непријатењ СударниМногоугао2Д нема утицаја на судар."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
#, fuzzy
msgid ""
@@ -14331,11 +14394,6 @@ msgstr ""
" \n"
"Као замену користи ИспеченеСенкеМапу."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
#, fuzzy
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
@@ -15087,10 +15145,6 @@ msgstr "Константе није могуће мењати."
#~ msgstr "CheckBox Radio2"
#, fuzzy
-#~ msgid "Custom Node"
-#~ msgstr "Направи чвор"
-
-#, fuzzy
#~ msgid "Snap (s): "
#~ msgstr "Један корак (сек.):"
diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po
index 232c53da80..3d979c3fc6 100644
--- a/editor/translations/sr_Latn.po
+++ b/editor/translations/sr_Latn.po
@@ -654,7 +654,7 @@ msgstr "Postavi tranzicije na:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1827,8 +1827,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2468,7 +2468,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2860,14 +2860,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -3022,6 +3014,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3225,7 +3233,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3908,6 +3916,19 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Uduplaj Selekciju"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4873,7 +4894,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4977,7 +4998,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6771,6 +6791,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6822,16 +6850,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6926,8 +6944,8 @@ msgstr "Napravi"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7153,6 +7171,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9733,6 +9755,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10096,6 +10122,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10340,6 +10370,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Animacija Uduplaj Ključeve"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10464,6 +10503,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Animacija Uduplaj Ključeve"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12060,6 +12104,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12315,11 +12367,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/sv.po b/editor/translations/sv.po
index cab4b7e5bc..a7bc3d6288 100644
--- a/editor/translations/sv.po
+++ b/editor/translations/sv.po
@@ -662,7 +662,7 @@ msgstr "Välj Spår att Kopiera"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopiera"
@@ -1899,8 +1899,8 @@ msgid "Open a File or Directory"
msgstr "Öppna en Fil eller Katalog"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Spara"
@@ -2598,7 +2598,8 @@ msgstr ""
"Kunde inte aktivera addon plugin vid: '%s' parsning av config misslyckades."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr "Kan inte hitta skriptfältet för addon plugin vid: 'res://addons/%s'."
#: editor/editor_node.cpp
@@ -3026,14 +3027,6 @@ msgid "Help"
msgstr "Hjälp"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Sök"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Dokumentation Online"
@@ -3193,6 +3186,23 @@ msgid "Open & Run a Script"
msgstr "Öppna & Kör ett Skript"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr "Följande filer gick inte att packa upp från tillägget:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Ladda om"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Spara om"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3405,7 +3415,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Klistra in"
@@ -4142,6 +4152,21 @@ msgstr ""
msgid "Saving..."
msgstr "Sparar..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Välj Node"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Importera"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Ladda Standard"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Filer"
@@ -5152,7 +5177,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5256,7 +5281,6 @@ msgid "Sort:"
msgstr "Sortera:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategori:"
@@ -7114,6 +7138,14 @@ msgstr ""
msgid "Run"
msgstr "Kör"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Sök"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -7166,16 +7198,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Ladda om"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Spara om"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7276,8 +7298,8 @@ msgstr "Radera punkter"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Klipp"
@@ -7515,6 +7537,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -10192,6 +10218,11 @@ msgid "Projects"
msgstr "Projekt"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "Laddar..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Senast Ändrad"
@@ -10559,6 +10590,11 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Ladda Standard"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10816,6 +10852,15 @@ msgid "Instance Child Scene"
msgstr "Instansiera Barn-Scen"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Klistra in Noder"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "Fäst Skript"
@@ -10946,6 +10991,11 @@ msgid "Attach Script"
msgstr "Fäst Skript"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Klipp ut Noder"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Ta bort Nod(er)"
@@ -12615,6 +12665,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "En tom CollisionPolygon2D har ingen effekt på kollision."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12893,11 +12951,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/ta.po b/editor/translations/ta.po
index 45de03bdb3..9f9f40b54b 100644
--- a/editor/translations/ta.po
+++ b/editor/translations/ta.po
@@ -650,7 +650,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1823,8 +1823,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2459,7 +2459,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2851,14 +2851,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -3012,6 +3004,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3215,7 +3223,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3899,6 +3907,19 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "அனைத்து தேர்வுகள்"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4858,7 +4879,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4962,7 +4983,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6738,6 +6758,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6789,16 +6817,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6891,8 +6909,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7114,6 +7132,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9654,6 +9676,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10015,6 +10041,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10259,6 +10289,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "அசைவூட்டு போலிபச்சாவிகள்"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10383,6 +10422,11 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "அசைவூட்டு போலிபச்சாவிகள்"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11968,6 +12012,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12223,11 +12275,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/te.po b/editor/translations/te.po
index aa703812fe..50c0fb5a4b 100644
--- a/editor/translations/te.po
+++ b/editor/translations/te.po
@@ -628,7 +628,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1797,8 +1797,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2432,7 +2432,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2822,14 +2822,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2983,6 +2975,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3185,7 +3193,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3866,6 +3874,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4813,7 +4833,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4917,7 +4937,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6684,6 +6703,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6735,16 +6762,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6837,8 +6854,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7059,6 +7076,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9580,6 +9601,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9940,6 +9965,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10183,6 +10212,14 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10303,6 +10340,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11877,6 +11918,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12132,11 +12181,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/th.po b/editor/translations/th.po
index 4b1d938c54..76a2d3c125 100644
--- a/editor/translations/th.po
+++ b/editor/translations/th.po
@@ -7,13 +7,13 @@
# Thanachart Monpassorn <nunf_2539@hotmail.com>, 2020.
# Anonymous <noreply@weblate.org>, 2020.
# Lon3r <mptube.p@gmail.com>, 2020.
-# Kongfa Warorot <gongpha@hotmail.com>, 2020.
+# Kongfa Warorot <gongpha@hotmail.com>, 2020, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-12-31 07:09+0000\n"
-"Last-Translator: Thanachart Monpassorn <nunf_2539@hotmail.com>\n"
+"PO-Revision-Date: 2021-02-15 10:51+0000\n"
+"Last-Translator: Kongfa Warorot <gongpha@hotmail.com>\n"
"Language-Team: Thai <https://hosted.weblate.org/projects/godot-engine/godot/"
"th/>\n"
"Language: th\n"
@@ -21,7 +21,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.4.1-dev\n"
+"X-Generator: Weblate 4.5-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -643,7 +643,7 @@ msgstr "เลือกแทร็กที่จะคัดลอก"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "คัดลอก"
@@ -1836,8 +1836,8 @@ msgid "Open a File or Directory"
msgstr "เปิดไฟล์หรือโฟลเดอร์"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "บันทึก"
@@ -2347,7 +2347,7 @@ msgstr "ยังไม่ได้เลือกฉากที่จะเล
#: editor/editor_node.cpp
msgid "Save scene before running..."
-msgstr ""
+msgstr "บันทึกฉากก่อนที่จะทำงาน..."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -2489,7 +2489,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr "ไม่สามารถเปิดใช้งานปลั๊กอิน: '%s'"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr "ไม่พบชื่อสคริปต์ในปลั๊กอิน: 'res://addons/%s'"
#: editor/editor_node.cpp
@@ -2907,14 +2908,6 @@ msgid "Help"
msgstr "ช่วยเหลือ"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "ค้นหา"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "คู่มือ"
@@ -3076,6 +3069,25 @@ msgid "Open & Run a Script"
msgstr "เปิดและรันสคริปต์"
#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"ไฟล์ต่อไปนี้ในดิสก์ใหม่กว่า\n"
+"จะทำอย่างไรต่อไป?:"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "โหลดใหม่"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "บันทึกอีกครั้ง"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "สืบทอด"
@@ -3282,7 +3294,7 @@ msgstr "ไม่ใช้ร่วมกับวัตถุอื่น"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "วาง"
@@ -3975,6 +3987,21 @@ msgstr "คุณส่งคืนออบเจกต์โหนดย่อ
msgid "Saving..."
msgstr "กำลังบันทึก..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "โหมดเลือก"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "นำเข้า"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "โหลดค่าเริ่มต้น"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "ไฟล์ %d"
@@ -4930,7 +4957,8 @@ msgid "Got:"
msgstr "ที่ได้รับ:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+#, fuzzy
+msgid "Failed SHA-256 hash check"
msgstr "ผิดพลาดในการตรวจสอบแฮช SHA256"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5034,7 +5062,6 @@ msgid "Sort:"
msgstr "เรียงตาม:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "หมวดหมู่:"
@@ -6834,6 +6861,14 @@ msgstr "ปิดคู่มือ"
msgid "Run"
msgstr "เริ่ม"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "ค้นหา"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "คำสั่งต่อไป"
@@ -6887,16 +6922,6 @@ msgstr ""
"ไฟล์ต่อไปนี้ในดิสก์ใหม่กว่า\n"
"จะทำอย่างไรต่อไป?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "โหลดใหม่"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "บันทึกอีกครั้ง"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "ตัวดีบัก"
@@ -6989,8 +7014,8 @@ msgstr "เบรกพอยต์"
msgid "Go To"
msgstr "ไปยัง"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "ตัด"
@@ -7213,6 +7238,11 @@ msgid "Yaw"
msgstr "Yaw"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "ขนาด: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "ออบเจกต์ที่วาด"
@@ -9846,6 +9876,11 @@ msgid "Projects"
msgstr "โปรเจกต์"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "กำลังเรียกข้อมูล โปรดรอ..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "แก้ไขล่าสุด"
@@ -10210,6 +10245,11 @@ msgstr "ออโต้โหลด"
msgid "Plugins"
msgstr "ปลั๊กอิน"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "โหลดค่าเริ่มต้น"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "พรีเซ็ต..."
@@ -10457,6 +10497,16 @@ msgid "Instance Child Scene"
msgstr "อินสแตนซ์ฉากลูก"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Can't paste root node into the same scene."
+msgstr "ทำกับโหนดของฉากอื่นไม่ได้!"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "วางโหนด"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "ค้นพบสคริปต์"
@@ -10582,6 +10632,11 @@ msgid "Attach Script"
msgstr "แนบสคริปต์"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "ตัดโหนด"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "ลบโหนด"
@@ -12204,6 +12259,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "CollisionPolygon2D ที่ว่างเปล่าจะไม่มีผลทางกายภาพ"
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12493,11 +12556,6 @@ msgstr ""
"ไดรเวอร์วีดีโอ GLES2 ไม่สนับสนุน GIProbe\n"
"ใช้ BakedLightmap แทน"
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamera เลิกใช้งานแล้วและจะถูกลบออกใน Godot 4.0"
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "SpotLight ที่มีมุมมากกว่า 90 ไม่สามารถสร้างเงา"
@@ -12818,6 +12876,10 @@ msgstr "Varyings สามารถกำหนดในังก์ชันเ
msgid "Constants cannot be modified."
msgstr "ค่าคงที่ไม่สามารถแก้ไขได้"
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr "InterpolatedCamera เลิกใช้งานแล้วและจะถูกลบออกใน Godot 4.0"
+
#~ msgid "No"
#~ msgstr "ไม่"
diff --git a/editor/translations/tr.po b/editor/translations/tr.po
index 867a66b3dc..9a815d3f25 100644
--- a/editor/translations/tr.po
+++ b/editor/translations/tr.po
@@ -46,22 +46,23 @@
# Kaan Genç <kaan@kaangenc.me>, 2020.
# Anonymous <noreply@weblate.org>, 2020.
# Güneş Gümüş <gunes.gumus.001@gmail.com>, 2020.
-# Oğuz Ersen <oguzersen@protonmail.com>, 2020.
+# Oğuz Ersen <oguzersen@protonmail.com>, 2020, 2021.
# Vedat Günel <gunel15@itu.edu.tr>, 2020.
# Ahmet Elgün <ahmetelgn@gmail.com>, 2020.
# Efruz Yıldırır <efruzyildirir@gmail.com>, 2020.
# Hazar <duurkak@yandex.com>, 2020.
# Mutlu ORAN <mutlu.oran66@gmail.com>, 2020.
# Yusuf Osman YILMAZ <wolfkan4219@gmail.com>, 2020.
-# furkan atalar <fatalar55@gmail.com>, 2020.
+# furkan atalar <fatalar55@gmail.com>, 2020, 2021.
# Suleyman Poyraz <zaryob.dev@gmail.com>, 2020.
# Çağlar KOPARIR <ckoparir@gmail.com>, 2021.
+# Cem Eren Fukara <cefukara@hotmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-22 10:21+0000\n"
-"Last-Translator: Çağlar KOPARIR <ckoparir@gmail.com>\n"
+"PO-Revision-Date: 2021-03-16 10:40+0000\n"
+"Last-Translator: furkan atalar <fatalar55@gmail.com>\n"
"Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/"
"godot/tr/>\n"
"Language: tr\n"
@@ -69,7 +70,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -698,7 +699,7 @@ msgstr "Kopyalanacak izleri seç"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopyala"
@@ -1720,7 +1721,7 @@ msgstr "Dock Nod"
#: editor/editor_feature_profile.cpp
msgid "FileSystem Dock"
-msgstr "Dosya sistemi"
+msgstr "Dosya Sistemi"
#: editor/editor_feature_profile.cpp
msgid "Import Dock"
@@ -1903,8 +1904,8 @@ msgid "Open a File or Directory"
msgstr "Bir Dosya ya da Dizin Aç"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Kaydet"
@@ -2038,7 +2039,7 @@ msgstr "Çevrimiçi Rehberler"
#: editor/editor_help.cpp
msgid "Properties"
-msgstr "Özellikler"
+msgstr "Özellikleri"
#: editor/editor_help.cpp
msgid "override:"
@@ -2050,7 +2051,7 @@ msgstr "varsayılan:"
#: editor/editor_help.cpp
msgid "Methods"
-msgstr "Yöntemler"
+msgstr "Metotlar"
#: editor/editor_help.cpp
msgid "Theme Properties"
@@ -2578,7 +2579,8 @@ msgstr ""
"başarısız oldu."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr "Eklentideki betik alanı bulunamıyor: 'res://addons/%s'."
#: editor/editor_node.cpp
@@ -3009,14 +3011,6 @@ msgid "Help"
msgstr "Yardım"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Ara"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Çevrimiçi Belgeler"
@@ -3182,6 +3176,24 @@ msgid "Open & Run a Script"
msgstr "Aç & Bir Betik Çalıştır"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Aşağıdaki dosyalar diskte daha yeni.\n"
+"Hangi eylem yapılsın?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Yeniden Yükle"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Yeniden Kaydet"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Yeni Örnekleme"
@@ -3393,7 +3405,7 @@ msgstr "Benzersiz Yap"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Yapıştır"
@@ -3953,15 +3965,15 @@ msgstr "Aranıyor..."
#: editor/find_in_files.cpp
msgid "%d match in %d file."
-msgstr "%d dosyada %d eşleşme."
+msgstr "%d eşleşme %d dosyada."
#: editor/find_in_files.cpp
msgid "%d matches in %d file."
-msgstr "%d dosyada %d eşleşme."
+msgstr "%d eşleşme %d dosyada."
#: editor/find_in_files.cpp
msgid "%d matches in %d files."
-msgstr "%d dosyada %d eşleşme."
+msgstr "%d eşleşme %d dosyada."
#: editor/groups_editor.cpp
msgid "Add to Group"
@@ -4099,6 +4111,18 @@ msgstr "`Post_import ()` yönteminde Node türevi bir nesne döndürdünüz mü?
msgid "Saving..."
msgstr "Kaydediliyor..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "İçe Aktarıcı'yı seçin"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "İçe Aktar"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Varsayılanlara dön"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d Dosya"
@@ -5066,8 +5090,8 @@ msgid "Got:"
msgstr "Alınan:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Başarısız sha256 hash sınaması"
+msgid "Failed SHA-256 hash check"
+msgstr "SHA-256 hash kontrolü başarısız oldu"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5170,7 +5194,6 @@ msgid "Sort:"
msgstr "Sırala:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Kategori:"
@@ -6990,6 +7013,14 @@ msgstr "Belgeleri Kapat"
msgid "Run"
msgstr "Çalıştır"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Ara"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "İçeri Adımla"
@@ -7043,16 +7074,6 @@ msgstr ""
"Aşağıdaki dosyalar diskte daha yeni.\n"
"Hangi eylem yapılsın?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Yeniden Yükle"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Yeniden Kaydet"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Hata Ayıklayıcı"
@@ -7147,8 +7168,8 @@ msgstr "Hata ayıklama noktaları"
msgid "Go To"
msgstr "Şuna Git"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Kes"
@@ -7371,6 +7392,10 @@ msgid "Yaw"
msgstr "Yalpala"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Boyut"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Çizilmiş Nesneler"
@@ -10051,6 +10076,10 @@ msgid "Projects"
msgstr "Projeler"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Yükleniyor, lütfen bekleyin..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Son Değişiklik"
@@ -10420,6 +10449,11 @@ msgstr "Otomatik Yükle"
msgid "Plugins"
msgstr "Eklentiler"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Varsayılanları İçe Aktar"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Ön ayar..."
@@ -10669,6 +10703,14 @@ msgid "Instance Child Scene"
msgstr "Çocuk Sahnesini Örnekle"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "Kök düğüm aynı sahneye yapıştırılamıyor."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Düğümleri Yapıştır"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Betiği Ayır"
@@ -10796,6 +10838,10 @@ msgid "Attach Script"
msgstr "Betik İliştir"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Düğümleri Kes(s)"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Düğümleri Kaldır"
@@ -12446,6 +12492,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Boş bir CollisionPolygon2D'nin çarpışmaya hiçbir etkisi yoktur."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12765,13 +12819,6 @@ msgstr ""
"GIProbes GLES2 video sürücüsü tarafından desteklenmez.\n"
"Bunun yerine bir BakedLightmap kullanın."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-"InterpolatedCamera kullanımdan kaldırılmıştır ve Godot 4.0'da "
-"kaldırılacaktır."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "90 dereceden geniş açılı SpotIşık gölge oluşturamaz."
@@ -13024,7 +13071,7 @@ msgstr "Geçerli bir uzantı kullanılmalı."
#: scene/gui/graph_edit.cpp
msgid "Enable grid minimap."
-msgstr "Izgara mini haritasını etkinleştir."
+msgstr "Izgara haritasını etkinleştir."
#: scene/gui/popup.cpp
msgid ""
@@ -13115,6 +13162,12 @@ msgstr "varyings yalnızca vertex işlevinde atanabilir."
msgid "Constants cannot be modified."
msgstr "Sabit değerler değiştirilemez."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr ""
+#~ "InterpolatedCamera kullanımdan kaldırılmıştır ve Godot 4.0'da "
+#~ "kaldırılacaktır."
+
#~ msgid "No"
#~ msgstr "Hayır"
@@ -14748,9 +14801,6 @@ msgstr "Sabit değerler değiştirilemez."
#~ msgid "Use Default Light"
#~ msgstr "Önyüklü Işık Kullan"
-#~ msgid "Use Default sRGB"
-#~ msgstr "Önyüklü sRGB'yi Kullan"
-
#~ msgid "Default Light Normal:"
#~ msgstr "Önyüklü Işığın Olağanı:"
diff --git a/editor/translations/tzm.po b/editor/translations/tzm.po
index 7853cd3b8c..c4614c7eb3 100644
--- a/editor/translations/tzm.po
+++ b/editor/translations/tzm.po
@@ -626,7 +626,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1795,8 +1795,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2430,7 +2430,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2820,14 +2820,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -2981,6 +2973,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr ""
@@ -3183,7 +3191,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3864,6 +3872,18 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr ""
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr ""
@@ -4811,7 +4831,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -4915,7 +4935,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6682,6 +6701,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6733,16 +6760,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6835,8 +6852,8 @@ msgstr ""
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7057,6 +7074,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9577,6 +9598,10 @@ msgid "Projects"
msgstr ""
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -9937,6 +9962,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10180,6 +10209,14 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr ""
@@ -10300,6 +10337,10 @@ msgid "Attach Script"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -11874,6 +11915,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12129,11 +12178,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/uk.po b/editor/translations/uk.po
index 75da46cdc4..6a8af58119 100644
--- a/editor/translations/uk.po
+++ b/editor/translations/uk.po
@@ -12,7 +12,7 @@
# Kirill Omelchenko <kirill.omelchenko@gmail.com>, 2018.
# Александр <ol-vin@mail.ru>, 2018.
# Богдан Матвіїв <bomtvv@gmail.com>, 2019.
-# Tymofij Lytvynenko <till.svit@gmail.com>, 2020.
+# Tymofij Lytvynenko <till.svit@gmail.com>, 2020, 2021.
# Vladislav Glinsky <cl0ne@mithril.org.ua>, 2020.
# Микола Тимошенко <9081@ukr.net>, 2020.
# Miroslav <zinmirx@gmail.com>, 2020.
@@ -20,8 +20,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Ukrainian (Godot Engine)\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-16 01:29+0000\n"
-"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
+"PO-Revision-Date: 2021-03-10 22:14+0000\n"
+"Last-Translator: Tymofij Lytvynenko <till.svit@gmail.com>\n"
"Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/"
"godot/uk/>\n"
"Language: uk\n"
@@ -30,7 +30,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.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -666,7 +666,7 @@ msgstr "Виберіть доріжки для копіювання"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Копіювати"
@@ -1152,7 +1152,7 @@ msgstr "Ведучий розробник"
#. you do not have to keep it in your translation.
#: editor/editor_about.cpp
msgid "Project Manager "
-msgstr "Керівник проектів "
+msgstr "Керівник проєктів "
#: editor/editor_about.cpp
msgid "Developers"
@@ -1873,8 +1873,8 @@ msgid "Open a File or Directory"
msgstr "Відкрити файл або каталог"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Зберегти"
@@ -2548,9 +2548,8 @@ msgstr ""
"налаштування."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr ""
-"Не вдалося знайти поле скрипт для доповнення плагіну в: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "Не вдалося знайти поле скрипту для додатка тут: «%s»."
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2984,14 +2983,6 @@ msgid "Help"
msgstr "Довідка"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Пошук"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Онлайн документація"
@@ -3157,6 +3148,24 @@ msgid "Open & Run a Script"
msgstr "Відкрити і запустити скрипт"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"На диску зберігаються новіші версії вказаних нижче файлів.\n"
+"Що слід зробити?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Перезавантажити"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Перезаписати"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Новий успадкований"
@@ -3368,7 +3377,7 @@ msgstr "Зробити унікальним"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Вставити"
@@ -4073,6 +4082,18 @@ msgstr "Повернули об'єкт, що походить від Node, у м
msgid "Saving..."
msgstr "Збереження..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "Виберіть засіб імпортування"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "Засіб імпортування:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "Відновити типові параметри"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d файлів"
@@ -5045,8 +5066,8 @@ msgid "Got:"
msgstr "Отримав:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Помилка перевірки хешування sha256"
+msgid "Failed SHA-256 hash check"
+msgstr "Не вдалося пройти перевірку хешу SHA-256"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5149,7 +5170,6 @@ msgid "Sort:"
msgstr "Сортувати:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Категорія:"
@@ -6977,6 +6997,14 @@ msgstr "Закрити документацію"
msgid "Run"
msgstr "Запустити"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Пошук"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "Крок в"
@@ -7030,16 +7058,6 @@ msgstr ""
"Такі файли на диску новіші.\n"
"Що робити?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "Перезавантажити"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "Перезаписати"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "Зневаджувач"
@@ -7136,8 +7154,8 @@ msgstr "Точки зупину"
msgid "Go To"
msgstr "Перейти"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Вирізати"
@@ -7360,6 +7378,10 @@ msgid "Yaw"
msgstr "Відхилення"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "Розмір"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "Намальовано об'єктів"
@@ -10044,13 +10066,17 @@ msgstr ""
#. TRANSLATORS: This refers to the application where users manage their Godot projects.
#: editor/project_manager.cpp
msgid "Project Manager"
-msgstr "Керівник проекту"
+msgstr "Керівник проєкту"
#: editor/project_manager.cpp
msgid "Projects"
msgstr "Проєкти"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "Завантаження. Будь ласка, зачекайте..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "Востаннє змінено"
@@ -10420,6 +10446,10 @@ msgstr "Автозавантаження"
msgid "Plugins"
msgstr "Плаґіни (додатки)"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "Типові параметри імпортування"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Заздалегідь установлений..."
@@ -10671,6 +10701,14 @@ msgid "Instance Child Scene"
msgstr "Створити екземпляр дочірньої сцени"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "Не можна вставляти кореневий вузол до сцени цього кореневого вузла."
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "Вставити вузли"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "Від'єднати скрипт"
@@ -10797,6 +10835,10 @@ msgid "Attach Script"
msgstr "Долучити скрипт"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "Вирізати вузли"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Вилучити вузли"
@@ -12475,6 +12517,16 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "Порожній CollisionPolygon2D ніяк не вплине на зіткнення."
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+"Некоректний полігон. У режимі збирання «Solids» потрібно принаймні 3 точки."
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+"Некоректний полігон. У режимі збирання «Segments» потрібні принаймні 2 точки."
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12796,12 +12848,6 @@ msgstr ""
"У драйвері GLES2 не передбачено підтримки GIProbes.\n"
"Скористайтеся замість них BakedLightmap."
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-"InterpolatedCamera вважається застарілою, її буде вилучено у Godot 4.0."
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "SpotLight з кутом, який є більшим за 90 градусів, не може давати тіні."
@@ -13147,6 +13193,11 @@ msgstr "Змінні величини можна пов'язувати лише
msgid "Constants cannot be modified."
msgstr "Сталі не можна змінювати."
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr ""
+#~ "InterpolatedCamera вважається застарілою, її буде вилучено у Godot 4.0."
+
#~ msgid "No"
#~ msgstr "Ні"
diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po
index c7722c84c4..a2e1decab6 100644
--- a/editor/translations/ur_PK.po
+++ b/editor/translations/ur_PK.po
@@ -636,7 +636,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -1829,8 +1829,8 @@ msgid "Open a File or Directory"
msgstr ""
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr ""
@@ -2480,7 +2480,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2874,14 +2874,6 @@ msgid "Help"
msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr ""
@@ -3037,6 +3029,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
#, fuzzy
msgid "New Inherited"
msgstr "سب سکریپشن بنائیں"
@@ -3244,7 +3252,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
@@ -3942,6 +3950,20 @@ msgstr ""
msgid "Saving..."
msgstr ""
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr ".تمام کا انتخاب"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr ".سپورٹ"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr ""
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -4913,7 +4935,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5018,7 +5040,6 @@ msgid "Sort:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr ""
@@ -6835,6 +6856,14 @@ msgstr ""
msgid "Run"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -6886,16 +6915,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -6992,8 +7011,8 @@ msgstr ".تمام کا انتخاب"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr ""
@@ -7218,6 +7237,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -9822,6 +9845,10 @@ msgid "Projects"
msgstr ".تمام کا انتخاب"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10187,6 +10214,10 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr ""
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10430,6 +10461,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "ایکشن منتقل کریں"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "سب سکریپشن بنائیں"
@@ -10557,6 +10597,11 @@ msgid "Attach Script"
msgstr "سب سکریپشن بنائیں"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "ایکشن منتقل کریں"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12179,6 +12224,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12434,11 +12487,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/vi.po b/editor/translations/vi.po
index 97c2be742e..94692dc9b2 100644
--- a/editor/translations/vi.po
+++ b/editor/translations/vi.po
@@ -15,13 +15,15 @@
# Steve Dang <bynguu@outlook.com>, 2020.
# Harry Mitchell <minhyh0987@gmail.com>, 2020.
# HSGamer <huynhqtienvtag@gmail.com>, 2020.
-# LetterC67 <hoangdeptoong@gmail.com>, 2020.
+# LetterC67 <hoangdeptoong@gmail.com>, 2020, 2021.
+# Rev <revolnoom7801@gmail.com>, 2021.
+# SyliawDeV <thanhlongstranger@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2020-08-11 14:04+0000\n"
-"Last-Translator: LetterC67 <hoangdeptoong@gmail.com>\n"
+"PO-Revision-Date: 2021-03-08 15:33+0000\n"
+"Last-Translator: Rev <revolnoom7801@gmail.com>\n"
"Language-Team: Vietnamese <https://hosted.weblate.org/projects/godot-engine/"
"godot/vi/>\n"
"Language: vi\n"
@@ -29,12 +31,13 @@ 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.2-dev\n"
+"X-Generator: Weblate 4.5.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
-msgstr "Hàm convert() có loại đối số không hợp lệ, sử dụng các hằng TYPE_*."
+msgstr ""
+"Hàm convert() có loại đối số không hợp lệ, hãy sử dụng các hằng TYPE_*."
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
msgid "Expected a string of length 1 (a character)."
@@ -171,9 +174,8 @@ msgid "Anim Change Call"
msgstr "Đổi Function Gọi Animation"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Anim Multi Change Keyframe Time"
-msgstr "Đổi thời gian khung hình"
+msgstr "Đổi nhiều thời gian khung hình"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -206,26 +208,25 @@ msgstr "Chỉnh Vòng Lặp Hoạt Ảnh"
#: editor/animation_track_editor.cpp
msgid "Property Track"
-msgstr ""
+msgstr "Theo dõi đặc tính"
#: editor/animation_track_editor.cpp
msgid "3D Transform Track"
-msgstr ""
+msgstr "Theo dõi chuyển đổi 3D"
#: editor/animation_track_editor.cpp
msgid "Call Method Track"
-msgstr ""
+msgstr "Gọi phương thức theo dõi"
#: editor/animation_track_editor.cpp
msgid "Bezier Curve Track"
-msgstr ""
+msgstr "Theo dõi đường cong Bezier"
#: editor/animation_track_editor.cpp
msgid "Audio Playback Track"
-msgstr ""
+msgstr "Bản nhạc phát lại âm thanh"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Animation Playback Track"
msgstr "Ngưng chạy animation. (S)"
@@ -238,7 +239,6 @@ msgid "Animation length (seconds)"
msgstr "Độ dài hoạt ảnh (giây)"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Add Track"
msgstr "Thêm Track Animation"
@@ -257,7 +257,7 @@ msgstr "Âm thanh:"
#: editor/animation_track_editor.cpp
msgid "Anim Clips:"
-msgstr ""
+msgstr "Hoạt ảnh:"
#: editor/animation_track_editor.cpp
msgid "Change Track Path"
@@ -265,7 +265,7 @@ msgstr "Thay đổi đường dẫn Track"
#: editor/animation_track_editor.cpp
msgid "Toggle this track on/off."
-msgstr "Bật tắt track này on/off."
+msgstr "Bật hoặc tắt track này, on/off"
#: editor/animation_track_editor.cpp
msgid "Update Mode (How this property is set)"
@@ -383,7 +383,7 @@ msgstr "Chèn Anim"
#: editor/animation_track_editor.cpp
msgid "AnimationPlayer can't animate itself, only other players."
-msgstr "AnimationPlayer không thể tự tạo hoạt ảnh, chỉ các player khác."
+msgstr "AnimationPlayer không thể tự tạo hoạt ảnh, phải nhờ các Player khác."
#: editor/animation_track_editor.cpp
msgid "Anim Create & Insert"
@@ -407,7 +407,7 @@ msgstr "Sắp xếp lại Tracks"
#: editor/animation_track_editor.cpp
msgid "Transform tracks only apply to Spatial-based nodes."
-msgstr ""
+msgstr "Các chuyển đổi chỉ có thể áp dụng cho các node Spatial"
#: editor/animation_track_editor.cpp
msgid ""
@@ -416,7 +416,7 @@ msgid ""
"-AudioStreamPlayer2D\n"
"-AudioStreamPlayer3D"
msgstr ""
-"Các bản âm thanh chỉ có thể trỏ đến các nút:\n"
+"Các bản âm thanh chỉ có thể trỏ đến các loại:\n"
"-AudioStreamPlayer\n"
"-AudioStreamPlayer2D\n"
"-AudioStreamPlayer3D"
@@ -428,10 +428,11 @@ msgstr "Các bản hoạt ảnh chỉ có thể trỏ tới các nút AnimationP
#: editor/animation_track_editor.cpp
msgid "An animation player can't animate itself, only other players."
msgstr ""
+"Animation player không tự tạo hoạt ảnh được, phải thông qua các player khác."
#: editor/animation_track_editor.cpp
msgid "Not possible to add a new track without a root"
-msgstr ""
+msgstr "Không thể thêm track mới mà không có root."
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
@@ -482,14 +483,13 @@ msgid "Paste Tracks"
msgstr "Dán Tracks"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Anim Scale Keys"
-msgstr "Anim Scale Keys"
+msgstr "Key để scale hoạt ảnh"
#: editor/animation_track_editor.cpp
msgid ""
"This option does not work for Bezier editing, as it's only a single track."
-msgstr ""
+msgstr "Tùy chọn này không áp lên Bezier được, vì nó chỉ là một track."
#: editor/animation_track_editor.cpp
msgid ""
@@ -503,6 +503,16 @@ msgid ""
"Alternatively, use an import preset that imports animations to separate "
"files."
msgstr ""
+"Cáianimation này thuộc về một cảnh đã nhập, vì vậy những thay đổi đối với "
+"các bản nhạc đã nhập sẽ không được lưu.\n"
+"\n"
+"Để bật khả năng thêm các bản nhạc tùy chỉnh, hãy điều hướng đến cài đặt nhập "
+"của cảnh và đặt\n"
+"\"animation > Lưu trữ\" thành \"Tệp\", bật \"Hoạt hình> Giữ các bản nhạc tùy "
+"chỉnh\", sau đó nhập lại.(vn)\n"
+"\"Animation > Storage\" to \"Files\", enable \"Animation > Keep Custom Tracks"
+"\", sau đó nhập lại (english).\n"
+"Hoặc, sử dụng cài đặt trước nhập khẩu nhập hình ảnh động để tách các tệp."
#: editor/animation_track_editor.cpp
msgid "Warning: Editing imported animation"
@@ -536,7 +546,7 @@ msgstr "Giây"
#: editor/animation_track_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "FPS"
-msgstr ""
+msgstr "Khung hình(FPS)"
#: editor/animation_track_editor.cpp editor/editor_properties.cpp
#: editor/plugins/polygon_2d_editor_plugin.cpp
@@ -554,7 +564,7 @@ msgstr "Thuộc tính hoạt cảnh."
#: editor/animation_track_editor.cpp
msgid "Copy Tracks"
-msgstr ""
+msgstr "Sao Chép Tracks"
#: editor/animation_track_editor.cpp
msgid "Scale Selection"
@@ -570,7 +580,7 @@ msgstr "Nhân đôi lựa chọn"
#: editor/animation_track_editor.cpp
msgid "Duplicate Transposed"
-msgstr ""
+msgstr "Chuyển đổi trùng lặp"
#: editor/animation_track_editor.cpp
msgid "Delete Selection"
@@ -598,7 +608,7 @@ msgstr "Chọn node để được làm diễn hoạt:"
#: editor/animation_track_editor.cpp
msgid "Use Bezier Curves"
-msgstr ""
+msgstr "Sử dụng đường cong Bezier"
#: editor/animation_track_editor.cpp
msgid "Anim. Optimizer"
@@ -606,15 +616,15 @@ msgstr "Tối ưu hóa Animation"
#: editor/animation_track_editor.cpp
msgid "Max. Linear Error:"
-msgstr ""
+msgstr "Sai lệch tuyến tính lớn nhất:"
#: editor/animation_track_editor.cpp
msgid "Max. Angular Error:"
-msgstr ""
+msgstr "Sai lệch góc lớn nhất:"
#: editor/animation_track_editor.cpp
msgid "Max Optimizable Angle:"
-msgstr ""
+msgstr "Góc lớn nhất có thể tối ưu:"
#: editor/animation_track_editor.cpp
msgid "Optimize"
@@ -622,7 +632,7 @@ msgstr "Tối ưu"
#: editor/animation_track_editor.cpp
msgid "Remove invalid keys"
-msgstr "Gỡ bỏ các khoá không hợp lệ"
+msgstr "Xóa các khoá không hợp lệ"
#: editor/animation_track_editor.cpp
msgid "Remove unresolved and empty tracks"
@@ -654,14 +664,13 @@ msgstr "Chọn các Track để sao chép:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Sao chép"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Select All/None"
-msgstr "Chọn Không có"
+msgstr "Chọn tất cả/ hoặc không"
#: editor/animation_track_editor_plugins.cpp
msgid "Add Audio Track Clip"
@@ -669,19 +678,19 @@ msgstr "Thêm Track Âm thanh"
#: editor/animation_track_editor_plugins.cpp
msgid "Change Audio Track Clip Start Offset"
-msgstr ""
+msgstr "Thay đổi thời điểm bắt đầu phát track âm thanh."
#: editor/animation_track_editor_plugins.cpp
msgid "Change Audio Track Clip End Offset"
-msgstr ""
+msgstr "Thay đổi thời điểm kết thúc track âm thanh"
#: editor/array_property_edit.cpp
msgid "Resize Array"
-msgstr "Đổi lại size Array"
+msgstr "Thay đổi kích thước mảng"
#: editor/array_property_edit.cpp
msgid "Change Array Value Type"
-msgstr "Đổi loại giá trị Array"
+msgstr "Đổi kiểu giá trị Array"
#: editor/array_property_edit.cpp
msgid "Change Array Value"
@@ -768,9 +777,8 @@ msgid "Method in target node must be specified."
msgstr "Phương thức trong nút đích phải được chỉ định."
#: editor/connections_dialog.cpp
-#, fuzzy
msgid "Method name must be a valid identifier."
-msgstr "Phương thức trong nút đích phải được chỉ định."
+msgstr "Tên phương thức phải được chỉ định."
#: editor/connections_dialog.cpp
msgid ""
@@ -822,9 +830,8 @@ msgid "Extra Call Arguments:"
msgstr "Mở rộng Đối số được gọi:"
#: editor/connections_dialog.cpp
-#, fuzzy
msgid "Receiver Method:"
-msgstr "Lọc các nút"
+msgstr "Hàm nhận:"
#: editor/connections_dialog.cpp
msgid "Advanced"
@@ -846,7 +853,7 @@ msgstr "Một lần"
#: editor/connections_dialog.cpp
msgid "Disconnects the signal after its first emission."
-msgstr "Ngắt kết nối tín hiệu sau lần phát xạ đầu tiên."
+msgstr "Ngắt kết nối tín hiệu sau lần phát đầu tiên."
#: editor/connections_dialog.cpp
msgid "Cannot connect signal"
@@ -864,7 +871,7 @@ msgstr "Không thể kết nối tín hiệu"
#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "Close"
-msgstr "Tắt"
+msgstr "Đóng"
#: editor/connections_dialog.cpp
msgid "Connect"
@@ -912,9 +919,8 @@ msgid "Signals"
msgstr "Tín hiệu (Signal)"
#: editor/connections_dialog.cpp
-#, fuzzy
msgid "Filter signals"
-msgstr "Lọc tệp tin ..."
+msgstr "Lọc tín hiệu"
#: editor/connections_dialog.cpp
msgid "Are you sure you want to remove all connections from this signal?"
@@ -978,7 +984,6 @@ msgid "Search Replacement For:"
msgstr "Tìm kiếm thay thế cho:"
#: editor/dependency_editor.cpp
-#, fuzzy
msgid "Dependencies For:"
msgstr "Phần phụ thuộc cho:"
@@ -1026,7 +1031,7 @@ msgstr "Trình chỉnh sửa Phụ thuộc"
#: editor/dependency_editor.cpp
msgid "Search Replacement Resource:"
-msgstr ""
+msgstr "Tìm kiếm tài nguyên thay thế:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
@@ -1090,13 +1095,12 @@ msgid "Permanently delete %d item(s)? (No undo!)"
msgstr "Xoá vĩnh viễn các đối tượng %d? (Không thể hoàn lại!)"
#: editor/dependency_editor.cpp
-#, fuzzy
msgid "Show Dependencies"
-msgstr "Phần phụ thuộc cho:"
+msgstr "Hiện các phần phụ thuộc"
#: editor/dependency_editor.cpp
msgid "Orphan Resource Explorer"
-msgstr ""
+msgstr "Tìm tài nguyên mất gốc"
#: editor/dependency_editor.cpp editor/editor_audio_buses.cpp
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
@@ -1464,15 +1468,15 @@ msgstr ""
#: editor/editor_autoload_settings.cpp
msgid "Keyword cannot be used as an autoload name."
-msgstr ""
+msgstr "Từ khóa không thể dùng làm tên một nạp tự động."
#: editor/editor_autoload_settings.cpp
msgid "Autoload '%s' already exists!"
-msgstr ""
+msgstr "Nạp tự động '%s' đã tồn tại!"
#: editor/editor_autoload_settings.cpp
msgid "Rename Autoload"
-msgstr ""
+msgstr "Đổi tên"
#: editor/editor_autoload_settings.cpp
msgid "Toggle AutoLoad Globals"
@@ -1875,8 +1879,8 @@ msgid "Open a File or Directory"
msgstr "Mở một tệp tin hoặc thư mục"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "Lưu"
@@ -2550,7 +2554,7 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgid "Unable to find script field for addon plugin at: '%s'."
msgstr ""
#: editor/editor_node.cpp
@@ -2787,9 +2791,8 @@ msgid "Project Settings..."
msgstr "Cài đặt Dự Án"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Version Control"
-msgstr "Phiên bản:"
+msgstr "Theo dõi phiên bản"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Set Up Version Control"
@@ -2966,14 +2969,6 @@ msgid "Help"
msgstr "Trợ giúp"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "Tìm kiếm"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "Tài liệu trực tuyến"
@@ -2983,9 +2978,8 @@ msgid "Q&A"
msgstr "Hỏi và Đáp"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Report a Bug"
-msgstr "Nhập vào lại"
+msgstr "Báo lỗi"
#: editor/editor_node.cpp
msgid "Send Docs Feedback"
@@ -2997,7 +2991,7 @@ msgstr "Cộng đồng"
#: editor/editor_node.cpp
msgid "About"
-msgstr "Thông tin chúng tôi"
+msgstr "Về chúng tôi"
#: editor/editor_node.cpp
msgid "Play the project."
@@ -3009,7 +3003,7 @@ msgstr "Chạy"
#: editor/editor_node.cpp
msgid "Pause the scene execution for debugging."
-msgstr ""
+msgstr "Dừng chạy Cảnh để gỡ lỗi."
#: editor/editor_node.cpp
msgid "Pause Scene"
@@ -3037,7 +3031,7 @@ msgstr "Chạy Cảnh Tuỳ Chọn"
#: editor/editor_node.cpp
msgid "Changing the video driver requires restarting the editor."
-msgstr "Thay đổi trình điều kiển Video, yêu cầu khởi động lại Trình biên tập."
+msgstr "Thay đổi trình điều khiển Video cần phải khởi động lại Trình biên tập."
#: editor/editor_node.cpp editor/project_settings_editor.cpp
#: editor/settings_config_dialog.cpp
@@ -3049,14 +3043,12 @@ msgid "Spins when the editor window redraws."
msgstr ""
#: editor/editor_node.cpp
-#, fuzzy
msgid "Update Continuously"
-msgstr "Liên tục"
+msgstr "Cập nhật Liên tục"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Update When Changed"
-msgstr "Đối số đã thay đổi"
+msgstr "Cập nhật khi có thay đổi"
#: editor/editor_node.cpp
msgid "Hide Update Spinner"
@@ -3072,7 +3064,7 @@ msgstr "Quan Sát Viên"
#: editor/editor_node.cpp
msgid "Expand Bottom Panel"
-msgstr "Mở rộng bảng điều khiển phía dưới"
+msgstr "Mở rộng bảng điều khiển dưới"
#: editor/editor_node.cpp
msgid "Output"
@@ -3101,7 +3093,7 @@ msgid ""
"the \"Use Custom Build\" option should be enabled in the Android export "
"preset."
msgstr ""
-"Điều này sẽ thiết lập dự án của bạn cho các bản dựng Android tùy chỉnh bằng "
+"Việc này sẽ thiết lập dự án của bạn cho các bản dựng Android tùy chỉnh bằng "
"cách cài đặt nguồn mẫu thành \"res://android/build\".\n"
"Bạn có thể áp dụng các sửa đổi và xây dựng APK tùy chỉnh khi xuất (thêm các "
"mô-đun, thay đổi AndroidManifest.xml, ...).\n"
@@ -3140,6 +3132,24 @@ msgid "Open & Run a Script"
msgstr "Mở & Chạy mã lệnh"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"Các tệp sau xuất hiện trên ổ cứng gần đây hơn.\n"
+"Bạn muốn làm gì đây?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "Tải lại"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "Lưu lại"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "Kế thừa mới"
@@ -3176,9 +3186,8 @@ msgid "Open the previous Editor"
msgstr ""
#: editor/editor_node.h
-#, fuzzy
msgid "Warning!"
-msgstr "Cảnh báo"
+msgstr "Cảnh báo!"
#: editor/editor_path.cpp
msgid "No sub-resources found."
@@ -3193,9 +3202,8 @@ msgid "Thumbnail..."
msgstr ""
#: editor/editor_plugin_settings.cpp
-#, fuzzy
msgid "Main Script:"
-msgstr "Tạo Script"
+msgstr "Mã lệnh chính:"
#: editor/editor_plugin_settings.cpp
msgid "Edit Plugin"
@@ -3236,7 +3244,7 @@ msgstr ""
#: editor/editor_profiler.cpp
msgid "Average Time (sec)"
-msgstr ""
+msgstr "Thời gian trung bình (giây)"
#: editor/editor_profiler.cpp
msgid "Frame %"
@@ -3281,7 +3289,7 @@ msgstr ""
#: editor/editor_properties.cpp
msgid "Bit %d, value %d"
-msgstr ""
+msgstr "Bit %d, giá trị %d"
#: editor/editor_properties.cpp
msgid "[Empty]"
@@ -3347,7 +3355,7 @@ msgstr "Duy nhất"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Dán"
@@ -4049,6 +4057,21 @@ msgstr ""
msgid "Saving..."
msgstr "Đang lưu ..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "Chế độ chọn"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "Nhập vào"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "Nạp mặc định"
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -5027,7 +5050,7 @@ msgid "Got:"
msgstr "Nhận được:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5135,7 +5158,6 @@ msgid "Sort:"
msgstr "Sắp xếp:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "Danh mục:"
@@ -6974,6 +6996,14 @@ msgstr "Đóng Docs"
msgid "Run"
msgstr "Chạy"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "Tìm kiếm"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -7025,16 +7055,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7133,8 +7153,8 @@ msgstr "Tạo các điểm."
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "Cắt"
@@ -7366,6 +7386,11 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Size"
+msgstr "Kích thước: "
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -10026,6 +10051,13 @@ msgid "Projects"
msgstr "Dự án"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr ""
+"Đang quét các tệp tin,\n"
+"Chờ một chút ..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10396,6 +10428,11 @@ msgstr ""
msgid "Plugins"
msgstr ""
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "Nạp mặc định"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "Cài sẵn ..."
@@ -10650,6 +10687,16 @@ msgstr ""
#: editor/scene_tree_dock.cpp
#, fuzzy
+msgid "Can't paste root node into the same scene."
+msgstr "Không thể hoạt động trên các nút từ ngoại cảnh!"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "Dán các nút"
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
msgid "Detach Script"
msgstr "Đính kèm Script"
@@ -10777,6 +10824,11 @@ msgid "Attach Script"
msgstr "Đính kèm Script"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "Cắt các nút"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "Xóa các nút"
@@ -12432,6 +12484,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12687,11 +12747,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po
index 2c46f95dc0..deca89e9ea 100644
--- a/editor/translations/zh_CN.po
+++ b/editor/translations/zh_CN.po
@@ -43,7 +43,7 @@
# Song DongHui <14729626293@163.com>, 2019.
# simano clio <sim2cle@gmail.com>, 2019.
# ByonkoGalilei <byonko@qq.com>, 2019.
-# qjyqjyqjyqjy <qjyqjyqjyqjy@sina.com.cn>, 2019.
+# qjyqjyqjyqjy <qjyqjyqjyqjy@sina.com.cn>, 2019, 2021.
# liushuyu011 <liushuyu011@gmail.com>, 2019.
# DS <dseqrasd@126.com>, 2019.
# ZeroAurora <zeroaurora@qq.com>, 2019.
@@ -58,7 +58,7 @@
# idleman <1524328475@qq.com>, 2019.
# king <wangding1992@126.com>, 2019.
# silentbird <silentbird520@outlook.com>, 2019.
-# Haoyu Qiu <timothyqiu32@gmail.com>, 2019, 2020.
+# Haoyu Qiu <timothyqiu32@gmail.com>, 2019, 2020, 2021.
# Revan Ji <jiruifancr@gmail.com>, 2020.
# nieyuanhong <15625988003@163.com>, 2020.
# binotaliu <binota@protonmail.ch>, 2020.
@@ -71,15 +71,18 @@
# MintSoda <lionlxh@qq.com>, 2020.
# Gardner Belgrade <hapenia@sina.com>, 2020.
# godhidden <z2zz2zz@yahoo.com>, 2020.
-# BinotaLIU <me@binota.org>, 2020.
+# BinotaLIU <me@binota.org>, 2020, 2021.
# TakWolf <takwolf@foxmail.com>, 2020.
# twoBornottwoB <305766341@qq.com>, 2021.
+# Magian <magian1127@gmail.com>, 2021.
+# Weiduo Xie <xwditfr@gmail.com>, 2021.
+# suplife <2634557184@qq.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Chinese (Simplified) (Godot Engine)\n"
"POT-Creation-Date: 2018-01-20 12:15+0200\n"
-"PO-Revision-Date: 2021-01-22 10:21+0000\n"
-"Last-Translator: twoBornottwoB <305766341@qq.com>\n"
+"PO-Revision-Date: 2021-03-16 10:40+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"
"Language: zh_CN\n"
@@ -87,7 +90,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.5-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -96,13 +99,13 @@ msgstr "convert() 的参数类型无效,请使用 TYPE_* 常量。"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
msgid "Expected a string of length 1 (a character)."
-msgstr "应为长度 1 的字符串(1 字符)。"
+msgstr "应为长度为 1 的字符串(1 字符)。"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: 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 "没有足够的字节可解码或格式无效。"
+msgstr "解码字节数不够,或格式无效。"
#: core/math/expression.cpp
msgid "Invalid input %i (not passed) in expression"
@@ -708,7 +711,7 @@ msgstr "选择要复制的轨道"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "复制"
@@ -1896,8 +1899,8 @@ msgid "Open a File or Directory"
msgstr "打开文件或目录"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "保存"
@@ -2552,8 +2555,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr "无法在 “%s” 上启用加载项插件:配置解析失败。"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr "无法在 “res://addons/%s” 中找到加载项插件的脚本字段。"
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "无法在 “%s” 上找到加载项的 script 字段。"
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2693,7 +2696,7 @@ msgstr "专注模式"
#: editor/editor_node.cpp
msgid "Toggle distraction-free mode."
-msgstr "进入/离开专注模式。"
+msgstr "切换专注模式。"
#: editor/editor_node.cpp
msgid "Add a new scene."
@@ -2933,7 +2936,7 @@ msgstr "截图将保存在编辑器数据或设置文件夹中。"
#: editor/editor_node.cpp
msgid "Toggle Fullscreen"
-msgstr "进入/离开全屏模式"
+msgstr "切换全屏模式"
#: editor/editor_node.cpp
msgid "Toggle System Console"
@@ -2964,14 +2967,6 @@ msgid "Help"
msgstr "帮助"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "搜索"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "在线文档"
@@ -3133,6 +3128,24 @@ msgid "Open & Run a Script"
msgstr "打开并运行脚本"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"磁盘中的下列文件较新。\n"
+"应该执行什么操作?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "重新加载"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "重新保存"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "新建继承"
@@ -3339,7 +3352,7 @@ msgstr "唯一化"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "粘贴"
@@ -3773,7 +3786,7 @@ msgstr "全部折叠"
#: editor/filesystem_dock.cpp
msgid "Duplicate..."
-msgstr "重复..."
+msgstr "复制为..."
#: editor/filesystem_dock.cpp
msgid "Move to Trash"
@@ -4031,6 +4044,18 @@ msgstr "有在 `post_import()` 方法中返回继承了 Node 的对象吗?"
msgid "Saving..."
msgstr "保存中..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "选择导入器"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "导入器:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "重置为默认值"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d 个文件"
@@ -4691,7 +4716,7 @@ msgstr "过渡已存在!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
-msgstr "添加转换"
+msgstr "添加过渡"
#: editor/plugins/animation_state_machine_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
@@ -4732,7 +4757,7 @@ msgstr "节点已移除"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Transition Removed"
-msgstr "转换已移除"
+msgstr "过渡已移除"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Set Start Node (Autoplay)"
@@ -4955,7 +4980,7 @@ msgstr "无法将响应保存到:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Write error."
-msgstr "写错误。"
+msgstr "写入错误。"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Request failed, too many redirects"
@@ -4986,7 +5011,7 @@ msgid "Got:"
msgstr "获得:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr "SHA-256 哈希值校验失败"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5090,7 +5115,6 @@ msgid "Sort:"
msgstr "排序:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "分类:"
@@ -5119,7 +5143,6 @@ msgid "Assets ZIP File"
msgstr "素材 ZIP 文件"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid ""
"Can't determine a save path for lightmap images.\n"
"Save your scene and try again."
@@ -5140,18 +5163,18 @@ 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 ""
"Some mesh is invalid. Make sure the UV2 channel values are contained within "
"the [0.0,1.0] square region."
-msgstr ""
+msgstr "某些网格无效。确保UV2通道值包含在[0.0,1.0]平方区域内。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
"Godot editor was built without ray tracing support, lightmaps can't be baked."
-msgstr ""
+msgstr "Godot编辑器是在没有光线跟踪支持的情况下构建的,光照贴图无法烘焙。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
@@ -5159,7 +5182,7 @@ msgstr "烘焙光照贴图"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Select lightmap bake file:"
-msgstr "选择模板文件:"
+msgstr "选择光照贴图烘焙文件:"
#: editor/plugins/camera_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -5812,7 +5835,7 @@ msgstr "发射色彩"
#: editor/plugins/cpu_particles_editor_plugin.cpp
msgid "CPUParticles"
-msgstr "CPUParticles"
+msgstr "CPU粒子"
#: editor/plugins/cpu_particles_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
@@ -5826,11 +5849,11 @@ msgstr "从节点创建发射点"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Flat 0"
-msgstr "Flat 0"
+msgstr "平面 0"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Flat 1"
-msgstr "Flat 1"
+msgstr "平面 1"
#: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp
msgid "Ease In"
@@ -5894,7 +5917,7 @@ msgstr "鼠标右键添加点"
#: editor/plugins/gi_probe_editor_plugin.cpp
msgid "Bake GI Probe"
-msgstr "烘培 GI 探针"
+msgstr "烘焙 GI 探针"
#: editor/plugins/gradient_editor_plugin.cpp
msgid "Gradient Edited"
@@ -5990,7 +6013,7 @@ msgstr "网格没有可用来创建轮廓的表面!"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Mesh primitive type is not PRIMITIVE_TRIANGLES!"
-msgstr "Mesh 原始类型不是 PRIMITIVE_TRIANGLES!"
+msgstr "网格的原始类型不是 PRIMITIVE_TRIANGLES!"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Could not create outline!"
@@ -6154,7 +6177,7 @@ msgstr "表面的源无效(路径无效)。"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Surface source is invalid (no geometry)."
-msgstr "表面的源无效(无几何)。"
+msgstr "表面的源无效(无几何体)。"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Surface source is invalid (no faces)."
@@ -6194,7 +6217,7 @@ msgstr "Y 轴"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Z-Axis"
-msgstr "Z轴"
+msgstr "Z 轴"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Mesh Up Axis:"
@@ -6239,9 +6262,8 @@ msgid "Can only set point into a ParticlesMaterial process material"
msgstr "只可设为指向 ParticlesMaterial 处理材料"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Convert to CPUParticles2D"
-msgstr "转换为 CPUParticles"
+msgstr "转换为 CPUParticles2D"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
@@ -6270,7 +6292,7 @@ msgstr "“%s” 不包含面几何体。"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Create Emitter"
-msgstr "创建发射器 (Emitter)"
+msgstr "创建发射器"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Emission Points:"
@@ -6887,6 +6909,14 @@ msgstr "关闭文档"
msgid "Run"
msgstr "运行"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "搜索"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "单步进入"
@@ -6940,16 +6970,6 @@ msgstr ""
"磁盘中的下列文件已更新。\n"
"请选择执行哪项操作?:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "重新加载"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "重新保存"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "调试器"
@@ -7042,8 +7062,8 @@ msgstr "断点"
msgid "Go To"
msgstr "转到"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "剪切"
@@ -7266,6 +7286,10 @@ msgid "Yaw"
msgstr "偏航角"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "大小"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "绘制对象"
@@ -9891,6 +9915,10 @@ msgid "Projects"
msgstr "项目"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "正在加载,请稍候..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "修改时间"
@@ -10256,6 +10284,10 @@ msgstr "自动加载"
msgid "Plugins"
msgstr "插件"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "默认导入设置"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "预设..."
@@ -10503,6 +10535,14 @@ msgid "Instance Child Scene"
msgstr "实例化子场景"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "不能将根节点粘贴进相同场景。"
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "粘贴节点"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "分离脚本"
@@ -10625,6 +10665,10 @@ msgid "Attach Script"
msgstr "添加脚本"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "剪切节点"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "移除节点"
@@ -11425,35 +11469,31 @@ msgstr "向此 GridMap 提供网格库资源以使用其网格。"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Begin Bake"
-msgstr ""
+msgstr "开始烘焙"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Preparing data structures"
-msgstr ""
+msgstr "准备数据结构"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Generate buffers"
-msgstr "生成 AABB"
+msgstr "生成缓冲区"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Direct lighting"
-msgstr "方向"
+msgstr "直接照明"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Indirect lighting"
-msgstr "向右缩进"
+msgstr "间接照明"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Post processing"
-msgstr "后期处理"
+msgstr "后处理"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Plotting lightmaps"
-msgstr "正在绘制灯光"
+msgstr "绘制光照图"
#: modules/mono/csharp_script.cpp
msgid "Class name can't be a reserved keyword"
@@ -11465,7 +11505,7 @@ msgstr "内部异常堆栈追朔结束"
#: modules/recast/navigation_mesh_editor_plugin.cpp
msgid "Bake NavMesh"
-msgstr "烘焙导航网"
+msgstr "烘焙导航网格"
#: modules/recast/navigation_mesh_editor_plugin.cpp
msgid "Clear the navigation mesh."
@@ -11954,9 +11994,8 @@ msgid "Select device from the list"
msgstr "从列表中选择设备"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Unable to find the 'apksigner' tool."
-msgstr "未找到 zipalign 工具。"
+msgstr "找不到“apksigner”工具。"
#: platform/android/export/export.cpp
msgid ""
@@ -11973,14 +12012,12 @@ msgid "Release keystore incorrectly configured in the export preset."
msgstr "用于发布的密钥存储在导出预设中未被正确设置。"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "A valid Android SDK path is required in Editor Settings."
-msgstr "用于 “编辑器设置” 中自定义构建的 Android SDK 路径是无效的。"
+msgstr "编辑器设置中需要有效的Android SDK路径。"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Invalid Android SDK path in Editor Settings."
-msgstr "用于 “编辑器设置” 中自定义构建的 Android SDK 路径是无效的。"
+msgstr "编辑器设置中的Android SDK路径无效。"
#: platform/android/export/export.cpp
msgid "Missing 'platform-tools' directory!"
@@ -11988,12 +12025,11 @@ msgstr "缺失“platform-tools”目录!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK platform-tools' adb command."
-msgstr ""
+msgstr "找不到Android SDK平台工具的adb命令。"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Please check in the Android SDK directory specified in Editor Settings."
-msgstr "用于 “编辑器设置” 中自定义构建的 Android SDK 路径是无效的。"
+msgstr "请签入编辑器设置中指定的Android SDK目录。"
#: platform/android/export/export.cpp
msgid "Missing 'build-tools' directory!"
@@ -12001,7 +12037,7 @@ msgstr "缺失“build-tools”目录!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK build-tools' apksigner command."
-msgstr ""
+msgstr "找不到Android SDK生成工具的apksigner命令。"
#: platform/android/export/export.cpp
msgid "Invalid public key for APK expansion."
@@ -12244,6 +12280,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "空的 CollisionPolygon2D 不起任何碰撞检测作用。"
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr "多边形无效。“Solids”构建模式需要至少三个点。"
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr "多边形无效。“Segments”构建模式需要至少两个点。"
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12431,27 +12475,23 @@ msgstr "ARVROrigin 需要一个 ARVRCamera 子节点。"
#: scene/3d/baked_lightmap.cpp
msgid "Finding meshes and lights"
-msgstr ""
+msgstr "正在查找网格和灯光"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing geometry (%d/%d)"
-msgstr "解析多边形中..."
+msgstr "正在准备几何体(%d/%d)"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing environment"
-msgstr "查看环境"
+msgstr "正在准备环境"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Generating capture"
-msgstr "正在生成光照贴图"
+msgstr "正在生成捕获"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Saving lightmaps"
-msgstr "正在生成光照贴图"
+msgstr "正在保存光照贴图"
#: scene/3d/baked_lightmap.cpp
msgid "Done"
@@ -12534,11 +12574,6 @@ msgstr ""
"GLES2 视频驱动程序不支持 GIProbes。\n"
"请改用 BakedLightmap。"
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamera 已废弃,将在 Godot 4.0 中删除。"
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "角度宽于 90 度的 SpotLight 无法投射出阴影。"
@@ -12833,7 +12868,7 @@ msgstr "Viewport 大小大于 0 时才能进行渲染。"
msgid ""
"The sampler port is connected but not used. Consider changing the source to "
"'SamplerPort'."
-msgstr ""
+msgstr "采样器端口已连接但未使用。考虑将源更改为“SamplerPort”。"
#: scene/resources/visual_shader_nodes.cpp
msgid "Invalid source for preview."
@@ -12863,6 +12898,10 @@ msgstr "变量只能在顶点函数中指定。"
msgid "Constants cannot be modified."
msgstr "不允许修改常量。"
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr "InterpolatedCamera 已废弃,将在 Godot 4.0 中删除。"
+
#~ msgid "No"
#~ msgstr "否"
@@ -14510,9 +14549,6 @@ msgstr "不允许修改常量。"
#~ msgid "Use Default Light"
#~ msgstr "使用默认光照"
-#~ msgid "Use Default sRGB"
-#~ msgstr "使用默认sRGB"
-
#~ msgid "Default Light Normal:"
#~ msgstr "默认光照法线:"
diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po
index 99d673b0fa..2009ba8f20 100644
--- a/editor/translations/zh_HK.po
+++ b/editor/translations/zh_HK.po
@@ -682,7 +682,7 @@ msgstr "選擇模式"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "複製"
@@ -1922,8 +1922,8 @@ msgid "Open a File or Directory"
msgstr "選擇資料夾/檔案"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "儲存"
@@ -2598,8 +2598,9 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr ""
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "載入字形出現錯誤"
#: editor/editor_node.cpp
#, fuzzy
@@ -3029,14 +3030,6 @@ msgid "Help"
msgstr "幫助"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "搜尋"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
#, fuzzy
msgid "Online Docs"
@@ -3199,6 +3192,22 @@ msgid "Open & Run a Script"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/editor_node.cpp
#, fuzzy
msgid "New Inherited"
msgstr "下一個腳本"
@@ -3416,7 +3425,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "貼上"
@@ -4164,6 +4173,21 @@ msgstr ""
msgid "Saving..."
msgstr "儲存中..."
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Select Importer"
+msgstr "選擇模式"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Importer:"
+msgstr "導入"
+
+#: editor/import_defaults_editor.cpp
+#, fuzzy
+msgid "Reset to Defaults"
+msgstr "預設"
+
#: editor/import_dock.cpp
#, fuzzy
msgid "%d Files"
@@ -5190,7 +5214,7 @@ msgid "Got:"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5304,7 +5328,6 @@ msgid "Sort:"
msgstr "排序:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "分類:"
@@ -7164,6 +7187,14 @@ msgstr "關閉場景"
msgid "Run"
msgstr "運行"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "搜尋"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr ""
@@ -7218,16 +7249,6 @@ msgid ""
"What action should be taken?:"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr ""
@@ -7329,8 +7350,8 @@ msgstr "刪除"
msgid "Go To"
msgstr ""
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "剪下"
@@ -7569,6 +7590,10 @@ msgid "Yaw"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr ""
@@ -10251,6 +10276,11 @@ msgid "Projects"
msgstr "專案"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Loading, please wait..."
+msgstr "接收 mirrors中, 請稍侯..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr ""
@@ -10627,6 +10657,11 @@ msgstr ""
msgid "Plugins"
msgstr "插件"
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Import Defaults"
+msgstr "預設"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr ""
@@ -10885,6 +10920,15 @@ msgid "Instance Child Scene"
msgstr ""
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Paste Node(s)"
+msgstr "貼上"
+
+#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Detach Script"
msgstr "腳本"
@@ -11019,6 +11063,11 @@ msgid "Attach Script"
msgstr "腳本"
#: editor/scene_tree_dock.cpp
+#, fuzzy
+msgid "Cut Node(s)"
+msgstr "貼上"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr ""
@@ -12705,6 +12754,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr ""
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr ""
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12962,11 +13019,6 @@ msgid ""
"Use a BakedLightmap instead."
msgstr ""
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr ""
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr ""
@@ -13451,10 +13503,6 @@ msgstr ""
#~ msgstr "新增資料夾"
#, fuzzy
-#~ msgid "Custom Node"
-#~ msgstr "貼上"
-
-#, fuzzy
#~ msgid "Invalid Path"
#~ msgstr "有效的路徑"
diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po
index a1228463b9..62ef5a616c 100644
--- a/editor/translations/zh_TW.po
+++ b/editor/translations/zh_TW.po
@@ -29,7 +29,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-01-01 10:30+0000\n"
+"PO-Revision-Date: 2021-03-16 10:40+0000\n"
"Last-Translator: BinotaLIU <me@binota.org>\n"
"Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/"
"godot-engine/godot/zh_Hant/>\n"
@@ -38,7 +38,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.4.1-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -659,7 +659,7 @@ msgstr "選擇軌道以複製"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "複製"
@@ -1851,8 +1851,8 @@ msgid "Open a File or Directory"
msgstr "開啟檔案或資料夾"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
-#: editor/editor_properties.cpp editor/inspector_dock.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/editor_properties.cpp editor/import_defaults_editor.cpp
+#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
msgstr "保存"
@@ -2364,7 +2364,7 @@ msgstr "未定義欲執行之場景。"
#: editor/editor_node.cpp
msgid "Save scene before running..."
-msgstr ""
+msgstr "執行前先保存場景..."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -2505,8 +2505,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr "無法在「%s」上啟用擴充功能,解析組態設定失敗。"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
-msgstr "無法在擴充功能「res://addons/%s」中無法找到腳本欄位。"
+msgid "Unable to find script field for addon plugin at: '%s'."
+msgstr "無法在擴充功能「r%s」中找到腳本欄位。"
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s'."
@@ -2917,14 +2917,6 @@ msgid "Help"
msgstr "說明"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
-#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-msgid "Search"
-msgstr "搜尋"
-
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Online Docs"
msgstr "線上說明文件"
@@ -3086,6 +3078,24 @@ msgid "Open & Run a Script"
msgstr "開啟並執行腳本"
#: editor/editor_node.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?"
+msgstr ""
+"磁碟中的下列檔案已更新。\n"
+"要執行什麼操作?"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Reload"
+msgstr "重新載入"
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Resave"
+msgstr "重新保存"
+
+#: editor/editor_node.cpp
msgid "New Inherited"
msgstr "新增繼承"
@@ -3292,7 +3302,7 @@ msgstr "獨立化"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
#: editor/plugins/tile_map_editor_plugin.cpp editor/property_editor.cpp
-#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "貼上"
@@ -3984,6 +3994,18 @@ msgstr "是否有在 `post_import()` 方法內回傳繼承 Node 之物件?"
msgid "Saving..."
msgstr "正在保存..."
+#: editor/import_defaults_editor.cpp
+msgid "Select Importer"
+msgstr "選擇匯入程式"
+
+#: editor/import_defaults_editor.cpp
+msgid "Importer:"
+msgstr "匯入程式:"
+
+#: editor/import_defaults_editor.cpp
+msgid "Reset to Defaults"
+msgstr "重設為預設"
+
#: editor/import_dock.cpp
msgid "%d Files"
msgstr "%d 個檔案"
@@ -4939,7 +4961,7 @@ msgid "Got:"
msgstr "獲得:"
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
+msgid "Failed SHA-256 hash check"
msgstr "SHA-256 雜湊檢查失敗"
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -5043,7 +5065,6 @@ msgid "Sort:"
msgstr "排序:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#: editor/project_settings_editor.cpp
msgid "Category:"
msgstr "分類:"
@@ -5072,14 +5093,12 @@ msgid "Assets ZIP File"
msgstr "素材 ZIP 檔"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid ""
"Can't determine a save path for lightmap images.\n"
"Save your scene and try again."
msgstr ""
"無法判斷光照圖的保存路徑。\n"
-"請保存場景(圖片將保存於相同資料夾),或是在 BackedLightmap 屬性內選擇一個保"
-"存路徑。"
+"請保存場景並重試。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
@@ -5094,27 +5113,27 @@ 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 ""
"Some mesh is invalid. Make sure the UV2 channel values are contained within "
"the [0.0,1.0] square region."
-msgstr ""
+msgstr "部分網格無效。請確保 UV2 通道的值位於 [0.0,1.0] 矩形內。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
"Godot editor was built without ray tracing support, lightmaps can't be baked."
msgstr ""
+"Godot 編輯器在建制時未啟用光線追蹤 (Ray Tracing) 支援,無法烘焙光照圖。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Bake Lightmaps"
msgstr "烘焙光照圖"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
-#, fuzzy
msgid "Select lightmap bake file:"
-msgstr "選擇樣板檔案"
+msgstr "選擇光照圖烘焙檔案:"
#: editor/plugins/camera_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -6194,9 +6213,8 @@ msgid "Can only set point into a ParticlesMaterial process material"
msgstr "僅可設為指向 ProticlesMaterial 處理材料"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Convert to CPUParticles2D"
-msgstr "轉換為 CPUParticles"
+msgstr "轉換為 CPUParticles2D"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
@@ -6842,6 +6860,14 @@ msgstr "關閉說明文件"
msgid "Run"
msgstr "執行"
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
+#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Search"
+msgstr "搜尋"
+
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Into"
msgstr "逐步執行"
@@ -6895,16 +6921,6 @@ msgstr ""
"磁碟中的下列檔案已更新。\n"
"請選擇於執行之操作:"
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Reload"
-msgstr "重新載入"
-
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/shader_editor_plugin.cpp
-msgid "Resave"
-msgstr "重新保存"
-
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Debugger"
msgstr "除錯工具"
@@ -6997,8 +7013,8 @@ msgstr "中斷點"
msgid "Go To"
msgstr "跳至"
-#: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Cut"
msgstr "剪下"
@@ -7221,6 +7237,10 @@ msgid "Yaw"
msgstr "偏航"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Size"
+msgstr "大小"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
msgstr "繪製的物件"
@@ -9847,6 +9867,10 @@ msgid "Projects"
msgstr "專案"
#: editor/project_manager.cpp
+msgid "Loading, please wait..."
+msgstr "載入中,請稍後..."
+
+#: editor/project_manager.cpp
msgid "Last Modified"
msgstr "最後修改時間"
@@ -10211,6 +10235,10 @@ msgstr "Autoload"
msgid "Plugins"
msgstr "外掛"
+#: editor/project_settings_editor.cpp
+msgid "Import Defaults"
+msgstr "匯入預設"
+
#: editor/property_editor.cpp
msgid "Preset..."
msgstr "預設設定..."
@@ -10458,6 +10486,14 @@ msgid "Instance Child Scene"
msgstr "實體化子場景"
#: editor/scene_tree_dock.cpp
+msgid "Can't paste root node into the same scene."
+msgstr "無法將跟節點貼到相同的場景中。"
+
+#: editor/scene_tree_dock.cpp
+msgid "Paste Node(s)"
+msgstr "貼上節點"
+
+#: editor/scene_tree_dock.cpp
msgid "Detach Script"
msgstr "取消附加腳本"
@@ -10580,6 +10616,10 @@ msgid "Attach Script"
msgstr "附加腳本"
#: editor/scene_tree_dock.cpp
+msgid "Cut Node(s)"
+msgstr "剪下節點"
+
+#: editor/scene_tree_dock.cpp
msgid "Remove Node(s)"
msgstr "移除節點"
@@ -11380,36 +11420,31 @@ msgstr "提供 MeshLibrary 予該 GridMap 以使用其網格。"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Begin Bake"
-msgstr ""
+msgstr "開始烘焙"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Preparing data structures"
-msgstr ""
+msgstr "正在準備資料結構"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Generate buffers"
-msgstr "產生 AABB"
+msgstr "產生緩衝"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Direct lighting"
-msgstr "方向"
+msgstr "向性光照"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Indirect lighting"
-msgstr "向右縮排"
+msgstr "非向性光照"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Post processing"
msgstr "後處理"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Plotting lightmaps"
-msgstr "正在繪製光照:"
+msgstr "正在繪製光照"
#: modules/mono/csharp_script.cpp
msgid "Class name can't be a reserved keyword"
@@ -11909,9 +11944,8 @@ msgid "Select device from the list"
msgstr "自清單中選擇裝置"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Unable to find the 'apksigner' tool."
-msgstr "找不到 zipalign 工具。"
+msgstr "找不到「apksigner」工具。"
#: platform/android/export/export.cpp
msgid ""
@@ -11928,14 +11962,12 @@ msgid "Release keystore incorrectly configured in the export preset."
msgstr "發行金鑰儲存區中不正確之組態設定至匯出預設設定。"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "A valid Android SDK path is required in Editor Settings."
-msgstr "編輯器設定中用於自定義設定之 Android SDK 路徑無效。"
+msgstr "必須於 [編輯器設定] 中提供一個有效的 Android SDK 路徑。"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Invalid Android SDK path in Editor Settings."
-msgstr "編輯器設定中用於自定義設定之 Android SDK 路徑無效。"
+msgstr "[編輯器設定] 中所指定的 Android SDK 路徑無效。"
#: platform/android/export/export.cpp
msgid "Missing 'platform-tools' directory!"
@@ -11943,12 +11975,11 @@ msgstr "缺少「platform-tools」資料夾!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK platform-tools' adb command."
-msgstr ""
+msgstr "找不到 Android SDK platform-tools 的 adb 指令。"
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Please check in the Android SDK directory specified in Editor Settings."
-msgstr "編輯器設定中用於自定義設定之 Android SDK 路徑無效。"
+msgstr "請檢查 [編輯器設定] 中所指定的 Android SDK 資料夾。"
#: platform/android/export/export.cpp
msgid "Missing 'build-tools' directory!"
@@ -11956,7 +11987,7 @@ msgstr "缺少「build-tools」資料夾!"
#: platform/android/export/export.cpp
msgid "Unable to find Android SDK build-tools' apksigner command."
-msgstr ""
+msgstr "找不到 Android SDK build-tools 的 apksigner 指令。"
#: platform/android/export/export.cpp
msgid "Invalid public key for APK expansion."
@@ -12204,6 +12235,14 @@ msgstr ""
msgid "An empty CollisionPolygon2D has no effect on collision."
msgstr "空白的 CollisionPolygon2D 不會產生任何碰撞效果。"
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode."
+msgstr "無效的多邊形。至少必須有三個點為「Solids」建構模式。"
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode."
+msgstr "無效的多邊形。至少必須有 2 個點為「Segments」建構模式。"
+
#: scene/2d/collision_shape_2d.cpp
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
@@ -12391,32 +12430,27 @@ msgstr "ARVROrigin 必須有一個 ARVRCamera 子節點。"
#: scene/3d/baked_lightmap.cpp
msgid "Finding meshes and lights"
-msgstr ""
+msgstr "正在尋找網格與光照"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing geometry (%d/%d)"
-msgstr "正在解析多邊形..."
+msgstr "正在解析幾何 (%d/%d)"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Preparing environment"
-msgstr "檢視環境"
+msgstr "正在準備環境"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Generating capture"
-msgstr "正在產生光照圖"
+msgstr "正在產生捕捉"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Saving lightmaps"
-msgstr "正在產生光照圖"
+msgstr "正在保存光照圖"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Done"
-msgstr "完成!"
+msgstr "完成"
#: scene/3d/collision_object.cpp
msgid ""
@@ -12494,11 +12528,6 @@ msgstr ""
"GLES2 視訊驅動程式不支援 GIProbes。\n"
"請改為使用 BakedLightmap。"
-#: scene/3d/interpolated_camera.cpp
-msgid ""
-"InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
-msgstr "InterpolatedCamera 已停止維護,且將於 Godot 4.0 中移除。"
-
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
msgstr "角度大於 90 度的 SpotLight 無法投射出陰影。"
@@ -12794,7 +12823,7 @@ msgstr "Viewport 大小必須大於 0 才可進行算繪。"
msgid ""
"The sampler port is connected but not used. Consider changing the source to "
"'SamplerPort'."
-msgstr ""
+msgstr "已連線至取樣器連結埠但並未使用。建議將來源設為「SamplerPort」。"
#: scene/resources/visual_shader_nodes.cpp
msgid "Invalid source for preview."
@@ -12824,6 +12853,10 @@ msgstr "Varying 變數只可在頂點函式中指派。"
msgid "Constants cannot be modified."
msgstr "不可修改常數。"
+#~ msgid ""
+#~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0."
+#~ msgstr "InterpolatedCamera 已停止維護,且將於 Godot 4.0 中移除。"
+
#~ msgid "No"
#~ msgstr "否"
diff --git a/main/main.cpp b/main/main.cpp
index d70f0eb291..aa925c508c 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -71,7 +71,6 @@
#include "servers/physics_server_3d.h"
#include "servers/register_server_types.h"
#include "servers/rendering/rendering_server_default.h"
-#include "servers/rendering/rendering_server_wrap_mt.h"
#include "servers/text_server.h"
#include "servers/xr_server.h"
@@ -124,7 +123,9 @@ static bool _start_success = false;
// Drivers
+String tablet_driver = "";
String text_driver = "";
+
static int text_driver_idx = -1;
static int display_driver_idx = -1;
static int audio_driver_idx = -1;
@@ -330,13 +331,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
- OS::get_singleton()->print(" --tablet-driver Tablet input driver (");
- for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
- if (i != 0)
- OS::get_singleton()->print(", ");
- OS::get_singleton()->print("'%s'", OS::get_singleton()->get_tablet_driver_name(i).utf8().get_data());
- }
- OS::get_singleton()->print(") (Windows only).\n");
+ OS::get_singleton()->print(" --tablet-driver Pen tablet input driver.\n");
OS::get_singleton()->print("\n");
#endif
@@ -400,6 +395,8 @@ Error Main::test_setup() {
GLOBAL_DEF("debug/settings/crash_handler/message",
String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues"));
+ translation_server = memnew(TranslationServer);
+
// From `Main::setup2()`.
preregister_module_types();
preregister_server_types();
@@ -407,6 +404,16 @@ Error Main::test_setup() {
register_core_singletons();
register_server_types();
+
+ translation_server->setup(); //register translations, load them, etc.
+ if (locale != "") {
+ translation_server->set_locale(locale);
+ }
+ translation_server->load_translations();
+ ResourceLoader::load_translation_remaps(); //load remaps for resources
+
+ ResourceLoader::load_path_remaps();
+
register_scene_types();
#ifdef TOOLS_ENABLED
@@ -446,6 +453,9 @@ void Main::test_cleanup() {
OS::get_singleton()->finalize();
+ if (translation_server) {
+ memdelete(translation_server);
+ }
if (globals) {
memdelete(globals);
}
@@ -516,10 +526,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
MAIN_PRINT("Main: Initialize Globals");
- globals = memnew(ProjectSettings);
input_map = memnew(InputMap);
+ globals = memnew(ProjectSettings);
- register_core_settings(); //here globals is present
+ register_core_settings(); //here globals are present
translation_server = memnew(TranslationServer);
performance = memnew(Performance);
@@ -528,8 +538,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
// Only flush stdout in debug builds by default, as spamming `print()` will
// decrease performance if this is enabled.
- GLOBAL_DEF("application/run/flush_stdout_on_print", false);
- GLOBAL_DEF("application/run/flush_stdout_on_print.debug", true);
+ GLOBAL_DEF_RST("application/run/flush_stdout_on_print", false);
+ GLOBAL_DEF_RST("application/run/flush_stdout_on_print.debug", true);
GLOBAL_DEF("debug/settings/crash_handler/message",
String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues"));
@@ -557,7 +567,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
String display_driver = "";
String audio_driver = "";
- String tablet_driver = "";
String project_path = ".";
bool upwards = false;
String debug_uri = "";
@@ -726,19 +735,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get() == "--tablet-driver") {
if (I->next()) {
tablet_driver = I->next()->get();
- bool found = false;
- for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
- if (tablet_driver == OS::get_singleton()->get_tablet_driver_name(i)) {
- found = true;
- }
- }
-
- if (!found) {
- OS::get_singleton()->print("Unknown tablet driver '%s', aborting.\n",
- tablet_driver.utf8().get_data());
- goto error;
- }
-
N = I->next()->next();
} else {
OS::get_singleton()->print("Missing tablet driver argument, aborting.\n");
@@ -1126,29 +1122,29 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
#endif
- GLOBAL_DEF("logging/file_logging/enable_file_logging", false);
+ GLOBAL_DEF("debug/file_logging/enable_file_logging", false);
// Only file logging by default on desktop platforms as logs can't be
// accessed easily on mobile/Web platforms (if at all).
// This also prevents logs from being created for the editor instance, as feature tags
// are disabled while in the editor (even if they should logically apply).
- GLOBAL_DEF("logging/file_logging/enable_file_logging.pc", true);
- GLOBAL_DEF("logging/file_logging/log_path", "user://logs/godot.log");
- GLOBAL_DEF("logging/file_logging/max_log_files", 5);
- ProjectSettings::get_singleton()->set_custom_property_info("logging/file_logging/max_log_files",
+ GLOBAL_DEF("debug/file_logging/enable_file_logging.pc", true);
+ GLOBAL_DEF("debug/file_logging/log_path", "user://logs/godot.log");
+ GLOBAL_DEF("debug/file_logging/max_log_files", 5);
+ ProjectSettings::get_singleton()->set_custom_property_info("debug/file_logging/max_log_files",
PropertyInfo(Variant::INT,
- "logging/file_logging/max_log_files",
+ "debug/file_logging/max_log_files",
PROPERTY_HINT_RANGE,
"0,20,1,or_greater")); //no negative numbers
if (!project_manager && !editor && FileAccess::get_create_func(FileAccess::ACCESS_USERDATA) &&
- GLOBAL_GET("logging/file_logging/enable_file_logging")) {
+ GLOBAL_GET("debug/file_logging/enable_file_logging")) {
// Don't create logs for the project manager as they would be written to
// the current working directory, which is inconvenient.
- String base_path = GLOBAL_GET("logging/file_logging/log_path");
- int max_files = GLOBAL_GET("logging/file_logging/max_log_files");
+ String base_path = GLOBAL_GET("debug/file_logging/log_path");
+ int max_files = GLOBAL_GET("debug/file_logging/max_log_files");
OS::get_singleton()->add_logger(memnew(RotatedFileLogger(base_path, max_files)));
}
- if (main_args.size() == 0 && String(GLOBAL_DEF("application/run/main_scene", "")) == "") {
+ if (main_args.size() == 0 && String(GLOBAL_GET("application/run/main_scene")) == "") {
#ifdef TOOLS_ENABLED
if (!editor && !project_manager) {
#endif
@@ -1178,30 +1174,32 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
_print_line_enabled = false;
}
+ Logger::set_flush_stdout_on_print(ProjectSettings::get_singleton()->get("application/run/flush_stdout_on_print"));
+
OS::get_singleton()->set_cmdline(execpath, main_args);
- GLOBAL_DEF("rendering/quality/driver/driver_name", "Vulkan");
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/driver/driver_name",
+ GLOBAL_DEF("rendering/driver/driver_name", "Vulkan");
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/driver/driver_name",
PropertyInfo(Variant::STRING,
- "rendering/quality/driver/driver_name",
+ "rendering/driver/driver_name",
PROPERTY_HINT_ENUM, "Vulkan"));
if (display_driver == "") {
- display_driver = GLOBAL_GET("rendering/quality/driver/driver_name");
+ display_driver = GLOBAL_GET("rendering/driver/driver_name");
}
- GLOBAL_DEF("display/window/size/width", 1024);
+ GLOBAL_DEF_BASIC("display/window/size/width", 1024);
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/width",
PropertyInfo(Variant::INT, "display/window/size/width",
PROPERTY_HINT_RANGE,
"0,7680,or_greater")); // 8K resolution
- GLOBAL_DEF("display/window/size/height", 600);
+ GLOBAL_DEF_BASIC("display/window/size/height", 600);
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/height",
PropertyInfo(Variant::INT, "display/window/size/height",
PROPERTY_HINT_RANGE,
"0,4320,or_greater")); // 8K resolution
- GLOBAL_DEF("display/window/size/resizable", true);
- GLOBAL_DEF("display/window/size/borderless", false);
- GLOBAL_DEF("display/window/size/fullscreen", false);
+ GLOBAL_DEF_BASIC("display/window/size/resizable", true);
+ GLOBAL_DEF_BASIC("display/window/size/borderless", false);
+ GLOBAL_DEF_BASIC("display/window/size/fullscreen", false);
GLOBAL_DEF("display/window/size/always_on_top", false);
GLOBAL_DEF("display/window/size/test_width", 0);
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_width",
@@ -1249,7 +1247,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
}
- GLOBAL_DEF("display/window/force_right_to_left_layout_direction", false);
+ GLOBAL_DEF("internationalization/rendering/force_right_to_left_layout_direction", false);
if (!force_lowdpi) {
OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false);
@@ -1268,28 +1266,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->_vsync_via_compositor = window_vsync_via_compositor;
- if (tablet_driver == "") { // specified in project.godot
- tablet_driver = GLOBAL_DEF_RST_NOVAL("display/window/tablet_driver", OS::get_singleton()->get_tablet_driver_name(0));
- }
-
- for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
- if (tablet_driver == OS::get_singleton()->get_tablet_driver_name(i)) {
- OS::get_singleton()->set_current_tablet_driver(OS::get_singleton()->get_tablet_driver_name(i));
- break;
- }
- }
-
- if (tablet_driver == "") {
- OS::get_singleton()->set_current_tablet_driver(OS::get_singleton()->get_tablet_driver_name(0));
- }
-
/* todo restore
OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false);
video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false);
*/
- GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation", 2);
- GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation.mobile", 3);
-
if (editor || project_manager) {
// The editor and project manager always detect and use hiDPI if needed
OS::get_singleton()->_allow_hidpi = true;
@@ -1298,7 +1278,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->_keep_screen_on = GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true);
if (rtm == -1) {
- rtm = GLOBAL_DEF("rendering/threads/thread_model", OS::RENDER_THREAD_SAFE);
+ rtm = GLOBAL_DEF("rendering/driver/threads/thread_model", OS::RENDER_THREAD_SAFE);
}
if (rtm >= 0 && rtm < 3) {
@@ -1326,7 +1306,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
if (audio_driver == "") { // specified in project.godot
- audio_driver = GLOBAL_DEF_RST_NOVAL("audio/driver", AudioDriverManager::get_driver(0)->get_name());
+ audio_driver = GLOBAL_DEF_RST_NOVAL("audio/driver/driver", AudioDriverManager::get_driver(0)->get_name());
}
for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
@@ -1360,7 +1340,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
}
- Engine::get_singleton()->set_iterations_per_second(GLOBAL_DEF("physics/common/physics_fps", 60));
+ Engine::get_singleton()->set_iterations_per_second(GLOBAL_DEF_BASIC("physics/common/physics_fps", 60));
ProjectSettings::get_singleton()->set_custom_property_info("physics/common/physics_fps",
PropertyInfo(Variant::INT, "physics/common/physics_fps",
PROPERTY_HINT_RANGE, "1,120,1,or_greater"));
@@ -1477,9 +1457,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
/* Determine text driver */
- GLOBAL_DEF("display/window/text_name", "");
if (text_driver == "") {
- text_driver = GLOBAL_GET("display/window/text_name");
+ text_driver = GLOBAL_GET("internationalization/rendering/text_driver");
}
if (text_driver != "") {
@@ -1508,7 +1487,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
}
}
}
- printf("Using %s text server...\n", TextServerManager::get_interface_name(text_driver_idx).utf8().get_data());
+ print_verbose("Using \"" + TextServerManager::get_interface_name(text_driver_idx) + "\" text server...");
/* Initialize Text Server */
@@ -1538,7 +1517,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
input = memnew(Input);
- /* Iniitalize Display Server */
+ /* Initialize Display Server */
{
String rendering_driver; // temp broken
@@ -1568,15 +1547,38 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
display_server->screen_set_orientation(window_orientation);
}
- /* Initialize Visual Server */
+ /* Initialize Pen Tablet Driver */
+
+ {
+ GLOBAL_DEF_RST_NOVAL("input_devices/pen_tablet/driver", "");
+ GLOBAL_DEF_RST_NOVAL("input_devices/pen_tablet/driver.Windows", "");
+ ProjectSettings::get_singleton()->set_custom_property_info("input_devices/pen_tablet/driver.Windows", PropertyInfo(Variant::STRING, "input_devices/pen_tablet/driver.Windows", PROPERTY_HINT_ENUM, "wintab,winink"));
+ }
- rendering_server = memnew(RenderingServerDefault);
- if (OS::get_singleton()->get_render_thread_mode() != OS::RENDER_THREAD_UNSAFE) {
- rendering_server = memnew(RenderingServerWrapMT(rendering_server,
- OS::get_singleton()->get_render_thread_mode() ==
- OS::RENDER_SEPARATE_THREAD));
+ if (tablet_driver == "") { // specified in project.godot
+ tablet_driver = GLOBAL_GET("input_devices/pen_tablet/driver");
+ if (tablet_driver == "") {
+ tablet_driver = DisplayServer::get_singleton()->tablet_get_driver_name(0);
+ }
}
+ for (int i = 0; i < DisplayServer::get_singleton()->tablet_get_driver_count(); i++) {
+ if (tablet_driver == DisplayServer::get_singleton()->tablet_get_driver_name(i)) {
+ DisplayServer::get_singleton()->tablet_set_current_driver(DisplayServer::get_singleton()->tablet_get_driver_name(i));
+ break;
+ }
+ }
+
+ if (DisplayServer::get_singleton()->tablet_get_current_driver() == "") {
+ DisplayServer::get_singleton()->tablet_set_current_driver(DisplayServer::get_singleton()->tablet_get_driver_name(0));
+ }
+
+ print_verbose("Using \"" + tablet_driver + "\" pen tablet driver...");
+
+ /* Initialize Visual Server */
+
+ rendering_server = memnew(RenderingServerDefault(OS::get_singleton()->get_render_thread_mode() == OS::RENDER_SEPARATE_THREAD));
+
rendering_server->init();
rendering_server->set_render_loop_enabled(!disable_render_loop);
@@ -1608,7 +1610,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
MAIN_PRINT("Main: Setup Logo");
-#ifdef JAVASCRIPT_ENABLED
+#if defined(JAVASCRIPT_ENABLED) || defined(ANDROID_ENABLED)
bool show_logo = false;
#else
bool show_logo = true;
@@ -1636,7 +1638,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
MAIN_PRINT("Main: Load Boot Image");
- Color clear = GLOBAL_DEF("rendering/environment/default_clear_color", Color(0.3, 0.3, 0.3));
+ Color clear = GLOBAL_DEF("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3));
RenderingServer::get_singleton()->set_default_clear_color(clear);
if (show_logo) { //boot logo!
@@ -1660,7 +1662,13 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
}
}
- Color boot_bg_color = GLOBAL_DEF("application/boot_splash/bg_color", boot_splash_bg_color);
+#if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH)
+ const Color boot_bg_color =
+ GLOBAL_DEF("application/boot_splash/bg_color",
+ (editor || project_manager) ? boot_splash_editor_bg_color : boot_splash_bg_color);
+#else
+ const Color boot_bg_color = GLOBAL_DEF("application/boot_splash/bg_color", boot_splash_bg_color);
+#endif
if (boot_logo.is_valid()) {
RenderingServer::get_singleton()->set_boot_image(boot_logo, boot_bg_color, boot_logo_scale,
boot_logo_filter);
@@ -1689,7 +1697,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
MAIN_PRINT("Main: DCC");
RenderingServer::get_singleton()->set_default_clear_color(
- GLOBAL_DEF("rendering/environment/default_clear_color", Color(0.3, 0.3, 0.3)));
+ GLOBAL_DEF("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3)));
GLOBAL_DEF("application/config/icon", String());
ProjectSettings::get_singleton()->set_custom_property_info("application/config/icon",
@@ -1742,6 +1750,19 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
register_scene_types();
+#ifdef TOOLS_ENABLED
+ ClassDB::set_current_api(ClassDB::API_EDITOR);
+ EditorNode::register_editor_types();
+
+ ClassDB::set_current_api(ClassDB::API_CORE);
+
+#endif
+
+ MAIN_PRINT("Main: Load Modules, Physics, Drivers, Scripts");
+
+ register_platform_apis();
+ register_module_types();
+
GLOBAL_DEF("display/mouse_cursor/custom_image", String());
GLOBAL_DEF("display/mouse_cursor/custom_image_hotspot", Vector2());
GLOBAL_DEF("display/mouse_cursor/tooltip_position_offset", Point2(10, 10));
@@ -1758,18 +1779,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
Input::get_singleton()->set_custom_mouse_cursor(cursor, Input::CURSOR_ARROW, hotspot);
}
}
-#ifdef TOOLS_ENABLED
- ClassDB::set_current_api(ClassDB::API_EDITOR);
- EditorNode::register_editor_types();
-
- ClassDB::set_current_api(ClassDB::API_CORE);
-
-#endif
-
- MAIN_PRINT("Main: Load Modules, Physics, Drivers, Scripts");
-
- register_platform_apis();
- register_module_types();
camera_server = CameraServer::create();
@@ -1793,7 +1802,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
if (!project_manager) {
// If not running the project manager, and now that the engine is
// able to load resources, load the global shader variables.
- // If running on editor, dont load the textures because the editor
+ // If running on editor, don't load the textures because the editor
// may want to import them first. Editor will reload those later.
rendering_server->global_variables_load_settings(!editor);
}
@@ -1801,7 +1810,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
_start_success = true;
locale = String();
- ClassDB::set_current_api(ClassDB::API_NONE); //no more api is registered at this point
+ ClassDB::set_current_api(ClassDB::API_NONE); //no more APIs are registered at this point
print_verbose("CORE API HASH: " + uitos(ClassDB::get_api_hash(ClassDB::API_CORE)));
print_verbose("EDITOR API HASH: " + uitos(ClassDB::get_api_hash(ClassDB::API_EDITOR)));
@@ -1976,8 +1985,8 @@ bool Main::start() {
#endif
- if (script == "" && game_path == "" && String(GLOBAL_DEF("application/run/main_scene", "")) != "") {
- game_path = GLOBAL_DEF("application/run/main_scene", "");
+ if (script == "" && game_path == "" && String(GLOBAL_GET("application/run/main_scene")) != "") {
+ game_path = GLOBAL_GET("application/run/main_scene");
}
MainLoop *main_loop = nullptr;
@@ -1992,7 +2001,7 @@ bool Main::start() {
if (check_only) {
if (!script_res->is_valid()) {
- OS::get_singleton()->set_exit_code(1);
+ OS::get_singleton()->set_exit_code(EXIT_FAILURE);
}
return false;
}
@@ -2152,10 +2161,10 @@ bool Main::start() {
if (!editor && !project_manager) {
//standard helpers that can be changed from main config
- String stretch_mode = GLOBAL_DEF("display/window/stretch/mode", "disabled");
- String stretch_aspect = GLOBAL_DEF("display/window/stretch/aspect", "ignore");
- Size2i stretch_size = Size2i(GLOBAL_DEF("display/window/size/width", 0),
- GLOBAL_DEF("display/window/size/height", 0));
+ String stretch_mode = GLOBAL_DEF_BASIC("display/window/stretch/mode", "disabled");
+ String stretch_aspect = GLOBAL_DEF_BASIC("display/window/stretch/aspect", "ignore");
+ Size2i stretch_size = Size2i(GLOBAL_DEF_BASIC("display/window/size/width", 0),
+ GLOBAL_DEF_BASIC("display/window/size/height", 0));
Window::ContentScaleMode cs_sm = Window::CONTENT_SCALE_MODE_DISABLED;
if (stretch_mode == "canvas_items") {
@@ -2195,30 +2204,30 @@ bool Main::start() {
bool snap_controls = GLOBAL_DEF("gui/common/snap_controls_to_pixels", true);
sml->get_root()->set_snap_controls_to_pixels(snap_controls);
- bool font_oversampling = GLOBAL_DEF("rendering/quality/dynamic_fonts/use_oversampling", true);
+ bool font_oversampling = GLOBAL_DEF("gui/fonts/dynamic_fonts/use_oversampling", true);
sml->get_root()->set_use_font_oversampling(font_oversampling);
- int texture_filter = GLOBAL_DEF("rendering/canvas_textures/default_texture_filter", 1);
- int texture_repeat = GLOBAL_DEF("rendering/canvas_textures/default_texture_repeat", 0);
+ int texture_filter = GLOBAL_DEF("rendering/textures/canvas_textures/default_texture_filter", 1);
+ int texture_repeat = GLOBAL_DEF("rendering/textures/canvas_textures/default_texture_repeat", 0);
sml->get_root()->set_default_canvas_item_texture_filter(
Viewport::DefaultCanvasItemTextureFilter(texture_filter));
sml->get_root()->set_default_canvas_item_texture_repeat(
Viewport::DefaultCanvasItemTextureRepeat(texture_repeat));
} else {
- GLOBAL_DEF("display/window/stretch/mode", "disabled");
+ GLOBAL_DEF_BASIC("display/window/stretch/mode", "disabled");
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/mode",
PropertyInfo(Variant::STRING,
"display/window/stretch/mode",
PROPERTY_HINT_ENUM,
"disabled,canvas_items,viewport"));
- GLOBAL_DEF("display/window/stretch/aspect", "ignore");
+ GLOBAL_DEF_BASIC("display/window/stretch/aspect", "ignore");
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/aspect",
PropertyInfo(Variant::STRING,
"display/window/stretch/aspect",
PROPERTY_HINT_ENUM,
"ignore,keep,keep_width,keep_height,expand"));
- GLOBAL_DEF("display/window/stretch/shrink", 1.0);
+ GLOBAL_DEF_BASIC("display/window/stretch/shrink", 1.0);
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/shrink",
PropertyInfo(Variant::FLOAT,
"display/window/stretch/shrink",
@@ -2226,18 +2235,18 @@ bool Main::start() {
"1.0,8.0,0.1"));
sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true));
sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true));
- GLOBAL_DEF("gui/common/snap_controls_to_pixels", true);
- GLOBAL_DEF("rendering/quality/dynamic_fonts/use_oversampling", true);
+ GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
+ GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true);
- GLOBAL_DEF("rendering/canvas_textures/default_texture_filter", 1);
+ GLOBAL_DEF_BASIC("rendering/textures/canvas_textures/default_texture_filter", 1);
ProjectSettings::get_singleton()->set_custom_property_info(
- "rendering/canvas_textures/default_texture_filter",
- PropertyInfo(Variant::INT, "rendering/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM,
+ "rendering/textures/canvas_textures/default_texture_filter",
+ PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM,
"Nearest,Linear,MipmapLinear,MipmapNearest"));
- GLOBAL_DEF("rendering/canvas_textures/default_texture_repeat", 0);
+ GLOBAL_DEF_BASIC("rendering/textures/canvas_textures/default_texture_repeat", 0);
ProjectSettings::get_singleton()->set_custom_property_info(
- "rendering/canvas_textures/default_texture_repeat",
- PropertyInfo(Variant::INT, "rendering/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM,
+ "rendering/textures/canvas_textures/default_texture_repeat",
+ PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM,
"Disable,Enable,Mirror"));
}
@@ -2451,6 +2460,7 @@ bool Main::iteration() {
for (int iters = 0; iters < advance.physics_steps; ++iters) {
uint64_t physics_begin = OS::get_singleton()->get_ticks_usec();
+ PhysicsServer3D::get_singleton()->sync();
PhysicsServer3D::get_singleton()->flush_queries();
PhysicsServer2D::get_singleton()->sync();
@@ -2465,6 +2475,7 @@ bool Main::iteration() {
message_queue->flush();
+ PhysicsServer3D::get_singleton()->end_sync();
PhysicsServer3D::get_singleton()->step(physics_step * time_scale);
PhysicsServer2D::get_singleton()->end_sync();
@@ -2574,8 +2585,10 @@ void Main::force_redraw() {
* so that the engine closes cleanly without leaking memory or crashing.
* The order matters as some of those steps are linked with each other.
*/
-void Main::cleanup() {
- ERR_FAIL_COND(!_start_success);
+void Main::cleanup(bool p_force) {
+ if (!p_force) {
+ ERR_FAIL_COND(!_start_success);
+ }
EngineDebugger::deinitialize();
@@ -2599,7 +2612,7 @@ void Main::cleanup() {
// Sync pending commands that may have been queued from a different thread during ScriptServer finalization
RenderingServer::get_singleton()->sync();
- //clear global shader variables before scene and other graphics stuff is deinitialized.
+ //clear global shader variables before scene and other graphics stuff are deinitialized.
rendering_server->global_variables_clear();
#ifdef TOOLS_ENABLED
diff --git a/main/main.h b/main/main.h
index 9e606c188d..f4fff6b97e 100644
--- a/main/main.h
+++ b/main/main.h
@@ -59,7 +59,7 @@ public:
static bool is_iterating();
- static void cleanup();
+ static void cleanup(bool p_force = false);
};
// Test main override is for the testing behaviour.
diff --git a/main/main_builders.py b/main/main_builders.py
index aa91201c3e..c880bfa3c4 100644
--- a/main/main_builders.py
+++ b/main/main_builders.py
@@ -17,6 +17,7 @@ def make_splash(target, source, env):
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef BOOT_SPLASH_H\n")
g.write("#define BOOT_SPLASH_H\n")
+ # Use a neutral gray color to better fit various kinds of projects.
g.write("static const Color boot_splash_bg_color = Color(0.14, 0.14, 0.14);\n")
g.write("static const unsigned char boot_splash_png[] = {\n")
for i in range(len(buf)):
@@ -36,7 +37,9 @@ def make_splash_editor(target, source, env):
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef BOOT_SPLASH_EDITOR_H\n")
g.write("#define BOOT_SPLASH_EDITOR_H\n")
- g.write("static const Color boot_splash_editor_bg_color = Color(0.14, 0.14, 0.14);\n")
+ # The editor splash background color is taken from the default editor theme's background color.
+ # This helps achieve a visually "smoother" transition between the splash screen and the editor.
+ g.write("static const Color boot_splash_editor_bg_color = Color(0.125, 0.145, 0.192);\n")
g.write("static const unsigned char boot_splash_editor_png[] = {\n")
for i in range(len(buf)):
g.write(str(buf[i]) + ",\n")
diff --git a/main/performance.cpp b/main/performance.cpp
index 1a422dc499..a2e53f2ee2 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -119,7 +119,7 @@ String Performance::get_monitor_name(Monitor p_monitor) const {
"physics_3d/active_objects",
"physics_3d/collision_pairs",
"physics_3d/islands",
- "audio/output_latency",
+ "audio/driver/output_latency",
};
diff --git a/methods.py b/methods.py
index 15eb82ae74..725fb36caa 100644
--- a/methods.py
+++ b/methods.py
@@ -6,9 +6,11 @@ from collections import OrderedDict
# We need to define our own `Action` method to control the verbosity of output
# and whenever we need to run those commands in a subprocess on some platforms.
-from SCons.Script import Action
from SCons import Node
+from SCons.Script import Action
+from SCons.Script import ARGUMENTS
from SCons.Script import Glob
+from SCons.Variables.BoolVariable import _text2bool
from platform_methods import run_in_subprocess
@@ -145,34 +147,97 @@ def parse_cg_file(fname, uniforms, sizes, conditionals):
fs.close()
-def detect_modules(at_path):
- module_list = OrderedDict() # name : path
+def get_cmdline_bool(option, default):
+ """We use `ARGUMENTS.get()` to check if options were manually overridden on the command line,
+ and SCons' _text2bool helper to convert them to booleans, otherwise they're handled as strings.
+ """
+ cmdline_val = ARGUMENTS.get(option)
+ if cmdline_val is not None:
+ return _text2bool(cmdline_val)
+ else:
+ return default
- modules_glob = os.path.join(at_path, "*")
- files = glob.glob(modules_glob)
- files.sort() # so register_module_types does not change that often, and also plugins are registered in alphabetic order
- for x in files:
- if not is_module(x):
- continue
- name = os.path.basename(x)
- path = x.replace("\\", "/") # win32
- module_list[name] = path
+def detect_modules(search_path, recursive=False):
+ """Detects and collects a list of C++ modules at specified path
- return module_list
+ `search_path` - a directory path containing modules. The path may point to
+ a single module, which may have other nested modules. A module must have
+ "register_types.h", "SCsub", "config.py" files created to be detected.
+
+ `recursive` - if `True`, then all subdirectories are searched for modules as
+ specified by the `search_path`, otherwise collects all modules under the
+ `search_path` directory. If the `search_path` is a module, it is collected
+ in all cases.
+
+ Returns an `OrderedDict` with module names as keys, and directory paths as
+ values. If a path is relative, then it is a built-in module. If a path is
+ absolute, then it is a custom module collected outside of the engine source.
+ """
+ modules = OrderedDict()
+
+ def add_module(path):
+ module_name = os.path.basename(path)
+ module_path = path.replace("\\", "/") # win32
+ modules[module_name] = module_path
+
+ def is_engine(path):
+ # Prevent recursively detecting modules in self and other
+ # Godot sources when using `custom_modules` build option.
+ version_path = os.path.join(path, "version.py")
+ if os.path.exists(version_path):
+ with open(version_path) as f:
+ if 'short_name = "godot"' in f.read():
+ return True
+ return False
+
+ def get_files(path):
+ files = glob.glob(os.path.join(path, "*"))
+ # Sort so that `register_module_types` does not change that often,
+ # and plugins are registered in alphabetic order as well.
+ files.sort()
+ return files
+
+ if not recursive:
+ if is_module(search_path):
+ add_module(search_path)
+ for path in get_files(search_path):
+ if is_engine(path):
+ continue
+ if is_module(path):
+ add_module(path)
+ else:
+ to_search = [search_path]
+ while to_search:
+ path = to_search.pop()
+ if is_module(path):
+ add_module(path)
+ for child in get_files(path):
+ if not os.path.isdir(child):
+ continue
+ if is_engine(child):
+ continue
+ to_search.insert(0, child)
+ return modules
def is_module(path):
- return os.path.isdir(path) and os.path.exists(os.path.join(path, "SCsub"))
+ if not os.path.isdir(path):
+ return False
+ must_exist = ["register_types.h", "SCsub", "config.py"]
+ for f in must_exist:
+ if not os.path.exists(os.path.join(path, f)):
+ return False
+ return True
-def write_modules(module_list):
+def write_modules(modules):
includes_cpp = ""
preregister_cpp = ""
register_cpp = ""
unregister_cpp = ""
- for name, path in module_list.items():
+ for name, path in modules.items():
try:
with open(os.path.join(path, "register_types.h")):
includes_cpp += '#include "' + path + '/register_types.h"\n'
@@ -230,8 +295,6 @@ def convert_custom_modules_path(path):
raise ValueError(err_msg % "point to an existing directory.")
if path == os.path.realpath("modules"):
raise ValueError(err_msg % "be a directory other than built-in `modules` directory.")
- if is_module(path):
- raise ValueError(err_msg % "point to a directory with modules, not a single module.")
return path
@@ -271,7 +334,7 @@ def use_windows_spawn_fix(self, platform=None):
# On Windows, due to the limited command line length, when creating a static library
# from a very high number of objects SCons will invoke "ar" once per object file;
# that makes object files with same names to be overwritten so the last wins and
- # the library looses symbols defined by overwritten objects.
+ # the library loses symbols defined by overwritten objects.
# By enabling quick append instead of the default mode (replacing), libraries will
# got built correctly regardless the invocation strategy.
# Furthermore, since SCons will rebuild the library from scratch when an object file
@@ -415,7 +478,7 @@ def detect_visual_c_compiler_version(tools_env):
# and not scons setup environment (env)... so make sure you call the right environment on it or it will fail to detect
# the proper vc version that will be called
- # There is no flag to give to visual c compilers to set the architecture, ie scons bits argument (32,64,ARM etc)
+ # There is no flag to give to visual c compilers to set the architecture, i.e. scons bits argument (32,64,ARM etc)
# There are many different cl.exe files that are run, and each one compiles & links to a different architecture
# As far as I know, the only way to figure out what compiler will be run when Scons calls cl.exe via Program()
# is to check the PATH variable and figure out which one will be called first. Code below does that and returns:
@@ -570,7 +633,7 @@ def generate_vs_project(env, num_jobs):
'call "' + batch_file + '" !plat!',
]
- # windows allows us to have spaces in paths, so we need
+ # Windows allows us to have spaces in paths, so we need
# to double quote off the directory. However, the path ends
# in a backslash, so we need to remove this, lest it escape the
# last double quote off, confusing MSBuild
diff --git a/misc/dist/html/editor.html b/misc/dist/html/editor.html
index 53ad826730..99ac2379ce 100644
--- a/misc/dist/html/editor.html
+++ b/misc/dist/html/editor.html
@@ -2,11 +2,20 @@
<html xmlns='http://www.w3.org/1999/xhtml' lang='' xml:lang=''>
<head>
<meta charset='utf-8' />
- <meta name='viewport' content='width=device-width, user-scalable=no' />
+ <meta name='viewport' content='width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no' />
+ <meta name="mobile-web-app-capable" content="yes" />
+ <meta name="apple-mobile-web-app-capable" content="yes" />
+ <meta name="application-name" content="Godot" />
+ <meta name="apple-mobile-web-app-title" content="Godot" />
+ <meta name="theme-color" content="#478cbf" />
+ <meta name="msapplication-navbutton-color" content="#478cbf" />
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
+ <meta name="msapplication-starturl" content="/latest" />
<link id='-gd-engine-icon' rel='icon' type='image/png' href='favicon.png' />
- <title>Godot Engine Web Editor ($GODOT_VERSION)</title>
- <style type='text/css'>
-
+ <link rel="apple-touch-icon" type="image/png" href="favicon.png" />
+ <link rel="manifest" href="manifest.json" />
+ <title>Godot Engine Web Editor (@GODOT_VERSION@)</title>
+ <style>
*:focus {
/* More visible outline for better keyboard navigation. */
outline: 0.125rem solid hsl(220, 100%, 62.5%);
@@ -40,13 +49,30 @@
filter: brightness(82.5%);
}
+ #tabs-buttons {
+ /* Match the default background color of the editor window for a seamless appearance. */
+ background-color: #202531;
+ }
+
+ #tab-game {
+ /* Use a pure black background to better distinguish the running project */
+ /* from the editor window, and to use a more neutral background color (no tint). */
+ background-color: black;
+ /* Make the background span the entire page height. */
+ min-height: 100vh;
+ }
+
#canvas, #gameCanvas {
display: block;
margin: 0;
color: white;
}
- #canvas:focus, #gameCanvas:focus {
+ /* Don't show distracting focus outlines for the main tabs' contents. */
+ #tab-editor canvas:focus,
+ #tab-game canvas:focus,
+ #canvas:focus,
+ #gameCanvas:focus {
outline: none;
}
@@ -189,7 +215,7 @@
<br />
<img src="logo.svg" width="1024" height="414" style="width: auto; height: auto; max-width: 85%; max-height: 250px" />
<br />
- $GODOT_VERSION
+ @GODOT_VERSION@
<br />
<a href="releases/">Need an old version?</a>
<br />
@@ -200,9 +226,11 @@
<a href="demo.zip">(Try this for example)</a>
<br />
<br />
- <button id="startButton" class="btn" style="margin-bottom: 4rem">Start Godot editor</button>
+ <button id="startButton" class="btn" style="margin-bottom: 4rem; font-weight: 700">Start Godot editor</button>
+ <br />
+ <button class="btn" onclick="clearPersistence()" style="margin-bottom: 1.5rem">Clear persistent data</button>
<br />
- <button class="btn" onclick="clearPersistence()">Clear persistent data</button>
+ <a href="https://docs.godotengine.org/en/latest/tutorials/editor/using_the_web_editor.html">Web editor documentation</a>
</div>
</div>
<div id='tab-editor' style="display: none;">
@@ -232,11 +260,17 @@
<div id='status-notice' class='godot' style='display: none;'></div>
</div>
</div>
+ <script>
+ window.addEventListener("load", () => {
+ if ("serviceWorker" in navigator) {
+ navigator.serviceWorker.register("service.worker.js");
+ }
+ });
+ </script>
+ <script src='godot.tools.js'></script>
+ <script>//<![CDATA[
- <script type='text/javascript' src='godot.tools.js'></script>
- <script type='text/javascript'>//<![CDATA[
-
- var engine = new Engine;
+ var editor = null;
var game = null;
var setStatusMode;
var setStatusNotice;
@@ -258,13 +292,11 @@
});
}
- if (!window.confirm("Are you sure you want to delete all the locally stored files?")) {
+ if (!window.confirm("Are you sure you want to delete all the locally stored files?\nClicking \"OK\" will permanently remove your projects and editor settings!")) {
return;
}
Promise.all([
- deleteDB("/home/web_user/projects"),
- deleteDB("/home/web_user/.config"),
- deleteDB("/home/web_user/.cache"),
+ deleteDB("/home/web_user"),
]).then(function(results) {
alert("Done.");
}).catch(function (err) {
@@ -286,6 +318,10 @@
tabs.forEach(function (elem) {
if (elem.id == 'tab-' + name) {
elem.style.display = 'block';
+ if (name == 'editor' || name == 'game') {
+ const canvas = document.getElementById(name + '-canvas');
+ canvas.focus();
+ }
} else {
elem.style.display = 'none';
}
@@ -319,14 +355,14 @@
function closeEditor() {
closeGame();
- if (engine) {
- engine.requestQuit();
+ if (editor) {
+ editor.requestQuit();
}
}
function startEditor(zip) {
const INDETERMINATE_STATUS_STEP_MS = 100;
- const persistentPaths = ['/home/web_user/.config', '/home/web_user/.cache', '/home/web_user/projects'];
+ const persistentPaths = ['/home/web_user'];
var editorCanvas = document.getElementById('editor-canvas');
var gameCanvas = document.getElementById('game-canvas');
@@ -334,6 +370,7 @@
var statusProgressInner = document.getElementById('status-progress-inner');
var statusIndeterminate = document.getElementById('status-indeterminate');
var statusNotice = document.getElementById('status-notice');
+ var headerDiv = document.getElementById('tabs-buttons');
var initializing = true;
var statusMode = 'hidden';
@@ -347,16 +384,23 @@
}
requestAnimationFrame(animate);
+ var lastScale = 0;
+ var lastWidth = 0;
+ var lastHeight = 0;
function adjustCanvasDimensions() {
var scale = window.devicePixelRatio || 1;
- var header = document.getElementById('tabs-buttons');
- var headerHeight = header.offsetHeight + 1;
+ var headerHeight = headerDiv.offsetHeight + 1;
var width = window.innerWidth;
var height = window.innerHeight - headerHeight;
- editorCanvas.width = width * scale;
- editorCanvas.height = height * scale;
- editorCanvas.style.width = width + "px";
- editorCanvas.style.height = height + "px";
+ if (lastScale !== scale || lastWidth !== width || lastHeight !== height) {
+ editorCanvas.width = width * scale;
+ editorCanvas.height = height * scale;
+ editorCanvas.style.width = width + "px";
+ editorCanvas.style.height = height + "px";
+ lastScale = scale;
+ lastWidth = width;
+ lastHeight = height;
+ }
}
animationCallbacks.push(adjustCanvasDimensions);
adjustCanvasDimensions();
@@ -410,24 +454,23 @@
});
};
- engine.setProgressFunc((current, total) => {
- if (total > 0) {
- statusProgressInner.style.width = current/total * 100 + '%';
- setStatusMode('progress');
- if (current === total) {
- // wait for progress bar animation
- setTimeout(() => {
- setStatusMode('indeterminate');
- }, 100);
- }
- } else {
- setStatusMode('indeterminate');
- }
- });
-
- engine.setPersistentPaths(persistentPaths);
+ const gameConfig = {
+ 'persistentPaths': persistentPaths,
+ 'unloadAfterInit': false,
+ 'canvas': gameCanvas,
+ 'canvasResizePolicy': 1,
+ 'onExit': function () {
+ setGameTabEnabled(false);
+ showTab('editor');
+ game = null;
+ },
+ };
- engine.setOnExecute(function(args) {
+ var OnEditorExit = function () {
+ showTab('loader');
+ setLoaderEnabled(true);
+ };
+ function Execute(args) {
const is_editor = args.filter(function(v) { return v == '--editor' || v == '-e' }).length != 0;
const is_project_manager = args.filter(function(v) { return v == '--project-manager' }).length != 0;
const is_game = !is_editor && !is_project_manager;
@@ -440,42 +483,60 @@
return;
}
setGameTabEnabled(true);
- game = new Engine();
- game.setPersistentPaths(persistentPaths);
- game.setUnloadAfterInit(false);
- game.setOnExecute(engine.onExecute);
- game.setCanvas(gameCanvas);
- game.setCanvasResizedOnStart(true);
- game.setOnExit(function() {
- setGameTabEnabled(false);
- showTab('editor');
- game = null;
- });
+ game = new Engine(gameConfig);
showTab('game');
game.init().then(function() {
requestAnimationFrame(function() {
- game.start.apply(game, args).then(function() {
+ game.start({'args': args}).then(function() {
gameCanvas.focus();
});
});
});
} else { // New editor instances will be run in the same canvas. We want to wait for it to exit.
- engine.setOnExit(function(code) {
+ OnEditorExit = function(code) {
setLoaderEnabled(true);
setTimeout(function() {
- engine.init().then(function() {
+ editor.init().then(function() {
setLoaderEnabled(false);
- engine.setOnExit(function() {
+ OnEditorExit = function() {
showTab('loader');
setLoaderEnabled(true);
- });
- engine.start.apply(engine, args);
+ };
+ editor.start({'args': args, 'persistentDrops': is_project_manager});
});
}, 0);
- engine.setOnExit(null);
- });
+ OnEditorExit = null;
+ };
}
- });
+ }
+
+ const editorConfig = {
+ 'unloadAfterInit': false,
+ 'onProgress': function progressFunction (current, total) {
+ if (total > 0) {
+ statusProgressInner.style.width = current/total * 100 + '%';
+ setStatusMode('progress');
+ if (current === total) {
+ // wait for progress bar animation
+ setTimeout(() => {
+ setStatusMode('indeterminate');
+ }, 100);
+ }
+ } else {
+ setStatusMode('indeterminate');
+ }
+ },
+ 'canvas': editorCanvas,
+ 'canvasResizePolicy': 0,
+ 'onExit': function() {
+ if (OnEditorExit) {
+ OnEditorExit();
+ }
+ },
+ 'onExecute': Execute,
+ 'persistentPaths': persistentPaths,
+ };
+ editor = new Engine(editorConfig);
function displayFailureNotice(err) {
var msg = err.message || err;
@@ -489,26 +550,20 @@
displayFailureNotice('WebGL not available');
} else {
setStatusMode('indeterminate');
- engine.setCanvas(editorCanvas);
- engine.setUnloadAfterInit(false); // Don't want to reload when starting game.
- engine.init('godot.tools').then(function() {
+ editor.init('godot.tools').then(function() {
if (zip) {
- engine.copyToFS("/home/web_user/preload.zip", zip);
+ editor.copyToFS("/tmp/preload.zip", zip);
}
try {
// Avoid user creating project in the persistent root folder.
- engine.copyToFS("/home/web_user/projects/keep", new Uint8Array());
+ editor.copyToFS("/home/web_user/keep", new Uint8Array());
} catch(e) {
// File exists
}
//selectVideoMode();
showTab('editor');
setLoaderEnabled(false);
- engine.setOnExit(function() {
- showTab('loader');
- setLoaderEnabled(true);
- });
- engine.start('--video-driver', video_driver).then(function() {
+ editor.start({'args': ['--project-manager', '--video-driver', video_driver], 'persistentDrops': true}).then(function() {
setStatusMode('hidden');
initializing = false;
});
diff --git a/misc/dist/html/full-size.html b/misc/dist/html/full-size.html
index 85c5305b85..abc0479739 100644
--- a/misc/dist/html/full-size.html
+++ b/misc/dist/html/full-size.html
@@ -134,22 +134,14 @@ $GODOT_HEAD_INCLUDE
<div id='status-notice' class='godot' style='display: none;'></div>
</div>
- <script type='text/javascript' src='$GODOT_BASENAME.js'></script>
+ <script type='text/javascript' src='$GODOT_URL'></script>
<script type='text/javascript'>//<![CDATA[
- var engine = new Engine;
- var setStatusMode;
- var setStatusNotice;
+ const GODOT_CONFIG = $GODOT_CONFIG;
+ var engine = new Engine(GODOT_CONFIG);
(function() {
- const EXECUTABLE_NAME = '$GODOT_BASENAME';
- const MAIN_PACK = '$GODOT_BASENAME.pck';
- const EXTRA_ARGS = JSON.parse('$GODOT_ARGS');
- const GDNATIVE_LIBS = [$GODOT_GDNATIVE_LIBS];
const INDETERMINATE_STATUS_STEP_MS = 100;
- const FULL_WINDOW = $GODOT_FULL_WINDOW;
-
- var canvas = document.getElementById('canvas');
var statusProgress = document.getElementById('status-progress');
var statusProgressInner = document.getElementById('status-progress-inner');
var statusIndeterminate = document.getElementById('status-indeterminate');
@@ -157,9 +149,6 @@ $GODOT_HEAD_INCLUDE
var initializing = true;
var statusMode = 'hidden';
- var lastWidth = 0;
- var lastHeight = 0;
- var lastScale = 0;
var animationCallbacks = [];
function animate(time) {
@@ -168,26 +157,8 @@ $GODOT_HEAD_INCLUDE
}
requestAnimationFrame(animate);
- function adjustCanvasDimensions() {
- const scale = window.devicePixelRatio || 1;
- if (lastWidth != window.innerWidth || lastHeight != window.innerHeight || lastScale != scale) {
- lastScale = scale;
- lastWidth = window.innerWidth;
- lastHeight = window.innerHeight;
- canvas.width = Math.floor(lastWidth * scale);
- canvas.height = Math.floor(lastHeight * scale);
- canvas.style.width = lastWidth + "px";
- canvas.style.height = lastHeight + "px";
- }
- }
- if (FULL_WINDOW) {
- animationCallbacks.push(adjustCanvasDimensions);
- adjustCanvasDimensions();
- } else {
- engine.setCanvasResizedOnStart(true);
- }
+ function setStatusMode(mode) {
- setStatusMode = function setStatusMode(mode) {
if (statusMode === mode || !initializing)
return;
[statusProgress, statusIndeterminate, statusNotice].forEach(elem => {
@@ -213,7 +184,7 @@ $GODOT_HEAD_INCLUDE
throw new Error('Invalid status mode');
}
statusMode = mode;
- };
+ }
function animateStatusIndeterminate(ms) {
var i = Math.floor(ms / INDETERMINATE_STATUS_STEP_MS % 8);
@@ -225,7 +196,7 @@ $GODOT_HEAD_INCLUDE
}
}
- setStatusNotice = function setStatusNotice(text) {
+ function setStatusNotice(text) {
while (statusNotice.lastChild) {
statusNotice.removeChild(statusNotice.lastChild);
}
@@ -236,21 +207,6 @@ $GODOT_HEAD_INCLUDE
});
};
- engine.setProgressFunc((current, total) => {
- if (total > 0) {
- statusProgressInner.style.width = current/total * 100 + '%';
- setStatusMode('progress');
- if (current === total) {
- // wait for progress bar animation
- setTimeout(() => {
- setStatusMode('indeterminate');
- }, 500);
- }
- } else {
- setStatusMode('indeterminate');
- }
- });
-
function displayFailureNotice(err) {
var msg = err.message || err;
console.error(msg);
@@ -263,9 +219,22 @@ $GODOT_HEAD_INCLUDE
displayFailureNotice('WebGL not available');
} else {
setStatusMode('indeterminate');
- engine.setCanvas(canvas);
- engine.setGDNativeLibraries(GDNATIVE_LIBS);
- engine.startGame(EXECUTABLE_NAME, MAIN_PACK, EXTRA_ARGS).then(() => {
+ engine.startGame({
+ 'onProgress': function (current, total) {
+ if (total > 0) {
+ statusProgressInner.style.width = current/total * 100 + '%';
+ setStatusMode('progress');
+ if (current === total) {
+ // wait for progress bar animation
+ setTimeout(() => {
+ setStatusMode('indeterminate');
+ }, 500);
+ }
+ } else {
+ setStatusMode('indeterminate');
+ }
+ },
+ }).then(() => {
setStatusMode('hidden');
initializing = false;
}, displayFailureNotice);
diff --git a/misc/dist/html/manifest.json b/misc/dist/html/manifest.json
new file mode 100644
index 0000000000..6fbed737c7
--- /dev/null
+++ b/misc/dist/html/manifest.json
@@ -0,0 +1,18 @@
+{
+ "name": "Godot Engine",
+ "short_name": "Godot",
+ "description": "Multi-platform 2D and 3D game engine with a feature-rich editor",
+ "lang": "en",
+ "start_url": "./godot.tools.html",
+ "display": "standalone",
+ "orientation": "landscape",
+ "theme_color": "#478cbf",
+ "icons": [
+ {
+ "src": "favicon.png",
+ "sizes": "256x256",
+ "type": "image/png"
+ }
+ ],
+ "background_color": "#333b4f"
+}
diff --git a/misc/dist/html/offline.html b/misc/dist/html/offline.html
new file mode 100644
index 0000000000..000c21b4d3
--- /dev/null
+++ b/misc/dist/html/offline.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>You are offline</title>
+ <style>
+ html {
+ background-color: #333b4f;
+ color: #e0e0e0;
+ }
+
+ body {
+ font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ margin: 2rem;
+ }
+
+ p {
+ margin-block: 1rem;
+ }
+
+ button {
+ display: block;
+ padding: 1rem 2rem;
+ margin: 3rem auto 0;
+ }
+ </style>
+</head>
+<body>
+ <h1>You are offline</h1>
+ <p>This application requires an Internet connection to run for the first time.</p>
+ <p>Press the button below to try reloading:</p>
+ <button type="button">Reload</button>
+
+ <script>
+ document.querySelector("button").addEventListener("click", () => {
+ window.location.reload();
+ });
+ </script>
+</body>
+</html>
diff --git a/misc/dist/html/service-worker.js b/misc/dist/html/service-worker.js
new file mode 100644
index 0000000000..d4eaed2b17
--- /dev/null
+++ b/misc/dist/html/service-worker.js
@@ -0,0 +1,84 @@
+// This service worker is required to expose an exported Godot project as a
+// Progressive Web App. It provides an offline fallback page telling the user
+// that they need an Internet conneciton to run the project if desired.
+// Incrementing CACHE_VERSION will kick off the install event and force
+// previously cached resources to be updated from the network.
+const CACHE_VERSION = "@GODOT_VERSION@";
+const CACHE_NAME = "@GODOT_NAME@-cache";
+const OFFLINE_URL = "offline.html";
+// Files that will be cached on load.
+const CACHED_FILES = [
+ "godot.tools.html",
+ "offline.html",
+ "godot.tools.js",
+ "godot.tools.worker.js",
+ "godot.tools.audio.worklet.js",
+ "logo.svg",
+ "favicon.png",
+];
+
+// Files that we might not want the user to preload, and will only be cached on first load.
+const CACHABLE_FILES = [
+ "godot.tools.wasm",
+];
+const FULL_CACHE = CACHED_FILES.concat(CACHABLE_FILES);
+
+self.addEventListener("install", (event) => {
+ event.waitUntil(async function () {
+ const cache = await caches.open(CACHE_NAME);
+ // Clear old cache (including optionals).
+ await Promise.all(FULL_CACHE.map(path => cache.delete(path)));
+ // Insert new one.
+ const done = await cache.addAll(CACHED_FILES);
+ return done;
+ }());
+});
+
+self.addEventListener("activate", (event) => {
+ event.waitUntil(async function () {
+ if ("navigationPreload" in self.registration) {
+ await self.registration.navigationPreload.enable();
+ }
+ }());
+ // Tell the active service worker to take control of the page immediately.
+ self.clients.claim();
+});
+
+self.addEventListener("fetch", (event) => {
+ const isNavigate = event.request.mode === "navigate";
+ const url = event.request.url || "";
+ const referrer = event.request.referrer || "";
+ const base = referrer.slice(0, referrer.lastIndexOf("/") + 1);
+ const local = url.startsWith(base) ? url.replace(base, "") : "";
+ const isCachable = FULL_CACHE.some(v => v === local) || (base === referrer && base.endsWith(CACHED_FILES[0]));
+ if (isNavigate || isCachable) {
+ event.respondWith(async function () {
+ try {
+ // Use the preloaded response, if it's there
+ let request = event.request.clone();
+ let response = await event.preloadResponse;
+ if (!response) {
+ // Or, go over network.
+ response = await fetch(event.request);
+ }
+ if (isCachable) {
+ // Update the cache
+ const cache = await caches.open(CACHE_NAME);
+ cache.put(request, response.clone());
+ }
+ return response;
+ } catch (error) {
+ const cache = await caches.open(CACHE_NAME);
+ if (event.request.mode === "navigate") {
+ // Check if we have full cache.
+ const cached = await Promise.all(FULL_CACHE.map(name => cache.match(name)));
+ const missing = cached.some(v => v === undefined);
+ const cachedResponse = missing ? await caches.match(OFFLINE_URL) : await caches.match(CACHED_FILES[0]);
+ return cachedResponse;
+ }
+ const cachedResponse = await caches.match(event.request);
+ return cachedResponse;
+ }
+ }());
+ }
+});
diff --git a/misc/dist/linux/org.godotengine.Godot.xml b/misc/dist/linux/org.godotengine.Godot.xml
new file mode 100644
index 0000000000..2f647f71a6
--- /dev/null
+++ b/misc/dist/linux/org.godotengine.Godot.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+ <mime-type type="application/x-godot-project">
+ <comment>Godot Engine project</comment>
+ <icon name="x-godot-project" />
+ <glob pattern="*.godot"/>
+ </mime-type>
+
+ <mime-type type="application/x-godot-resource">
+ <comment>Godot Engine resource</comment>
+ <icon name="x-godot-resource" />
+ <glob pattern="*.res"/>
+ <glob pattern="*.tres"/>
+ </mime-type>
+
+ <mime-type type="application/x-godot-scene">
+ <comment>Godot Engine scene</comment>
+ <icon name="x-godot-scene" />
+ <glob pattern="*.scn"/>
+ <glob pattern="*.tscn"/>
+ <glob pattern="*.escn"/>
+ </mime-type>
+
+ <mime-type type="application/x-gdscript">
+ <comment>GDScript script</comment>
+ <icon name="x-gdscript" />
+ <glob pattern="*.gd"/>
+ </mime-type>
+</mime-info>
diff --git a/misc/dist/linux/x-godot-project.xml b/misc/dist/linux/x-godot-project.xml
deleted file mode 100644
index 9f28bab2ae..0000000000
--- a/misc/dist/linux/x-godot-project.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0"?>
-<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
- <mime-type type="application/x-godot-project">
- <comment>Godot Engine project</comment>
- <icon name="godot" />
- <glob pattern="*.godot" weight="100" />
- </mime-type>
-</mime-info>
diff --git a/misc/dist/project_icon.svg b/misc/dist/project_icon.svg
index cece381340..39a8cd6332 100644
--- a/misc/dist/project_icon.svg
+++ b/misc/dist/project_icon.svg
@@ -1 +1 @@
-<svg height="1024" width="1024" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -98.519719)"><rect fill="#1e1a21" height="1008" rx="176.28572" stroke="#2e2832" stroke-width="16" width="1008" x="8" y="106.51972"/><path d="m0 0v-47.514-6.035-5.492c.108-.001.216-.005.323-.015l36.196-3.49c1.896-.183 3.382-1.709 3.514-3.609l1.116-15.978 31.574-2.253 2.175 14.747c.282 1.912 1.922 3.329 3.856 3.329h38.188c1.933 0 3.573-1.417 3.855-3.329l2.175-14.747 31.575 2.253 1.115 15.978c.133 1.9 1.618 3.425 3.514 3.609l36.182 3.49c.107.01.214.014.322.015v4.711l.015.005v54.325c5.09692 6.4164712 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.642-7.702.88-11.567.926v.006c-.027 0-.052-.006-.075-.006-.024 0-.049.006-.073.006v-.006c-3.872-.046-7.729-.284-11.572-.926-3.238 7.238-6.956 14.642-11.03 21.479-10.184-2.264-20.258-5.416-29.703-10.17.216-8.34.755-16.331 1.848-24.448-3.668-2.35-7.523-4.367-10.949-7.118-3.481-2.678-7.036-5.24-10.188-8.372-6.297 4.165-12.962 8.079-19.828 11.534-7.401-7.965-14.321-16.562-19.974-26.182 4.4426581-6.973693 9.2079704-13.9828879 13.621-19.449z" fill="#478cbf" transform="matrix(4.2343801 0 0 -4.2343764 97.676491 522.86238)"/><path d="m0 0-1.121-16.063c-.135-1.936-1.675-3.477-3.611-3.616l-38.555-2.751c-.094-.007-.188-.01-.281-.01-1.916 0-3.569 1.406-3.852 3.33l-2.211 14.994h-31.459l-2.211-14.994c-.297-2.018-2.101-3.469-4.133-3.32l-38.555 2.751c-1.936.139-3.476 1.68-3.611 3.616l-1.121 16.063-32.547 3.138c.015-3.498.06-7.33.06-8.093 0-34.374 43.605-50.896 97.781-51.086h.066.067c54.176.19 97.766 16.712 97.766 51.086 0 .777.047 4.593.063 8.093z" fill="#478cbf" transform="matrix(4.2343801 0 0 -4.2343764 788.7623 819.22103)"/><path d="m0 0c0-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 12.048 0 21.813-9.758 21.813-21.802" fill="#fff" transform="matrix(4.2343801 0 0 -4.2343764 387.09785 624.34645)"/><path d="m0 0c0-7.994-6.479-14.473-14.479-14.473-7.996 0-14.479 6.479-14.479 14.473s6.483 14.479 14.479 14.479c8 0 14.479-6.485 14.479-14.479" fill="#414042" transform="matrix(4.2343801 0 0 -4.2343764 364.87318 629.82505)"/><path d="m0 0c-3.878 0-7.021 2.858-7.021 6.381v20.081c0 3.52 3.143 6.381 7.021 6.381s7.028-2.861 7.028-6.381v-20.081c0-3.523-3.15-6.381-7.028-6.381" fill="#fff" transform="matrix(4.2343801 0 0 -4.2343764 511.99324 725.12292)"/><path d="m0 0c0-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-12.05 0-21.815-9.758-21.815-21.802" fill="#fff" transform="matrix(4.2343801 0 0 -4.2343764 636.90407 624.34645)"/><path d="m0 0c0-7.994 6.477-14.473 14.471-14.473 8.002 0 14.479 6.479 14.479 14.473s-6.477 14.479-14.479 14.479c-7.994 0-14.471-6.485-14.471-14.479" fill="#414042" transform="matrix(4.2343801 0 0 -4.2343764 659.13434 629.82505)"/></g></svg>
+<svg height="1024" width="1024" xmlns="http://www.w3.org/2000/svg"><rect fill="#1e1a21" height="1008" rx="176.28572" stroke="#2e2832" stroke-width="16" width="1008" x="8" y="8.000001"/><path d="m0 0s-.325 1.994-.515 1.976l-36.182-3.491c-2.879-.278-5.115-2.574-5.317-5.459l-.994-14.247-27.992-1.997-1.904 12.912c-.424 2.872-2.932 5.037-5.835 5.037h-38.188c-2.902 0-5.41-2.165-5.834-5.037l-1.905-12.912-27.992 1.997-.994 14.247c-.202 2.886-2.438 5.182-5.317 5.46l-36.2 3.49c-.187.018-.324-1.978-.511-1.978l-.049-7.83 30.658-4.944 1.004-14.374c.203-2.91 2.551-5.263 5.463-5.472l38.551-2.75c.146-.01.29-.016.434-.016 2.897 0 5.401 2.166 5.825 5.038l1.959 13.286h28.005l1.959-13.286c.423-2.871 2.93-5.037 5.831-5.037.142 0 .284.005.423.015l38.556 2.75c2.911.209 5.26 2.562 5.463 5.472l1.003 14.374 30.645 4.966z" fill="#fff" transform="matrix(4.23438024 0 0 -4.23438024 926.261959 674.345124)"/><path d="m0 0v-47.514-6.035-5.492c.108-.001.216-.005.323-.015l36.196-3.49c1.896-.183 3.382-1.709 3.514-3.609l1.116-15.978 31.574-2.253 2.175 14.747c.282 1.912 1.922 3.329 3.856 3.329h38.188c1.933 0 3.573-1.417 3.855-3.329l2.175-14.747 31.575 2.253 1.115 15.978c.133 1.9 1.618 3.425 3.514 3.609l36.182 3.49c.107.01.214.014.322.015v4.711l.015.005v54.325c5.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.642-7.702.88-11.567.926v.006c-.027 0-.052-.006-.075-.006-.024 0-.049.006-.073.006v-.006c-3.872-.046-7.729-.284-11.572-.926-3.238 7.238-6.956 14.642-11.03 21.479-10.184-2.264-20.258-5.416-29.703-10.17.216-8.34.755-16.331 1.848-24.448-3.668-2.35-7.523-4.367-10.949-7.118-3.481-2.678-7.036-5.24-10.188-8.372-6.297 4.165-12.962 8.079-19.828 11.534-7.401-7.965-14.321-16.562-19.974-26.182 4.4426579-6.973692 9.2079702-13.9828876 13.621-19.449z" fill="#478cbf" transform="matrix(4.23438024 0 0 -4.23438024 97.676501 424.342903)"/><path d="m0 0-1.121-16.063c-.135-1.936-1.675-3.477-3.611-3.616l-38.555-2.751c-.094-.007-.188-.01-.281-.01-1.916 0-3.569 1.406-3.852 3.33l-2.211 14.994h-31.459l-2.211-14.994c-.297-2.018-2.101-3.469-4.133-3.32l-38.555 2.751c-1.936.139-3.476 1.68-3.611 3.616l-1.121 16.063-32.547 3.138c.015-3.498.06-7.33.06-8.093 0-34.374 43.605-50.896 97.781-51.086h.066.067c54.176.19 97.766 16.712 97.766 51.086 0 .777.047 4.593.063 8.093z" fill="#478cbf" transform="matrix(4.23438024 0 0 -4.23438024 788.762303 720.701811)"/><path d="m0 0c0-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 12.048 0 21.813-9.758 21.813-21.802" fill="#fff" transform="matrix(4.23438024 0 0 -4.23438024 387.097823 525.827045)"/><path d="m0 0c0-7.994-6.479-14.473-14.479-14.473-7.996 0-14.479 6.479-14.479 14.473s6.483 14.479 14.479 14.479c8 0 14.479-6.485 14.479-14.479" fill="#414042" transform="matrix(4.23438024 0 0 -4.23438024 364.873153 531.305653)"/><path d="m0 0c-3.878 0-7.021 2.858-7.021 6.381v20.081c0 3.52 3.143 6.381 7.021 6.381s7.028-2.861 7.028-6.381v-20.081c0-3.523-3.15-6.381-7.028-6.381" fill="#fff" transform="matrix(4.23438024 0 0 -4.23438024 511.993216 626.603625)"/><path d="m0 0c0-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-12.05 0-21.815-9.758-21.815-21.802" fill="#fff" transform="matrix(4.23438024 0 0 -4.23438024 636.904052 525.827045)"/><path d="m0 0c0-7.994 6.477-14.473 14.471-14.473 8.002 0 14.479 6.479 14.479 14.473s-6.477 14.479-14.479 14.479c-7.994 0-14.471-6.485-14.471-14.479" fill="#414042" transform="matrix(4.23438024 0 0 -4.23438024 659.134337 531.305653)"/></svg>
diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format
index 6467efe22e..7c6e5fcb42 100755
--- a/misc/hooks/pre-commit-clang-format
+++ b/misc/hooks/pre-commit-clang-format
@@ -103,7 +103,7 @@ CLANG_FORMAT_VERSION="$(clang-format --version | cut -d' ' -f3)"
CLANG_FORMAT_MAJOR="$(echo "$CLANG_FORMAT_VERSION" | cut -d'.' -f1)"
if [ "$CLANG_FORMAT_MAJOR" != "$RECOMMENDED_CLANG_FORMAT_MAJOR" ]; then
- echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected $CLANG_FORMAT_MAJOR.x.x)."
+ echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x)."
echo " Consider upgrading or downgrading clang-format as formatting may not be applied correctly."
fi
@@ -125,6 +125,9 @@ do
if grep -q "platform/android/java/lib/src/com" <<< $file; then
continue;
fi
+ if grep -q "\-so_wrap." <<< $file; then
+ continue;
+ fi
# ignore file if we do check for file extensions and the file
# does not match any of the extensions specified in $FILE_EXTS
diff --git a/misc/scripts/clang_format.sh b/misc/scripts/clang_format.sh
index e686305dea..63c66d41c3 100755
--- a/misc/scripts/clang_format.sh
+++ b/misc/scripts/clang_format.sh
@@ -16,6 +16,8 @@ while IFS= read -rd '' f; do
continue
elif [[ "$f" == "platform/android/java/lib/src/com/google"* ]]; then
continue
+ elif [[ "$f" == *"-so_wrap."* ]]; then
+ continue
fi
for extension in ${CLANG_FORMAT_FILE_EXTS[@]}; do
diff --git a/misc/scripts/file_format.sh b/misc/scripts/file_format.sh
index 0e9db68a90..795431cd28 100755
--- a/misc/scripts/file_format.sh
+++ b/misc/scripts/file_format.sh
@@ -30,6 +30,8 @@ while IFS= read -rd '' f; do
continue
elif [[ "$f" == "platform/android/java/lib/src/com/google"* ]]; then
continue
+ elif [[ "$f" == *"-so_wrap."* ]]; then
+ continue
fi
# Ensure that files are UTF-8 formatted.
recode UTF-8 "$f" 2> /dev/null
@@ -38,15 +40,6 @@ while IFS= read -rd '' f; do
# Remove trailing space characters and ensures that files end
# with newline characters. -l option handles newlines conveniently.
perl -i -ple 's/\s*$//g' "$f"
- # Remove the character sequence "== true" if it has a leading space.
- perl -i -pe 's/\x20== true//g' "$f"
-
- if [[ $(uname) == "Linux" ]] && [[ "$f" != *"xml" ]]; then
- # Remove empty lines after the opening brace of indented blocks.
- sed -z -i 's/\x7B\x0A\x0A\x09/\x7B\x0A\x09/g' "$f"
- # Remove empty lines before the closing brace (in some cases).
- sed -z -i 's/\x0A\x0A\x7D/\x0A\x7D/g' "$f"
- fi
done
git diff > patch.patch
diff --git a/modules/basis_universal/texture_basisu.cpp b/modules/basis_universal/texture_basisu.cpp
index 66eb81d7f2..92882a1cc8 100644
--- a/modules/basis_universal/texture_basisu.cpp
+++ b/modules/basis_universal/texture_basisu.cpp
@@ -207,7 +207,6 @@ Vector<uint8_t> TextureBasisU::get_basisu_data() const {
};
TextureBasisU::TextureBasisU() {
- flags = FLAGS_DEFAULT;
texture = RenderingServer::get_singleton()->texture_create();
};
diff --git a/modules/basis_universal/texture_basisu.h b/modules/basis_universal/texture_basisu.h
index 0a4783eaff..282a0dfc8a 100644
--- a/modules/basis_universal/texture_basisu.h
+++ b/modules/basis_universal/texture_basisu.h
@@ -47,7 +47,7 @@ class TextureBasisU : public Texture {
RID texture;
Size2 tex_size;
- uint32_t flags;
+ uint32_t flags = FLAGS_DEFAULT;
Vector<uint8_t> data;
diff --git a/modules/bmp/image_loader_bmp.h b/modules/bmp/image_loader_bmp.h
index d3f12f0115..379e971458 100644
--- a/modules/bmp/image_loader_bmp.h
+++ b/modules/bmp/image_loader_bmp.h
@@ -55,24 +55,24 @@ protected:
struct bmp_header_s {
struct bmp_file_header_s {
- uint16_t bmp_signature;
- uint32_t bmp_file_size;
- uint32_t bmp_file_padding;
- uint32_t bmp_file_offset;
+ uint16_t bmp_signature = 0;
+ uint32_t bmp_file_size = 0;
+ uint32_t bmp_file_padding = 0;
+ uint32_t bmp_file_offset = 0;
} bmp_file_header;
struct bmp_info_header_s {
- uint32_t bmp_header_size;
- uint32_t bmp_width;
- uint32_t bmp_height;
- uint16_t bmp_planes;
- uint16_t bmp_bit_count;
- uint32_t bmp_compression;
- uint32_t bmp_size_image;
- uint32_t bmp_pixels_per_meter_x;
- uint32_t bmp_pixels_per_meter_y;
- uint32_t bmp_colors_used;
- uint32_t bmp_important_colors;
+ uint32_t bmp_header_size = 0;
+ uint32_t bmp_width = 0;
+ uint32_t bmp_height = 0;
+ uint16_t bmp_planes = 0;
+ uint16_t bmp_bit_count = 0;
+ uint32_t bmp_compression = 0;
+ uint32_t bmp_size_image = 0;
+ uint32_t bmp_pixels_per_meter_x = 0;
+ uint32_t bmp_pixels_per_meter_y = 0;
+ uint32_t bmp_colors_used = 0;
+ uint32_t bmp_important_colors = 0;
} bmp_info_header;
};
diff --git a/modules/bullet/area_bullet.h b/modules/bullet/area_bullet.h
index a5fa678fec..7cf666c119 100644
--- a/modules/bullet/area_bullet.h
+++ b/modules/bullet/area_bullet.h
@@ -80,18 +80,18 @@ public:
private:
// These are used by function callEvent. Instead to create this each call I create if one time.
Variant call_event_res[5];
- Variant *call_event_res_ptr[5];
+ Variant *call_event_res_ptr[5] = {};
- btGhostObject *btGhost;
+ btGhostObject *btGhost = nullptr;
Vector<OverlappingObjectData> overlappingObjects;
bool monitorable = true;
PhysicsServer3D::AreaSpaceOverrideMode spOv_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
bool spOv_gravityPoint = false;
- real_t spOv_gravityPointDistanceScale = 0;
- real_t spOv_gravityPointAttenuation = 1;
+ real_t spOv_gravityPointDistanceScale = 0.0;
+ real_t spOv_gravityPointAttenuation = 1.0;
Vector3 spOv_gravityVec = Vector3(0, -1, 0);
- real_t spOv_gravityMag = 10;
+ real_t spOv_gravityMag = 10.0;
real_t spOv_linearDump = 0.1;
real_t spOv_angularDump = 0.1;
int spOv_priority = 0;
diff --git a/modules/bullet/btRayShape.cpp b/modules/bullet/btRayShape.cpp
index 1568cca63d..109854c9dd 100644
--- a/modules/bullet/btRayShape.cpp
+++ b/modules/bullet/btRayShape.cpp
@@ -39,11 +39,9 @@
*/
btRayShape::btRayShape(btScalar length) :
- btConvexInternalShape(),
- m_shapeAxis(0, 0, 1) {
+ btConvexInternalShape() {
m_shapeType = CUSTOM_CONVEX_SHAPE_TYPE;
setLength(length);
- slipsOnSlope = false;
}
btRayShape::~btRayShape() {
diff --git a/modules/bullet/btRayShape.h b/modules/bullet/btRayShape.h
index dcc4cc79c7..330755aa31 100644
--- a/modules/bullet/btRayShape.h
+++ b/modules/bullet/btRayShape.h
@@ -42,10 +42,10 @@
/// Ray shape around z axis
ATTRIBUTE_ALIGNED16(class)
btRayShape : public btConvexInternalShape {
- btScalar m_length;
- bool slipsOnSlope;
+ btScalar m_length = 0;
+ bool slipsOnSlope = false;
/// The default axis is the z
- btVector3 m_shapeAxis;
+ btVector3 m_shapeAxis = btVector3(0, 0, 1);
btTransform m_cacheSupportPoint;
btScalar m_cacheScaledLength;
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp
index 9144a781a0..93642f2d5c 100644
--- a/modules/bullet/bullet_physics_server.cpp
+++ b/modules/bullet/bullet_physics_server.cpp
@@ -433,12 +433,6 @@ void BulletPhysicsServer3D::area_set_ray_pickable(RID p_area, bool p_enable) {
area->set_ray_pickable(p_enable);
}
-bool BulletPhysicsServer3D::area_is_ray_pickable(RID p_area) const {
- AreaBullet *area = area_owner.getornull(p_area);
- ERR_FAIL_COND_V(!area, false);
- return area->is_ray_pickable();
-}
-
RID BulletPhysicsServer3D::body_create(BodyMode p_mode, bool p_init_sleeping) {
RigidBodyBullet *body = bulletnew(RigidBodyBullet);
body->set_mode(p_mode);
@@ -461,7 +455,7 @@ void BulletPhysicsServer3D::body_set_space(RID p_body, RID p_space) {
}
if (body->get_space() == space) {
- return; //pointles
+ return; //pointless
}
body->set_space(space);
@@ -617,11 +611,11 @@ uint32_t BulletPhysicsServer3D::body_get_collision_mask(RID p_body) const {
}
void BulletPhysicsServer3D::body_set_user_flags(RID p_body, uint32_t p_flags) {
- // This function si not currently supported
+ // This function is not currently supported
}
uint32_t BulletPhysicsServer3D::body_get_user_flags(RID p_body) const {
- // This function si not currently supported
+ // This function is not currently supported
return 0;
}
@@ -842,12 +836,6 @@ void BulletPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) {
body->set_ray_pickable(p_enable);
}
-bool BulletPhysicsServer3D::body_is_ray_pickable(RID p_body) const {
- RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, false);
- return body->is_ray_pickable();
-}
-
PhysicsDirectBodyState3D *BulletPhysicsServer3D::body_get_direct_state(RID p_body) {
RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, nullptr);
@@ -880,7 +868,7 @@ RID BulletPhysicsServer3D::soft_body_create(bool p_init_sleeping) {
CreateThenReturnRID(soft_body_owner, body);
}
-void BulletPhysicsServer3D::soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) {
+void BulletPhysicsServer3D::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
@@ -898,7 +886,7 @@ void BulletPhysicsServer3D::soft_body_set_space(RID p_body, RID p_space) {
}
if (body->get_space() == space) {
- return; //pointles
+ return; //pointless
}
body->set_space(space);
@@ -922,6 +910,13 @@ void BulletPhysicsServer3D::soft_body_set_mesh(RID p_body, const REF &p_mesh) {
body->set_soft_mesh(p_mesh);
}
+AABB BulletPhysicsServer::soft_body_get_bounds(RID p_body) const {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, AABB());
+
+ return body->get_bounds();
+}
+
void BulletPhysicsServer3D::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
@@ -1002,34 +997,19 @@ void BulletPhysicsServer3D::soft_body_set_transform(RID p_body, const Transform
body->set_soft_transform(p_transform);
}
-Vector3 BulletPhysicsServer3D::soft_body_get_vertex_position(RID p_body, int vertex_index) const {
- const SoftBodyBullet *body = soft_body_owner.getornull(p_body);
- Vector3 pos;
- ERR_FAIL_COND_V(!body, pos);
-
- body->get_node_position(vertex_index, pos);
- return pos;
-}
-
void BulletPhysicsServer3D::soft_body_set_ray_pickable(RID p_body, bool p_enable) {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
body->set_ray_pickable(p_enable);
}
-bool BulletPhysicsServer3D::soft_body_is_ray_pickable(RID p_body) const {
- SoftBodyBullet *body = soft_body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, false);
- return body->is_ray_pickable();
-}
-
void BulletPhysicsServer3D::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
body->set_simulation_precision(p_simulation_precision);
}
-int BulletPhysicsServer3D::soft_body_get_simulation_precision(RID p_body) {
+int BulletPhysicsServer3D::soft_body_get_simulation_precision(RID p_body) const {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, 0.f);
return body->get_simulation_precision();
@@ -1041,13 +1021,13 @@ void BulletPhysicsServer3D::soft_body_set_total_mass(RID p_body, real_t p_total_
body->set_total_mass(p_total_mass);
}
-real_t BulletPhysicsServer3D::soft_body_get_total_mass(RID p_body) {
+real_t BulletPhysicsServer3D::soft_body_get_total_mass(RID p_body) const {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, 0.f);
return body->get_total_mass();
}
-void BulletPhysicsServer3D::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) {
+void BulletPhysicsServer3D::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) const {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
body->set_linear_stiffness(p_stiffness);
@@ -1059,61 +1039,25 @@ real_t BulletPhysicsServer3D::soft_body_get_linear_stiffness(RID p_body) {
return body->get_linear_stiffness();
}
-void BulletPhysicsServer3D::soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) {
- SoftBodyBullet *body = soft_body_owner.getornull(p_body);
- ERR_FAIL_COND(!body);
- body->set_areaAngular_stiffness(p_stiffness);
-}
-
-real_t BulletPhysicsServer3D::soft_body_get_areaAngular_stiffness(RID p_body) {
- SoftBodyBullet *body = soft_body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, 0.f);
- return body->get_areaAngular_stiffness();
-}
-
-void BulletPhysicsServer3D::soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) {
- SoftBodyBullet *body = soft_body_owner.getornull(p_body);
- ERR_FAIL_COND(!body);
- body->set_volume_stiffness(p_stiffness);
-}
-
-real_t BulletPhysicsServer3D::soft_body_get_volume_stiffness(RID p_body) {
- SoftBodyBullet *body = soft_body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, 0.f);
- return body->get_volume_stiffness();
-}
-
void BulletPhysicsServer3D::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
body->set_pressure_coefficient(p_pressure_coefficient);
}
-real_t BulletPhysicsServer3D::soft_body_get_pressure_coefficient(RID p_body) {
+real_t BulletPhysicsServer3D::soft_body_get_pressure_coefficient(RID p_body) const {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, 0.f);
return body->get_pressure_coefficient();
}
-void BulletPhysicsServer3D::soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) {
- SoftBodyBullet *body = soft_body_owner.getornull(p_body);
- ERR_FAIL_COND(!body);
- return body->set_pose_matching_coefficient(p_pose_matching_coefficient);
-}
-
-real_t BulletPhysicsServer3D::soft_body_get_pose_matching_coefficient(RID p_body) {
- SoftBodyBullet *body = soft_body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, 0.f);
- return body->get_pose_matching_coefficient();
-}
-
void BulletPhysicsServer3D::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
body->set_damping_coefficient(p_damping_coefficient);
}
-real_t BulletPhysicsServer3D::soft_body_get_damping_coefficient(RID p_body) {
+real_t BulletPhysicsServer3D::soft_body_get_damping_coefficient(RID p_body) const {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, 0.f);
return body->get_damping_coefficient();
@@ -1125,7 +1069,7 @@ void BulletPhysicsServer3D::soft_body_set_drag_coefficient(RID p_body, real_t p_
body->set_drag_coefficient(p_drag_coefficient);
}
-real_t BulletPhysicsServer3D::soft_body_get_drag_coefficient(RID p_body) {
+real_t BulletPhysicsServer3D::soft_body_get_drag_coefficient(RID p_body) const {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, 0.f);
return body->get_drag_coefficient();
@@ -1137,7 +1081,7 @@ void BulletPhysicsServer3D::soft_body_move_point(RID p_body, int p_point_index,
body->set_node_position(p_point_index, p_global_position);
}
-Vector3 BulletPhysicsServer3D::soft_body_get_point_global_position(RID p_body, int p_point_index) {
+Vector3 BulletPhysicsServer3D::soft_body_get_point_global_position(RID p_body, int p_point_index) const {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, Vector3(0., 0., 0.));
Vector3 pos;
@@ -1145,14 +1089,6 @@ Vector3 BulletPhysicsServer3D::soft_body_get_point_global_position(RID p_body, i
return pos;
}
-Vector3 BulletPhysicsServer3D::soft_body_get_point_offset(RID p_body, int p_point_index) const {
- SoftBodyBullet *body = soft_body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, Vector3());
- Vector3 res;
- body->get_node_offset(p_point_index, res);
- return res;
-}
-
void BulletPhysicsServer3D::soft_body_remove_all_pinned_points(RID p_body) {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
@@ -1165,7 +1101,7 @@ void BulletPhysicsServer3D::soft_body_pin_point(RID p_body, int p_point_index, b
body->set_node_mass(p_point_index, p_pin ? 0 : 1);
}
-bool BulletPhysicsServer3D::soft_body_is_point_pinned(RID p_body, int p_point_index) {
+bool BulletPhysicsServer3D::soft_body_is_point_pinned(RID p_body, int p_point_index) const {
SoftBodyBullet *body = soft_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, 0.f);
return body->get_node_mass(p_point_index);
diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h
index f2740c9c75..856ff74963 100644
--- a/modules/bullet/bullet_physics_server.h
+++ b/modules/bullet/bullet_physics_server.h
@@ -163,7 +163,6 @@ public:
virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
virtual void area_set_ray_pickable(RID p_area, bool p_enable) override;
- virtual bool area_is_ray_pickable(RID p_area) const override;
/* RIGID BODY API */
@@ -250,7 +249,6 @@ public:
virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) override;
virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
- virtual bool body_is_ray_pickable(RID p_body) const override;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override;
@@ -262,13 +260,15 @@ public:
virtual RID soft_body_create(bool p_init_sleeping = false) override;
- virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) override;
+ virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) override;
virtual void soft_body_set_space(RID p_body, RID p_space) override;
virtual RID soft_body_get_space(RID p_body) const override;
virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) override;
+ virtual AABB soft_body_get_bounds(RID p_body) const override;
+
virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) override;
virtual uint32_t soft_body_get_collision_layer(RID p_body) const override;
@@ -284,46 +284,33 @@ public:
/// Special function. This function has bad performance
virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) override;
- virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const override;
virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) override;
- virtual bool soft_body_is_ray_pickable(RID p_body) const override;
virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) override;
- virtual int soft_body_get_simulation_precision(RID p_body) override;
+ virtual int soft_body_get_simulation_precision(RID p_body) const override;
virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) override;
- virtual real_t soft_body_get_total_mass(RID p_body) override;
+ virtual real_t soft_body_get_total_mass(RID p_body) const override;
virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) override;
- virtual real_t soft_body_get_linear_stiffness(RID p_body) override;
-
- virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) override;
- virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) override;
-
- virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) override;
- virtual real_t soft_body_get_volume_stiffness(RID p_body) override;
+ virtual real_t soft_body_get_linear_stiffness(RID p_body) const override;
virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) override;
- virtual real_t soft_body_get_pressure_coefficient(RID p_body) override;
-
- virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) override;
- virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) override;
+ virtual real_t soft_body_get_pressure_coefficient(RID p_body) const override;
virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) override;
- virtual real_t soft_body_get_damping_coefficient(RID p_body) override;
+ virtual real_t soft_body_get_damping_coefficient(RID p_body) const override;
virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) override;
- virtual real_t soft_body_get_drag_coefficient(RID p_body) override;
+ virtual real_t soft_body_get_drag_coefficient(RID p_body) const override;
virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) override;
- virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) override;
-
- virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const override;
+ virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) const override;
virtual void soft_body_remove_all_pinned_points(RID p_body) override;
virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) override;
- virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) override;
+ virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) const override;
/* JOINT API */
diff --git a/modules/bullet/bullet_types_converter.cpp b/modules/bullet/bullet_types_converter.cpp
index 7b21e4e4b2..19d4816372 100644
--- a/modules/bullet/bullet_types_converter.cpp
+++ b/modules/bullet/bullet_types_converter.cpp
@@ -116,7 +116,7 @@ void UNSCALE_BT_BASIS(btTransform &scaledBasis) {
}
} else { // Column 1 scale not fuzzy zero.
if (column2.fuzzyZero()) {
- // Create two vectors othogonal to column 1.
+ // Create two vectors orthogonal to column 1.
// Ensure that a default basis is created if column 1 = <0, 1, 0>
column0 = btVector3(column1[1], -column1[0], 0);
column2 = column0.cross(column1);
diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp
index bce8ec8076..d9f5beb5a1 100644
--- a/modules/bullet/collision_object_bullet.cpp
+++ b/modules/bullet/collision_object_bullet.cpp
@@ -148,6 +148,9 @@ void CollisionObjectBullet::add_collision_exception(const CollisionObjectBullet
void CollisionObjectBullet::remove_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject) {
exceptions.erase(p_ignoreCollisionObject->get_self());
+ if (!bt_collision_object) {
+ return;
+ }
bt_collision_object->setIgnoreCollisionCheck(p_ignoreCollisionObject->bt_collision_object, false);
if (space) {
space->get_broadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bt_collision_object->getBroadphaseHandle(), space->get_dispatcher());
@@ -155,11 +158,14 @@ void CollisionObjectBullet::remove_collision_exception(const CollisionObjectBull
}
bool CollisionObjectBullet::has_collision_exception(const CollisionObjectBullet *p_otherCollisionObject) const {
- return !bt_collision_object->checkCollideWith(p_otherCollisionObject->bt_collision_object);
+ return exceptions.has(p_otherCollisionObject->get_self());
}
void CollisionObjectBullet::set_collision_enabled(bool p_enabled) {
collisionsEnabled = p_enabled;
+ if (!bt_collision_object) {
+ return;
+ }
if (collisionsEnabled) {
bt_collision_object->setCollisionFlags(bt_collision_object->getCollisionFlags() & (~btCollisionObject::CF_NO_CONTACT_RESPONSE));
} else {
diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h
index bea28f2183..c8081a53f1 100644
--- a/modules/bullet/collision_object_bullet.h
+++ b/modules/bullet/collision_object_bullet.h
@@ -110,7 +110,7 @@ public:
};
protected:
- Type type;
+ Type type = TYPE_AREA;
ObjectID instance_id;
uint32_t collisionLayer = 0;
uint32_t collisionMask = 0;
diff --git a/modules/bullet/config.py b/modules/bullet/config.py
index d22f9454ed..be7cf74f6f 100644
--- a/modules/bullet/config.py
+++ b/modules/bullet/config.py
@@ -1,5 +1,6 @@
def can_build(env, platform):
- return True
+ # API Changed and bullet is disabled at the moment
+ return False
def configure(env):
diff --git a/modules/bullet/godot_collision_dispatcher.cpp b/modules/bullet/godot_collision_dispatcher.cpp
index 5d1e4d34d8..423166c408 100644
--- a/modules/bullet/godot_collision_dispatcher.cpp
+++ b/modules/bullet/godot_collision_dispatcher.cpp
@@ -43,7 +43,7 @@ GodotCollisionDispatcher::GodotCollisionDispatcher(btCollisionConfiguration *col
bool GodotCollisionDispatcher::needsCollision(const btCollisionObject *body0, const btCollisionObject *body1) {
if (body0->getUserIndex() == CASTED_TYPE_AREA || body1->getUserIndex() == CASTED_TYPE_AREA) {
- // Avoide area narrow phase
+ // Avoid area narrow phase
return false;
}
return btCollisionDispatcher::needsCollision(body0, body1);
@@ -51,7 +51,7 @@ bool GodotCollisionDispatcher::needsCollision(const btCollisionObject *body0, co
bool GodotCollisionDispatcher::needsResponse(const btCollisionObject *body0, const btCollisionObject *body1) {
if (body0->getUserIndex() == CASTED_TYPE_AREA || body1->getUserIndex() == CASTED_TYPE_AREA) {
- // Avoide area narrow phase
+ // Avoid area narrow phase
return false;
}
return btCollisionDispatcher::needsResponse(body0, body1);
diff --git a/modules/bullet/godot_motion_state.h b/modules/bullet/godot_motion_state.h
index 0669d2739a..ca17349130 100644
--- a/modules/bullet/godot_motion_state.h
+++ b/modules/bullet/godot_motion_state.h
@@ -51,7 +51,7 @@ class GodotMotionState : public btMotionState {
/// This data is used to store last world position
btTransform bodyCurrentWorldTransform;
- RigidBodyBullet *owner;
+ RigidBodyBullet *owner = nullptr;
public:
GodotMotionState(RigidBodyBullet *p_owner) :
diff --git a/modules/bullet/godot_ray_world_algorithm.h b/modules/bullet/godot_ray_world_algorithm.h
index f705edef81..25798aecb4 100644
--- a/modules/bullet/godot_ray_world_algorithm.h
+++ b/modules/bullet/godot_ray_world_algorithm.h
@@ -45,7 +45,7 @@ class GodotRayWorldAlgorithm : public btActivatingCollisionAlgorithm {
const btDiscreteDynamicsWorld *m_world;
btPersistentManifold *m_manifoldPtr;
bool m_ownManifold = false;
- bool m_isSwapped;
+ bool m_isSwapped = false;
public:
GodotRayWorldAlgorithm(const btDiscreteDynamicsWorld *world, btPersistentManifold *mf, const btCollisionAlgorithmConstructionInfo &ci, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, bool isSwapped);
diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp
index 15d625afeb..e92b6c189c 100644
--- a/modules/bullet/godot_result_callbacks.cpp
+++ b/modules/bullet/godot_result_callbacks.cpp
@@ -113,7 +113,7 @@ btScalar GodotAllConvexResultCallback::addSingleResult(btCollisionWorld::LocalCo
PhysicsDirectSpaceState3D::ShapeResult &result = m_results[count];
- result.shape = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID
+ result.shape = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is an odd name but contains the compound shape ID
result.rid = gObj->get_self();
result.collider_id = gObj->get_instance_id();
result.collider = result.collider_id.is_null() ? nullptr : ObjectDB::get_instance(result.collider_id);
@@ -176,7 +176,7 @@ bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0)
btScalar GodotClosestConvexResultCallback::addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) {
if (convexResult.m_localShapeInfo) {
- m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID
+ m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is an odd name but contains the compound shape ID
} else {
m_shapeId = 0;
}
diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h
index 4f40f7ecfd..f92665f3e4 100644
--- a/modules/bullet/godot_result_callbacks.h
+++ b/modules/bullet/godot_result_callbacks.h
@@ -59,8 +59,8 @@ struct GodotClosestRayResultCallback : public btCollisionWorld::ClosestRayResult
bool m_pickRay = false;
int m_shapeId = 0;
- bool collide_with_bodies;
- bool collide_with_areas;
+ bool collide_with_bodies = false;
+ bool collide_with_areas = false;
public:
GodotClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
@@ -84,8 +84,8 @@ public:
// store all colliding object
struct GodotAllConvexResultCallback : public btCollisionWorld::ConvexResultCallback {
public:
- PhysicsDirectSpaceState3D::ShapeResult *m_results;
- int m_resultMax;
+ PhysicsDirectSpaceState3D::ShapeResult *m_results = nullptr;
+ int m_resultMax = 0;
const Set<RID> *m_exclude;
int count = 0;
@@ -117,8 +117,8 @@ public:
const Set<RID> *m_exclude;
int m_shapeId = 0;
- bool collide_with_bodies;
- bool collide_with_areas;
+ bool collide_with_bodies = false;
+ bool collide_with_areas = false;
GodotClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld),
@@ -134,13 +134,13 @@ public:
struct GodotAllContactResultCallback : public btCollisionWorld::ContactResultCallback {
public:
const btCollisionObject *m_self_object;
- PhysicsDirectSpaceState3D::ShapeResult *m_results;
- int m_resultMax;
+ PhysicsDirectSpaceState3D::ShapeResult *m_results = nullptr;
+ int m_resultMax = 0;
const Set<RID> *m_exclude;
int m_count = 0;
- bool collide_with_bodies;
- bool collide_with_areas;
+ bool collide_with_bodies = false;
+ bool collide_with_areas = false;
GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState3D::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
m_self_object(p_self_object),
@@ -159,13 +159,13 @@ public:
struct GodotContactPairContactResultCallback : public btCollisionWorld::ContactResultCallback {
public:
const btCollisionObject *m_self_object;
- Vector3 *m_results;
- int m_resultMax;
+ Vector3 *m_results = nullptr;
+ int m_resultMax = 0;
const Set<RID> *m_exclude;
int m_count = 0;
- bool collide_with_bodies;
- bool collide_with_areas;
+ bool collide_with_bodies = false;
+ bool collide_with_areas = false;
GodotContactPairContactResultCallback(btCollisionObject *p_self_object, Vector3 *p_results, int p_resultMax, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
m_self_object(p_self_object),
@@ -183,14 +183,14 @@ public:
struct GodotRestInfoContactResultCallback : public btCollisionWorld::ContactResultCallback {
public:
const btCollisionObject *m_self_object;
- PhysicsDirectSpaceState3D::ShapeRestInfo *m_result;
+ PhysicsDirectSpaceState3D::ShapeRestInfo *m_result = nullptr;
const Set<RID> *m_exclude;
bool m_collided = false;
- real_t m_min_distance = 0;
- const btCollisionObject *m_rest_info_collision_object;
+ real_t m_min_distance = 0.0;
+ const btCollisionObject *m_rest_info_collision_object = nullptr;
btVector3 m_rest_info_bt_point;
- bool collide_with_bodies;
- bool collide_with_areas;
+ bool collide_with_bodies = false;
+ bool collide_with_areas = false;
GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState3D::ShapeRestInfo *p_result, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
m_self_object(p_self_object),
diff --git a/modules/bullet/rid_bullet.h b/modules/bullet/rid_bullet.h
index 0b74a0cc4d..face6b4861 100644
--- a/modules/bullet/rid_bullet.h
+++ b/modules/bullet/rid_bullet.h
@@ -41,7 +41,7 @@ class BulletPhysicsServer3D;
class RIDBullet {
RID self;
- BulletPhysicsServer3D *physicsServer;
+ BulletPhysicsServer3D *physicsServer = nullptr;
public:
_FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index a5093afe9d..433bff8c38 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -515,7 +515,7 @@ real_t RigidBodyBullet::get_param(PhysicsServer3D::BodyParameter p_param) const
}
void RigidBodyBullet::set_mode(PhysicsServer3D::BodyMode p_mode) {
- // This is necessary to block force_integration untile next move
+ // This is necessary to block force_integration until next move
can_integrate_forces = false;
destroy_kinematic_utilities();
// The mode change is relevant to its mass
@@ -725,7 +725,7 @@ void RigidBodyBullet::set_continuous_collision_detection(bool p_enable) {
// 1 meter in one simulation frame
btBody->setCcdMotionThreshold(1e-7);
- /// Calculate using the rule writte below the CCD swept sphere radius
+ /// Calculate using the rule write below the CCD swept sphere radius
/// CCD works on an embedded sphere of radius, make sure this radius
/// is embedded inside the convex objects, preferably smaller:
/// for an object of dimensions 1 meter, try 0.2
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index 57b80cf50c..a4be7f9e07 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -81,8 +81,8 @@ public:
}
public:
- RigidBodyBullet *body;
- real_t deltaTime;
+ RigidBodyBullet *body = nullptr;
+ real_t deltaTime = 0.0;
private:
BulletPhysicsDirectBodyState3D() {}
@@ -144,13 +144,13 @@ public:
class RigidBodyBullet : public RigidCollisionObjectBullet {
public:
struct CollisionData {
- RigidBodyBullet *otherObject;
- int other_object_shape;
- int local_shape;
+ RigidBodyBullet *otherObject = nullptr;
+ int other_object_shape = 0;
+ int local_shape = 0;
Vector3 hitLocalLocation;
Vector3 hitWorldLocation;
Vector3 hitNormal;
- real_t appliedImpulse;
+ real_t appliedImpulse = 0.0;
};
struct ForceIntegrationCallback {
@@ -169,7 +169,7 @@ public:
};
struct KinematicUtilities {
- RigidBodyBullet *owner;
+ RigidBodyBullet *owner = nullptr;
btScalar safe_margin;
Vector<KinematicShape> shapes;
@@ -194,10 +194,10 @@ private:
GodotMotionState *godotMotionState;
btRigidBody *btBody;
uint16_t locked_axis = 0;
- real_t mass = 1;
- real_t gravity_scale = 1;
- real_t linearDamp = 0;
- real_t angularDamp = 0;
+ real_t mass = 1.0;
+ real_t gravity_scale = 1.0;
+ real_t linearDamp = 0.0;
+ real_t angularDamp = 0.0;
bool can_sleep = true;
bool omit_forces_integration = false;
bool can_integrate_forces = false;
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
index 82876ab77c..471b154813 100644
--- a/modules/bullet/shape_bullet.cpp
+++ b/modules/bullet/shape_bullet.cpp
@@ -375,11 +375,17 @@ ConcavePolygonShapeBullet::~ConcavePolygonShapeBullet() {
}
void ConcavePolygonShapeBullet::set_data(const Variant &p_data) {
- setup(p_data);
+ Dictionary d = p_data;
+ ERR_FAIL_COND(!d.has("faces"));
+
+ setup(d["faces"]);
}
Variant ConcavePolygonShapeBullet::get_data() const {
- return faces;
+ Dictionary d;
+ d["faces"] = faces;
+
+ return d;
}
PhysicsServer3D::ShapeType ConcavePolygonShapeBullet::get_type() const {
diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h
index 63475822de..bfd95747eb 100644
--- a/modules/bullet/shape_bullet.h
+++ b/modules/bullet/shape_bullet.h
@@ -213,10 +213,10 @@ private:
class HeightMapShapeBullet : public ShapeBullet {
public:
Vector<real_t> heights;
- int width;
- int depth;
- real_t min_height;
- real_t max_height;
+ int width = 0;
+ int depth = 0;
+ real_t min_height = 0.0;
+ real_t max_height = 0.0;
HeightMapShapeBullet();
@@ -231,7 +231,7 @@ private:
class RayShapeBullet : public ShapeBullet {
public:
- real_t length = 1;
+ real_t length = 1.0;
bool slips_on_slope = false;
RayShapeBullet();
diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp
index a490179964..2c8727baf2 100644
--- a/modules/bullet/soft_body_bullet.cpp
+++ b/modules/bullet/soft_body_bullet.cpp
@@ -65,7 +65,7 @@ void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {}
void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {}
-void SoftBodyBullet::update_rendering_server(SoftBodyRenderingServerHandler *p_rendering_server_handler) {
+void SoftBodyBullet::update_rendering_server(RenderingServerHandler *p_rendering_server_handler) {
if (!bt_soft_body) {
return;
}
@@ -141,6 +141,24 @@ void SoftBodyBullet::set_soft_transform(const Transform &p_transform) {
move_all_nodes(p_transform);
}
+AABB SoftBodyBullet::get_bounds() const {
+ if (!bt_soft_body) {
+ return AABB();
+ }
+
+ btVector3 aabb_min;
+ btVector3 aabb_max;
+ bt_soft_body->getAabb(aabb_min, aabb_max);
+
+ btVector3 size(aabb_max - aabb_min);
+
+ AABB aabb;
+ B_TO_G(aabb_min, aabb.position);
+ B_TO_G(size, aabb.size);
+
+ return aabb;
+}
+
void SoftBodyBullet::move_all_nodes(const Transform &p_transform) {
if (!bt_soft_body) {
return;
@@ -169,25 +187,6 @@ void SoftBodyBullet::get_node_position(int p_node_index, Vector3 &r_position) co
}
}
-void SoftBodyBullet::get_node_offset(int p_node_index, Vector3 &r_offset) const {
- if (soft_mesh.is_null()) {
- return;
- }
-
- Array arrays = soft_mesh->surface_get_arrays(0);
- Vector<Vector3> vertices(arrays[RS::ARRAY_VERTEX]);
-
- if (0 <= p_node_index && vertices.size() > p_node_index) {
- r_offset = vertices[p_node_index];
- }
-}
-
-void SoftBodyBullet::get_node_offset(int p_node_index, btVector3 &r_offset) const {
- Vector3 off;
- get_node_offset(p_node_index, off);
- G_TO_B(off, r_offset);
-}
-
void SoftBodyBullet::set_node_mass(int node_index, btScalar p_mass) {
if (0 >= p_mass) {
pin_node(node_index);
@@ -259,20 +258,6 @@ void SoftBodyBullet::set_linear_stiffness(real_t p_val) {
}
}
-void SoftBodyBullet::set_areaAngular_stiffness(real_t p_val) {
- areaAngular_stiffness = p_val;
- if (bt_soft_body) {
- mat0->m_kAST = areaAngular_stiffness;
- }
-}
-
-void SoftBodyBullet::set_volume_stiffness(real_t p_val) {
- volume_stiffness = p_val;
- if (bt_soft_body) {
- mat0->m_kVST = volume_stiffness;
- }
-}
-
void SoftBodyBullet::set_simulation_precision(int p_val) {
simulation_precision = p_val;
if (bt_soft_body) {
@@ -290,13 +275,6 @@ void SoftBodyBullet::set_pressure_coefficient(real_t p_val) {
}
}
-void SoftBodyBullet::set_pose_matching_coefficient(real_t p_val) {
- pose_matching_coefficient = p_val;
- if (bt_soft_body) {
- bt_soft_body->m_cfg.kMT = pose_matching_coefficient;
- }
-}
-
void SoftBodyBullet::set_damping_coefficient(real_t p_val) {
damping_coefficient = p_val;
if (bt_soft_body) {
@@ -336,7 +314,7 @@ void SoftBodyBullet::set_trimesh_body_shape(Vector<int> p_indices, Vector<Vector
Map<Vector3, int>::Element *e = unique_vertices.find(p_vertices_read[vs_vertex_index]);
int vertex_id;
if (e) {
- // Already rxisting
+ // Already existing
vertex_id = e->value();
} else {
// Create new one
@@ -409,8 +387,6 @@ void SoftBodyBullet::setup_soft_body() {
bt_soft_body->generateBendingConstraints(2, mat0);
mat0->m_kLST = linear_stiffness;
- mat0->m_kAST = areaAngular_stiffness;
- mat0->m_kVST = volume_stiffness;
// Clusters allow to have Soft vs Soft collision but doesn't work well right now
@@ -430,7 +406,6 @@ void SoftBodyBullet::setup_soft_body() {
bt_soft_body->m_cfg.kDP = damping_coefficient;
bt_soft_body->m_cfg.kDG = drag_coefficient;
bt_soft_body->m_cfg.kPR = pressure_coefficient;
- bt_soft_body->m_cfg.kMT = pose_matching_coefficient;
bt_soft_body->setTotalMass(total_mass);
btSoftBodyHelpers::ReoptimizeLinkOrder(bt_soft_body);
diff --git a/modules/bullet/soft_body_bullet.h b/modules/bullet/soft_body_bullet.h
index b15b72daf9..87023b2517 100644
--- a/modules/bullet/soft_body_bullet.h
+++ b/modules/bullet/soft_body_bullet.h
@@ -55,11 +55,13 @@
@author AndreaCatania
*/
+class RenderingServerHandler;
+
class SoftBodyBullet : public CollisionObjectBullet {
private:
btSoftBody *bt_soft_body = nullptr;
Vector<Vector<int>> indices_table;
- btSoftBody::Material *mat0; // This is just a copy of pointer managed by btSoftBody
+ btSoftBody::Material *mat0 = nullptr; // This is just a copy of pointer managed by btSoftBody
bool isScratched = false;
Ref<Mesh> soft_mesh;
@@ -67,10 +69,7 @@ private:
int simulation_precision = 5;
real_t total_mass = 1.;
real_t linear_stiffness = 0.5; // [0,1]
- real_t areaAngular_stiffness = 0.5; // [0,1]
- real_t volume_stiffness = 0.5; // [0,1]
real_t pressure_coefficient = 0.; // [-inf,+inf]
- real_t pose_matching_coefficient = 0.; // [0,1]
real_t damping_coefficient = 0.01; // [0,1]
real_t drag_coefficient = 0.; // [0,1]
Vector<int> pinned_nodes;
@@ -99,7 +98,7 @@ public:
_FORCE_INLINE_ btSoftBody *get_bt_soft_body() const { return bt_soft_body; }
- void update_rendering_server(class SoftBodyRenderingServerHandler *p_rendering_server_handler);
+ void update_rendering_server(RenderingServerHandler *p_rendering_server_handler);
void set_soft_mesh(const Ref<Mesh> &p_mesh);
void destroy_soft_body();
@@ -107,14 +106,12 @@ public:
// Special function. This function has bad performance
void set_soft_transform(const Transform &p_transform);
+ AABB get_bounds() const;
+
void move_all_nodes(const Transform &p_transform);
void set_node_position(int node_index, const Vector3 &p_global_position);
void set_node_position(int node_index, const btVector3 &p_global_position);
void get_node_position(int node_index, Vector3 &r_position) const;
- // Heavy function, Please cache this info
- void get_node_offset(int node_index, Vector3 &r_offset) const;
- // Heavy function, Please cache this info
- void get_node_offset(int node_index, btVector3 &r_offset) const;
void set_node_mass(int node_index, btScalar p_mass);
btScalar get_node_mass(int node_index) const;
@@ -129,21 +126,12 @@ public:
void set_linear_stiffness(real_t p_val);
_FORCE_INLINE_ real_t get_linear_stiffness() const { return linear_stiffness; }
- void set_areaAngular_stiffness(real_t p_val);
- _FORCE_INLINE_ real_t get_areaAngular_stiffness() const { return areaAngular_stiffness; }
-
- void set_volume_stiffness(real_t p_val);
- _FORCE_INLINE_ real_t get_volume_stiffness() const { return volume_stiffness; }
-
void set_simulation_precision(int p_val);
_FORCE_INLINE_ int get_simulation_precision() const { return simulation_precision; }
void set_pressure_coefficient(real_t p_val);
_FORCE_INLINE_ real_t get_pressure_coefficient() const { return pressure_coefficient; }
- void set_pose_matching_coefficient(real_t p_val);
- _FORCE_INLINE_ real_t get_pose_matching_coefficient() const { return pose_matching_coefficient; }
-
void set_damping_coefficient(real_t p_val);
_FORCE_INLINE_ real_t get_damping_coefficient() const { return damping_coefficient; }
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index 79a5fdb3d2..ceae3be8bc 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -81,7 +81,7 @@ int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, Shape
btResult.m_collisionFilterMask = p_collision_mask;
space->dynamicsWorld->contactTest(&collision_object_point, btResult);
- // The results is already populated by GodotAllConvexResultCallback
+ // The results are already populated by GodotAllConvexResultCallback
return btResult.m_count;
}
@@ -1092,13 +1092,13 @@ private:
btDbvtVolume bounds;
const btCollisionObject *self_collision_object;
- uint32_t collision_layer;
- uint32_t collision_mask;
+ uint32_t collision_layer = 0;
+ uint32_t collision_mask = 0;
struct CompoundLeafCallback : btDbvt::ICollide {
private:
- RecoverPenetrationBroadPhaseCallback *parent_callback;
- btCollisionObject *collision_object;
+ RecoverPenetrationBroadPhaseCallback *parent_callback = nullptr;
+ btCollisionObject *collision_object = nullptr;
public:
CompoundLeafCallback(RecoverPenetrationBroadPhaseCallback *p_parent_callback, btCollisionObject *p_collision_object) :
@@ -1116,8 +1116,8 @@ private:
public:
struct BroadphaseResult {
- btCollisionObject *collision_object;
- int compound_child_index;
+ btCollisionObject *collision_object = nullptr;
+ int compound_child_index = 0;
};
Vector<BroadphaseResult> results;
diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h
index 1caa3c2a0c..87aa2b9e93 100644
--- a/modules/bullet/space_bullet.h
+++ b/modules/bullet/space_bullet.h
@@ -100,12 +100,12 @@ class SpaceBullet : public RIDBullet {
btGhostPairCallback *ghostPairCallback = nullptr;
GodotFilterCallback *godotFilterCallback = nullptr;
- btGjkEpaPenetrationDepthSolver *gjk_epa_pen_solver;
- btVoronoiSimplexSolver *gjk_simplex_solver;
+ btGjkEpaPenetrationDepthSolver *gjk_epa_pen_solver = nullptr;
+ btVoronoiSimplexSolver *gjk_simplex_solver = nullptr;
BulletPhysicsDirectSpaceState *direct_access;
Vector3 gravityDirection = Vector3(0, -1, 0);
- real_t gravityMagnitude = 10;
+ real_t gravityMagnitude = 10.0;
real_t linear_damp = 0.0;
real_t angular_damp = 0.0;
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index f0a2f17ba9..8b46447f04 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -970,7 +970,7 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_
continue;
}
- // Check if point is on an each edge.
+ // Check if point is on each edge.
for (int face_edge_idx = 0; face_edge_idx < 3; ++face_edge_idx) {
Vector2 edge_points[2] = {
face_points[face_edge_idx],
@@ -1076,7 +1076,7 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s
break;
}
- // If opposite point is on the segemnt, add its index to segment indices too.
+ // If opposite point is on the segment, add its index to segment indices too.
Vector2 closest_point = Geometry2D::get_closest_point_to_segment(vertices[opposite_vertex_idx].point, p_segment_points);
if ((closest_point - vertices[opposite_vertex_idx].point).length_squared() < vertex_snap2) {
_add_vertex_idx_sorted(r_segment_indices, opposite_vertex_idx);
@@ -1137,7 +1137,7 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) {
}
}
- // Check if point is on an each edge.
+ // Check if point is on each edge.
bool on_edge = false;
for (int face_edge_idx = 0; face_edge_idx < 3; ++face_edge_idx) {
Vector2 edge_points[2] = {
@@ -1400,7 +1400,7 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face
under_count++;
}
}
- // If all points under or over the plane, there is no intesection.
+ // If all points under or over the plane, there is no intersection.
if (over_count == 3 || under_count == 3) {
return;
}
@@ -1421,7 +1421,7 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face
under_count++;
}
}
- // If all points under or over the plane, there is no intesection.
+ // If all points under or over the plane, there is no intersection.
if (over_count == 3 || under_count == 3) {
return;
}
diff --git a/modules/csg/csg.h b/modules/csg/csg.h
index 1612c16a32..3fbed66e5c 100644
--- a/modules/csg/csg.h
+++ b/modules/csg/csg.h
@@ -48,9 +48,9 @@ struct CSGBrush {
Vector3 vertices[3];
Vector2 uvs[3];
AABB aabb;
- bool smooth;
- bool invert;
- int material;
+ bool smooth = false;
+ bool invert = false;
+ int material = 0;
};
Vector<Face> faces;
@@ -74,20 +74,20 @@ struct CSGBrushOperation {
struct MeshMerge {
struct Face {
- bool from_b;
- bool inside;
- int points[3];
+ bool from_b = false;
+ bool inside = false;
+ int points[3] = {};
Vector2 uvs[3];
- bool smooth;
- bool invert;
- int material_idx;
+ bool smooth = false;
+ bool invert = false;
+ int material_idx = 0;
};
struct FaceBVH {
- int face;
- int left;
- int right;
- int next;
+ int face = 0;
+ int left = 0;
+ int right = 0;
+ int next = 0;
Vector3 center;
AABB aabb;
};
@@ -142,7 +142,7 @@ struct CSGBrushOperation {
Map<Ref<Material>, int> materials;
Map<Vector3, int> vertex_map;
OAHashMap<VertexKey, int, VertexKeyHash> snap_cache;
- float vertex_snap;
+ float vertex_snap = 0.0;
inline void _add_distance(List<real_t> &r_intersectionsA, List<real_t> &r_intersectionsB, bool p_from_B, real_t p_distance) const;
inline bool _bvh_inside(FaceBVH *facebvhptr, int p_max_depth, int p_bvh_first, int p_face_idx) const;
@@ -159,7 +159,7 @@ struct CSGBrushOperation {
};
struct Face2D {
- int vertex_idx[3];
+ int vertex_idx[3] = {};
};
Vector<Vertex2D> vertices;
@@ -167,7 +167,7 @@ struct CSGBrushOperation {
Plane plane;
Transform to_2D;
Transform to_3D;
- float vertex_snap2;
+ float vertex_snap2 = 0.0;
inline int _get_point_idx(const Vector2 &p_point);
inline int _add_vertex(const Vertex2D &p_vertex);
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index e348f8a568..b97ee6ce4c 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -45,7 +45,8 @@ void CSGShape3D::set_use_collision(bool p_enable) {
if (use_collision) {
root_collision_shape.instance();
- root_collision_instance = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC);
+ root_collision_instance = PhysicsServer3D::get_singleton()->body_create();
+ PhysicsServer3D::get_singleton()->body_set_mode(root_collision_instance, PhysicsServer3D::BODY_MODE_STATIC);
PhysicsServer3D::get_singleton()->body_set_state(root_collision_instance, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
PhysicsServer3D::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid());
PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world_3d()->get_space());
@@ -58,7 +59,7 @@ void CSGShape3D::set_use_collision(bool p_enable) {
root_collision_instance = RID();
root_collision_shape.unref();
}
- _change_notify();
+ notify_property_list_changed();
}
bool CSGShape3D::is_using_collision() const {
@@ -494,7 +495,8 @@ void CSGShape3D::_notification(int p_what) {
if (use_collision && is_root_shape()) {
root_collision_shape.instance();
- root_collision_instance = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC);
+ root_collision_instance = PhysicsServer3D::get_singleton()->body_create();
+ PhysicsServer3D::get_singleton()->body_set_mode(root_collision_instance, PhysicsServer3D::BODY_MODE_STATIC);
PhysicsServer3D::get_singleton()->body_set_state(root_collision_instance, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
PhysicsServer3D::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid());
PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world_3d()->get_space());
@@ -625,15 +627,6 @@ void CSGShape3D::_bind_methods() {
}
CSGShape3D::CSGShape3D() {
- operation = OPERATION_UNION;
- parent = nullptr;
- brush = nullptr;
- dirty = false;
- snap = 0.001;
- use_collision = false;
- collision_layer = 1;
- collision_mask = 1;
- calculate_tangents = true;
set_notify_local_transform(true);
}
@@ -1040,7 +1033,6 @@ void CSGSphere3D::set_radius(const float p_radius) {
radius = p_radius;
_make_dirty();
update_gizmo();
- _change_notify("radius");
}
float CSGSphere3D::get_radius() const {
@@ -1168,7 +1160,7 @@ CSGBrush *CSGBox3D::_build_brush() {
materialsw[face] = material;
face++;
- //face 1
+ //face 2
facesw[face * 3 + 0] = face_points[2] * vertex_mul;
facesw[face * 3 + 1] = face_points[3] * vertex_mul;
facesw[face * 3 + 2] = face_points[0] * vertex_mul;
@@ -1210,7 +1202,6 @@ void CSGBox3D::set_size(const Vector3 &p_size) {
size = p_size;
_make_dirty();
update_gizmo();
- _change_notify("size");
}
Vector3 CSGBox3D::get_size() const {
@@ -1392,7 +1383,6 @@ void CSGCylinder3D::set_radius(const float p_radius) {
radius = p_radius;
_make_dirty();
update_gizmo();
- _change_notify("radius");
}
float CSGCylinder3D::get_radius() const {
@@ -1403,7 +1393,6 @@ void CSGCylinder3D::set_height(const float p_height) {
height = p_height;
_make_dirty();
update_gizmo();
- _change_notify("height");
}
float CSGCylinder3D::get_height() const {
@@ -1613,7 +1602,6 @@ void CSGTorus3D::set_inner_radius(const float p_inner_radius) {
inner_radius = p_inner_radius;
_make_dirty();
update_gizmo();
- _change_notify("inner_radius");
}
float CSGTorus3D::get_inner_radius() const {
@@ -1624,7 +1612,6 @@ void CSGTorus3D::set_outer_radius(const float p_outer_radius) {
outer_radius = p_outer_radius;
_make_dirty();
update_gizmo();
- _change_notify("outer_radius");
}
float CSGTorus3D::get_outer_radius() const {
@@ -2271,7 +2258,7 @@ void CSGPolygon3D::set_mode(Mode p_mode) {
mode = p_mode;
_make_dirty();
update_gizmo();
- _change_notify();
+ notify_property_list_changed();
}
CSGPolygon3D::Mode CSGPolygon3D::get_mode() const {
diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h
index 7dff8b6d3b..de7de09f00 100644
--- a/modules/csg/csg_shape.h
+++ b/modules/csg/csg_shape.h
@@ -50,23 +50,23 @@ public:
};
private:
- Operation operation;
- CSGShape3D *parent;
+ Operation operation = OPERATION_UNION;
+ CSGShape3D *parent = nullptr;
- CSGBrush *brush;
+ CSGBrush *brush = nullptr;
AABB node_aabb;
- bool dirty;
- float snap;
+ bool dirty = false;
+ float snap = 0.001;
- bool use_collision;
- uint32_t collision_layer;
- uint32_t collision_mask;
+ bool use_collision = false;
+ uint32_t collision_layer = 1;
+ uint32_t collision_mask = 1;
Ref<ConcavePolygonShape3D> root_collision_shape;
RID root_collision_instance;
- bool calculate_tangents;
+ bool calculate_tangents = true;
Ref<ArrayMesh> root_mesh;
@@ -85,12 +85,12 @@ private:
Vector<Vector2> uvs;
Vector<float> tans;
Ref<Material> material;
- int last_added;
+ int last_added = 0;
- Vector3 *verticesw;
- Vector3 *normalsw;
- Vector2 *uvsw;
- float *tansw;
+ Vector3 *verticesw = nullptr;
+ Vector3 *normalsw = nullptr;
+ Vector2 *uvsw = nullptr;
+ float *tansw = nullptr;
};
//mikktspace callbacks
diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp
index 43faa52218..3beca3d12a 100644
--- a/modules/cvtt/image_compress_cvtt.cpp
+++ b/modules/cvtt/image_compress_cvtt.cpp
@@ -33,30 +33,31 @@
#include "core/os/os.h"
#include "core/os/thread.h"
#include "core/string/print_string.h"
+#include "core/templates/safe_refcount.h"
#include <ConvectionKernels.h>
struct CVTTCompressionJobParams {
- bool is_hdr;
- bool is_signed;
- int bytes_per_pixel;
+ bool is_hdr = false;
+ bool is_signed = false;
+ int bytes_per_pixel = 0;
cvtt::Options options;
};
struct CVTTCompressionRowTask {
const uint8_t *in_mm_bytes;
- uint8_t *out_mm_bytes;
- int y_start;
- int width;
- int height;
+ uint8_t *out_mm_bytes = nullptr;
+ int y_start = 0;
+ int width = 0;
+ int height = 0;
};
struct CVTTCompressionJobQueue {
CVTTCompressionJobParams job_params;
const CVTTCompressionRowTask *job_tasks;
- uint32_t num_tasks;
- uint32_t current_task;
+ uint32_t num_tasks = 0;
+ SafeNumeric<uint32_t> current_task;
};
static void _digest_row_task(const CVTTCompressionJobParams &p_job_params, const CVTTCompressionRowTask &p_row_task) {
@@ -131,7 +132,7 @@ static void _digest_row_task(const CVTTCompressionJobParams &p_job_params, const
static void _digest_job_queue(void *p_job_queue) {
CVTTCompressionJobQueue *job_queue = static_cast<CVTTCompressionJobQueue *>(p_job_queue);
- for (uint32_t next_task = atomic_increment(&job_queue->current_task); next_task <= job_queue->num_tasks; next_task = atomic_increment(&job_queue->current_task)) {
+ for (uint32_t next_task = job_queue->current_task.increment(); next_task <= job_queue->num_tasks; next_task = job_queue->current_task.increment()) {
_digest_row_task(job_queue->job_params, job_queue->job_tasks[next_task - 1]);
}
}
@@ -263,7 +264,7 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann
const CVTTCompressionRowTask *tasks_rb = tasks.ptr();
job_queue.job_tasks = &tasks_rb[0];
- job_queue.current_task = 0;
+ job_queue.current_task.set(0);
job_queue.num_tasks = static_cast<uint32_t>(tasks.size());
for (int i = 0; i < num_job_threads; i++) {
diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp
index 2865b3c9ae..2fef576b77 100644
--- a/modules/dds/texture_loader_dds.cpp
+++ b/modules/dds/texture_loader_dds.cpp
@@ -69,11 +69,11 @@ enum DDSFormat {
struct DDSFormatInfo {
const char *name;
- bool compressed;
- bool palette;
- uint32_t divisor;
- uint32_t block_size;
- Image::Format format;
+ bool compressed = false;
+ bool palette = false;
+ uint32_t divisor = 0;
+ uint32_t block_size = 0;
+ Image::Format format = Image::Format::FORMAT_BPTC_RGBA;
};
static const DDSFormatInfo dds_format_info[DDS_MAX] = {
@@ -94,7 +94,7 @@ static const DDSFormatInfo dds_format_info[DDS_MAX] = {
{ "GRAYSCALE_ALPHA", false, false, 1, 2, Image::FORMAT_LA8 }
};
-RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
diff --git a/modules/dds/texture_loader_dds.h b/modules/dds/texture_loader_dds.h
index 605e791969..cf93156423 100644
--- a/modules/dds/texture_loader_dds.h
+++ b/modules/dds/texture_loader_dds.h
@@ -36,7 +36,7 @@
class ResourceFormatDDS : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
index 6c713fa1ce..c8f32ffde6 100644
--- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
+++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
@@ -124,6 +124,22 @@
Configure the [CryptoKey] to use when [member use_dtls] is [code]true[/code]. Remember to also call [method set_dtls_certificate] to setup your [X509Certificate].
</description>
</method>
+ <method name="set_peer_timeout">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="timeout_limit" type="int">
+ </argument>
+ <argument index="2" name="timeout_min" type="int">
+ </argument>
+ <argument index="3" name="timeout_max" type="int">
+ </argument>
+ <description>
+ Sets the timeout parameters for a peer. The timeout parameters control how and when a peer will timeout from a failure to acknowledge reliable traffic. Timeout values are expressed in milliseconds.
+ The [code]timeout_limit[/code] is a factor that, multiplied by a value based on the avarage round trip time, will determine the timeout limit for a reliable packet. When that limit is reached, the timeout will be doubled, and the peer will be disconnected if that limit has reached [code]timeout_min[/code]. The [code]timeout_max[/code] parameter, on the other hand, defines a fixed timeout for which any packet must be acknowledged or the peer will be dropped.
+ </description>
+ </method>
</methods>
<members>
<member name="always_ordered" type="bool" setter="set_always_ordered" getter="is_always_ordered" default="false">
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp
index 66db9ab84e..25b87145b6 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/networked_multiplayer_enet.cpp
@@ -248,7 +248,7 @@ void NetworkedMultiplayerENet::poll() {
int *new_id = memnew(int);
*new_id = event.data;
- if (*new_id == 0) { // Data zero is sent by server (enet won't let you configure this). Server is always 1.
+ if (*new_id == 0) { // Data zero is sent by server (ENet won't let you configure this). Server is always 1.
*new_id = 1;
}
@@ -784,6 +784,14 @@ int NetworkedMultiplayerENet::get_peer_port(int p_peer_id) const {
#endif
}
+void NetworkedMultiplayerENet::set_peer_timeout(int p_peer_id, int p_timeout_limit, int p_timeout_min, int p_timeout_max) {
+ ERR_FAIL_COND_MSG(!peer_map.has(p_peer_id), vformat("Peer ID %d not found in the list of peers.", p_peer_id));
+ ERR_FAIL_COND_MSG(!is_server() && p_peer_id != 1, "Can't change the timeout of peers other then the server when acting as a client.");
+ ERR_FAIL_COND_MSG(peer_map[p_peer_id] == nullptr, vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id));
+ ERR_FAIL_COND_MSG(p_timeout_limit > p_timeout_min || p_timeout_min > p_timeout_max, "Timeout limit must be less than minimum timeout, which itself must be less then maximum timeout");
+ enet_peer_timeout(peer_map[p_peer_id], p_timeout_limit, p_timeout_min, p_timeout_max);
+}
+
void NetworkedMultiplayerENet::set_transfer_channel(int p_channel) {
ERR_FAIL_COND_MSG(p_channel < -1 || p_channel >= channel_count, vformat("The transfer channel must be set between 0 and %d, inclusive (got %d).", channel_count - 1, p_channel));
ERR_FAIL_COND_MSG(p_channel == SYSCH_CONFIG, vformat("The channel %d is reserved.", SYSCH_CONFIG));
@@ -838,6 +846,7 @@ void NetworkedMultiplayerENet::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_dtls_verify_enabled"), &NetworkedMultiplayerENet::is_dtls_verify_enabled);
ClassDB::bind_method(D_METHOD("get_peer_address", "id"), &NetworkedMultiplayerENet::get_peer_address);
ClassDB::bind_method(D_METHOD("get_peer_port", "id"), &NetworkedMultiplayerENet::get_peer_port);
+ ClassDB::bind_method(D_METHOD("set_peer_timeout", "id", "timeout_limit", "timeout_min", "timeout_max"), &NetworkedMultiplayerENet::set_peer_timeout);
ClassDB::bind_method(D_METHOD("get_packet_channel"), &NetworkedMultiplayerENet::get_packet_channel);
ClassDB::bind_method(D_METHOD("get_last_packet_channel"), &NetworkedMultiplayerENet::get_last_packet_channel);
@@ -866,28 +875,12 @@ void NetworkedMultiplayerENet::_bind_methods() {
}
NetworkedMultiplayerENet::NetworkedMultiplayerENet() {
- active = false;
- server = false;
- refuse_connections = false;
- server_relay = true;
- unique_id = 0;
- target_peer = 0;
- current_packet.packet = nullptr;
- transfer_mode = TRANSFER_MODE_RELIABLE;
- channel_count = SYSCH_MAX;
- transfer_channel = -1;
- always_ordered = false;
- connection_status = CONNECTION_DISCONNECTED;
- compression_mode = COMPRESS_NONE;
enet_compressor.context = this;
enet_compressor.compress = enet_compress;
enet_compressor.decompress = enet_decompress;
enet_compressor.destroy = enet_compressor_destroy;
bind_ip = IP_Address("*");
-
- dtls_enabled = false;
- dtls_verify = true;
}
NetworkedMultiplayerENet::~NetworkedMultiplayerENet() {
diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/networked_multiplayer_enet.h
index 4baa48be5e..b99b14d218 100644
--- a/modules/enet/networked_multiplayer_enet.h
+++ b/modules/enet/networked_multiplayer_enet.h
@@ -62,35 +62,35 @@ private:
SYSCH_MAX
};
- bool active;
- bool server;
+ bool active = false;
+ bool server = false;
- uint32_t unique_id;
+ uint32_t unique_id = 0;
- int target_peer;
- TransferMode transfer_mode;
- int transfer_channel;
- int channel_count;
- bool always_ordered;
+ int target_peer = 0;
+ TransferMode transfer_mode = TRANSFER_MODE_RELIABLE;
+ int transfer_channel = -1;
+ int channel_count = SYSCH_MAX;
+ bool always_ordered = false;
ENetEvent event;
- ENetPeer *peer;
- ENetHost *host;
+ ENetPeer *peer = nullptr;
+ ENetHost *host = nullptr;
- bool refuse_connections;
- bool server_relay;
+ bool refuse_connections = false;
+ bool server_relay = true;
- ConnectionStatus connection_status;
+ ConnectionStatus connection_status = CONNECTION_DISCONNECTED;
Map<int, ENetPeer *> peer_map;
struct Packet {
- ENetPacket *packet;
- int from;
- int channel;
+ ENetPacket *packet = nullptr;
+ int from = 0;
+ int channel = 0;
};
- CompressionMode compression_mode;
+ CompressionMode compression_mode = COMPRESS_NONE;
List<Packet> incoming_packets;
@@ -110,10 +110,10 @@ private:
IP_Address bind_ip;
- bool dtls_enabled;
+ bool dtls_enabled = false;
Ref<CryptoKey> dtls_key;
Ref<X509Certificate> dtls_cert;
- bool dtls_verify;
+ bool dtls_verify = true;
protected:
static void _bind_methods();
@@ -127,6 +127,7 @@ public:
virtual IP_Address get_peer_address(int p_peer_id) const;
virtual int get_peer_port(int p_peer_id) const;
+ void set_peer_timeout(int p_peer_id, int p_timeout_limit, int p_timeout_min, int p_timeout_max);
Error create_server(int p_port, int p_max_clients = 32, int p_in_bandwidth = 0, int p_out_bandwidth = 0);
Error create_client(const String &p_address, int p_port, int p_in_bandwidth = 0, int p_out_bandwidth = 0, int p_client_port = 0);
diff --git a/modules/etc/texture_loader_pkm.cpp b/modules/etc/texture_loader_pkm.cpp
index b0ea109f76..95db9315d5 100644
--- a/modules/etc/texture_loader_pkm.cpp
+++ b/modules/etc/texture_loader_pkm.cpp
@@ -35,14 +35,14 @@
struct ETC1Header {
char tag[6]; // "PKM 10"
- uint16_t format; // Format == number of mips (== zero)
- uint16_t texWidth; // Texture dimensions, multiple of 4 (big-endian)
- uint16_t texHeight;
- uint16_t origWidth; // Original dimensions (big-endian)
- uint16_t origHeight;
+ uint16_t format = 0; // Format == number of mips (== zero)
+ uint16_t texWidth = 0; // Texture dimensions, multiple of 4 (big-endian)
+ uint16_t texHeight = 0;
+ uint16_t origWidth = 0; // Original dimensions (big-endian)
+ uint16_t origHeight = 0;
};
-RES ResourceFormatPKM::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatPKM::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
diff --git a/modules/etc/texture_loader_pkm.h b/modules/etc/texture_loader_pkm.h
index 67fbee3a7e..2ed5e75807 100644
--- a/modules/etc/texture_loader_pkm.h
+++ b/modules/etc/texture_loader_pkm.h
@@ -36,7 +36,7 @@
class ResourceFormatPKM : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/fbx/data/fbx_mesh_data.cpp b/modules/fbx/data/fbx_mesh_data.cpp
index 883651943e..b088dd8640 100644
--- a/modules/fbx/data/fbx_mesh_data.cpp
+++ b/modules/fbx/data/fbx_mesh_data.cpp
@@ -417,6 +417,7 @@ void FBXMeshData::sanitize_vertex_weights(const ImportState &state) {
int bind_id = 0;
for (const FBXDocParser::Cluster *cluster : fbx_skin->Clusters()) {
+ ERR_CONTINUE_MSG(!state.fbx_bone_map.has(cluster->TargetNode()->ID()), "Missing bone map for cluster target node with id " + uitos(cluster->TargetNode()->ID()) + ".");
Ref<FBXBone> bone = state.fbx_bone_map[cluster->TargetNode()->ID()];
skeleton_to_skin_bind_id.insert(bone->godot_bone_id, bind_id);
bind_id++;
diff --git a/modules/fbx/editor_scene_importer_fbx.cpp b/modules/fbx/editor_scene_importer_fbx.cpp
index 6576147b2b..e18ebe3930 100644
--- a/modules/fbx/editor_scene_importer_fbx.cpp
+++ b/modules/fbx/editor_scene_importer_fbx.cpp
@@ -628,7 +628,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
mesh_data_precached->mesh_node = fbx_node;
// mesh node, mesh id
- mesh_node = mesh_data_precached->create_fbx_mesh(state, mesh_geometry, fbx_node->fbx_model, (p_flags & IMPORT_USE_COMPRESSION) != 0);
+ mesh_node = mesh_data_precached->create_fbx_mesh(state, mesh_geometry, fbx_node->fbx_model, 0);
if (!state.MeshNodes.has(mesh_id)) {
state.MeshNodes.insert(mesh_id, fbx_node);
}
@@ -1132,7 +1132,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
max_duration = animation_track_time;
}
- rot_values.push_back(final_rotation);
+ rot_values.push_back(final_rotation.normalized());
rot_times.push_back(animation_track_time);
}
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index e3a359e09a..86bd8b820d 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -110,6 +110,16 @@ bool GDNativeLibrary::_get(const StringName &p_name, Variant &r_property) const
return false;
}
+void GDNativeLibrary::reset_state() {
+ config_file.instance();
+ current_library_path = "";
+ current_dependencies.clear();
+ symbol_prefix = default_symbol_prefix;
+ load_once = default_load_once;
+ singleton = default_singleton;
+ reloadable = default_reloadable;
+}
+
void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
// set entries
List<String> entry_key_list;
@@ -508,7 +518,7 @@ Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle, bool p_
return result;
}
-RES GDNativeLibraryResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES GDNativeLibraryResourceLoader::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<GDNativeLibrary> lib;
lib.instance();
diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h
index 765087d176..a28c58ec0d 100644
--- a/modules/gdnative/gdnative.h
+++ b/modules/gdnative/gdnative.h
@@ -63,6 +63,8 @@ class GDNativeLibrary : public Resource {
bool reloadable;
public:
+ virtual void reset_state() override;
+
GDNativeLibrary();
~GDNativeLibrary();
@@ -166,7 +168,7 @@ public:
class GDNativeLibraryResourceLoader : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES 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;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdnative/gdnative/aabb.cpp b/modules/gdnative/gdnative/aabb.cpp
index 5d3f224adc..c42b874b4b 100644
--- a/modules/gdnative/gdnative/aabb.cpp
+++ b/modules/gdnative/gdnative/aabb.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_aabb_new(godot_aabb *p_self) {
memnew_placement(p_self, AABB);
}
+void GDAPI godot_aabb_new_copy(godot_aabb *r_dest, const godot_aabb *p_src) {
+ memnew_placement(r_dest, AABB(*(AABB *)p_src));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/array.cpp b/modules/gdnative/gdnative/array.cpp
index 87a8c8e376..76e131dc06 100644
--- a/modules/gdnative/gdnative/array.cpp
+++ b/modules/gdnative/gdnative/array.cpp
@@ -43,10 +43,24 @@ void GDAPI godot_array_new(godot_array *p_self) {
memnew_placement(p_self, Array);
}
+void GDAPI godot_array_new_copy(godot_array *r_dest, const godot_array *p_src) {
+ memnew_placement(r_dest, Array(*(Array *)p_src));
+}
+
void GDAPI godot_array_destroy(godot_array *p_self) {
((Array *)p_self)->~Array();
}
+godot_variant GDAPI *godot_array_operator_index(godot_array *p_self, godot_int p_index) {
+ Array *self = (Array *)p_self;
+ return (godot_variant *)&self->operator[](p_index);
+}
+
+const godot_variant GDAPI *godot_array_operator_index_const(const godot_array *p_self, godot_int p_index) {
+ const Array *self = (const Array *)p_self;
+ return (const godot_variant *)&self->operator[](p_index);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/basis.cpp b/modules/gdnative/gdnative/basis.cpp
index 86a6d6216c..4641f0bacc 100644
--- a/modules/gdnative/gdnative/basis.cpp
+++ b/modules/gdnative/gdnative/basis.cpp
@@ -42,6 +42,20 @@ void GDAPI godot_basis_new(godot_basis *p_self) {
memnew_placement(p_self, Basis);
}
+void GDAPI godot_basis_new_copy(godot_basis *r_dest, const godot_basis *p_src) {
+ memnew_placement(r_dest, Basis(*(Basis *)p_src));
+}
+
+godot_vector3 GDAPI *godot_basis_operator_index(godot_basis *p_self, godot_int p_index) {
+ Basis *self = (Basis *)p_self;
+ return (godot_vector3 *)&self->operator[](p_index);
+}
+
+const godot_vector3 GDAPI *godot_basis_operator_index_const(const godot_basis *p_self, godot_int p_index) {
+ const Basis *self = (const Basis *)p_self;
+ return (const godot_vector3 *)&self->operator[](p_index);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/callable.cpp b/modules/gdnative/gdnative/callable.cpp
index 7c62b5928f..85274e5e22 100644
--- a/modules/gdnative/gdnative/callable.cpp
+++ b/modules/gdnative/gdnative/callable.cpp
@@ -43,6 +43,10 @@ void GDAPI godot_callable_new(godot_callable *p_self) {
memnew_placement(p_self, Callable);
}
+void GDAPI godot_callable_new_copy(godot_callable *r_dest, const godot_callable *p_src) {
+ memnew_placement(r_dest, Callable(*(Callable *)p_src));
+}
+
void GDAPI godot_callable_destroy(godot_callable *p_self) {
Callable *self = (Callable *)p_self;
self->~Callable();
diff --git a/modules/gdnative/gdnative/color.cpp b/modules/gdnative/gdnative/color.cpp
index 784c8d439e..502f89c027 100644
--- a/modules/gdnative/gdnative/color.cpp
+++ b/modules/gdnative/gdnative/color.cpp
@@ -42,6 +42,20 @@ void GDAPI godot_color_new(godot_color *p_self) {
memnew_placement(p_self, Color);
}
+void GDAPI godot_color_new_copy(godot_color *r_dest, const godot_color *p_src) {
+ memnew_placement(r_dest, Color(*(Color *)p_src));
+}
+
+float GDAPI *godot_color_operator_index(godot_color *p_self, godot_int p_index) {
+ Color *self = (Color *)p_self;
+ return (float *)&self->operator[](p_index);
+}
+
+const float GDAPI *godot_color_operator_index_const(const godot_color *p_self, godot_int p_index) {
+ const Color *self = (const Color *)p_self;
+ return (const float *)&self->operator[](p_index);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/dictionary.cpp b/modules/gdnative/gdnative/dictionary.cpp
index d58e08f4b0..2bfad6e695 100644
--- a/modules/gdnative/gdnative/dictionary.cpp
+++ b/modules/gdnative/gdnative/dictionary.cpp
@@ -31,6 +31,7 @@
#include "gdnative/dictionary.h"
#include "core/variant/dictionary.h"
+#include "core/variant/variant.h"
static_assert(sizeof(godot_dictionary) == sizeof(Dictionary), "Dictionary size mismatch");
@@ -42,11 +43,25 @@ void GDAPI godot_dictionary_new(godot_dictionary *p_self) {
memnew_placement(p_self, Dictionary);
}
+void GDAPI godot_dictionary_new_copy(godot_dictionary *r_dest, const godot_dictionary *p_src) {
+ memnew_placement(r_dest, Dictionary(*(Dictionary *)p_src));
+}
+
void GDAPI godot_dictionary_destroy(godot_dictionary *p_self) {
Dictionary *self = (Dictionary *)p_self;
self->~Dictionary();
}
+godot_variant GDAPI *godot_dictionary_operator_index(godot_dictionary *p_self, const godot_variant *p_key) {
+ Dictionary *self = (Dictionary *)p_self;
+ return (godot_variant *)&self->operator[](*((const Variant *)p_key));
+}
+
+const godot_variant GDAPI *godot_dictionary_operator_index_const(const godot_dictionary *p_self, const godot_variant *p_key) {
+ const Dictionary *self = (const Dictionary *)p_self;
+ return (const godot_variant *)&self->operator[](*((const Variant *)p_key));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp
index c3d25f81c7..b84ce2d192 100644
--- a/modules/gdnative/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative/gdnative.cpp
@@ -127,6 +127,17 @@ void GDAPI godot_free(void *p_ptr) {
memfree(p_ptr);
}
+// Helper print functions.
+void GDAPI godot_print_error(const char *p_description, const char *p_function, const char *p_file, int p_line) {
+ _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_ERROR);
+}
+void GDAPI godot_print_warning(const char *p_description, const char *p_function, const char *p_file, int p_line) {
+ _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_WARNING);
+}
+void GDAPI godot_print_script_error(const char *p_description, const char *p_function, const char *p_file, int p_line) {
+ _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_SCRIPT);
+}
+
void _gdnative_report_version_mismatch(const godot_object *p_library, const char *p_ext, godot_gdnative_api_version p_want, godot_gdnative_api_version p_have) {
String message = "Error loading GDNative file ";
GDNativeLibrary *library = (GDNativeLibrary *)p_library;
diff --git a/modules/gdnative/gdnative/node_path.cpp b/modules/gdnative/gdnative/node_path.cpp
index 02c2f9b22b..57d67b9abb 100644
--- a/modules/gdnative/gdnative/node_path.cpp
+++ b/modules/gdnative/gdnative/node_path.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_node_path_new(godot_node_path *p_self) {
memnew_placement(p_self, NodePath);
}
+void GDAPI godot_node_path_new_copy(godot_node_path *r_dest, const godot_node_path *p_src) {
+ memnew_placement(r_dest, NodePath(*(NodePath *)p_src));
+}
+
void GDAPI godot_node_path_destroy(godot_node_path *p_self) {
NodePath *self = (NodePath *)p_self;
self->~NodePath();
diff --git a/modules/gdnative/gdnative/packed_arrays.cpp b/modules/gdnative/gdnative/packed_arrays.cpp
index 9e4c6e6f38..396109e576 100644
--- a/modules/gdnative/gdnative/packed_arrays.cpp
+++ b/modules/gdnative/gdnative/packed_arrays.cpp
@@ -59,110 +59,264 @@ void GDAPI godot_packed_byte_array_new(godot_packed_byte_array *p_self) {
memnew_placement(p_self, PackedByteArray);
}
+void GDAPI godot_packed_byte_array_new_copy(godot_packed_byte_array *r_dest, const godot_packed_byte_array *p_src) {
+ memnew_placement(r_dest, PackedByteArray(*(PackedByteArray *)p_src));
+}
+
void GDAPI godot_packed_byte_array_destroy(godot_packed_byte_array *p_self) {
((PackedByteArray *)p_self)->~PackedByteArray();
}
+uint8_t GDAPI *godot_packed_byte_array_operator_index(godot_packed_byte_array *p_self, godot_int p_index) {
+ PackedByteArray *self = (PackedByteArray *)p_self;
+ return (uint8_t *)&self->operator[](p_index);
+}
+
+const uint8_t GDAPI *godot_packed_byte_array_operator_index_const(const godot_packed_byte_array *p_self, godot_int p_index) {
+ const PackedByteArray *self = (const PackedByteArray *)p_self;
+ return (const uint8_t *)&self->operator[](p_index);
+}
+
// int32
void GDAPI godot_packed_int32_array_new(godot_packed_int32_array *p_self) {
memnew_placement(p_self, PackedInt32Array);
}
+void GDAPI godot_packed_int32_array_new_copy(godot_packed_int32_array *r_dest, const godot_packed_int32_array *p_src) {
+ memnew_placement(r_dest, PackedInt32Array(*(PackedInt32Array *)p_src));
+}
+
void GDAPI godot_packed_int32_array_destroy(godot_packed_int32_array *p_self) {
((PackedInt32Array *)p_self)->~PackedInt32Array();
}
+int32_t GDAPI *godot_packed_int32_array_operator_index(godot_packed_int32_array *p_self, godot_int p_index) {
+ PackedInt32Array *self = (PackedInt32Array *)p_self;
+ return (int32_t *)&self->operator[](p_index);
+}
+
+const int32_t GDAPI *godot_packed_int32_array_operator_index_const(const godot_packed_int32_array *p_self, godot_int p_index) {
+ const PackedInt32Array *self = (const PackedInt32Array *)p_self;
+ return (const int32_t *)&self->operator[](p_index);
+}
+
// int64
void GDAPI godot_packed_int64_array_new(godot_packed_int64_array *p_self) {
memnew_placement(p_self, PackedInt64Array);
}
+void GDAPI godot_packed_int64_array_new_copy(godot_packed_int64_array *r_dest, const godot_packed_int64_array *p_src) {
+ memnew_placement(r_dest, PackedInt64Array(*(PackedInt64Array *)p_src));
+}
+
void GDAPI godot_packed_int64_array_destroy(godot_packed_int64_array *p_self) {
((PackedInt64Array *)p_self)->~PackedInt64Array();
}
+int64_t GDAPI *godot_packed_int64_array_operator_index(godot_packed_int64_array *p_self, godot_int p_index) {
+ PackedInt64Array *self = (PackedInt64Array *)p_self;
+ return (int64_t *)&self->operator[](p_index);
+}
+
+const int64_t GDAPI *godot_packed_int64_array_operator_index_const(const godot_packed_int64_array *p_self, godot_int p_index) {
+ const PackedInt64Array *self = (const PackedInt64Array *)p_self;
+ return (const int64_t *)&self->operator[](p_index);
+}
+
// float32
void GDAPI godot_packed_float32_array_new(godot_packed_float32_array *p_self) {
memnew_placement(p_self, PackedFloat32Array);
}
+void GDAPI godot_packed_float32_array_new_copy(godot_packed_float32_array *r_dest, const godot_packed_float32_array *p_src) {
+ memnew_placement(r_dest, PackedFloat32Array(*(PackedFloat32Array *)p_src));
+}
+
void GDAPI godot_packed_float32_array_destroy(godot_packed_float32_array *p_self) {
((PackedFloat32Array *)p_self)->~PackedFloat32Array();
}
+float GDAPI *godot_packed_float32_array_operator_index(godot_packed_float32_array *p_self, godot_int p_index) {
+ PackedFloat32Array *self = (PackedFloat32Array *)p_self;
+ return (float *)&self->operator[](p_index);
+}
+
+const float GDAPI *godot_packed_float32_array_operator_index_const(const godot_packed_float32_array *p_self, godot_int p_index) {
+ const PackedFloat32Array *self = (const PackedFloat32Array *)p_self;
+ return (const float *)&self->operator[](p_index);
+}
+
// float64
void GDAPI godot_packed_float64_array_new(godot_packed_float64_array *p_self) {
memnew_placement(p_self, PackedFloat64Array);
}
+void GDAPI godot_packed_float64_array_new_copy(godot_packed_float64_array *r_dest, const godot_packed_float64_array *p_src) {
+ memnew_placement(r_dest, PackedFloat64Array(*(PackedFloat64Array *)p_src));
+}
+
void GDAPI godot_packed_float64_array_destroy(godot_packed_float64_array *p_self) {
((PackedFloat64Array *)p_self)->~PackedFloat64Array();
}
+double GDAPI *godot_packed_float64_array_operator_index(godot_packed_float64_array *p_self, godot_int p_index) {
+ PackedFloat64Array *self = (PackedFloat64Array *)p_self;
+ return (double *)&self->operator[](p_index);
+}
+
+const double GDAPI *godot_packed_float64_array_operator_index_const(const godot_packed_float64_array *p_self, godot_int p_index) {
+ const PackedFloat64Array *self = (const PackedFloat64Array *)p_self;
+ return (const double *)&self->operator[](p_index);
+}
+
// string
void GDAPI godot_packed_string_array_new(godot_packed_string_array *p_self) {
memnew_placement(p_self, PackedStringArray);
}
+void GDAPI godot_packed_string_array_new_copy(godot_packed_string_array *r_dest, const godot_packed_string_array *p_src) {
+ memnew_placement(r_dest, PackedStringArray(*(PackedStringArray *)p_src));
+}
+
void GDAPI godot_packed_string_array_destroy(godot_packed_string_array *p_self) {
((PackedStringArray *)p_self)->~PackedStringArray();
}
+godot_string GDAPI *godot_packed_string_array_operator_index(godot_packed_string_array *p_self, godot_int p_index) {
+ PackedStringArray *self = (PackedStringArray *)p_self;
+ return (godot_string *)&self->operator[](p_index);
+}
+
+const godot_string GDAPI *godot_packed_string_array_operator_index_const(const godot_packed_string_array *p_self, godot_int p_index) {
+ const PackedStringArray *self = (const PackedStringArray *)p_self;
+ return (const godot_string *)&self->operator[](p_index);
+}
+
// vector2
void GDAPI godot_packed_vector2_array_new(godot_packed_vector2_array *p_self) {
memnew_placement(p_self, PackedVector2Array);
}
+void GDAPI godot_packed_vector2_array_new_copy(godot_packed_vector2_array *r_dest, const godot_packed_vector2_array *p_src) {
+ memnew_placement(r_dest, PackedVector2Array(*(PackedVector2Array *)p_src));
+}
+
void GDAPI godot_packed_vector2_array_destroy(godot_packed_vector2_array *p_self) {
((PackedVector2Array *)p_self)->~PackedVector2Array();
}
+godot_vector2 GDAPI *godot_packed_vector2_array_operator_index(godot_packed_vector2_array *p_self, godot_int p_index) {
+ PackedVector2Array *self = (PackedVector2Array *)p_self;
+ return (godot_vector2 *)&self->operator[](p_index);
+}
+
+const godot_vector2 GDAPI *godot_packed_vector2_array_operator_index_const(const godot_packed_vector2_array *p_self, godot_int p_index) {
+ const PackedVector2Array *self = (const PackedVector2Array *)p_self;
+ return (const godot_vector2 *)&self->operator[](p_index);
+}
+
// vector2i
void GDAPI godot_packed_vector2i_array_new(godot_packed_vector2i_array *p_self) {
memnew_placement(p_self, Vector<Vector2i>);
}
+void GDAPI godot_packed_vector2i_array_new_copy(godot_packed_vector2i_array *r_dest, const godot_packed_vector2i_array *p_src) {
+ memnew_placement(r_dest, Vector<Vector2i>(*(Vector<Vector2i> *)p_src));
+}
+
void GDAPI godot_packed_vector2i_array_destroy(godot_packed_vector2i_array *p_self) {
((Vector<Vector2i> *)p_self)->~Vector();
}
+godot_vector2i GDAPI *godot_packed_vector2i_array_operator_index(godot_packed_vector2i_array *p_self, godot_int p_index) {
+ Vector<Vector2i> *self = (Vector<Vector2i> *)p_self;
+ return (godot_vector2i *)&self->operator[](p_index);
+}
+
+const godot_vector2i GDAPI *godot_packed_vector2i_array_operator_index_const(const godot_packed_vector2i_array *p_self, godot_int p_index) {
+ const Vector<Vector2i> *self = (const Vector<Vector2i> *)p_self;
+ return (const godot_vector2i *)&self->operator[](p_index);
+}
+
// vector3
void GDAPI godot_packed_vector3_array_new(godot_packed_vector3_array *p_self) {
memnew_placement(p_self, PackedVector3Array);
}
+void GDAPI godot_packed_vector3_array_new_copy(godot_packed_vector3_array *r_dest, const godot_packed_vector3_array *p_src) {
+ memnew_placement(r_dest, PackedVector3Array(*(PackedVector3Array *)p_src));
+}
+
void GDAPI godot_packed_vector3_array_destroy(godot_packed_vector3_array *p_self) {
((PackedVector3Array *)p_self)->~PackedVector3Array();
}
+godot_vector3 GDAPI *godot_packed_vector3_array_operator_index(godot_packed_vector3_array *p_self, godot_int p_index) {
+ PackedVector3Array *self = (PackedVector3Array *)p_self;
+ return (godot_vector3 *)&self->operator[](p_index);
+}
+
+const godot_vector3 GDAPI *godot_packed_vector3_array_operator_index_const(const godot_packed_vector3_array *p_self, godot_int p_index) {
+ const PackedVector3Array *self = (const PackedVector3Array *)p_self;
+ return (const godot_vector3 *)&self->operator[](p_index);
+}
+
// vector3i
void GDAPI godot_packed_vector3i_array_new(godot_packed_vector3i_array *p_self) {
memnew_placement(p_self, Vector<Vector3i>);
}
+void GDAPI godot_packed_vector3i_array_new_copy(godot_packed_vector3i_array *r_dest, const godot_packed_vector3i_array *p_src) {
+ memnew_placement(r_dest, Vector<Vector3i>(*(Vector<Vector3i> *)p_src));
+}
+
void GDAPI godot_packed_vector3i_array_destroy(godot_packed_vector3i_array *p_self) {
((Vector<Vector3i> *)p_self)->~Vector();
}
+godot_vector3i GDAPI *godot_packed_vector3i_array_operator_index(godot_packed_vector3i_array *p_self, godot_int p_index) {
+ Vector<Vector3i> *self = (Vector<Vector3i> *)p_self;
+ return (godot_vector3i *)&self->operator[](p_index);
+}
+
+const godot_vector3i GDAPI *godot_packed_vector3i_array_operator_index_const(const godot_packed_vector3i_array *p_self, godot_int p_index) {
+ const Vector<Vector3i> *self = (const Vector<Vector3i> *)p_self;
+ return (const godot_vector3i *)&self->operator[](p_index);
+}
+
// color
void GDAPI godot_packed_color_array_new(godot_packed_color_array *p_self) {
memnew_placement(p_self, PackedColorArray);
}
+void GDAPI godot_packed_color_array_new_copy(godot_packed_color_array *r_dest, const godot_packed_color_array *p_src) {
+ memnew_placement(r_dest, PackedColorArray(*(PackedColorArray *)p_src));
+}
+
void GDAPI godot_packed_color_array_destroy(godot_packed_color_array *p_self) {
((PackedColorArray *)p_self)->~PackedColorArray();
}
+godot_color GDAPI *godot_packed_color_array_operator_index(godot_packed_color_array *p_self, godot_int p_index) {
+ PackedColorArray *self = (PackedColorArray *)p_self;
+ return (godot_color *)&self->operator[](p_index);
+}
+
+const godot_color GDAPI *godot_packed_color_array_operator_index_const(const godot_packed_color_array *p_self, godot_int p_index) {
+ const PackedColorArray *self = (const PackedColorArray *)p_self;
+ return (const godot_color *)&self->operator[](p_index);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/plane.cpp b/modules/gdnative/gdnative/plane.cpp
index 61d5e09fad..8b8e84e3c1 100644
--- a/modules/gdnative/gdnative/plane.cpp
+++ b/modules/gdnative/gdnative/plane.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_plane_new(godot_plane *p_self) {
memnew_placement(p_self, Plane);
}
+void GDAPI godot_plane_new_copy(godot_plane *r_dest, const godot_plane *p_src) {
+ memnew_placement(r_dest, Plane(*(Plane *)p_src));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/quat.cpp b/modules/gdnative/gdnative/quat.cpp
index 87f1d7d8e5..8ebcf7c91f 100644
--- a/modules/gdnative/gdnative/quat.cpp
+++ b/modules/gdnative/gdnative/quat.cpp
@@ -42,6 +42,20 @@ void GDAPI godot_quat_new(godot_quat *p_self) {
memnew_placement(p_self, Quat);
}
+void GDAPI godot_quat_new_copy(godot_quat *r_dest, const godot_quat *p_src) {
+ memnew_placement(r_dest, Quat(*(Quat *)p_src));
+}
+
+godot_real_t GDAPI *godot_quat_operator_index(godot_quat *p_self, godot_int p_index) {
+ Quat *self = (Quat *)p_self;
+ return (godot_real_t *)&self->operator[](p_index);
+}
+
+const godot_real_t GDAPI *godot_quat_operator_index_const(const godot_quat *p_self, godot_int p_index) {
+ const Quat *self = (const Quat *)p_self;
+ return (const godot_real_t *)&self->operator[](p_index);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/rect2.cpp b/modules/gdnative/gdnative/rect2.cpp
index 086592ec22..a196a63188 100644
--- a/modules/gdnative/gdnative/rect2.cpp
+++ b/modules/gdnative/gdnative/rect2.cpp
@@ -43,10 +43,18 @@ void GDAPI godot_rect2_new(godot_rect2 *p_self) {
memnew_placement(p_self, Rect2);
}
+void GDAPI godot_rect2_new_copy(godot_rect2 *r_dest, const godot_rect2 *p_src) {
+ memnew_placement(r_dest, Rect2(*(Rect2 *)p_src));
+}
+
void GDAPI godot_rect2i_new(godot_rect2i *p_self) {
memnew_placement(p_self, Rect2i);
}
+void GDAPI godot_rect2i_new_copy(godot_rect2i *r_dest, const godot_rect2i *p_src) {
+ memnew_placement(r_dest, Rect2i(*(Rect2i *)p_src));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/rid.cpp b/modules/gdnative/gdnative/rid.cpp
index 5cab9a21ed..f8599afcf9 100644
--- a/modules/gdnative/gdnative/rid.cpp
+++ b/modules/gdnative/gdnative/rid.cpp
@@ -43,6 +43,10 @@ void GDAPI godot_rid_new(godot_rid *p_self) {
memnew_placement(p_self, RID);
}
+void GDAPI godot_rid_new_copy(godot_rid *r_dest, const godot_rid *p_src) {
+ memnew_placement(r_dest, RID(*(RID *)p_src));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/signal.cpp b/modules/gdnative/gdnative/signal.cpp
index bcb4c93b62..5963c0e6c6 100644
--- a/modules/gdnative/gdnative/signal.cpp
+++ b/modules/gdnative/gdnative/signal.cpp
@@ -43,6 +43,10 @@ void GDAPI godot_signal_new(godot_signal *p_self) {
memnew_placement(p_self, Signal);
}
+void GDAPI godot_signal_new_copy(godot_signal *r_dest, const godot_signal *p_src) {
+ memnew_placement(r_dest, Signal(*(Signal *)p_src));
+}
+
void GDAPI godot_signal_destroy(godot_signal *p_self) {
Signal *self = (Signal *)p_self;
self->~Signal();
diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp
index 19d95f2048..1ad1ea8bdf 100644
--- a/modules/gdnative/gdnative/string.cpp
+++ b/modules/gdnative/gdnative/string.cpp
@@ -45,10 +45,7 @@ void GDAPI godot_string_new(godot_string *r_dest) {
}
void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src) {
- String *dest = (String *)r_dest;
- const String *src = (const String *)p_src;
- memnew_placement(dest, String);
- *dest = String(*src);
+ memnew_placement(r_dest, String(*(String *)p_src));
}
void GDAPI godot_string_new_with_latin1_chars(godot_string *r_dest, const char *p_contents) {
@@ -125,6 +122,45 @@ void GDAPI godot_string_new_with_wide_chars_and_len(godot_string *r_dest, const
}
}
+const char GDAPI *godot_string_to_latin1_chars(const godot_string *p_self) {
+ String *self = (String *)p_self;
+ return self->ascii(true).get_data();
+}
+
+const char GDAPI *godot_string_to_utf8_chars(const godot_string *p_self) {
+ String *self = (String *)p_self;
+ return self->utf8().get_data();
+}
+
+const char16_t GDAPI *godot_string_to_utf16_chars(const godot_string *p_self) {
+ String *self = (String *)p_self;
+ return self->utf16().get_data();
+}
+
+const char32_t GDAPI *godot_string_to_utf32_chars(const godot_string *p_self) {
+ String *self = (String *)p_self;
+ return self->get_data();
+}
+
+const wchar_t GDAPI *godot_string_to_wide_chars(const godot_string *p_self) {
+ String *self = (String *)p_self;
+ if (sizeof(wchar_t) == 2) {
+ return (const wchar_t *)self->utf16().get_data();
+ } else {
+ return (const wchar_t *)self->get_data();
+ }
+}
+
+char32_t GDAPI *godot_string_operator_index(godot_string *p_self, godot_int p_index) {
+ String *self = (String *)p_self;
+ return self->ptrw();
+}
+
+const char32_t GDAPI *godot_string_operator_index_const(const godot_string *p_self, godot_int p_index) {
+ const String *self = (const String *)p_self;
+ return self->ptr();
+}
+
void GDAPI godot_string_destroy(godot_string *p_self) {
String *self = (String *)p_self;
self->~String();
diff --git a/modules/gdnative/gdnative/string_name.cpp b/modules/gdnative/gdnative/string_name.cpp
index c9d2dd5bc3..bd8f69674e 100644
--- a/modules/gdnative/gdnative/string_name.cpp
+++ b/modules/gdnative/gdnative/string_name.cpp
@@ -44,9 +44,7 @@ void GDAPI godot_string_name_new(godot_string_name *r_dest) {
}
void GDAPI godot_string_name_new_copy(godot_string_name *r_dest, const godot_string_name *p_src) {
- StringName *dest = (StringName *)r_dest;
- const StringName *src = (const StringName *)p_src;
- memnew_placement(dest, StringName(*src));
+ memnew_placement(r_dest, StringName(*(StringName *)p_src));
}
void GDAPI godot_string_name_new_with_latin1_chars(godot_string_name *r_dest, const char *p_contents) {
diff --git a/modules/gdnative/gdnative/transform.cpp b/modules/gdnative/gdnative/transform.cpp
index eae981bd07..bfaaa13db2 100644
--- a/modules/gdnative/gdnative/transform.cpp
+++ b/modules/gdnative/gdnative/transform.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_transform_new(godot_transform *p_self) {
memnew_placement(p_self, Transform);
}
+void GDAPI godot_transform_new_copy(godot_transform *r_dest, const godot_transform *p_src) {
+ memnew_placement(r_dest, Transform(*(Transform *)p_src));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/transform2d.cpp b/modules/gdnative/gdnative/transform2d.cpp
index e2c933f1ea..2864818831 100644
--- a/modules/gdnative/gdnative/transform2d.cpp
+++ b/modules/gdnative/gdnative/transform2d.cpp
@@ -42,6 +42,20 @@ void GDAPI godot_transform2d_new(godot_transform2d *p_self) {
memnew_placement(p_self, Transform2D);
}
+void GDAPI godot_transform2d_new_copy(godot_transform2d *r_dest, const godot_transform2d *p_src) {
+ memnew_placement(r_dest, Transform2D(*(Transform2D *)p_src));
+}
+
+godot_vector2 GDAPI *godot_transform2d_operator_index(godot_transform2d *p_self, godot_int p_index) {
+ Transform2D *self = (Transform2D *)p_self;
+ return (godot_vector2 *)&self->operator[](p_index);
+}
+
+const godot_vector2 GDAPI *godot_transform2d_operator_index_const(const godot_transform2d *p_self, godot_int p_index) {
+ const Transform2D *self = (const Transform2D *)p_self;
+ return (const godot_vector2 *)&self->operator[](p_index);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp
index 79f5a536e5..7801e21ab2 100644
--- a/modules/gdnative/gdnative/variant.cpp
+++ b/modules/gdnative/gdnative/variant.cpp
@@ -577,6 +577,54 @@ void GDAPI godot_variant_call(godot_variant *p_self, const godot_string_name *p_
}
}
+void GDAPI godot_variant_call_with_cstring(godot_variant *p_self, const char *p_method, const godot_variant **p_args, const godot_int p_argcount, godot_variant *r_return, godot_variant_call_error *r_error) {
+ Variant *self = (Variant *)p_self;
+ const StringName method(p_method);
+ const Variant **args = (const Variant **)p_args;
+ Variant ret;
+ Callable::CallError error;
+ self->call(method, args, p_argcount, ret, error);
+ memnew_placement_custom(r_return, Variant, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (godot_variant_call_error_error)error.error;
+ r_error->argument = error.argument;
+ r_error->expected = (godot_variant_type)error.expected;
+ }
+}
+
+void GDAPI godot_variant_call_static(godot_variant_type p_type, const godot_string_name *p_method, const godot_variant **p_args, const godot_int p_argcount, godot_variant *r_return, godot_variant_call_error *r_error) {
+ Variant::Type type = (Variant::Type)p_type;
+ const StringName *method = (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_custom(r_return, Variant, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (godot_variant_call_error_error)error.error;
+ r_error->argument = error.argument;
+ r_error->expected = (godot_variant_type)error.expected;
+ }
+}
+
+void GDAPI godot_variant_call_static_with_cstring(godot_variant_type p_type, const char *p_method, const godot_variant **p_args, const godot_int p_argcount, godot_variant *r_return, godot_variant_call_error *r_error) {
+ Variant::Type type = (Variant::Type)p_type;
+ const StringName method(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_custom(r_return, Variant, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (godot_variant_call_error_error)error.error;
+ r_error->argument = error.argument;
+ r_error->expected = (godot_variant_type)error.expected;
+ }
+}
+
void GDAPI godot_variant_evaluate(godot_variant_operator p_op, const godot_variant *p_a, const godot_variant *p_b, godot_variant *r_return, bool *r_valid) {
Variant::Operator op = (Variant::Operator)p_op;
const Variant *a = (const Variant *)p_a;
@@ -593,12 +641,20 @@ void GDAPI godot_variant_set(godot_variant *p_self, const godot_variant *p_key,
self->set(*key, *value, r_valid);
}
-void GDAPI godot_variant_set_named(godot_variant *p_self, const godot_string_name *p_name, const godot_variant *p_value, bool *r_valid) {
+void GDAPI godot_variant_set_named(godot_variant *p_self, const godot_string_name *p_key, const godot_variant *p_value, bool *r_valid) {
Variant *self = (Variant *)p_self;
- const StringName *name = (const StringName *)p_name;
+ const StringName *key = (const StringName *)p_key;
const Variant *value = (const Variant *)p_value;
- self->set_named(*name, *value, *r_valid);
+ self->set_named(*key, *value, *r_valid);
+}
+
+void GDAPI godot_variant_set_named_with_cstring(godot_variant *p_self, const char *p_key, const godot_variant *p_value, bool *r_valid) {
+ Variant *self = (Variant *)p_self;
+ const StringName key(p_key);
+ const Variant *value = (const Variant *)p_value;
+
+ self->set_named(key, *value, *r_valid);
}
void GDAPI godot_variant_set_keyed(godot_variant *p_self, const godot_variant *p_key, const godot_variant *p_value, bool *r_valid) {
@@ -638,6 +694,17 @@ godot_variant GDAPI godot_variant_get_named(const godot_variant *p_self, const g
return result;
}
+godot_variant GDAPI godot_variant_get_named_with_cstring(const godot_variant *p_self, const char *p_key, bool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ const StringName *key = (const StringName *)p_key;
+ Variant ret;
+
+ ret = self->get_named(*key, *r_valid);
+ godot_variant result;
+ memnew_placement_custom(&result, Variant, Variant(ret));
+ return result;
+}
+
godot_variant GDAPI godot_variant_get_keyed(const godot_variant *p_self, const godot_variant *p_key, bool *r_valid) {
const Variant *self = (const Variant *)p_self;
const Variant *key = (const Variant *)p_key;
@@ -824,6 +891,14 @@ bool GDAPI godot_variant_is_builtin_method_const_with_cstring(godot_variant_type
return Variant::is_builtin_method_const((Variant::Type)p_type, StringName(p_method));
}
+bool GDAPI godot_variant_is_builtin_method_static(godot_variant_type p_type, const godot_string_name *p_method) {
+ return Variant::is_builtin_method_static((Variant::Type)p_type, *((const StringName *)p_method));
+}
+
+bool GDAPI godot_variant_is_builtin_method_static_with_cstring(godot_variant_type p_type, const char *p_method) {
+ return Variant::is_builtin_method_static((Variant::Type)p_type, StringName(p_method));
+}
+
bool GDAPI godot_variant_is_builtin_method_vararg(godot_variant_type p_type, const godot_string_name *p_method) {
return Variant::is_builtin_method_vararg((Variant::Type)p_type, *((const StringName *)p_method));
}
@@ -1065,6 +1140,22 @@ void GDAPI godot_variant_call_utility_function_with_cstring(const char *p_functi
}
}
+godot_ptr_utility_function GDAPI godot_variant_get_ptr_utility_function(const godot_string_name *p_function) {
+ return (godot_ptr_utility_function)Variant::get_ptr_utility_function(*((const StringName *)p_function));
+}
+
+godot_ptr_utility_function GDAPI godot_variant_get_ptr_utility_function_with_cstring(const char *p_function) {
+ return (godot_ptr_utility_function)Variant::get_ptr_utility_function(StringName(p_function));
+}
+
+godot_validated_utility_function GDAPI godot_variant_get_validated_utility_function(const godot_string_name *p_function) {
+ return (godot_validated_utility_function)Variant::get_validated_utility_function(*((const StringName *)p_function));
+}
+
+godot_validated_utility_function GDAPI godot_variant_get_validated_utility_function_with_cstring(const char *p_function) {
+ return (godot_validated_utility_function)Variant::get_validated_utility_function(StringName(p_function));
+}
+
godot_variant_utility_function_type GDAPI godot_variant_get_utility_function_type(const godot_string_name *p_function) {
return (godot_variant_utility_function_type)Variant::get_utility_function_type(*((const StringName *)p_function));
}
diff --git a/modules/gdnative/gdnative/vector2.cpp b/modules/gdnative/gdnative/vector2.cpp
index e2f957e4f2..6a01a7ad59 100644
--- a/modules/gdnative/gdnative/vector2.cpp
+++ b/modules/gdnative/gdnative/vector2.cpp
@@ -43,10 +43,38 @@ void GDAPI godot_vector2_new(godot_vector2 *p_self) {
memnew_placement(p_self, Vector2);
}
+void GDAPI godot_vector2_new_copy(godot_vector2 *r_dest, const godot_vector2 *p_src) {
+ memnew_placement(r_dest, Vector2(*(Vector2 *)p_src));
+}
+
void GDAPI godot_vector2i_new(godot_vector2i *p_self) {
memnew_placement(p_self, Vector2i);
}
+void GDAPI godot_vector2i_new_copy(godot_vector2i *r_dest, const godot_vector2i *p_src) {
+ memnew_placement(r_dest, Vector2i(*(Vector2i *)p_src));
+}
+
+godot_real_t GDAPI *godot_vector2_operator_index(godot_vector2 *p_self, godot_int p_index) {
+ Vector2 *self = (Vector2 *)p_self;
+ return (godot_real_t *)&self->operator[](p_index);
+}
+
+const godot_real_t GDAPI *godot_vector2_operator_index_const(const godot_vector2 *p_self, godot_int p_index) {
+ const Vector2 *self = (const Vector2 *)p_self;
+ return (const godot_real_t *)&self->operator[](p_index);
+}
+
+int32_t GDAPI *godot_vector2i_operator_index(godot_vector2i *p_self, godot_int p_index) {
+ Vector2i *self = (Vector2i *)p_self;
+ return (int32_t *)&self->operator[](p_index);
+}
+
+const int32_t GDAPI *godot_vector2i_operator_index_const(const godot_vector2i *p_self, godot_int p_index) {
+ const Vector2i *self = (const Vector2i *)p_self;
+ return (const int32_t *)&self->operator[](p_index);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/vector3.cpp b/modules/gdnative/gdnative/vector3.cpp
index ee365edaec..fb426c8ac4 100644
--- a/modules/gdnative/gdnative/vector3.cpp
+++ b/modules/gdnative/gdnative/vector3.cpp
@@ -43,10 +43,38 @@ void GDAPI godot_vector3_new(godot_vector3 *p_self) {
memnew_placement(p_self, Vector3);
}
+void GDAPI godot_vector3_new_copy(godot_vector3 *r_dest, const godot_vector3 *p_src) {
+ memnew_placement(r_dest, Vector3(*(Vector3 *)p_src));
+}
+
void GDAPI godot_vector3i_new(godot_vector3i *p_self) {
memnew_placement(p_self, Vector3i);
}
+void GDAPI godot_vector3i_new_copy(godot_vector3i *r_dest, const godot_vector3i *p_src) {
+ memnew_placement(r_dest, Vector3i(*(Vector3i *)p_src));
+}
+
+godot_real_t GDAPI *godot_vector3_operator_index(godot_vector3 *p_self, godot_int p_index) {
+ Vector3 *self = (Vector3 *)p_self;
+ return (godot_real_t *)&self->operator[](p_index);
+}
+
+const godot_real_t GDAPI *godot_vector3_operator_index_const(const godot_vector3 *p_self, godot_int p_index) {
+ const Vector3 *self = (const Vector3 *)p_self;
+ return (const godot_real_t *)&self->operator[](p_index);
+}
+
+int32_t GDAPI *godot_vector3i_operator_index(godot_vector3i *p_self, godot_int p_index) {
+ Vector3i *self = (Vector3i *)p_self;
+ return (int32_t *)&self->operator[](p_index);
+}
+
+const int32_t GDAPI *godot_vector3i_operator_index_const(const godot_vector3i *p_self, godot_int p_index) {
+ const Vector3i *self = (const Vector3i *)p_self;
+ return (const int32_t *)&self->operator[](p_index);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 909e91393e..59b078f2b6 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -153,6 +153,72 @@
]
},
{
+ "name": "godot_print_error",
+ "return_type": "void",
+ "arguments": [
+ [
+ "const char *",
+ "p_description"
+ ],
+ [
+ "const char *",
+ "p_function"
+ ],
+ [
+ "const char *",
+ "p_file"
+ ],
+ [
+ "int",
+ "p_line"
+ ]
+ ]
+ },
+ {
+ "name": "godot_print_warning",
+ "return_type": "void",
+ "arguments": [
+ [
+ "const char *",
+ "p_description"
+ ],
+ [
+ "const char *",
+ "p_function"
+ ],
+ [
+ "const char *",
+ "p_file"
+ ],
+ [
+ "int",
+ "p_line"
+ ]
+ ]
+ },
+ {
+ "name": "godot_print_script_error",
+ "return_type": "void",
+ "arguments": [
+ [
+ "const char *",
+ "p_description"
+ ],
+ [
+ "const char *",
+ "p_function"
+ ],
+ [
+ "const char *",
+ "p_file"
+ ],
+ [
+ "int",
+ "p_line"
+ ]
+ ]
+ },
+ {
"name": "godot_get_class_tag",
"return_type": "void *",
"arguments": [
@@ -1077,6 +1143,36 @@
]
},
{
+ "name": "godot_variant_call_with_cstring",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_variant *",
+ "p_self"
+ ],
+ [
+ "const char *",
+ "p_method"
+ ],
+ [
+ "const godot_variant **",
+ "p_args"
+ ],
+ [
+ "const godot_int",
+ "p_argument_count"
+ ],
+ [
+ "godot_variant *",
+ "r_return"
+ ],
+ [
+ "godot_variant_call_error *",
+ "r_error"
+ ]
+ ]
+ },
+ {
"name": "godot_variant_evaluate",
"return_type": "void",
"arguments": [
@@ -1134,7 +1230,29 @@
],
[
"const godot_string_name *",
- "p_name"
+ "p_key"
+ ],
+ [
+ "const godot_variant *",
+ "p_value"
+ ],
+ [
+ "bool *",
+ "r_valid"
+ ]
+ ]
+ },
+ {
+ "name": "godot_variant_set_named_with_cstring",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_variant *",
+ "p_self"
+ ],
+ [
+ "const char *",
+ "p_key"
],
[
"const godot_variant *",
@@ -1231,6 +1349,24 @@
]
},
{
+ "name": "godot_variant_get_named_with_cstring",
+ "return_type": "godot_variant",
+ "arguments": [
+ [
+ "const godot_variant *",
+ "p_self"
+ ],
+ [
+ "const char *",
+ "p_key"
+ ],
+ [
+ "bool *",
+ "r_valid"
+ ]
+ ]
+ },
+ {
"name": "godot_variant_get_keyed",
"return_type": "godot_variant",
"arguments": [
@@ -1749,6 +1885,34 @@
]
},
{
+ "name": "godot_variant_is_builtin_method_static",
+ "return_type": "bool",
+ "arguments": [
+ [
+ "godot_variant_type",
+ "p_type"
+ ],
+ [
+ "const godot_string_name *",
+ "p_method"
+ ]
+ ]
+ },
+ {
+ "name": "godot_variant_is_builtin_method_static_with_cstring",
+ "return_type": "bool",
+ "arguments": [
+ [
+ "godot_variant_type",
+ "p_type"
+ ],
+ [
+ "const char *",
+ "p_method"
+ ]
+ ]
+ },
+ {
"name": "godot_variant_is_builtin_method_vararg",
"return_type": "bool",
"arguments": [
@@ -2371,6 +2535,46 @@
]
},
{
+ "name": "godot_variant_get_ptr_utility_function",
+ "return_type": "godot_ptr_utility_function",
+ "arguments": [
+ [
+ "const godot_string_name *",
+ "p_function"
+ ]
+ ]
+ },
+ {
+ "name": "godot_variant_get_ptr_utility_function_with_cstring",
+ "return_type": "godot_ptr_utility_function",
+ "arguments": [
+ [
+ "const char *",
+ "p_function"
+ ]
+ ]
+ },
+ {
+ "name": "godot_variant_get_validated_utility_function",
+ "return_type": "godot_validated_utility_function",
+ "arguments": [
+ [
+ "const godot_string_name *",
+ "p_function"
+ ]
+ ]
+ },
+ {
+ "name": "godot_variant_get_validated_utility_function_with_cstring",
+ "return_type": "godot_validated_utility_function",
+ "arguments": [
+ [
+ "const char *",
+ "p_function"
+ ]
+ ]
+ },
+ {
"name": "godot_variant_get_utility_function_type",
"return_type": "godot_variant_utility_function_type",
"arguments": [
@@ -2646,6 +2850,20 @@
]
},
{
+ "name": "godot_aabb_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_aabb *",
+ "r_dest"
+ ],
+ [
+ "const godot_aabb *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_array_new",
"return_type": "void",
"arguments": [
@@ -2656,6 +2874,20 @@
]
},
{
+ "name": "godot_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_array_destroy",
"return_type": "void",
"arguments": [
@@ -2666,6 +2898,34 @@
]
},
{
+ "name": "godot_array_operator_index",
+ "return_type": "godot_variant *",
+ "arguments": [
+ [
+ "godot_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_array_operator_index_const",
+ "return_type": "const godot_variant *",
+ "arguments": [
+ [
+ "const godot_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_basis_new",
"return_type": "void",
"arguments": [
@@ -2676,6 +2936,48 @@
]
},
{
+ "name": "godot_basis_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_basis *",
+ "r_dest"
+ ],
+ [
+ "const godot_basis *",
+ "p_src"
+ ]
+ ]
+ },
+ {
+ "name": "godot_basis_operator_index",
+ "return_type": "godot_vector3 *",
+ "arguments": [
+ [
+ "godot_basis *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_basis_operator_index_const",
+ "return_type": "const godot_vector3 *",
+ "arguments": [
+ [
+ "const godot_basis *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_callable_new",
"return_type": "void",
"arguments": [
@@ -2686,6 +2988,20 @@
]
},
{
+ "name": "godot_callable_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_callable *",
+ "r_dest"
+ ],
+ [
+ "const godot_callable *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_callable_destroy",
"return_type": "void",
"arguments": [
@@ -2706,6 +3022,48 @@
]
},
{
+ "name": "godot_color_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_color *",
+ "r_dest"
+ ],
+ [
+ "const godot_color *",
+ "p_src"
+ ]
+ ]
+ },
+ {
+ "name": "godot_color_operator_index",
+ "return_type": "float *",
+ "arguments": [
+ [
+ "godot_color *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_color_operator_index_const",
+ "return_type": "const float *",
+ "arguments": [
+ [
+ "const godot_color *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_dictionary_new",
"return_type": "void",
"arguments": [
@@ -2716,6 +3074,20 @@
]
},
{
+ "name": "godot_dictionary_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_dictionary *",
+ "r_dest"
+ ],
+ [
+ "const godot_dictionary *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_dictionary_destroy",
"return_type": "void",
"arguments": [
@@ -2726,6 +3098,34 @@
]
},
{
+ "name": "godot_dictionary_operator_index",
+ "return_type": "godot_variant *",
+ "arguments": [
+ [
+ "godot_dictionary *",
+ "p_self"
+ ],
+ [
+ "const godot_variant *",
+ "p_key"
+ ]
+ ]
+ },
+ {
+ "name": "godot_dictionary_operator_index_const",
+ "return_type": "const godot_variant *",
+ "arguments": [
+ [
+ "const godot_dictionary *",
+ "p_self"
+ ],
+ [
+ "const godot_variant *",
+ "p_key"
+ ]
+ ]
+ },
+ {
"name": "godot_node_path_new",
"return_type": "void",
"arguments": [
@@ -2736,6 +3136,20 @@
]
},
{
+ "name": "godot_node_path_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_node_path *",
+ "r_dest"
+ ],
+ [
+ "const godot_node_path *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_node_path_destroy",
"return_type": "void",
"arguments": [
@@ -2756,6 +3170,20 @@
]
},
{
+ "name": "godot_packed_byte_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_byte_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_byte_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_byte_array_destroy",
"return_type": "void",
"arguments": [
@@ -2766,6 +3194,34 @@
]
},
{
+ "name": "godot_packed_byte_array_operator_index",
+ "return_type": "uint8_t *",
+ "arguments": [
+ [
+ "godot_packed_byte_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_byte_array_operator_index_const",
+ "return_type": "const uint8_t *",
+ "arguments": [
+ [
+ "const godot_packed_byte_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_int32_array_new",
"return_type": "void",
"arguments": [
@@ -2776,6 +3232,20 @@
]
},
{
+ "name": "godot_packed_int32_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_int32_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_int32_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_int32_array_destroy",
"return_type": "void",
"arguments": [
@@ -2786,6 +3256,34 @@
]
},
{
+ "name": "godot_packed_int32_array_operator_index",
+ "return_type": "int32_t *",
+ "arguments": [
+ [
+ "godot_packed_int32_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_int32_array_operator_index_const",
+ "return_type": "const int32_t *",
+ "arguments": [
+ [
+ "const godot_packed_int32_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_int64_array_new",
"return_type": "void",
"arguments": [
@@ -2796,6 +3294,20 @@
]
},
{
+ "name": "godot_packed_int64_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_int64_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_int64_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_int64_array_destroy",
"return_type": "void",
"arguments": [
@@ -2806,6 +3318,34 @@
]
},
{
+ "name": "godot_packed_int64_array_operator_index",
+ "return_type": "int64_t *",
+ "arguments": [
+ [
+ "godot_packed_int64_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_operator_index_const",
+ "return_type": "const int64_t *",
+ "arguments": [
+ [
+ "const godot_packed_int64_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_float32_array_new",
"return_type": "void",
"arguments": [
@@ -2816,6 +3356,20 @@
]
},
{
+ "name": "godot_packed_float32_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_float32_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_float32_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_float32_array_destroy",
"return_type": "void",
"arguments": [
@@ -2826,6 +3380,34 @@
]
},
{
+ "name": "godot_packed_float32_array_operator_index",
+ "return_type": "float *",
+ "arguments": [
+ [
+ "godot_packed_float32_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_float32_array_operator_index_const",
+ "return_type": "const float *",
+ "arguments": [
+ [
+ "const godot_packed_float32_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_float64_array_new",
"return_type": "void",
"arguments": [
@@ -2836,6 +3418,20 @@
]
},
{
+ "name": "godot_packed_float64_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_float64_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_float64_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_float64_array_destroy",
"return_type": "void",
"arguments": [
@@ -2846,6 +3442,34 @@
]
},
{
+ "name": "godot_packed_float64_array_operator_index",
+ "return_type": "double *",
+ "arguments": [
+ [
+ "godot_packed_float64_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_operator_index_const",
+ "return_type": "const double *",
+ "arguments": [
+ [
+ "const godot_packed_float64_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_string_array_new",
"return_type": "void",
"arguments": [
@@ -2856,6 +3480,20 @@
]
},
{
+ "name": "godot_packed_string_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_string_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_string_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_string_array_destroy",
"return_type": "void",
"arguments": [
@@ -2866,6 +3504,34 @@
]
},
{
+ "name": "godot_packed_string_array_operator_index",
+ "return_type": "godot_string *",
+ "arguments": [
+ [
+ "godot_packed_string_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_string_array_operator_index_const",
+ "return_type": "const godot_string *",
+ "arguments": [
+ [
+ "const godot_packed_string_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_vector2_array_new",
"return_type": "void",
"arguments": [
@@ -2876,6 +3542,20 @@
]
},
{
+ "name": "godot_packed_vector2_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_vector2_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_vector2_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_vector2_array_destroy",
"return_type": "void",
"arguments": [
@@ -2886,6 +3566,34 @@
]
},
{
+ "name": "godot_packed_vector2_array_operator_index",
+ "return_type": "godot_vector2 *",
+ "arguments": [
+ [
+ "godot_packed_vector2_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_vector2_array_operator_index_const",
+ "return_type": "const godot_vector2 *",
+ "arguments": [
+ [
+ "const godot_packed_vector2_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_vector2i_array_new",
"return_type": "void",
"arguments": [
@@ -2896,6 +3604,20 @@
]
},
{
+ "name": "godot_packed_vector2i_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_vector2i_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_vector2i_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_vector2i_array_destroy",
"return_type": "void",
"arguments": [
@@ -2906,6 +3628,34 @@
]
},
{
+ "name": "godot_packed_vector2i_array_operator_index",
+ "return_type": "godot_vector2i *",
+ "arguments": [
+ [
+ "godot_packed_vector2i_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_vector2i_array_operator_index_const",
+ "return_type": "const godot_vector2i *",
+ "arguments": [
+ [
+ "const godot_packed_vector2i_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_vector3_array_new",
"return_type": "void",
"arguments": [
@@ -2916,6 +3666,20 @@
]
},
{
+ "name": "godot_packed_vector3_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_vector3_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_vector3_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_vector3_array_destroy",
"return_type": "void",
"arguments": [
@@ -2926,6 +3690,96 @@
]
},
{
+ "name": "godot_packed_vector3_array_operator_index",
+ "return_type": "godot_vector3 *",
+ "arguments": [
+ [
+ "godot_packed_vector3_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_vector3_array_operator_index_const",
+ "return_type": "const godot_vector3 *",
+ "arguments": [
+ [
+ "const godot_packed_vector3_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_vector3i_array_new",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_vector3i_array *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_vector3i_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_vector3i_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_vector3i_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_vector3i_array_destroy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_vector3i_array *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_vector3i_array_operator_index",
+ "return_type": "godot_vector3i *",
+ "arguments": [
+ [
+ "godot_packed_vector3i_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_vector3i_array_operator_index_const",
+ "return_type": "const godot_vector3i *",
+ "arguments": [
+ [
+ "const godot_packed_vector3i_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_color_array_new",
"return_type": "void",
"arguments": [
@@ -2936,6 +3790,20 @@
]
},
{
+ "name": "godot_packed_color_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_color_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_color_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_color_array_destroy",
"return_type": "void",
"arguments": [
@@ -2946,6 +3814,34 @@
]
},
{
+ "name": "godot_packed_color_array_operator_index",
+ "return_type": "godot_color *",
+ "arguments": [
+ [
+ "godot_packed_color_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_packed_color_array_operator_index_const",
+ "return_type": "const godot_color *",
+ "arguments": [
+ [
+ "const godot_packed_color_array *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_plane_new",
"return_type": "void",
"arguments": [
@@ -2956,6 +3852,20 @@
]
},
{
+ "name": "godot_plane_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_plane *",
+ "r_dest"
+ ],
+ [
+ "const godot_plane *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_quat_new",
"return_type": "void",
"arguments": [
@@ -2966,6 +3876,48 @@
]
},
{
+ "name": "godot_quat_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_quat *",
+ "r_dest"
+ ],
+ [
+ "const godot_quat *",
+ "p_src"
+ ]
+ ]
+ },
+ {
+ "name": "godot_quat_operator_index",
+ "return_type": "godot_real_t *",
+ "arguments": [
+ [
+ "godot_quat *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_quat_operator_index_const",
+ "return_type": "const godot_real_t *",
+ "arguments": [
+ [
+ "const godot_quat *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_rect2_new",
"return_type": "void",
"arguments": [
@@ -2976,6 +3928,20 @@
]
},
{
+ "name": "godot_rect2_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_rect2 *",
+ "r_dest"
+ ],
+ [
+ "const godot_rect2 *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_rect2i_new",
"return_type": "void",
"arguments": [
@@ -2986,6 +3952,20 @@
]
},
{
+ "name": "godot_rect2i_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_rect2i *",
+ "r_dest"
+ ],
+ [
+ "const godot_rect2i *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_rid_new",
"return_type": "void",
"arguments": [
@@ -2996,6 +3976,20 @@
]
},
{
+ "name": "godot_rid_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_rid *",
+ "r_dest"
+ ],
+ [
+ "const godot_rid *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_signal_new",
"return_type": "void",
"arguments": [
@@ -3006,6 +4000,20 @@
]
},
{
+ "name": "godot_signal_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_signal *",
+ "r_dest"
+ ],
+ [
+ "const godot_signal *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_signal_destroy",
"return_type": "void",
"arguments": [
@@ -3210,6 +4218,84 @@
]
},
{
+ "name": "godot_string_to_latin1_chars",
+ "return_type": "const char *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_to_utf8_chars",
+ "return_type": "const char *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_to_utf16_chars",
+ "return_type": "const char16_t *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_to_utf32_chars",
+ "return_type": "const char32_t *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_to_wide_chars",
+ "return_type": "const wchar_t *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_operator_index",
+ "return_type": "char32_t *",
+ "arguments": [
+ [
+ "godot_string *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_operator_index_const",
+ "return_type": "const char32_t *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_string_name_new",
"return_type": "void",
"arguments": [
@@ -3268,6 +4354,20 @@
]
},
{
+ "name": "godot_transform_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_transform *",
+ "r_dest"
+ ],
+ [
+ "const godot_transform *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_transform2d_new",
"return_type": "void",
"arguments": [
@@ -3278,6 +4378,48 @@
]
},
{
+ "name": "godot_transform2d_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_transform2d *",
+ "r_dest"
+ ],
+ [
+ "const godot_transform2d *",
+ "p_src"
+ ]
+ ]
+ },
+ {
+ "name": "godot_transform2d_operator_index",
+ "return_type": "godot_vector2 *",
+ "arguments": [
+ [
+ "godot_transform2d *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_transform2d_operator_index_const",
+ "return_type": "const godot_vector2 *",
+ "arguments": [
+ [
+ "const godot_transform2d *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_vector2_new",
"return_type": "void",
"arguments": [
@@ -3288,6 +4430,48 @@
]
},
{
+ "name": "godot_vector2_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_vector2 *",
+ "r_dest"
+ ],
+ [
+ "const godot_vector2 *",
+ "p_src"
+ ]
+ ]
+ },
+ {
+ "name": "godot_vector2_operator_index",
+ "return_type": "godot_real_t *",
+ "arguments": [
+ [
+ "godot_vector2 *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_vector2_operator_index_const",
+ "return_type": "const godot_real_t *",
+ "arguments": [
+ [
+ "const godot_vector2 *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_vector2i_new",
"return_type": "void",
"arguments": [
@@ -3298,6 +4482,48 @@
]
},
{
+ "name": "godot_vector2i_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_vector2i *",
+ "r_dest"
+ ],
+ [
+ "const godot_vector2i *",
+ "p_src"
+ ]
+ ]
+ },
+ {
+ "name": "godot_vector2i_operator_index",
+ "return_type": "int32_t *",
+ "arguments": [
+ [
+ "godot_vector2i *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_vector2i_operator_index_const",
+ "return_type": "const int32_t *",
+ "arguments": [
+ [
+ "const godot_vector2i *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_vector3_new",
"return_type": "void",
"arguments": [
@@ -3308,6 +4534,48 @@
]
},
{
+ "name": "godot_vector3_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_vector3 *",
+ "r_dest"
+ ],
+ [
+ "const godot_vector3 *",
+ "p_src"
+ ]
+ ]
+ },
+ {
+ "name": "godot_vector3_operator_index",
+ "return_type": "godot_real_t *",
+ "arguments": [
+ [
+ "godot_vector3 *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_vector3_operator_index_const",
+ "return_type": "const godot_real_t *",
+ "arguments": [
+ [
+ "const godot_vector3 *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_vector3i_new",
"return_type": "void",
"arguments": [
@@ -3316,6 +4584,48 @@
"r_dest"
]
]
+ },
+ {
+ "name": "godot_vector3i_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_vector3i *",
+ "r_dest"
+ ],
+ [
+ "const godot_vector3i *",
+ "p_src"
+ ]
+ ]
+ },
+ {
+ "name": "godot_vector3i_operator_index",
+ "return_type": "int32_t *",
+ "arguments": [
+ [
+ "godot_vector3i *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_vector3i_operator_index_const",
+ "return_type": "const int32_t *",
+ "arguments": [
+ [
+ "const godot_vector3i *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
}
]
},
diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp
index d3cca5b1be..dfb26c13e3 100644
--- a/modules/gdnative/gdnative_library_editor_plugin.cpp
+++ b/modules/gdnative/gdnative_library_editor_plugin.cpp
@@ -257,7 +257,7 @@ void GDNativeLibraryEditor::_translate_to_config_file() {
}
}
- library->_change_notify();
+ library->notify_property_list_changed();
}
}
diff --git a/modules/gdnative/gdnative_library_editor_plugin.h b/modules/gdnative/gdnative_library_editor_plugin.h
index 184db3d817..61afb1aaaa 100644
--- a/modules/gdnative/gdnative_library_editor_plugin.h
+++ b/modules/gdnative/gdnative_library_editor_plugin.h
@@ -95,9 +95,9 @@ public:
class GDNativeLibraryEditorPlugin : public EditorPlugin {
GDCLASS(GDNativeLibraryEditorPlugin, EditorPlugin);
- GDNativeLibraryEditor *library_editor;
- EditorNode *editor;
- Button *button;
+ GDNativeLibraryEditor *library_editor = nullptr;
+ EditorNode *editor = nullptr;
+ Button *button = nullptr;
public:
virtual String get_name() const override { return "GDNativeLibrary"; }
diff --git a/modules/gdnative/include/gdnative/aabb.h b/modules/gdnative/include/gdnative/aabb.h
index be0235221f..860675065d 100644
--- a/modules/gdnative/include/gdnative/aabb.h
+++ b/modules/gdnative/include/gdnative/aabb.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_aabb_new(godot_aabb *p_self);
+void GDAPI godot_aabb_new_copy(godot_aabb *r_dest, const godot_aabb *p_src);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/array.h b/modules/gdnative/include/gdnative/array.h
index d734d49232..bf4b852449 100644
--- a/modules/gdnative/include/gdnative/array.h
+++ b/modules/gdnative/include/gdnative/array.h
@@ -47,9 +47,13 @@ typedef struct {
#endif
#include <gdnative/gdnative.h>
+#include <gdnative/variant_struct.h>
void GDAPI godot_array_new(godot_array *p_self);
+void GDAPI godot_array_new_copy(godot_array *r_dest, const godot_array *p_src);
void GDAPI godot_array_destroy(godot_array *p_self);
+godot_variant GDAPI *godot_array_operator_index(godot_array *p_self, godot_int p_index);
+const godot_variant GDAPI *godot_array_operator_index_const(const godot_array *p_self, godot_int p_index);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/basis.h b/modules/gdnative/include/gdnative/basis.h
index d40ca3d6a5..5477dbf811 100644
--- a/modules/gdnative/include/gdnative/basis.h
+++ b/modules/gdnative/include/gdnative/basis.h
@@ -49,6 +49,9 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_basis_new(godot_basis *p_self);
+void GDAPI godot_basis_new_copy(godot_basis *r_dest, const godot_basis *p_src);
+godot_vector3 GDAPI *godot_basis_operator_index(godot_basis *p_self, godot_int p_index);
+const godot_vector3 GDAPI *godot_basis_operator_index_const(const godot_basis *p_self, godot_int p_index);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/callable.h b/modules/gdnative/include/gdnative/callable.h
index 6f359ada5e..b84b0c1f1f 100644
--- a/modules/gdnative/include/gdnative/callable.h
+++ b/modules/gdnative/include/gdnative/callable.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_callable_new(godot_callable *p_self);
+void GDAPI godot_callable_new_copy(godot_callable *r_dest, const godot_callable *p_src);
void GDAPI godot_callable_destroy(godot_callable *p_self);
#ifdef __cplusplus
diff --git a/modules/gdnative/include/gdnative/color.h b/modules/gdnative/include/gdnative/color.h
index 12c4a829bd..3334013147 100644
--- a/modules/gdnative/include/gdnative/color.h
+++ b/modules/gdnative/include/gdnative/color.h
@@ -50,6 +50,9 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_color_new(godot_color *p_self);
+void GDAPI godot_color_new_copy(godot_color *r_dest, const godot_color *p_src);
+float GDAPI *godot_color_operator_index(godot_color *p_self, godot_int p_index);
+const float GDAPI *godot_color_operator_index_const(const godot_color *p_self, godot_int p_index);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/dictionary.h b/modules/gdnative/include/gdnative/dictionary.h
index 231d2ef578..b9525fb5e6 100644
--- a/modules/gdnative/include/gdnative/dictionary.h
+++ b/modules/gdnative/include/gdnative/dictionary.h
@@ -47,9 +47,13 @@ typedef struct {
#endif
#include <gdnative/gdnative.h>
+#include <gdnative/variant_struct.h>
void GDAPI godot_dictionary_new(godot_dictionary *p_self);
+void GDAPI godot_dictionary_new_copy(godot_dictionary *r_dest, const godot_dictionary *p_src);
void GDAPI godot_dictionary_destroy(godot_dictionary *p_self);
+godot_variant GDAPI *godot_dictionary_operator_index(godot_dictionary *p_self, const godot_variant *p_key);
+const godot_variant GDAPI *godot_dictionary_operator_index_const(const godot_dictionary *p_self, const godot_variant *p_key);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h
index 630966b035..9af9226a79 100644
--- a/modules/gdnative/include/gdnative/gdnative.h
+++ b/modules/gdnative/include/gdnative/gdnative.h
@@ -53,7 +53,9 @@ extern "C" {
#endif
// This is for libraries *using* the header, NOT GODOT EXPOSING STUFF!!
-#ifdef _WIN32
+#ifdef __GNUC__
+#define GDN_EXPORT __attribute__((visibility("default")))
+#elif defined(_WIN32)
#define GDN_EXPORT __declspec(dllexport)
#else
#define GDN_EXPORT
@@ -62,8 +64,6 @@ extern "C" {
#include <stdbool.h>
#include <stdint.h>
-#define GODOT_API_VERSION 1
-
////// Error
typedef enum {
@@ -266,6 +266,11 @@ void GDAPI *godot_alloc(int p_bytes);
void GDAPI *godot_realloc(void *p_ptr, int p_bytes);
void GDAPI godot_free(void *p_ptr);
+// Helper print functions.
+void GDAPI godot_print_error(const char *p_description, const char *p_function, const char *p_file, int p_line);
+void GDAPI godot_print_warning(const char *p_description, const char *p_function, const char *p_file, int p_line);
+void GDAPI godot_print_script_error(const char *p_description, const char *p_function, const char *p_file, int p_line);
+
//tags used for safe dynamic casting
void GDAPI *godot_get_class_tag(const godot_string_name *p_class);
godot_object GDAPI *godot_object_cast_to(const godot_object *p_object, void *p_class_tag);
diff --git a/modules/gdnative/include/gdnative/node_path.h b/modules/gdnative/include/gdnative/node_path.h
index 3c31b9a98f..a4607c0152 100644
--- a/modules/gdnative/include/gdnative/node_path.h
+++ b/modules/gdnative/include/gdnative/node_path.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_node_path_new(godot_node_path *p_self);
+void GDAPI godot_node_path_new_copy(godot_node_path *r_dest, const godot_node_path *p_src);
void GDAPI godot_node_path_destroy(godot_node_path *p_self);
#ifdef __cplusplus
diff --git a/modules/gdnative/include/gdnative/packed_arrays.h b/modules/gdnative/include/gdnative/packed_arrays.h
index 1a26d8ed6d..f9e4ba3a8d 100644
--- a/modules/gdnative/include/gdnative/packed_arrays.h
+++ b/modules/gdnative/include/gdnative/packed_arrays.h
@@ -163,55 +163,93 @@ typedef struct {
// Byte.
void GDAPI godot_packed_byte_array_new(godot_packed_byte_array *p_self);
+void GDAPI godot_packed_byte_array_new_copy(godot_packed_byte_array *r_dest, const godot_packed_byte_array *p_src);
void GDAPI godot_packed_byte_array_destroy(godot_packed_byte_array *p_self);
+uint8_t GDAPI *godot_packed_byte_array_operator_index(godot_packed_byte_array *p_self, godot_int p_index);
+const uint8_t GDAPI *godot_packed_byte_array_operator_index_const(const godot_packed_byte_array *p_self, godot_int p_index);
// Int32.
void GDAPI godot_packed_int32_array_new(godot_packed_int32_array *p_self);
+void GDAPI godot_packed_int32_array_new_copy(godot_packed_int32_array *r_dest, const godot_packed_int32_array *p_src);
void GDAPI godot_packed_int32_array_destroy(godot_packed_int32_array *p_self);
+int32_t GDAPI *godot_packed_int32_array_operator_index(godot_packed_int32_array *p_self, godot_int p_index);
+const int32_t GDAPI *godot_packed_int32_array_operator_index_const(const godot_packed_int32_array *p_self, godot_int p_index);
// Int64.
void GDAPI godot_packed_int64_array_new(godot_packed_int64_array *p_self);
+void GDAPI godot_packed_int64_array_new_copy(godot_packed_int64_array *r_dest, const godot_packed_int64_array *p_src);
void GDAPI godot_packed_int64_array_destroy(godot_packed_int64_array *p_self);
+int64_t GDAPI *godot_packed_int64_array_operator_index(godot_packed_int64_array *p_self, godot_int p_index);
+const int64_t GDAPI *godot_packed_int64_array_operator_index_const(const godot_packed_int64_array *p_self, godot_int p_index);
// Float32.
void GDAPI godot_packed_float32_array_new(godot_packed_float32_array *p_self);
+void GDAPI godot_packed_float32_array_new_copy(godot_packed_float32_array *r_dest, const godot_packed_float32_array *p_src);
void GDAPI godot_packed_float32_array_destroy(godot_packed_float32_array *p_self);
+float GDAPI *godot_packed_float32_array_operator_index(godot_packed_float32_array *p_self, godot_int p_index);
+const float GDAPI *godot_packed_float32_array_operator_index_const(const godot_packed_float32_array *p_self, godot_int p_index);
// Float64.
void GDAPI godot_packed_float64_array_new(godot_packed_float64_array *p_self);
+void GDAPI godot_packed_float64_array_new_copy(godot_packed_float64_array *r_dest, const godot_packed_float64_array *p_src);
void GDAPI godot_packed_float64_array_destroy(godot_packed_float64_array *p_self);
+double GDAPI *godot_packed_float64_array_operator_index(godot_packed_float64_array *p_self, godot_int p_index);
+const double GDAPI *godot_packed_float64_array_operator_index_const(const godot_packed_float64_array *p_self, godot_int p_index);
// String.
void GDAPI godot_packed_string_array_new(godot_packed_string_array *p_self);
+void GDAPI godot_packed_string_array_new_copy(godot_packed_string_array *r_dest, const godot_packed_string_array *p_src);
void GDAPI godot_packed_string_array_destroy(godot_packed_string_array *p_self);
+godot_string GDAPI *godot_packed_string_array_operator_index(godot_packed_string_array *p_self, godot_int p_index);
+const godot_string GDAPI *godot_packed_string_array_operator_index_const(const godot_packed_string_array *p_self, godot_int p_index);
// Vector2.
void GDAPI godot_packed_vector2_array_new(godot_packed_vector2_array *p_self);
+void GDAPI godot_packed_vector2_array_new_copy(godot_packed_vector2_array *r_dest, const godot_packed_vector2_array *p_src);
void GDAPI godot_packed_vector2_array_destroy(godot_packed_vector2_array *p_self);
+godot_vector2 GDAPI *godot_packed_vector2_array_operator_index(godot_packed_vector2_array *p_self, godot_int p_index);
+const godot_vector2 GDAPI *godot_packed_vector2_array_operator_index_const(const godot_packed_vector2_array *p_self, godot_int p_index);
// Vector2i.
void GDAPI godot_packed_vector2i_array_new(godot_packed_vector2i_array *p_self);
+void GDAPI godot_packed_vector2i_array_new_copy(godot_packed_vector2i_array *r_dest, const godot_packed_vector2i_array *p_src);
void GDAPI godot_packed_vector2i_array_destroy(godot_packed_vector2i_array *p_self);
+godot_vector2i GDAPI *godot_packed_vector2i_array_operator_index(godot_packed_vector2i_array *p_self, godot_int p_index);
+const godot_vector2i GDAPI *godot_packed_vector2i_array_operator_index_const(const godot_packed_vector2i_array *p_self, godot_int p_index);
// Vector3.
void GDAPI godot_packed_vector3_array_new(godot_packed_vector3_array *p_self);
+void GDAPI godot_packed_vector3_array_new_copy(godot_packed_vector3_array *r_dest, const godot_packed_vector3_array *p_src);
void GDAPI godot_packed_vector3_array_destroy(godot_packed_vector3_array *p_self);
+godot_vector3 GDAPI *godot_packed_vector3_array_operator_index(godot_packed_vector3_array *p_self, godot_int p_index);
+const godot_vector3 GDAPI *godot_packed_vector3_array_operator_index_const(const godot_packed_vector3_array *p_self, godot_int p_index);
+
+// Vector3i.
+
+void GDAPI godot_packed_vector3i_array_new(godot_packed_vector3i_array *p_self);
+void GDAPI godot_packed_vector3i_array_new_copy(godot_packed_vector3i_array *r_dest, const godot_packed_vector3i_array *p_src);
+void GDAPI godot_packed_vector3i_array_destroy(godot_packed_vector3i_array *p_self);
+godot_vector3i GDAPI *godot_packed_vector3i_array_operator_index(godot_packed_vector3i_array *p_self, godot_int p_index);
+const godot_vector3i GDAPI *godot_packed_vector3i_array_operator_index_const(const godot_packed_vector3i_array *p_self, godot_int p_index);
// Color.
void GDAPI godot_packed_color_array_new(godot_packed_color_array *p_self);
+void GDAPI godot_packed_color_array_new_copy(godot_packed_color_array *r_dest, const godot_packed_color_array *p_src);
void GDAPI godot_packed_color_array_destroy(godot_packed_color_array *p_self);
+godot_color GDAPI *godot_packed_color_array_operator_index(godot_packed_color_array *p_self, godot_int p_index);
+const godot_color GDAPI *godot_packed_color_array_operator_index_const(const godot_packed_color_array *p_self, godot_int p_index);
#ifdef __cplusplus
}
#endif
-#endif // GODOT_POOL_ARRAYS_H
+#endif // GODOT_PACKED_ARRAYS_H
diff --git a/modules/gdnative/include/gdnative/plane.h b/modules/gdnative/include/gdnative/plane.h
index ed10955e5f..6cd0ed6307 100644
--- a/modules/gdnative/include/gdnative/plane.h
+++ b/modules/gdnative/include/gdnative/plane.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_plane_new(godot_plane *p_self);
+void GDAPI godot_plane_new_copy(godot_plane *r_dest, const godot_plane *p_src);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/quat.h b/modules/gdnative/include/gdnative/quat.h
index a87d0bdbe5..00abdb4404 100644
--- a/modules/gdnative/include/gdnative/quat.h
+++ b/modules/gdnative/include/gdnative/quat.h
@@ -49,6 +49,9 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_quat_new(godot_quat *p_self);
+void GDAPI godot_quat_new_copy(godot_quat *r_dest, const godot_quat *p_src);
+godot_real_t GDAPI *godot_quat_operator_index(godot_quat *p_self, godot_int p_index);
+const godot_real_t GDAPI *godot_quat_operator_index_const(const godot_quat *p_self, godot_int p_index);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/rect2.h b/modules/gdnative/include/gdnative/rect2.h
index 9e51254cfe..326462be43 100644
--- a/modules/gdnative/include/gdnative/rect2.h
+++ b/modules/gdnative/include/gdnative/rect2.h
@@ -58,7 +58,9 @@ typedef struct godot_rect2i {
#include <gdnative/gdnative.h>
void GDAPI godot_rect2_new(godot_rect2 *p_self);
+void GDAPI godot_rect2_new_copy(godot_rect2 *r_dest, const godot_rect2 *p_src);
void GDAPI godot_rect2i_new(godot_rect2i *p_self);
+void GDAPI godot_rect2i_new_copy(godot_rect2i *r_dest, const godot_rect2i *p_src);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/rid.h b/modules/gdnative/include/gdnative/rid.h
index 7ea8cfd174..bc832fbeb9 100644
--- a/modules/gdnative/include/gdnative/rid.h
+++ b/modules/gdnative/include/gdnative/rid.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_rid_new(godot_rid *p_self);
+void GDAPI godot_rid_new_copy(godot_rid *r_dest, const godot_rid *p_src);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/signal.h b/modules/gdnative/include/gdnative/signal.h
index ad84542677..f4dc17e089 100644
--- a/modules/gdnative/include/gdnative/signal.h
+++ b/modules/gdnative/include/gdnative/signal.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_signal_new(godot_signal *p_self);
+void GDAPI godot_signal_new_copy(godot_signal *r_dest, const godot_signal *p_src);
void GDAPI godot_signal_destroy(godot_signal *p_self);
#ifdef __cplusplus
diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h
index 10fbb2c078..79de52c80f 100644
--- a/modules/gdnative/include/gdnative/string.h
+++ b/modules/gdnative/include/gdnative/string.h
@@ -55,6 +55,7 @@ typedef struct {
#endif
#include <gdnative/gdnative.h>
+#include <gdnative/math_defs.h>
void GDAPI godot_string_new(godot_string *r_dest);
void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src);
@@ -72,6 +73,15 @@ void GDAPI godot_string_new_with_utf16_chars_and_len(godot_string *r_dest, const
void GDAPI godot_string_new_with_utf32_chars_and_len(godot_string *r_dest, const char32_t *p_contents, const int p_size);
void GDAPI godot_string_new_with_wide_chars_and_len(godot_string *r_dest, const wchar_t *p_contents, const int p_size);
+const char GDAPI *godot_string_to_latin1_chars(const godot_string *p_self);
+const char GDAPI *godot_string_to_utf8_chars(const godot_string *p_self);
+const char16_t GDAPI *godot_string_to_utf16_chars(const godot_string *p_self);
+const char32_t GDAPI *godot_string_to_utf32_chars(const godot_string *p_self);
+const wchar_t GDAPI *godot_string_to_wide_chars(const godot_string *p_self);
+
+char32_t GDAPI *godot_string_operator_index(godot_string *p_self, godot_int p_index);
+const char32_t GDAPI *godot_string_operator_index_const(const godot_string *p_self, godot_int p_index);
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/include/gdnative/transform.h b/modules/gdnative/include/gdnative/transform.h
index e67862d140..3861b5683a 100644
--- a/modules/gdnative/include/gdnative/transform.h
+++ b/modules/gdnative/include/gdnative/transform.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_transform_new(godot_transform *p_self);
+void GDAPI godot_transform_new_copy(godot_transform *r_dest, const godot_transform *p_src);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/transform2d.h b/modules/gdnative/include/gdnative/transform2d.h
index 85e3a86972..5acb172081 100644
--- a/modules/gdnative/include/gdnative/transform2d.h
+++ b/modules/gdnative/include/gdnative/transform2d.h
@@ -49,6 +49,9 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_transform2d_new(godot_transform2d *p_self);
+void GDAPI godot_transform2d_new_copy(godot_transform2d *r_dest, const godot_transform2d *p_src);
+godot_vector2 GDAPI *godot_transform2d_operator_index(godot_transform2d *p_self, godot_int p_index);
+const godot_vector2 GDAPI *godot_transform2d_operator_index_const(const godot_transform2d *p_self, godot_int p_index);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h
index 82bd030170..3e06ed9aa4 100644
--- a/modules/gdnative/include/gdnative/variant.h
+++ b/modules/gdnative/include/gdnative/variant.h
@@ -36,15 +36,7 @@ extern "C" {
#endif
#include <gdnative/math_defs.h>
-
-#define GODOT_VARIANT_SIZE (sizeof(godot_real_t) * 4 + sizeof(int64_t))
-
-#ifndef GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED
-#define GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED
-typedef struct {
- uint8_t _dont_touch_that[GODOT_VARIANT_SIZE];
-} godot_variant;
-#endif
+#include <gdnative/variant_struct.h>
typedef enum godot_variant_type {
GODOT_VARIANT_TYPE_NIL,
@@ -280,6 +272,8 @@ void GDAPI godot_variant_destroy(godot_variant *p_self);
void GDAPI godot_variant_call(godot_variant *p_self, const godot_string_name *p_method, const godot_variant **p_args, const godot_int p_argument_count, godot_variant *r_return, godot_variant_call_error *r_error);
void GDAPI godot_variant_call_with_cstring(godot_variant *p_self, const char *p_method, const godot_variant **p_args, const godot_int p_argument_count, godot_variant *r_return, godot_variant_call_error *r_error);
+void GDAPI godot_variant_call_static(godot_variant_type p_type, const godot_string_name *p_method, const godot_variant **p_args, const godot_int p_argument_count, godot_variant *r_return, godot_variant_call_error *r_error);
+void GDAPI godot_variant_call_static_with_cstring(godot_variant_type p_type, const char *p_method, const godot_variant **p_args, const godot_int p_argument_count, godot_variant *r_return, godot_variant_call_error *r_error);
void GDAPI godot_variant_evaluate(godot_variant_operator p_op, const godot_variant *p_a, const godot_variant *p_b, godot_variant *r_return, bool *r_valid);
void GDAPI godot_variant_set(godot_variant *p_self, const godot_variant *p_key, const godot_variant *p_value, bool *r_valid);
void GDAPI godot_variant_set_named(godot_variant *p_self, const godot_string_name *p_name, const godot_variant *p_value, bool *r_valid);
@@ -331,6 +325,8 @@ godot_variant_type GDAPI godot_variant_get_builtin_method_return_type(godot_vari
godot_variant_type GDAPI godot_variant_get_builtin_method_return_type_with_cstring(godot_variant_type p_type, const char *p_method);
bool GDAPI godot_variant_is_builtin_method_const(godot_variant_type p_type, const godot_string_name *p_method);
bool GDAPI godot_variant_is_builtin_method_const_with_cstring(godot_variant_type p_type, const char *p_method);
+bool GDAPI godot_variant_is_builtin_method_static(godot_variant_type p_type, const godot_string_name *p_method);
+bool GDAPI godot_variant_is_builtin_method_static_with_cstring(godot_variant_type p_type, const char *p_method);
bool GDAPI godot_variant_is_builtin_method_vararg(godot_variant_type p_type, const godot_string_name *p_method);
bool GDAPI godot_variant_is_builtin_method_vararg_with_cstring(godot_variant_type p_type, const char *p_method);
int GDAPI godot_variant_get_builtin_method_count(godot_variant_type p_type);
@@ -390,6 +386,10 @@ bool GDAPI godot_variant_has_utility_function(const godot_string_name *p_functio
bool GDAPI godot_variant_has_utility_function_with_cstring(const char *p_function);
void GDAPI godot_variant_call_utility_function(const godot_string_name *p_function, godot_variant *r_ret, const godot_variant **p_args, int p_argument_count, godot_variant_call_error *r_error);
void GDAPI godot_variant_call_utility_function_with_cstring(const char *p_function, godot_variant *r_ret, const godot_variant **p_args, int p_argument_count, godot_variant_call_error *r_error);
+godot_ptr_utility_function GDAPI godot_variant_get_ptr_utility_function(const godot_string_name *p_function);
+godot_ptr_utility_function GDAPI godot_variant_get_ptr_utility_function_with_cstring(const char *p_function);
+godot_validated_utility_function GDAPI godot_variant_get_validated_utility_function(const godot_string_name *p_function);
+godot_validated_utility_function GDAPI godot_variant_get_validated_utility_function_with_cstring(const char *p_function);
godot_variant_utility_function_type GDAPI godot_variant_get_utility_function_type(const godot_string_name *p_function);
godot_variant_utility_function_type GDAPI godot_variant_get_utility_function_type_with_cstring(const char *p_function);
int GDAPI godot_variant_get_utility_function_argument_count(const godot_string_name *p_function);
diff --git a/platform/javascript/http_request.h b/modules/gdnative/include/gdnative/variant_struct.h
index d32b2f265e..321c76c206 100644
--- a/platform/javascript/http_request.h
+++ b/modules/gdnative/include/gdnative/variant_struct.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* http_request.h */
+/* variant_struct.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,48 +28,26 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef HTTP_REQUEST_H
-#define HTTP_REQUEST_H
+#ifndef GODOT_VARIANT_STRUCT_H
+#define GODOT_VARIANT_STRUCT_H
#ifdef __cplusplus
extern "C" {
#endif
-#include "stddef.h"
+#include <gdnative/math_defs.h>
-typedef enum {
- XHR_READY_STATE_UNSENT = 0,
- XHR_READY_STATE_OPENED = 1,
- XHR_READY_STATE_HEADERS_RECEIVED = 2,
- XHR_READY_STATE_LOADING = 3,
- XHR_READY_STATE_DONE = 4,
-} godot_xhr_ready_state_t;
+#define GODOT_VARIANT_SIZE (sizeof(godot_real_t) * 4 + sizeof(int64_t))
-extern int godot_xhr_new();
-extern void godot_xhr_reset(int p_xhr_id);
-extern void godot_xhr_free(int p_xhr_id);
-
-extern int godot_xhr_open(int p_xhr_id, const char *p_method, const char *p_url, const char *p_user = nullptr, const char *p_password = nullptr);
-
-extern void godot_xhr_set_request_header(int p_xhr_id, const char *p_header, const char *p_value);
-
-extern void godot_xhr_send_null(int p_xhr_id);
-extern void godot_xhr_send_string(int p_xhr_id, const char *p_data);
-extern void godot_xhr_send_data(int p_xhr_id, const void *p_data, int p_len);
-extern void godot_xhr_abort(int p_xhr_id);
-
-/* this is an HTTPClient::ResponseCode, not ::Status */
-extern int godot_xhr_get_status(int p_xhr_id);
-extern godot_xhr_ready_state_t godot_xhr_get_ready_state(int p_xhr_id);
-
-extern int godot_xhr_get_response_headers_length(int p_xhr_id);
-extern void godot_xhr_get_response_headers(int p_xhr_id, char *r_dst, int p_len);
-
-extern int godot_xhr_get_response_length(int p_xhr_id);
-extern void godot_xhr_get_response(int p_xhr_id, void *r_dst, int p_len);
+#ifndef GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_VARIANT_SIZE];
+} godot_variant;
+#endif
#ifdef __cplusplus
}
#endif
-#endif /* HTTP_REQUEST_H */
+#endif
diff --git a/modules/gdnative/include/gdnative/vector2.h b/modules/gdnative/include/gdnative/vector2.h
index a21ab304d0..00faffbad7 100644
--- a/modules/gdnative/include/gdnative/vector2.h
+++ b/modules/gdnative/include/gdnative/vector2.h
@@ -58,7 +58,13 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_vector2_new(godot_vector2 *p_self);
+void GDAPI godot_vector2_new_copy(godot_vector2 *r_dest, const godot_vector2 *p_src);
void GDAPI godot_vector2i_new(godot_vector2i *p_self);
+void GDAPI godot_vector2i_new_copy(godot_vector2i *r_dest, const godot_vector2i *p_src);
+godot_real_t GDAPI *godot_vector2_operator_index(godot_vector2 *p_self, godot_int p_index);
+const godot_real_t GDAPI *godot_vector2_operator_index_const(const godot_vector2 *p_self, godot_int p_index);
+int32_t GDAPI *godot_vector2i_operator_index(godot_vector2i *p_self, godot_int p_index);
+const int32_t GDAPI *godot_vector2i_operator_index_const(const godot_vector2i *p_self, godot_int p_index);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/vector3.h b/modules/gdnative/include/gdnative/vector3.h
index 354c7555b6..7db093ce52 100644
--- a/modules/gdnative/include/gdnative/vector3.h
+++ b/modules/gdnative/include/gdnative/vector3.h
@@ -58,7 +58,13 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_vector3_new(godot_vector3 *p_self);
+void GDAPI godot_vector3_new_copy(godot_vector3 *r_dest, const godot_vector3 *p_src);
void GDAPI godot_vector3i_new(godot_vector3i *p_self);
+void GDAPI godot_vector3i_new_copy(godot_vector3i *r_dest, const godot_vector3i *p_src);
+godot_real_t GDAPI *godot_vector3_operator_index(godot_vector3 *p_self, godot_int p_index);
+const godot_real_t GDAPI *godot_vector3_operator_index_const(const godot_vector3 *p_self, godot_int p_index);
+int32_t GDAPI *godot_vector3i_operator_index(godot_vector3i *p_self, godot_int p_index);
+const int32_t GDAPI *godot_vector3i_operator_index_const(const godot_vector3i *p_self, godot_int p_index);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h
index 73b1738b03..c97f5f0389 100644
--- a/modules/gdnative/include/nativescript/godot_nativescript.h
+++ b/modules/gdnative/include/nativescript/godot_nativescript.h
@@ -58,8 +58,10 @@ typedef enum {
GODOT_PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags)
GODOT_PROPERTY_HINT_LAYERS_2D_RENDER,
GODOT_PROPERTY_HINT_LAYERS_2D_PHYSICS,
+ GODOT_PROPERTY_HINT_LAYERS_2D_NAVIGATION,
GODOT_PROPERTY_HINT_LAYERS_3D_RENDER,
GODOT_PROPERTY_HINT_LAYERS_3D_PHYSICS,
+ GODOT_PROPERTY_HINT_LAYERS_3D_NAVIGATION,
GODOT_PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
GODOT_PROPERTY_HINT_DIR, ///< a directory path must be passed
GODOT_PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
diff --git a/modules/gdnative/include/text/godot_text.h b/modules/gdnative/include/text/godot_text.h
index 44fac3c190..86fc745134 100644
--- a/modules/gdnative/include/text/godot_text.h
+++ b/modules/gdnative/include/text/godot_text.h
@@ -74,11 +74,19 @@ typedef struct {
godot_rid (*create_font_system)(void *, const godot_string *, int);
godot_rid (*create_font_resource)(void *, const godot_string *, int);
godot_rid (*create_font_memory)(void *, const uint8_t *, size_t, godot_string *, int);
+ godot_rid (*create_font_bitmap)(void *, float, float, int);
+ void (*font_bitmap_add_texture)(void *, godot_rid *, const godot_object *);
+ void (*font_bitmap_add_char)(void *, godot_rid *, char32_t, int, const godot_rect2 *, const godot_vector2 *, float);
+ void (*font_bitmap_add_kerning_pair)(void *, godot_rid *, char32_t, char32_t, int);
float (*font_get_height)(void *, godot_rid *, int);
float (*font_get_ascent)(void *, godot_rid *, int);
float (*font_get_descent)(void *, godot_rid *, int);
float (*font_get_underline_position)(void *, godot_rid *, int);
float (*font_get_underline_thickness)(void *, godot_rid *, int);
+ int (*font_get_spacing_space)(void *, godot_rid *);
+ void (*font_set_spacing_space)(void *, godot_rid *, int);
+ int (*font_get_spacing_glyph)(void *, godot_rid *);
+ void (*font_set_spacing_glyph)(void *, godot_rid *, int);
void (*font_set_antialiased)(void *, godot_rid *, bool);
bool (*font_get_antialiased)(void *, godot_rid *);
godot_dictionary (*font_get_feature_list)(void *, godot_rid *);
diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp
index 2b824938f2..f184c84615 100644
--- a/modules/gdnative/nativescript/api_generator.cpp
+++ b/modules/gdnative/nativescript/api_generator.cpp
@@ -71,6 +71,7 @@ struct MethodAPI {
bool is_editor = false;
bool is_noscript = false;
bool is_const = false;
+ bool is_static = false; // For builtin types.
bool is_reverse = false;
bool is_virtual = false;
bool is_from_script = false;
@@ -122,6 +123,7 @@ struct ClassAPI {
// @Unclear
bool is_reference = false;
bool has_indexing = false; // For builtin types.
+ String indexed_type; // For builtin types.
bool is_keyed = false; // For builtin types.
List<MethodAPI> methods;
@@ -141,7 +143,7 @@ static String get_type_name(const PropertyInfo &info) {
return info.class_name;
}
if (info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
- return info.hint_string;
+ return info.class_name;
}
if (info.type == Variant::NIL && (info.usage & PROPERTY_USAGE_NIL_IS_VARIANT)) {
return "Variant";
@@ -196,11 +198,32 @@ List<ClassAPI> generate_c_api_classes() {
global_constants_api.singleton_name = "CoreConstants";
global_constants_api.is_instantiable = false;
const int constants_count = CoreConstants::get_global_constant_count();
+
+ Map<StringName, EnumAPI> enum_api_map;
for (int i = 0; i < constants_count; ++i) {
- ConstantAPI constant_api;
- constant_api.constant_name = CoreConstants::get_global_constant_name(i);
- constant_api.constant_value = CoreConstants::get_global_constant_value(i);
- global_constants_api.constants.push_back(constant_api);
+ StringName enum_name = CoreConstants::get_global_constant_enum(i);
+ String name = String(CoreConstants::get_global_constant_name(i));
+ int value = CoreConstants::get_global_constant_value(i);
+
+ if (enum_name == StringName()) {
+ ConstantAPI constant_api;
+ constant_api.constant_name = name;
+ constant_api.constant_value = value;
+ global_constants_api.constants.push_back(constant_api);
+ } else {
+ EnumAPI enum_api;
+ if (enum_api_map.has(enum_name)) {
+ enum_api = enum_api_map[enum_name];
+ } else {
+ enum_api.name = String(enum_name);
+ }
+ enum_api.values.push_back(Pair(value, name));
+
+ enum_api_map[enum_name] = enum_api;
+ }
+ }
+ for (const Map<StringName, EnumAPI>::Element *E = enum_api_map.front(); E; E = E->next()) {
+ global_constants_api.enums.push_back(E->get());
}
global_constants_api.constants.sort_custom<ConstantAPIComparator>();
api.push_back(global_constants_api);
@@ -308,7 +331,9 @@ List<ClassAPI> generate_c_api_classes() {
property_api.type = p->get().name.get_slice(":", 1);
property_api.name = p->get().name.get_slice(":", 0);
} else {
- property_api.type = get_type_name(p->get());
+ MethodInfo minfo;
+ ClassDB::get_method_info(class_name, property_api.getter, &minfo, true, false);
+ property_api.type = get_type_name(minfo.return_val);
}
property_api.index = ClassDB::get_property_index(class_name, p->get().name);
@@ -370,7 +395,7 @@ List<ClassAPI> generate_c_api_classes() {
arg_type = arg_info.name.get_slice(":", 1);
arg_name = arg_info.name.get_slice(":", 0);
} else if (arg_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
- arg_type = arg_info.hint_string;
+ arg_type = arg_info.class_name;
} else if (arg_info.type == Variant::NIL) {
arg_type = "Variant";
} else if (arg_info.type == Variant::OBJECT) {
@@ -468,6 +493,7 @@ List<ClassAPI> generate_c_builtin_api_types() {
class_api.class_name = Variant::get_type_name(type);
class_api.is_instantiable = true;
class_api.has_indexing = Variant::has_indexing(type);
+ class_api.indexed_type = Variant::get_type_name(Variant::get_indexed_element_type(type));
class_api.is_keyed = Variant::is_keyed(type);
// Types that are passed by reference.
switch (type) {
@@ -503,6 +529,7 @@ List<ClassAPI> generate_c_builtin_api_types() {
method_api.argument_count = Variant::get_builtin_method_argument_count(type, method_name);
method_api.has_varargs = Variant::is_builtin_method_vararg(type, method_name);
method_api.is_const = Variant::is_builtin_method_const(type, method_name);
+ method_api.is_static = Variant::is_builtin_method_static(type, method_name);
for (int i = 0; i < method_api.argument_count; i++) {
method_api.argument_names.push_back(Variant::get_builtin_method_argument_name(type, method_name, i));
@@ -732,6 +759,7 @@ static void write_builtin_method(StringBuilder &p_source, const MethodAPI &p_met
append_indented(p_source, vformat(R"("name": "%s",)", p_method.method_name));
append_indented(p_source, vformat(R"("return_type": "%s",)", p_method.return_type));
append_indented(p_source, vformat(R"("is_const": %s,)", p_method.is_const ? "true" : "false"));
+ append_indented(p_source, vformat(R"("is_static": %s,)", p_method.is_static ? "true" : "false"));
append_indented(p_source, vformat(R"("has_varargs": %s,)", p_method.has_varargs ? "true" : "false"));
append_indented(p_source, R"("arguments": [)");
@@ -768,6 +796,7 @@ static List<String> generate_c_builtin_api_json(const List<ClassAPI> &p_api) {
append_indented(source, vformat(R"("is_instantiable": %s,)", class_api.is_instantiable ? "true" : "false"));
append_indented(source, vformat(R"("is_reference": %s,)", class_api.is_reference ? "true" : "false"));
append_indented(source, vformat(R"("has_indexing": %s,)", class_api.has_indexing ? "true" : "false"));
+ append_indented(source, vformat(R"("indexed_type": "%s",)", class_api.has_indexing && class_api.indexed_type == "Nil" ? "Variant" : class_api.indexed_type));
append_indented(source, vformat(R"("is_keyed": %s,)", class_api.is_keyed ? "true" : "false"));
// Constructors.
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index 19cf1f980b..0025f4bb06 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -173,7 +173,7 @@ bool NativeScript::can_instance() const {
#ifdef TOOLS_ENABLED
// Only valid if this is either a tool script or a "regular" script.
- // (so an environment whre scripting is disabled (and not the editor) would not
+ // (so, an environment where scripting is disabled (and not the editor) would not
// create objects).
return script_data && (is_tool() || ScriptServer::is_scripting_enabled());
#else
@@ -1196,13 +1196,6 @@ void NativeScriptLanguage::_unload_stuff(bool p_reload) {
NativeScriptLanguage::NativeScriptLanguage() {
NativeScriptLanguage::singleton = this;
-#ifndef NO_THREADS
- has_objects_to_register = false;
-#endif
-
-#ifdef DEBUG_ENABLED
- profiling = false;
-#endif
_init_call_type = "nativescript_init";
_init_call_name = "nativescript_init";
@@ -1677,7 +1670,7 @@ void NativeScriptLanguage::defer_init_library(Ref<GDNativeLibrary> lib, NativeSc
MutexLock lock(mutex);
libs_to_init.insert(lib);
scripts_to_register.insert(script);
- has_objects_to_register = true;
+ has_objects_to_register.set();
}
#endif
@@ -1735,7 +1728,7 @@ void NativeScriptLanguage::unregister_script(NativeScript *script) {
library_script_users.erase(S);
Map<String, Ref<GDNative>>::Element *G = library_gdnatives.find(script->lib_path);
- if (G) {
+ if (G && G->get()->get_library()->is_reloadable()) {
G->get()->terminate();
library_gdnatives.erase(G);
}
@@ -1766,7 +1759,7 @@ void NativeScriptLanguage::call_libraries_cb(const StringName &name) {
void NativeScriptLanguage::frame() {
#ifndef NO_THREADS
- if (has_objects_to_register) {
+ if (has_objects_to_register.is_set()) {
MutexLock lock(mutex);
for (Set<Ref<GDNativeLibrary>>::Element *L = libs_to_init.front(); L; L = L->next()) {
init_library(L->get());
@@ -1776,7 +1769,7 @@ void NativeScriptLanguage::frame() {
register_script(S->get());
}
scripts_to_register.clear();
- has_objects_to_register = false;
+ has_objects_to_register.clear();
}
#endif
@@ -1947,7 +1940,7 @@ void NativeReloadNode::_notification(int p_what) {
#endif
}
-RES ResourceFormatLoaderNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_no_cache) {
return ResourceFormatLoaderText::singleton->load(p_path, p_original_path, r_error);
}
diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h
index 9d72bf39d1..d6ba2bbec1 100644
--- a/modules/gdnative/nativescript/nativescript.h
+++ b/modules/gdnative/nativescript/nativescript.h
@@ -40,6 +40,7 @@
#include "core/os/thread_safe.h"
#include "core/templates/oa_hash_map.h"
#include "core/templates/ordered_hash_map.h"
+#include "core/templates/safe_refcount.h"
#include "core/templates/self_list.h"
#include "scene/main/node.h"
@@ -51,8 +52,8 @@ struct NativeScriptDesc {
struct Method {
godot_nativescript_instance_method method;
MethodInfo info;
- int rpc_mode;
- uint16_t rpc_method_id;
+ int rpc_mode = 0;
+ uint16_t rpc_method_id = 0;
String documentation;
};
@@ -61,7 +62,7 @@ struct NativeScriptDesc {
godot_nativescript_property_get_func getter;
PropertyInfo info;
Variant default_value;
- int rset_mode;
+ int rset_mode = 0;
uint16_t rset_property_id;
String documentation;
};
@@ -78,7 +79,7 @@ struct NativeScriptDesc {
Map<StringName, Signal> signals_; // QtCreator doesn't like the name signals
StringName base;
StringName base_native_type;
- NativeScriptDesc *base_data;
+ NativeScriptDesc *base_data = nullptr;
godot_nativescript_instance_create_func create_func;
godot_nativescript_instance_destroy_func destroy_func;
@@ -86,7 +87,7 @@ struct NativeScriptDesc {
const void *type_tag = nullptr;
- bool is_tool;
+ bool is_tool = false;
inline NativeScriptDesc() {
zeromem(&create_func, sizeof(godot_nativescript_instance_create_func));
@@ -254,7 +255,7 @@ class NativeScriptLanguage : public ScriptLanguage {
private:
static NativeScriptLanguage *singleton;
- int lang_idx;
+ int lang_idx = 0;
void _unload_stuff(bool p_reload = false);
@@ -262,7 +263,7 @@ private:
#ifndef NO_THREADS
Set<Ref<GDNativeLibrary>> libs_to_init;
Set<NativeScript *> scripts_to_register;
- volatile bool has_objects_to_register; // so that we don't lock mutex every frame - it's rarely needed
+ SafeFlag has_objects_to_register; // so that we don't lock mutex every frame - it's rarely needed
void defer_init_library(Ref<GDNativeLibrary> lib, NativeScript *script);
#endif
@@ -279,19 +280,19 @@ private:
struct ProfileData {
StringName signature;
- uint64_t call_count;
- uint64_t self_time;
- uint64_t total_time;
- uint64_t frame_call_count;
- uint64_t frame_self_time;
- uint64_t frame_total_time;
- uint64_t last_frame_call_count;
- uint64_t last_frame_self_time;
- uint64_t last_frame_total_time;
+ uint64_t call_count = 0;
+ uint64_t self_time = 0;
+ uint64_t total_time = 0;
+ uint64_t frame_call_count = 0;
+ uint64_t frame_self_time = 0;
+ uint64_t frame_total_time = 0;
+ uint64_t last_frame_call_count = 0;
+ uint64_t last_frame_self_time = 0;
+ uint64_t last_frame_total_time = 0;
};
Map<StringName, ProfileData> profile_data;
- bool profiling;
+ bool profiling = false;
public:
// These two maps must only be touched on the main thread
@@ -402,7 +403,7 @@ public:
class ResourceFormatLoaderNativeScript : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h
index 865080fddf..536eb550e0 100644
--- a/modules/gdnative/pluginscript/pluginscript_instance.h
+++ b/modules/gdnative/pluginscript/pluginscript_instance.h
@@ -44,10 +44,10 @@ class PluginScriptInstance : public ScriptInstance {
private:
Ref<PluginScript> _script;
- Object *_owner;
+ Object *_owner = nullptr;
Variant _owner_variant;
- godot_pluginscript_instance_data *_data;
- const godot_pluginscript_instance_desc *_desc;
+ godot_pluginscript_instance_data *_data = nullptr;
+ const godot_pluginscript_instance_desc *_desc = nullptr;
public:
_FORCE_INLINE_ Object *get_owner() { return _owner; }
diff --git a/modules/gdnative/pluginscript/pluginscript_loader.cpp b/modules/gdnative/pluginscript/pluginscript_loader.cpp
index cd1879a13e..f2165cd225 100644
--- a/modules/gdnative/pluginscript/pluginscript_loader.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_loader.cpp
@@ -39,7 +39,7 @@ ResourceFormatLoaderPluginScript::ResourceFormatLoaderPluginScript(PluginScriptL
_language = language;
}
-RES ResourceFormatLoaderPluginScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderPluginScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
}
diff --git a/modules/gdnative/pluginscript/pluginscript_loader.h b/modules/gdnative/pluginscript/pluginscript_loader.h
index 7b1a7f5423..e5d665c186 100644
--- a/modules/gdnative/pluginscript/pluginscript_loader.h
+++ b/modules/gdnative/pluginscript/pluginscript_loader.h
@@ -43,7 +43,7 @@ class ResourceFormatLoaderPluginScript : public ResourceFormatLoader {
public:
ResourceFormatLoaderPluginScript(PluginScriptLanguage *language);
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp
index 31f4fecb19..d08bde9e23 100644
--- a/modules/gdnative/register_types.cpp
+++ b/modules/gdnative/register_types.cpp
@@ -142,7 +142,7 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty
}
}
- // Add symbols for staticaly linked libraries on iOS
+ // Add symbols for statically linked libraries on iOS
if (p_features.has("iOS")) {
bool should_fake_dynamic = false;
diff --git a/modules/gdnative/tests/test_variant.h b/modules/gdnative/tests/test_variant.h
index 5284bf26f0..aeceb6e68f 100644
--- a/modules/gdnative/tests/test_variant.h
+++ b/modules/gdnative/tests/test_variant.h
@@ -124,6 +124,7 @@ TEST_CASE("[GDNative Variant] Variant evaluate") {
godot_variant_new_int(&two, 2);
godot_variant three;
+ godot_variant_new_nil(&three);
bool valid = false;
godot_variant_evaluate(GODOT_VARIANT_OP_ADD, &one, &two, &three, &valid);
diff --git a/modules/gdnative/text/text_server_gdnative.cpp b/modules/gdnative/text/text_server_gdnative.cpp
index f7a3cb8135..7cd8de5f2e 100644
--- a/modules/gdnative/text/text_server_gdnative.cpp
+++ b/modules/gdnative/text/text_server_gdnative.cpp
@@ -113,6 +113,28 @@ RID TextServerGDNative::create_font_memory(const uint8_t *p_data, size_t p_size,
return rid;
}
+RID TextServerGDNative::create_font_bitmap(float p_height, float p_ascent, int p_base_size) {
+ ERR_FAIL_COND_V(interface == nullptr, RID());
+ godot_rid result = interface->create_font_bitmap(data, p_height, p_ascent, p_base_size);
+ RID rid = *(RID *)&result;
+ return rid;
+}
+
+void TextServerGDNative::font_bitmap_add_texture(RID p_font, const Ref<Texture> &p_texture) {
+ ERR_FAIL_COND(interface == nullptr);
+ interface->font_bitmap_add_texture(data, (godot_rid *)&p_font, (const godot_object *)p_texture.ptr());
+}
+
+void TextServerGDNative::font_bitmap_add_char(RID p_font, char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) {
+ ERR_FAIL_COND(interface == nullptr);
+ interface->font_bitmap_add_char(data, (godot_rid *)&p_font, p_char, p_texture_idx, (const godot_rect2 *)&p_rect, (const godot_vector2 *)&p_align, p_advance);
+}
+
+void TextServerGDNative::font_bitmap_add_kerning_pair(RID p_font, char32_t p_A, char32_t p_B, int p_kerning) {
+ ERR_FAIL_COND(interface == nullptr);
+ interface->font_bitmap_add_kerning_pair(data, (godot_rid *)&p_font, p_A, p_B, p_kerning);
+}
+
float TextServerGDNative::font_get_height(RID p_font, int p_size) const {
ERR_FAIL_COND_V(interface == nullptr, 0.f);
return interface->font_get_height(data, (godot_rid *)&p_font, p_size);
@@ -138,6 +160,26 @@ float TextServerGDNative::font_get_underline_thickness(RID p_font, int p_size) c
return interface->font_get_underline_thickness(data, (godot_rid *)&p_font, p_size);
}
+int TextServerGDNative::font_get_spacing_space(RID p_font) const {
+ ERR_FAIL_COND_V(interface == nullptr, 0);
+ return interface->font_get_spacing_space(data, (godot_rid *)&p_font);
+}
+
+void TextServerGDNative::font_set_spacing_space(RID p_font, int p_value) {
+ ERR_FAIL_COND(interface == nullptr);
+ interface->font_set_spacing_space(data, (godot_rid *)&p_font, p_value);
+}
+
+int TextServerGDNative::font_get_spacing_glyph(RID p_font) const {
+ ERR_FAIL_COND_V(interface == nullptr, 0);
+ return interface->font_get_spacing_glyph(data, (godot_rid *)&p_font);
+}
+
+void TextServerGDNative::font_set_spacing_glyph(RID p_font, int p_value) {
+ ERR_FAIL_COND(interface == nullptr);
+ interface->font_set_spacing_glyph(data, (godot_rid *)&p_font, p_value);
+}
+
void TextServerGDNative::font_set_antialiased(RID p_font, bool p_antialiased) {
ERR_FAIL_COND(interface == nullptr);
interface->font_set_antialiased(data, (godot_rid *)&p_font, p_antialiased);
diff --git a/modules/gdnative/text/text_server_gdnative.h b/modules/gdnative/text/text_server_gdnative.h
index 9cbb94217e..931bb44885 100644
--- a/modules/gdnative/text/text_server_gdnative.h
+++ b/modules/gdnative/text/text_server_gdnative.h
@@ -64,6 +64,11 @@ public:
virtual RID create_font_system(const String &p_name, int p_base_size = 16) override;
virtual RID create_font_resource(const String &p_filename, int p_base_size = 16) override;
virtual RID create_font_memory(const uint8_t *p_data, size_t p_size, const String &p_type, int p_base_size = 16) override;
+ virtual RID create_font_bitmap(float p_height, float p_ascent, int p_base_size = 16) override;
+
+ virtual void font_bitmap_add_texture(RID p_font, const Ref<Texture> &p_texture) override;
+ virtual void font_bitmap_add_char(RID p_font, char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) override;
+ virtual void font_bitmap_add_kerning_pair(RID p_font, char32_t p_A, char32_t p_B, int p_kerning) override;
virtual float font_get_height(RID p_font, int p_size) const override;
virtual float font_get_ascent(RID p_font, int p_size) const override;
@@ -72,6 +77,12 @@ public:
virtual float font_get_underline_position(RID p_font, int p_size) const override;
virtual float font_get_underline_thickness(RID p_font, int p_size) const override;
+ virtual int font_get_spacing_space(RID p_font) const override;
+ virtual void font_set_spacing_space(RID p_font, int p_value) override;
+
+ virtual int font_get_spacing_glyph(RID p_font) const override;
+ virtual void font_set_spacing_glyph(RID p_font, int p_value) override;
+
virtual void font_set_antialiased(RID p_font, bool p_antialiased) override;
virtual bool font_get_antialiased(RID p_font) const override;
diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
index 18d26a9528..f2fb0a2fdc 100644
--- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp
+++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
@@ -250,7 +250,7 @@ void VideoStreamPlaybackGDNative::play() {
playing = true;
- delay_compensation = ProjectSettings::get_singleton()->get("audio/video_delay_compensation_ms");
+ delay_compensation = ProjectSettings::get_singleton()->get("audio/video/video_delay_compensation_ms");
delay_compensation /= 1000.0;
}
@@ -360,7 +360,7 @@ void VideoStreamGDNative::set_audio_track(int p_track) {
/* --- NOTE ResourceFormatLoaderVideoStreamGDNative starts here. ----- */
-RES ResourceFormatLoaderVideoStreamGDNative::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderVideoStreamGDNative::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) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
if (r_error) {
diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.h b/modules/gdnative/videodecoder/video_stream_gdnative.h
index e64cda6602..140888cd4b 100644
--- a/modules/gdnative/videodecoder/video_stream_gdnative.h
+++ b/modules/gdnative/videodecoder/video_stream_gdnative.h
@@ -118,7 +118,7 @@ class VideoStreamPlaybackGDNative : public VideoStreamPlayback {
AudioMixCallback mix_callback = nullptr;
int num_channels = -1;
- float time = 0;
+ float time = 0.0;
bool seek_backward = false;
int mix_rate = 0;
double delay_compensation = 0;
@@ -196,7 +196,7 @@ public:
class ResourceFormatLoaderVideoStreamGDNative : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdnative/xr/xr_interface_gdnative.cpp b/modules/gdnative/xr/xr_interface_gdnative.cpp
index 5bbf70174c..1d5a9d98f8 100644
--- a/modules/gdnative/xr/xr_interface_gdnative.cpp
+++ b/modules/gdnative/xr/xr_interface_gdnative.cpp
@@ -398,7 +398,7 @@ void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_a
if (tracker != nullptr) {
int joyid = tracker->get_joy_id();
if (joyid != -1) {
- Input::JoyAxis jx;
+ Input::JoyAxisValue jx;
jx.min = p_can_be_negative ? -1 : 0;
jx.value = p_value;
input->joy_axis(joyid, p_axis, jx);
diff --git a/modules/gdnavigation/gd_navigation_server.cpp b/modules/gdnavigation/gd_navigation_server.cpp
index 4f61ad5040..39f208c7a4 100644
--- a/modules/gdnavigation/gd_navigation_server.cpp
+++ b/modules/gdnavigation/gd_navigation_server.cpp
@@ -145,9 +145,13 @@ COMMAND_2(map_set_active, RID, p_map, bool, p_active) {
if (p_active) {
if (!map_is_active(p_map)) {
active_maps.push_back(map);
+ active_maps_update_id.push_back(map->get_map_update_id());
}
} else {
- active_maps.erase(map);
+ int map_index = active_maps.find(map);
+ ERR_FAIL_COND(map_index < 0);
+ active_maps.remove(map_index);
+ active_maps_update_id.remove(map_index);
}
}
@@ -200,11 +204,11 @@ real_t GdNavigationServer::map_get_edge_connection_margin(RID p_map) const {
return map->get_edge_connection_margin();
}
-Vector<Vector3> GdNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const {
+Vector<Vector3> GdNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const {
const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == nullptr, Vector<Vector3>());
- return map->get_path(p_origin, p_destination, p_optimize);
+ return map->get_path(p_origin, p_destination, p_optimize, p_layers);
}
Vector3 GdNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
@@ -273,6 +277,20 @@ COMMAND_2(region_set_transform, RID, p_region, Transform, p_transform) {
region->set_transform(p_transform);
}
+COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers) {
+ NavRegion *region = region_owner.getornull(p_region);
+ ERR_FAIL_COND(region == nullptr);
+
+ region->set_layers(p_layers);
+}
+
+uint32_t GdNavigationServer::region_get_layers(RID p_region) const {
+ NavRegion *region = region_owner.getornull(p_region);
+ ERR_FAIL_COND_V(region == nullptr, 0);
+
+ return region->get_layers();
+}
+
COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh) {
NavRegion *region = region_owner.getornull(p_region);
ERR_FAIL_COND(region == nullptr);
@@ -290,6 +308,27 @@ void GdNavigationServer::region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p
#endif
}
+int GdNavigationServer::region_get_connections_count(RID p_region) const {
+ NavRegion *region = region_owner.getornull(p_region);
+ ERR_FAIL_COND_V(!region, 0);
+
+ return region->get_connections_count();
+}
+
+Vector3 GdNavigationServer::region_get_connection_pathway_start(RID p_region, int p_connection_id) const {
+ NavRegion *region = region_owner.getornull(p_region);
+ ERR_FAIL_COND_V(!region, Vector3());
+
+ return region->get_connection_pathway_start(p_connection_id);
+}
+
+Vector3 GdNavigationServer::region_get_connection_pathway_end(RID p_region, int p_connection_id) const {
+ NavRegion *region = region_owner.getornull(p_region);
+ ERR_FAIL_COND_V(!region, Vector3());
+
+ return region->get_connection_pathway_end(p_connection_id);
+}
+
RID GdNavigationServer::agent_create() const {
auto mut_this = const_cast<GdNavigationServer *>(this);
MutexLock lock(mut_this->operations_mutex);
@@ -429,7 +468,9 @@ COMMAND_1(free, RID, p_object) {
agents[i]->set_map(nullptr);
}
- active_maps.erase(map);
+ int map_index = active_maps.find(map);
+ active_maps.remove(map_index);
+ active_maps_update_id.remove(map_index);
map_owner.free(p_object);
memdelete(map);
@@ -490,10 +531,17 @@ void GdNavigationServer::process(real_t p_delta_time) {
// In c++ we can't be sure that this is performed in the main thread
// even with mutable functions.
MutexLock lock(operations_mutex);
- for (int i(0); i < active_maps.size(); i++) {
+ for (uint32_t i(0); i < active_maps.size(); i++) {
active_maps[i]->sync();
active_maps[i]->step(p_delta_time);
active_maps[i]->dispatch_callbacks();
+
+ // Emit a signal if a map changed.
+ const uint32_t new_map_update_id = active_maps[i]->get_map_update_id();
+ if (new_map_update_id != active_maps_update_id[i]) {
+ emit_signal("map_changed", active_maps[i]->get_self());
+ active_maps_update_id[i] = new_map_update_id;
+ }
}
}
diff --git a/modules/gdnavigation/gd_navigation_server.h b/modules/gdnavigation/gd_navigation_server.h
index 92f4ccfdd5..2f51f6431e 100644
--- a/modules/gdnavigation/gd_navigation_server.h
+++ b/modules/gdnavigation/gd_navigation_server.h
@@ -31,6 +31,7 @@
#ifndef GD_NAVIGATION_SERVER_H
#define GD_NAVIGATION_SERVER_H
+#include "core/templates/local_vector.h"
#include "core/templates/rid.h"
#include "core/templates/rid_owner.h"
#include "servers/navigation_server_3d.h"
@@ -79,7 +80,8 @@ class GdNavigationServer : public NavigationServer3D {
mutable RID_PtrOwner<RvoAgent> agent_owner;
bool active = true;
- Vector<NavMap *> active_maps;
+ LocalVector<NavMap *> active_maps;
+ LocalVector<uint32_t> active_maps_update_id;
public:
GdNavigationServer();
@@ -100,7 +102,7 @@ public:
COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin);
virtual real_t map_get_edge_connection_margin(RID p_map) const;
- virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const;
+ virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers = 1) const;
virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const;
virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const;
@@ -109,9 +111,14 @@ public:
virtual RID region_create() const;
COMMAND_2(region_set_map, RID, p_region, RID, p_map);
+ COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers);
+ virtual uint32_t region_get_layers(RID p_region) const;
COMMAND_2(region_set_transform, RID, p_region, Transform, 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;
+ virtual int region_get_connections_count(RID p_region) const;
+ virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const;
+ virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const;
virtual RID agent_create() const;
COMMAND_2(agent_set_map, RID, p_agent, RID, p_map);
diff --git a/modules/gdnavigation/nav_map.cpp b/modules/gdnavigation/nav_map.cpp
index 2646a4cc0c..80f367f3a6 100644
--- a/modules/gdnavigation/nav_map.cpp
+++ b/modules/gdnavigation/nav_map.cpp
@@ -40,7 +40,7 @@
@author AndreaCatania
*/
-#define USE_ENTRY_POINT
+#define THREE_POINTS_CROSS_PRODUCT(m_a, m_b, m_c) (((m_c) - (m_a)).cross((m_b) - (m_a)))
void NavMap::set_up(Vector3 p_up) {
up = p_up;
@@ -70,44 +70,52 @@ 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) const {
+Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const {
+ // Find the start poly and the end poly on this map.
const gd::Polygon *begin_poly = nullptr;
const gd::Polygon *end_poly = nullptr;
Vector3 begin_point;
Vector3 end_point;
float begin_d = 1e20;
float end_d = 1e20;
-
// Find the initial poly and the end poly on this map.
for (size_t i(0); i < polygons.size(); i++) {
const gd::Polygon &p = polygons[i];
+ // Only consider the polygon if it in a region with compatible layers.
+ if ((p_layers & p.owner->get_layers()) == 0) {
+ continue;
+ }
+
// For each point cast a face and check the distance between the origin/destination
- for (size_t point_id = 2; point_id < p.points.size(); point_id++) {
- Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos);
- Vector3 spoint = f.get_closest_point_to(p_origin);
- float dpoint = spoint.distance_to(p_origin);
- if (dpoint < begin_d) {
- begin_d = dpoint;
+ for (size_t point_id = 0; point_id < p.points.size(); point_id++) {
+ const Vector3 p1 = p.points[point_id].pos;
+ const Vector3 p2 = p.points[(point_id + 1) % p.points.size()].pos;
+ const Vector3 p3 = p.points[(point_id + 2) % p.points.size()].pos;
+ const Face3 face(p1, p2, p3);
+
+ Vector3 point = face.get_closest_point_to(p_origin);
+ float distance_to_point = point.distance_to(p_origin);
+ if (distance_to_point < begin_d) {
+ begin_d = distance_to_point;
begin_poly = &p;
- begin_point = spoint;
+ begin_point = point;
}
- spoint = f.get_closest_point_to(p_destination);
- dpoint = spoint.distance_to(p_destination);
- if (dpoint < end_d) {
- end_d = dpoint;
+ point = face.get_closest_point_to(p_destination);
+ distance_to_point = point.distance_to(p_destination);
+ if (distance_to_point < end_d) {
+ end_d = distance_to_point;
end_poly = &p;
- end_point = spoint;
+ end_point = point;
}
}
}
+ // Check for trival cases
if (!begin_poly || !end_poly) {
- // No path
return Vector<Vector3>();
}
-
if (begin_poly == end_poly) {
Vector<Vector3> path;
path.resize(2);
@@ -116,90 +124,89 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
return path;
}
+ // List of all reachable navigation polys.
std::vector<gd::NavigationPoly> navigation_polys;
navigation_polys.reserve(polygons.size() * 0.75);
- // The elements indices in the `navigation_polys`.
- int least_cost_id(-1);
- List<uint32_t> open_list;
- bool found_route = false;
+ // Add the start polygon to the reachable navigation polygons.
+ gd::NavigationPoly begin_navigation_poly = gd::NavigationPoly(begin_poly);
+ begin_navigation_poly.self_id = 0;
+ begin_navigation_poly.entry = begin_point;
+ begin_navigation_poly.back_navigation_edge_pathway_start = begin_point;
+ begin_navigation_poly.back_navigation_edge_pathway_end = begin_point;
+ navigation_polys.push_back(begin_navigation_poly);
- navigation_polys.push_back(gd::NavigationPoly(begin_poly));
- {
- least_cost_id = 0;
- gd::NavigationPoly *least_cost_poly = &navigation_polys[least_cost_id];
- least_cost_poly->self_id = least_cost_id;
- least_cost_poly->entry = begin_point;
- }
+ // List of polygon IDs to visit.
+ List<uint32_t> to_visit;
+ to_visit.push_back(0);
- open_list.push_back(0);
+ // This is an implementation of the A* algorithm.
+ int least_cost_id = 0;
+ bool found_route = false;
const gd::Polygon *reachable_end = nullptr;
float reachable_d = 1e30;
bool is_reachable = true;
- while (found_route == false) {
- {
- // Takes the current least_cost_poly neighbors and compute the traveled_distance of each
- for (size_t i = 0; i < navigation_polys[least_cost_id].poly->edges.size(); i++) {
- gd::NavigationPoly *least_cost_poly = &navigation_polys[least_cost_id];
+ while (true) {
+ gd::NavigationPoly *least_cost_poly = &navigation_polys[least_cost_id];
+
+ // Takes the current least_cost_poly neighbors (iterating over its edges) and compute the traveled_distance.
+ for (size_t i = 0; i < least_cost_poly->poly->edges.size(); i++) {
+ const gd::Edge &edge = least_cost_poly->poly->edges[i];
+
+ // Iterate over connections in this edge, then compute the new optimized travel distance assigned to this polygon.
+ for (int connection_index = 0; connection_index < edge.connections.size(); connection_index++) {
+ const gd::Edge::Connection &connection = edge.connections[connection_index];
- const gd::Edge &edge = least_cost_poly->poly->edges[i];
- if (!edge.other_polygon) {
+ // Only consider the connection to another polygon if this polygon is in a region with compatible layers.
+ if ((p_layers & connection.polygon->owner->get_layers()) == 0) {
continue;
}
-#ifdef USE_ENTRY_POINT
- Vector3 edge_line[2] = {
- least_cost_poly->poly->points[i].pos,
- least_cost_poly->poly->points[(i + 1) % least_cost_poly->poly->points.size()].pos
- };
-
- const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly->entry, edge_line);
+ Vector3 pathway[2] = { connection.pathway_start, connection.pathway_end };
+ const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly->entry, pathway);
const float new_distance = least_cost_poly->entry.distance_to(new_entry) + least_cost_poly->traveled_distance;
-#else
- const float new_distance = least_cost_poly->poly->center.distance_to(edge.other_polygon->center) + least_cost_poly->traveled_distance;
-#endif
auto it = std::find(
navigation_polys.begin(),
navigation_polys.end(),
- gd::NavigationPoly(edge.other_polygon));
+ gd::NavigationPoly(connection.polygon));
if (it != navigation_polys.end()) {
- // Oh this was visited already, can we win the cost?
- if (it->traveled_distance > new_distance) {
- it->prev_navigation_poly_id = least_cost_id;
- it->back_navigation_edge = edge.other_edge;
+ // Polygon already visited, check if we can reduce the travel cost.
+ if (new_distance < it->traveled_distance) {
+ it->back_navigation_poly_id = least_cost_id;
+ it->back_navigation_edge = connection.edge;
+ it->back_navigation_edge_pathway_start = connection.pathway_start;
+ it->back_navigation_edge_pathway_end = connection.pathway_end;
it->traveled_distance = new_distance;
-#ifdef USE_ENTRY_POINT
it->entry = new_entry;
-#endif
}
} else {
- // Add to open neighbours
-
- navigation_polys.push_back(gd::NavigationPoly(edge.other_polygon));
- gd::NavigationPoly *np = &navigation_polys[navigation_polys.size() - 1];
-
- np->self_id = navigation_polys.size() - 1;
- np->prev_navigation_poly_id = least_cost_id;
- np->back_navigation_edge = edge.other_edge;
- np->traveled_distance = new_distance;
-#ifdef USE_ENTRY_POINT
- np->entry = new_entry;
-#endif
- open_list.push_back(navigation_polys.size() - 1);
+ // Add the neighbour polygon to the reachable ones.
+ gd::NavigationPoly new_navigation_poly = gd::NavigationPoly(connection.polygon);
+ new_navigation_poly.self_id = navigation_polys.size();
+ new_navigation_poly.back_navigation_poly_id = least_cost_id;
+ new_navigation_poly.back_navigation_edge = connection.edge;
+ new_navigation_poly.back_navigation_edge_pathway_start = connection.pathway_start;
+ new_navigation_poly.back_navigation_edge_pathway_end = connection.pathway_end;
+ new_navigation_poly.traveled_distance = new_distance;
+ new_navigation_poly.entry = new_entry;
+ navigation_polys.push_back(new_navigation_poly);
+
+ // Add the neighbour polygon to the polygons to visit.
+ to_visit.push_back(navigation_polys.size() - 1);
}
}
}
- // Removes the least cost polygon from the open list so we can advance.
- open_list.erase(least_cost_id);
+ // Removes the least cost polygon from the list of polygons to visit so we can advance.
+ to_visit.erase(least_cost_id);
- if (open_list.size() == 0) {
- // When the open list is empty at this point the End Polygon is not reachable
- // so use the further reachable polygon
+ // When the list of polygons to visit is empty at this point it means the End Polygon is not reachable
+ if (to_visit.size() == 0) {
+ // Thus use the further reachable polygon
ERR_BREAK_MSG(is_reachable == false, "It's not expect to not find the most reachable polygons");
is_reachable = false;
if (reachable_end == nullptr) {
@@ -224,26 +231,21 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
gd::NavigationPoly np = navigation_polys[0];
navigation_polys.clear();
navigation_polys.push_back(np);
- open_list.clear();
- open_list.push_back(0);
+ to_visit.clear();
+ to_visit.push_back(0);
reachable_end = nullptr;
continue;
}
- // Now take the new least_cost_poly from the open list.
+ // Find the polygon with the minimum cost from the list of polygons to visit.
least_cost_id = -1;
float least_cost = 1e30;
-
- for (auto element = open_list.front(); element != nullptr; element = element->next()) {
+ for (List<uint32_t>::Element *element = to_visit.front(); element != nullptr; element = element->next()) {
gd::NavigationPoly *np = &navigation_polys[element->get()];
float cost = np->traveled_distance;
-#ifdef USE_ENTRY_POINT
cost += np->entry.distance_to(end_point);
-#else
- cost += np->poly->center.distance_to(end_point);
-#endif
if (cost < least_cost) {
least_cost_id = np->self_id;
least_cost = cost;
@@ -263,124 +265,108 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
// Check if we reached the end
if (navigation_polys[least_cost_id].poly == end_poly) {
- // Yep, done!!
found_route = true;
break;
}
}
- if (found_route) {
- Vector<Vector3> path;
- if (p_optimize) {
- // String pulling
-
- gd::NavigationPoly *apex_poly = &navigation_polys[least_cost_id];
- Vector3 apex_point = end_point;
- Vector3 portal_left = apex_point;
- Vector3 portal_right = apex_point;
- gd::NavigationPoly *left_poly = apex_poly;
- gd::NavigationPoly *right_poly = apex_poly;
- gd::NavigationPoly *p = apex_poly;
-
- path.push_back(end_point);
+ // If we did not find a route, return an empty path.
+ if (!found_route) {
+ return Vector<Vector3>();
+ }
- while (p) {
- Vector3 left;
- Vector3 right;
+ Vector<Vector3> path;
+ // Optimize the path.
+ if (p_optimize) {
+ // Set the apex poly/point to the end point
+ gd::NavigationPoly *apex_poly = &navigation_polys[least_cost_id];
+ Vector3 apex_point = end_point;
-#define CLOCK_TANGENT(m_a, m_b, m_c) (((m_a) - (m_c)).cross((m_a) - (m_b)))
+ gd::NavigationPoly *left_poly = apex_poly;
+ Vector3 left_portal = apex_point;
+ gd::NavigationPoly *right_poly = apex_poly;
+ Vector3 right_portal = apex_point;
- if (p->poly == begin_poly) {
- left = begin_point;
- right = begin_point;
- } else {
- int prev = p->back_navigation_edge;
- int prev_n = (p->back_navigation_edge + 1) % p->poly->points.size();
- left = p->poly->points[prev].pos;
- right = p->poly->points[prev_n].pos;
+ gd::NavigationPoly *p = apex_poly;
- if (p->poly->clockwise) {
- SWAP(left, right);
- }
- }
+ path.push_back(end_point);
- bool skip = false;
-
- if (CLOCK_TANGENT(apex_point, portal_left, left).dot(up) >= 0) {
- //process
- if (portal_left == apex_point || CLOCK_TANGENT(apex_point, left, portal_right).dot(up) > 0) {
- left_poly = p;
- portal_left = left;
- } else {
- clip_path(navigation_polys, path, apex_poly, portal_right, right_poly);
-
- apex_point = portal_right;
- p = right_poly;
- left_poly = p;
- apex_poly = p;
- portal_left = apex_point;
- portal_right = apex_point;
- path.push_back(apex_point);
- skip = true;
- }
- }
+ while (p) {
+ // Set left and right points of the pathway between polygons.
+ Vector3 left = p->back_navigation_edge_pathway_start;
+ Vector3 right = p->back_navigation_edge_pathway_end;
+ if (THREE_POINTS_CROSS_PRODUCT(apex_point, left, right).dot(up) < 0) {
+ SWAP(left, right);
+ }
- if (!skip && CLOCK_TANGENT(apex_point, portal_right, right).dot(up) <= 0) {
- //process
- if (portal_right == apex_point || CLOCK_TANGENT(apex_point, right, portal_left).dot(up) < 0) {
- right_poly = p;
- portal_right = right;
- } else {
- clip_path(navigation_polys, path, apex_poly, portal_left, left_poly);
-
- apex_point = portal_left;
- p = left_poly;
- right_poly = p;
- apex_poly = p;
- portal_right = apex_point;
- portal_left = apex_point;
- path.push_back(apex_point);
- }
+ bool skip = false;
+ if (THREE_POINTS_CROSS_PRODUCT(apex_point, left_portal, left).dot(up) >= 0) {
+ //process
+ if (left_portal == apex_point || THREE_POINTS_CROSS_PRODUCT(apex_point, left, right_portal).dot(up) > 0) {
+ left_poly = p;
+ left_portal = left;
+ } else {
+ clip_path(navigation_polys, path, apex_poly, right_portal, right_poly);
+
+ apex_point = right_portal;
+ p = right_poly;
+ left_poly = p;
+ apex_poly = p;
+ left_portal = apex_point;
+ right_portal = apex_point;
+ path.push_back(apex_point);
+ skip = true;
}
+ }
- if (p->prev_navigation_poly_id != -1) {
- p = &navigation_polys[p->prev_navigation_poly_id];
+ if (!skip && THREE_POINTS_CROSS_PRODUCT(apex_point, right_portal, right).dot(up) <= 0) {
+ //process
+ if (right_portal == apex_point || THREE_POINTS_CROSS_PRODUCT(apex_point, right, left_portal).dot(up) < 0) {
+ right_poly = p;
+ right_portal = right;
} else {
- // The end
- p = nullptr;
+ clip_path(navigation_polys, path, apex_poly, left_portal, left_poly);
+
+ apex_point = left_portal;
+ p = left_poly;
+ right_poly = p;
+ apex_poly = p;
+ right_portal = apex_point;
+ left_portal = apex_point;
+ path.push_back(apex_point);
}
}
- if (path[path.size() - 1] != begin_point) {
- path.push_back(begin_point);
+ // Go to the previous polygon.
+ if (p->back_navigation_poly_id != -1) {
+ p = &navigation_polys[p->back_navigation_poly_id];
+ } else {
+ // The end
+ p = nullptr;
}
+ }
- path.invert();
-
- } else {
- path.push_back(end_point);
+ // 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);
+ }
- // Add mid points
- int np_id = least_cost_id;
- while (np_id != -1) {
-#ifdef USE_ENTRY_POINT
- Vector3 point = navigation_polys[np_id].entry;
-#else
- 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;
-#endif
+ path.invert();
- path.push_back(point);
- np_id = navigation_polys[np_id].prev_navigation_poly_id;
- }
+ } else {
+ path.push_back(end_point);
- path.invert();
+ // Add mid points
+ int np_id = least_cost_id;
+ while (np_id != -1) {
+ path.push_back(navigation_polys[np_id].entry);
+ np_id = navigation_polys[np_id].back_navigation_poly_id;
}
- return path;
+ path.invert();
}
- return Vector<Vector3>();
+
+ return path;
}
Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
@@ -561,6 +547,7 @@ void NavMap::remove_agent_as_controlled(RvoAgent *agent) {
}
void NavMap::sync() {
+ // Check if we need to update the links.
if (regenerate_polygons) {
for (size_t r(0); r < regions.size(); r++) {
regions[r]->scratch_polygons();
@@ -575,27 +562,30 @@ void NavMap::sync() {
}
if (regenerate_links) {
- // Copy all region polygons in the map.
+ // Remove regions connections.
+ for (size_t r(0); r < regions.size(); r++) {
+ regions[r]->get_connections().clear();
+ }
+
+ // Resize the polygon count.
int count = 0;
for (size_t r(0); r < regions.size(); r++) {
count += regions[r]->get_polygons().size();
}
-
polygons.resize(count);
- count = 0;
+ // Copy all region polygons in the map.
+ count = 0;
for (size_t r(0); r < regions.size(); r++) {
std::copy(
regions[r]->get_polygons().data(),
regions[r]->get_polygons().data() + regions[r]->get_polygons().size(),
polygons.begin() + count);
-
count += regions[r]->get_polygons().size();
}
- // Connects the `Edges` of all the `Polygons` of all `Regions` each other.
- Map<gd::EdgeKey, gd::Connection> connections;
-
+ // Group all edges per key.
+ Map<gd::EdgeKey, Vector<gd::Edge::Connection>> connections;
for (size_t poly_id(0); poly_id < polygons.size(); poly_id++) {
gd::Polygon &poly(polygons[poly_id]);
@@ -603,69 +593,40 @@ void NavMap::sync() {
int next_point = (p + 1) % poly.points.size();
gd::EdgeKey ek(poly.points[p].key, poly.points[next_point].key);
- Map<gd::EdgeKey, gd::Connection>::Element *connection = connections.find(ek);
+ Map<gd::EdgeKey, Vector<gd::Edge::Connection>>::Element *connection = connections.find(ek);
if (!connection) {
- // Nothing yet
- gd::Connection c;
- c.A = &poly;
- c.A_edge = p;
- c.B = nullptr;
- c.B_edge = -1;
- connections[ek] = c;
-
- } else if (connection->get().B == nullptr) {
- CRASH_COND(connection->get().A == nullptr); // Unreachable
-
- // Connect the two Polygons by this edge
- connection->get().B = &poly;
- connection->get().B_edge = p;
-
- connection->get().A->edges[connection->get().A_edge].this_edge = connection->get().A_edge;
- connection->get().A->edges[connection->get().A_edge].other_polygon = connection->get().B;
- connection->get().A->edges[connection->get().A_edge].other_edge = connection->get().B_edge;
-
- connection->get().B->edges[connection->get().B_edge].this_edge = connection->get().B_edge;
- connection->get().B->edges[connection->get().B_edge].other_polygon = connection->get().A;
- connection->get().B->edges[connection->get().B_edge].other_edge = connection->get().A_edge;
+ connections[ek] = Vector<gd::Edge::Connection>();
+ }
+ if (connections[ek].size() <= 1) {
+ // Add the polygon/edge tuple to this key.
+ gd::Edge::Connection new_connection;
+ new_connection.polygon = &poly;
+ new_connection.edge = p;
+ new_connection.pathway_start = poly.points[p].pos;
+ new_connection.pathway_end = poly.points[next_point].pos;
+ connections[ek].push_back(new_connection);
} else {
// The edge is already connected with another edge, skip.
- ERR_PRINT("Attempted to merge a navigation mesh triangle edge with another already-merged edge. This happens when the Navigation3D's `cell_size` is different from the one used to generate the navigation mesh. This will cause navigation problem.");
+ ERR_PRINT("Attempted to merge a navigation mesh triangle edge with another already-merged edge. This happens when the current `cell_size` is different from the one used to generate the navigation mesh. This will cause navigation problem.");
}
}
}
- // Takes all the free edges.
- std::vector<gd::FreeEdge> free_edges;
- free_edges.reserve(connections.size());
-
- for (auto connection_element = connections.front(); connection_element; connection_element = connection_element->next()) {
- if (connection_element->get().B == nullptr) {
- CRASH_COND(connection_element->get().A == nullptr); // Unreachable
- CRASH_COND(connection_element->get().A_edge < 0); // Unreachable
-
- // This is a free edge
- uint32_t id(free_edges.size());
- free_edges.push_back(gd::FreeEdge());
- free_edges[id].is_free = true;
- free_edges[id].poly = connection_element->get().A;
- free_edges[id].edge_id = connection_element->get().A_edge;
- uint32_t point_0(free_edges[id].edge_id);
- uint32_t point_1((free_edges[id].edge_id + 1) % free_edges[id].poly->points.size());
- Vector3 pos_0 = free_edges[id].poly->points[point_0].pos;
- Vector3 pos_1 = free_edges[id].poly->points[point_1].pos;
- Vector3 relative = pos_1 - pos_0;
- free_edges[id].edge_center = (pos_0 + pos_1) / 2.0;
- free_edges[id].edge_dir = relative.normalized();
- free_edges[id].edge_len_squared = relative.length_squared();
+ Vector<gd::Edge::Connection> free_edges;
+ for (Map<gd::EdgeKey, Vector<gd::Edge::Connection>>::Element *E = connections.front(); E; E = E->next()) {
+ if (E->get().size() == 2) {
+ // Connect edge that are shared in different polygons.
+ gd::Edge::Connection &c1 = E->get().write[0];
+ gd::Edge::Connection &c2 = E->get().write[1];
+ c1.polygon->edges[c1.edge].connections.push_back(c2);
+ c2.polygon->edges[c2.edge].connections.push_back(c1);
+ // Note: The pathway_start/end are full for those connection and do not need to be modified.
+ } else {
+ CRASH_COND_MSG(E->get().size() != 1, vformat("Number of connection != 1. Found: %d", E->get().size()));
+ free_edges.push_back(E->get()[0]);
}
}
- const float ecm_squared(edge_connection_margin * edge_connection_margin);
-#define LEN_TOLLERANCE 0.1
-#define DIR_TOLLERANCE 0.9
- // In front of tolerance
-#define IFO_TOLLERANCE 0.5
-
// Find the compatible near edges.
//
// Note:
@@ -673,43 +634,67 @@ void NavMap::sync() {
// to be connected, create new polygons to remove that small gap is
// not really useful and would result in wasteful computation during
// connection, integration and path finding.
- for (size_t i(0); i < free_edges.size(); i++) {
- if (!free_edges[i].is_free) {
- continue;
- }
- gd::FreeEdge &edge = free_edges[i];
- for (size_t y(0); y < free_edges.size(); y++) {
- gd::FreeEdge &other_edge = free_edges[y];
- if (i == y || !other_edge.is_free || edge.poly->owner == other_edge.poly->owner) {
+ for (int i = 0; i < free_edges.size(); i++) {
+ const gd::Edge::Connection &free_edge = free_edges[i];
+ Vector3 edge_p1 = free_edge.polygon->points[free_edge.edge].pos;
+ Vector3 edge_p2 = free_edge.polygon->points[(free_edge.edge + 1) % free_edge.polygon->points.size()].pos;
+
+ for (int j = 0; j < free_edges.size(); j++) {
+ const gd::Edge::Connection &other_edge = free_edges[j];
+ if (i == j || free_edge.polygon->owner == other_edge.polygon->owner) {
continue;
}
- Vector3 rel_centers = other_edge.edge_center - edge.edge_center;
- if (ecm_squared > rel_centers.length_squared() // Are enough closer?
- && ABS(edge.edge_len_squared - other_edge.edge_len_squared) < LEN_TOLLERANCE // Are the same length?
- && ABS(edge.edge_dir.dot(other_edge.edge_dir)) > DIR_TOLLERANCE // Are aligned?
- && ABS(rel_centers.normalized().dot(edge.edge_dir)) < IFO_TOLLERANCE // Are one in front the other?
- ) {
- // The edges can be connected
- edge.is_free = false;
- other_edge.is_free = false;
-
- edge.poly->edges[edge.edge_id].this_edge = edge.edge_id;
- edge.poly->edges[edge.edge_id].other_edge = other_edge.edge_id;
- edge.poly->edges[edge.edge_id].other_polygon = other_edge.poly;
-
- other_edge.poly->edges[other_edge.edge_id].this_edge = other_edge.edge_id;
- other_edge.poly->edges[other_edge.edge_id].other_edge = edge.edge_id;
- other_edge.poly->edges[other_edge.edge_id].other_polygon = edge.poly;
+ Vector3 other_edge_p1 = other_edge.polygon->points[other_edge.edge].pos;
+ Vector3 other_edge_p2 = other_edge.polygon->points[(other_edge.edge + 1) % other_edge.polygon->points.size()].pos;
+
+ // Compute the projection of the opposite edge on the current one
+ Vector3 edge_vector = edge_p2 - edge_p1;
+ float projected_p1_ratio = edge_vector.dot(other_edge_p1 - edge_p1) / (edge_vector.length_squared());
+ float projected_p2_ratio = edge_vector.dot(other_edge_p2 - edge_p1) / (edge_vector.length_squared());
+ if ((projected_p1_ratio < 0.0 && projected_p2_ratio < 0.0) || (projected_p1_ratio > 1.0 && projected_p2_ratio > 1.0)) {
+ continue;
+ }
+
+ // Check if the two edges are close to each other enough and compute a pathway between the two regions.
+ Vector3 self1 = edge_vector * CLAMP(projected_p1_ratio, 0.0, 1.0) + edge_p1;
+ Vector3 other1;
+ if (projected_p1_ratio >= 0.0 && projected_p1_ratio <= 1.0) {
+ other1 = other_edge_p1;
+ } else {
+ other1 = other_edge_p1.lerp(other_edge_p2, (1.0 - projected_p1_ratio) / (projected_p2_ratio - projected_p1_ratio));
}
+ if ((self1 - other1).length() > edge_connection_margin) {
+ continue;
+ }
+
+ Vector3 self2 = edge_vector * CLAMP(projected_p2_ratio, 0.0, 1.0) + edge_p1;
+ Vector3 other2;
+ if (projected_p2_ratio >= 0.0 && projected_p2_ratio <= 1.0) {
+ other2 = other_edge_p2;
+ } else {
+ other2 = other_edge_p1.lerp(other_edge_p2, (0.0 - projected_p1_ratio) / (projected_p2_ratio - projected_p1_ratio));
+ }
+ if ((self2 - other2).length() > edge_connection_margin) {
+ continue;
+ }
+
+ // The edges can now be connected.
+ gd::Edge::Connection new_connection = other_edge;
+ new_connection.pathway_start = (self1 + other1) / 2.0;
+ new_connection.pathway_end = (self2 + other2) / 2.0;
+ free_edge.polygon->edges[free_edge.edge].connections.push_back(new_connection);
+
+ // Add the connection to the region_connection map.
+ free_edge.polygon->owner->get_connections().push_back(new_connection);
}
}
- }
- if (regenerate_links) {
+ // Update the update ID.
map_update_id = (map_update_id + 1) % 9999999;
}
+ // Update agents tree.
if (agents_dirty) {
std::vector<RVO::Agent *> raw_agents;
raw_agents.reserve(agents.size());
@@ -761,16 +746,15 @@ void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys
cut_plane.d = cut_plane.normal.dot(from);
while (from_poly != p_to_poly) {
- int back_nav_edge = from_poly->back_navigation_edge;
- Vector3 a = from_poly->poly->points[back_nav_edge].pos;
- Vector3 b = from_poly->poly->points[(back_nav_edge + 1) % from_poly->poly->points.size()].pos;
+ Vector3 pathway_start = from_poly->back_navigation_edge_pathway_start;
+ Vector3 pathway_end = from_poly->back_navigation_edge_pathway_end;
- ERR_FAIL_COND(from_poly->prev_navigation_poly_id == -1);
- from_poly = &p_navigation_polys[from_poly->prev_navigation_poly_id];
+ ERR_FAIL_COND(from_poly->back_navigation_poly_id == -1);
+ from_poly = &p_navigation_polys[from_poly->back_navigation_poly_id];
- if (a.distance_to(b) > CMP_EPSILON) {
+ if (pathway_start.distance_to(pathway_end) > CMP_EPSILON) {
Vector3 inters;
- if (cut_plane.intersects_segment(a, b, &inters)) {
+ if (cut_plane.intersects_segment(pathway_start, pathway_end, &inters)) {
if (inters.distance_to(p_to_point) > CMP_EPSILON && inters.distance_to(path[path.size() - 1]) > CMP_EPSILON) {
path.push_back(inters);
}
diff --git a/modules/gdnavigation/nav_map.h b/modules/gdnavigation/nav_map.h
index bffc1fbc1a..8e013a72eb 100644
--- a/modules/gdnavigation/nav_map.h
+++ b/modules/gdnavigation/nav_map.h
@@ -34,6 +34,7 @@
#include "nav_rid.h"
#include "core/math/math_defs.h"
+#include "core/templates/map.h"
#include "nav_utils.h"
#include <KdTree.h>
@@ -102,7 +103,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) const;
+ Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers = 1) 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;
diff --git a/modules/gdnavigation/nav_region.cpp b/modules/gdnavigation/nav_region.cpp
index 383b0f15a6..c1690b2a4b 100644
--- a/modules/gdnavigation/nav_region.cpp
+++ b/modules/gdnavigation/nav_region.cpp
@@ -39,6 +39,17 @@
void NavRegion::set_map(NavMap *p_map) {
map = p_map;
polygons_dirty = true;
+ if (!map) {
+ connections.clear();
+ }
+}
+
+void NavRegion::set_layers(uint32_t p_layers) {
+ layers = p_layers;
+}
+
+uint32_t NavRegion::get_layers() const {
+ return layers;
}
void NavRegion::set_transform(Transform p_transform) {
@@ -51,6 +62,25 @@ void NavRegion::set_mesh(Ref<NavigationMesh> p_mesh) {
polygons_dirty = true;
}
+int NavRegion::get_connections_count() const {
+ if (!map) {
+ return 0;
+ }
+ return connections.size();
+}
+
+Vector3 NavRegion::get_connection_pathway_start(int p_connection_id) const {
+ ERR_FAIL_COND_V(!map, Vector3());
+ ERR_FAIL_INDEX_V(p_connection_id, connections.size(), Vector3());
+ return connections[p_connection_id].pathway_start;
+}
+
+Vector3 NavRegion::get_connection_pathway_end(int p_connection_id) const {
+ ERR_FAIL_COND_V(!map, Vector3());
+ ERR_FAIL_INDEX_V(p_connection_id, connections.size(), Vector3());
+ return connections[p_connection_id].pathway_end;
+}
+
bool NavRegion::sync() {
bool something_changed = polygons_dirty /* || something_dirty? */;
diff --git a/modules/gdnavigation/nav_region.h b/modules/gdnavigation/nav_region.h
index 954780033b..527b2500ac 100644
--- a/modules/gdnavigation/nav_region.h
+++ b/modules/gdnavigation/nav_region.h
@@ -31,10 +31,10 @@
#ifndef NAV_REGION_H
#define NAV_REGION_H
-#include "nav_rid.h"
+#include "scene/resources/navigation_mesh.h"
+#include "nav_rid.h"
#include "nav_utils.h"
-#include "scene/3d/navigation_3d.h"
#include <vector>
/**
@@ -48,6 +48,8 @@ class NavRegion : public NavRid {
NavMap *map = nullptr;
Transform transform;
Ref<NavigationMesh> mesh;
+ uint32_t layers = 1;
+ Vector<gd::Edge::Connection> connections;
bool polygons_dirty = true;
@@ -66,6 +68,9 @@ public:
return map;
}
+ void set_layers(uint32_t p_layers);
+ uint32_t get_layers() const;
+
void set_transform(Transform transform);
const Transform &get_transform() const {
return transform;
@@ -76,6 +81,13 @@ public:
return mesh;
}
+ Vector<gd::Edge::Connection> &get_connections() {
+ return connections;
+ }
+ int get_connections_count() const;
+ Vector3 get_connection_pathway_start(int p_connection_id) const;
+ Vector3 get_connection_pathway_end(int p_connection_id) const;
+
std::vector<gd::Polygon> const &get_polygons() const {
return polygons;
}
diff --git a/modules/gdnavigation/nav_utils.h b/modules/gdnavigation/nav_utils.h
index d1d1687a1f..35da391eea 100644
--- a/modules/gdnavigation/nav_utils.h
+++ b/modules/gdnavigation/nav_utils.h
@@ -51,7 +51,7 @@ union PointKey {
int64_t z : 21;
};
- uint64_t key;
+ uint64_t key = 0;
bool operator<(const PointKey &p_key) const { return key < p_key.key; }
};
@@ -81,13 +81,14 @@ struct Edge {
/// This edge ID
int this_edge = -1;
- /// Other Polygon
- Polygon *other_polygon = nullptr;
-
- /// The other `Polygon` at this edge id has this `Polygon`.
- int other_edge = -1;
-
- Edge() {}
+ /// The gateway in the edge, as, in some case, the whole edge might not be navigable.
+ struct Connection {
+ Polygon *polygon = nullptr;
+ int edge = -1;
+ Vector3 pathway_start;
+ Vector3 pathway_end;
+ };
+ Vector<Connection> connections;
};
struct Polygon {
@@ -106,23 +107,17 @@ struct Polygon {
Vector3 center;
};
-struct Connection {
- Polygon *A = nullptr;
- int A_edge = -1;
- Polygon *B = nullptr;
- int B_edge = -1;
-
- Connection() {}
-};
-
struct NavigationPoly {
uint32_t self_id = 0;
/// This poly.
const Polygon *poly;
- /// The previous navigation poly (id in the `navigation_poly` array).
- int prev_navigation_poly_id = -1;
- /// The edge id in this `Poly` to reach the `prev_navigation_poly_id`.
- uint32_t back_navigation_edge = 0;
+
+ /// Those 4 variables are used to travel the path backwards.
+ int back_navigation_poly_id = -1;
+ uint32_t back_navigation_edge = UINT32_MAX;
+ Vector3 back_navigation_edge_pathway_start;
+ Vector3 back_navigation_edge_pathway_end;
+
/// The entry location of this poly.
Vector3 entry;
/// The distance to the destination.
@@ -140,14 +135,6 @@ struct NavigationPoly {
}
};
-struct FreeEdge {
- bool is_free;
- Polygon *poly;
- uint32_t edge_id;
- Vector3 edge_center;
- Vector3 edge_dir;
- float edge_len_squared;
-};
} // namespace gd
#endif // NAV_UTILS_H
diff --git a/modules/gdnavigation/rvo_agent.h b/modules/gdnavigation/rvo_agent.h
index d9e3345498..369cb1f9a3 100644
--- a/modules/gdnavigation/rvo_agent.h
+++ b/modules/gdnavigation/rvo_agent.h
@@ -53,7 +53,7 @@ class RvoAgent : public NavRid {
NavMap *map = nullptr;
RVO::Agent agent;
AvoidanceComputedCallback callback;
- uint32_t map_update_id;
+ uint32_t map_update_id = 0;
public:
RvoAgent();
diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp b/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp
index 6e930b6bf4..9d0d91162c 100644
--- a/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp
+++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp
@@ -44,7 +44,7 @@ Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Ve
// Search strings in AssignmentNode -> text = "__", hint_tooltip = "__" etc.
Error err;
- RES loaded_res = ResourceLoader::load(p_path, "", false, &err);
+ RES loaded_res = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err);
if (err) {
ERR_PRINT("Failed to load " + p_path);
return err;
diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.h b/modules/gdscript/editor/gdscript_translation_parser_plugin.h
index 5358a77140..fcf438422a 100644
--- a/modules/gdscript/editor/gdscript_translation_parser_plugin.h
+++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.h
@@ -39,8 +39,8 @@
class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlugin {
GDCLASS(GDScriptEditorTranslationParserPlugin, EditorTranslationParserPlugin);
- Vector<String> *ids;
- Vector<Vector<String>> *ids_ctx_plural;
+ Vector<String> *ids = nullptr;
+ Vector<Vector<String>> *ids_ctx_plural = nullptr;
// List of patterns used for extracting translation strings.
StringName tr_func = "tr";
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 502e294275..a129b73c1a 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -219,7 +219,7 @@ StringName GDScript::get_instance_base_type() const {
}
struct _GDScriptMemberSort {
- int index;
+ int index = 0;
StringName name;
_FORCE_INLINE_ bool operator<(const _GDScriptMemberSort &p_member) const { return index < p_member.index; }
};
@@ -1162,17 +1162,6 @@ String GDScript::_get_gdscript_reference_class_name(const GDScript *p_gdscript)
GDScript::GDScript() :
script_list(this) {
- valid = false;
- subclass_count = 0;
- initializer = nullptr;
- _base = nullptr;
- _owner = nullptr;
- tool = false;
-#ifdef TOOLS_ENABLED
- source_changed_cache = false;
- placeholder_fallback_enabled = false;
-#endif
-
#ifdef DEBUG_ENABLED
{
MutexLock lock(GDScriptLanguage::get_singleton()->lock);
@@ -2327,7 +2316,7 @@ Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_na
/*************** RESOURCE ***************/
-RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES 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) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
}
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 37f01b2571..12c909fd4f 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -57,11 +57,11 @@ public:
class GDScript : public Script {
GDCLASS(GDScript, Script);
- bool tool;
- bool valid;
+ bool tool = false;
+ bool valid = false;
struct MemberInfo {
- int index;
+ int index = 0;
StringName setter;
StringName getter;
MultiplayerAPI::RPCMode rpc_mode;
@@ -77,8 +77,8 @@ class GDScript : public Script {
Ref<GDScriptNativeClass> native;
Ref<GDScript> base;
- GDScript *_base; //fast pointer access
- GDScript *_owner; //for subclasses
+ GDScript *_base = nullptr; //fast pointer access
+ GDScript *_owner = nullptr; //for subclasses
Set<StringName> members; //members are just indices to the instanced script.
Map<StringName, Variant> constants;
@@ -97,8 +97,8 @@ class GDScript : public Script {
Map<StringName, Variant> member_default_values_cache;
Ref<GDScript> base_cache;
Set<ObjectID> inheriters_cache;
- bool source_changed_cache;
- bool placeholder_fallback_enabled;
+ bool source_changed_cache = false;
+ bool placeholder_fallback_enabled = false;
void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames);
DocData::ClassDoc doc;
@@ -121,7 +121,7 @@ class GDScript : public Script {
GDScriptFunction *implicit_initializer = nullptr;
GDScriptFunction *initializer = nullptr; //direct pointer to new , faster to locate
- int subclass_count;
+ int subclass_count = 0;
Set<Object *> instances;
//exported members
String source;
@@ -529,7 +529,7 @@ public:
class ResourceFormatLoaderGDScript : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index b491440d4c..63ca34fc24 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -255,36 +255,59 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
}
// Try class constants.
- GDScript *owner = codegen.script;
- while (owner) {
- GDScript *scr = owner;
- GDScriptNativeClass *nc = nullptr;
- while (scr) {
- if (scr->constants.has(identifier)) {
- return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::CLASS_CONSTANT, gen->add_or_get_name(identifier)); // TODO: Get type here.
+ {
+ GDScript *owner = codegen.script;
+ while (owner) {
+ GDScript *scr = owner;
+ GDScriptNativeClass *nc = nullptr;
+ while (scr) {
+ if (scr->constants.has(identifier)) {
+ return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::CLASS_CONSTANT, gen->add_or_get_name(identifier)); // TODO: Get type here.
+ }
+ if (scr->native.is_valid()) {
+ nc = scr->native.ptr();
+ }
+ scr = scr->_base;
}
- if (scr->native.is_valid()) {
- nc = scr->native.ptr();
+
+ // Class C++ integer constant.
+ if (nc) {
+ bool success = false;
+ int constant = ClassDB::get_integer_constant(nc->get_name(), identifier, &success);
+ if (success) {
+ return codegen.add_constant(constant);
+ }
}
- scr = scr->_base;
+
+ owner = owner->_owner;
}
+ }
- // Class C++ integer constant.
- if (nc) {
- bool success = false;
- int constant = ClassDB::get_integer_constant(nc->get_name(), identifier, &success);
- if (success) {
- return codegen.add_constant(constant);
+ // Try signals and methods (can be made callables).
+ {
+ if (codegen.class_node->members_indices.has(identifier)) {
+ const GDScriptParser::ClassNode::Member &member = codegen.class_node->members[codegen.class_node->members_indices[identifier]];
+ if (member.type == GDScriptParser::ClassNode::Member::FUNCTION || member.type == GDScriptParser::ClassNode::Member::SIGNAL) {
+ // Get like it was a property.
+ GDScriptCodeGenerator::Address temp = codegen.add_temporary(); // TODO: Get type here.
+ GDScriptCodeGenerator::Address self(GDScriptCodeGenerator::Address::SELF);
+
+ gen->write_get_named(temp, identifier, self);
+ return temp;
}
}
- owner = owner->_owner;
- }
+ // Try in native base.
+ GDScript *scr = codegen.script;
+ GDScriptNativeClass *nc = nullptr;
+ while (scr) {
+ if (scr->native.is_valid()) {
+ nc = scr->native.ptr();
+ }
+ scr = scr->_base;
+ }
- // Try signals and methods (can be made callables);
- if (codegen.class_node->members_indices.has(identifier)) {
- const GDScriptParser::ClassNode::Member &member = codegen.class_node->members[codegen.class_node->members_indices[identifier]];
- if (member.type == GDScriptParser::ClassNode::Member::FUNCTION || member.type == GDScriptParser::ClassNode::Member::SIGNAL) {
+ if (nc && (ClassDB::has_signal(nc->get_name(), identifier) || ClassDB::has_method(nc->get_name(), identifier))) {
// Get like it was a property.
GDScriptCodeGenerator::Address temp = codegen.add_temporary(); // TODO: Get type here.
GDScriptCodeGenerator::Address self(GDScriptCodeGenerator::Address::SELF);
@@ -1153,7 +1176,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
codegen.generator->write_and_left_operand(result_addr);
// Check value equality.
- codegen.generator->write_binary_operator(result_addr, Variant::OP_EQUAL, p_value_addr, expr_addr);
+ codegen.generator->write_binary_operator(equality_test_addr, Variant::OP_EQUAL, p_value_addr, expr_addr);
codegen.generator->write_and_right_operand(equality_test_addr);
// AND both type and value equality.
@@ -1488,17 +1511,17 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
codegen.start_block();
// Evaluate the match expression.
- GDScriptCodeGenerator::Address value_local = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype()));
- GDScriptCodeGenerator::Address value = _parse_expression(codegen, error, match->test);
+ GDScriptCodeGenerator::Address value = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype()));
+ GDScriptCodeGenerator::Address value_expr = _parse_expression(codegen, error, match->test);
if (error) {
return error;
}
// Assign to local.
// TODO: This can be improved by passing the target to parse_expression().
- gen->write_assign(value_local, value);
+ gen->write_assign(value, value_expr);
- if (value.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
+ if (value_expr.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
codegen.generator->pop_temporary();
}
@@ -2396,7 +2419,7 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa
p_script->initializer->call(instance, nullptr, 0, ce);
if (ce.error != Callable::CallError::CALL_OK) {
- //well, tough luck, not goinna do anything here
+ //well, tough luck, not gonna do anything here
}
}
#endif
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h
index 00953ad752..651391f972 100644
--- a/modules/gdscript/gdscript_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -133,8 +133,8 @@ class GDScriptCompiler {
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);
- int err_line;
- int err_column;
+ int err_line = 0;
+ int err_column = 0;
StringName source;
String error;
bool within_await = false;
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index b17971cf93..a9975c8602 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -2261,10 +2261,9 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
}
r_arghint = _make_arguments_hint(info, p_argidx);
- return;
}
- if (ClassDB::is_parent_class(class_name, "Node") && (p_method == "get_node" || p_method == "has_node") && p_argidx == 0) {
+ if (p_argidx == 0 && ClassDB::is_parent_class(class_name, "Node") && (p_method == "get_node" || p_method == "has_node")) {
// Get autoloads
List<PropertyInfo> props;
ProjectSettings::get_singleton()->get_property_list(&props);
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 2171426e6f..7b37aa40a2 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -77,14 +77,14 @@ int GDScriptFunction::get_max_stack_size() const {
}
struct _GDFKC {
- int order;
+ int order = 0;
List<int> pos;
};
struct _GDFKCS {
- int order;
+ int order = 0;
StringName id;
- int pos;
+ int pos = 0;
bool operator<(const _GDFKCS &p_r) const {
return order < p_r.order;
@@ -244,7 +244,7 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
bool completed = true;
// If the return value is a GDScriptFunctionState reference,
- // then the function did awaited again after resuming.
+ // then the function did await again after resuming.
if (ret.is_ref()) {
GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret);
if (gdfs && gdfs->function == function) {
@@ -294,7 +294,6 @@ void GDScriptFunctionState::_bind_methods() {
GDScriptFunctionState::GDScriptFunctionState() :
scripts_list(this),
instances_list(this) {
- function = nullptr;
}
GDScriptFunctionState::~GDScriptFunctionState() {
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index 6c791836b9..e64630a743 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -420,19 +420,19 @@ private:
public:
struct CallState {
- GDScript *script;
- GDScriptInstance *instance;
+ GDScript *script = nullptr;
+ GDScriptInstance *instance = nullptr;
#ifdef DEBUG_ENABLED
StringName function_name;
String script_path;
#endif
Vector<uint8_t> stack;
- int stack_size;
+ int stack_size = 0;
Variant self;
- uint32_t alloca_size;
- int ip;
- int line;
- int defarg;
+ uint32_t alloca_size = 0;
+ int ip = 0;
+ int line = 0;
+ int defarg = 0;
Variant result;
};
@@ -488,7 +488,7 @@ public:
class GDScriptFunctionState : public Reference {
GDCLASS(GDScriptFunctionState, Reference);
friend class GDScriptFunction;
- GDScriptFunction *function;
+ GDScriptFunction *function = nullptr;
GDScriptFunction::CallState state;
Variant _signal_callback(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
Ref<GDScriptFunctionState> first_state;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index a77fb14064..7f3dd6b2e5 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -130,8 +130,10 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@export_flags", { Variant::STRING, "names" }), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FLAGS, Variant::INT>, 0, true);
register_annotation(MethodInfo("@export_flags_2d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_RENDER, Variant::INT>);
register_annotation(MethodInfo("@export_flags_2d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_PHYSICS, Variant::INT>);
+ register_annotation(MethodInfo("@export_flags_2d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_NAVIGATION, Variant::INT>);
register_annotation(MethodInfo("@export_flags_3d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_RENDER, Variant::INT>);
register_annotation(MethodInfo("@export_flags_3d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_PHYSICS, Variant::INT>);
+ register_annotation(MethodInfo("@export_flags_3d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_NAVIGATION, Variant::INT>);
// Networking.
register_annotation(MethodInfo("@remote"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_REMOTE>);
register_annotation(MethodInfo("@master"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_MASTER>);
@@ -2080,6 +2082,17 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_unary_operator(ExpressionN
return operation;
}
+GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_not_in_operator(ExpressionNode *p_previous_operand, bool p_can_assign) {
+ // check that NOT is followed by IN by consuming it before calling parse_binary_operator which will only receive a plain IN
+ consume(GDScriptTokenizer::Token::IN, R"(Expected "in" after "not" in content-test operator.)");
+ ExpressionNode *in_operation = parse_binary_operator(p_previous_operand, p_can_assign);
+ UnaryOpNode *operation = alloc_node<UnaryOpNode>();
+ operation->operation = UnaryOpNode::OP_LOGIC_NOT;
+ operation->variant_op = Variant::OP_NOT;
+ operation->operand = in_operation;
+ return operation;
+}
+
GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(ExpressionNode *p_previous_operand, bool p_can_assign) {
GDScriptTokenizer::Token op = previous;
BinaryOpNode *operation = alloc_node<BinaryOpNode>();
@@ -2906,7 +2919,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty
// Logical
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_LOGIC_AND }, // AND,
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_LOGIC_OR }, // OR,
- { &GDScriptParser::parse_unary_operator, nullptr, PREC_NONE }, // NOT,
+ { &GDScriptParser::parse_unary_operator, &GDScriptParser::parse_binary_not_in_operator, PREC_CONTENT_TEST }, // NOT,
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_LOGIC_AND }, // AMPERSAND_AMPERSAND,
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_LOGIC_OR }, // PIPE_PIPE,
{ &GDScriptParser::parse_unary_operator, nullptr, PREC_NONE }, // BANG,
@@ -3005,7 +3018,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty
// Avoid desync.
static_assert(sizeof(rules) / sizeof(rules[0]) == GDScriptTokenizer::Token::TK_MAX, "Amount of parse rules don't match the amount of token types.");
- // Let's assume this this never invalid, since nothing generates a TK_MAX.
+ // Let's assume this is never invalid, since nothing generates a TK_MAX.
return &rules[p_token_type];
}
@@ -3157,11 +3170,16 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
push_error(R"(Cannot use "@export" annotation with variable without type or initializer, since type can't be inferred.)", p_annotation);
return false;
}
- if (variable->initializer->type != Node::LITERAL) {
+ if (variable->initializer->type == Node::LITERAL) {
+ variable->export_info.type = static_cast<LiteralNode *>(variable->initializer)->value.get_type();
+ } else if (variable->initializer->type == Node::ARRAY) {
+ variable->export_info.type = Variant::ARRAY;
+ } else if (variable->initializer->type == Node::DICTIONARY) {
+ variable->export_info.type = Variant::DICTIONARY;
+ } else {
push_error(R"(To use "@export" annotation with type-less variable, the default value must be a literal.)", p_annotation);
return false;
}
- variable->export_info.type = static_cast<LiteralNode *>(variable->initializer)->value.get_type();
} // else: Actual type will be set by the analyzer, which can infer the proper type.
}
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index f43708b81f..a4b1d4c866 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -351,7 +351,7 @@ public:
OP_COMP_GREATER_EQUAL,
};
- OpType operation;
+ OpType operation = OpType::OP_ADDITION;
Variant::Operator variant_op = Variant::OP_MAX;
ExpressionNode *left_operand = nullptr;
ExpressionNode *right_operand = nullptr;
@@ -753,7 +753,7 @@ public:
struct MatchBranchNode : public Node {
Vector<PatternNode *> patterns;
- SuiteNode *block;
+ SuiteNode *block = nullptr;
bool has_wildcard = false;
MatchBranchNode() {
@@ -1001,7 +1001,7 @@ public:
OP_LOGIC_NOT,
};
- OpType operation;
+ OpType operation = OP_POSITIVE;
Variant::Operator variant_op = Variant::OP_MAX;
ExpressionNode *operand = nullptr;
@@ -1285,6 +1285,7 @@ private:
ExpressionNode *parse_builtin_constant(ExpressionNode *p_previous_operand, bool p_can_assign);
ExpressionNode *parse_unary_operator(ExpressionNode *p_previous_operand, bool p_can_assign);
ExpressionNode *parse_binary_operator(ExpressionNode *p_previous_operand, bool p_can_assign);
+ ExpressionNode *parse_binary_not_in_operator(ExpressionNode *p_previous_operand, bool p_can_assign);
ExpressionNode *parse_ternary_operator(ExpressionNode *p_previous_operand, bool p_can_assign);
ExpressionNode *parse_assignment(ExpressionNode *p_previous_operand, bool p_can_assign);
ExpressionNode *parse_array(ExpressionNode *p_previous_operand, bool p_can_assign);
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 315b8ee3b4..e432dfc891 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -898,6 +898,9 @@ GDScriptTokenizer::Token GDScriptTokenizer::string() {
_advance();
_advance();
break;
+ } else {
+ // Not a multiline string termination, add consumed quote.
+ result += quote_char;
}
} else {
// Ended single-line string.
@@ -1169,7 +1172,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::scan() {
if (pending_newline) {
pending_newline = false;
if (!multiline_mode) {
- // Don't return newline tokens on multine mode.
+ // Don't return newline tokens on multiline mode.
return last_newline;
}
}
diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index cdb0072294..bea4b14019 100644
--- a/modules/gdscript/gdscript_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -178,7 +178,6 @@ public:
}
Token() {
- type = EMPTY;
}
};
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 4e098d7a6d..2216fcab2d 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -649,7 +649,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (scr_B) {
//if B is a script, the only valid condition is that A has an instance which inherits from the script
- //in other situation, this shoul return false.
+ //in other situation, this should return false.
if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) {
GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr());
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp
index 5e3d6213d3..912c9a174e 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.cpp
+++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp
@@ -163,7 +163,7 @@ void GDScriptLanguageProtocol::_bind_methods() {
ClassDB::bind_method(D_METHOD("initialized", "params"), &GDScriptLanguageProtocol::initialized);
ClassDB::bind_method(D_METHOD("on_client_connected"), &GDScriptLanguageProtocol::on_client_connected);
ClassDB::bind_method(D_METHOD("on_client_disconnected"), &GDScriptLanguageProtocol::on_client_disconnected);
- ClassDB::bind_method(D_METHOD("notify_client", "method", "params"), &GDScriptLanguageProtocol::notify_client, DEFVAL(Variant()), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("notify_client", "method", "params", "client_id"), &GDScriptLanguageProtocol::notify_client, DEFVAL(Variant()), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("is_smart_resolve_enabled"), &GDScriptLanguageProtocol::is_smart_resolve_enabled);
ClassDB::bind_method(D_METHOD("get_text_document"), &GDScriptLanguageProtocol::get_text_document);
ClassDB::bind_method(D_METHOD("get_workspace"), &GDScriptLanguageProtocol::get_workspace);
diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp
index 12ed56a568..98ada9de4d 100644
--- a/modules/gdscript/language_server/gdscript_language_server.cpp
+++ b/modules/gdscript/language_server/gdscript_language_server.cpp
@@ -36,11 +36,6 @@
#include "editor/editor_node.h"
GDScriptLanguageServer::GDScriptLanguageServer() {
- thread_running = false;
- started = false;
-
- use_thread = false;
- port = 6008;
_EDITOR_DEF("network/language_server/remote_port", port);
_EDITOR_DEF("network/language_server/enable_smart_resolve", true);
_EDITOR_DEF("network/language_server/show_native_symbols_in_editor", false);
diff --git a/modules/gdscript/language_server/gdscript_language_server.h b/modules/gdscript/language_server/gdscript_language_server.h
index 7b7837a463..29c5ddd70e 100644
--- a/modules/gdscript/language_server/gdscript_language_server.h
+++ b/modules/gdscript/language_server/gdscript_language_server.h
@@ -41,10 +41,10 @@ class GDScriptLanguageServer : public EditorPlugin {
GDScriptLanguageProtocol protocol;
Thread thread;
- bool thread_running;
- bool started;
- bool use_thread;
- int port;
+ bool thread_running = false;
+ bool started = false;
+ bool use_thread = false;
+ int port = 6008;
static void thread_main(void *p_userdata);
private:
diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp
index 6a913edbbf..6635098be2 100644
--- a/modules/gdscript/language_server/lsp.hpp
+++ b/modules/gdscript/language_server/lsp.hpp
@@ -547,7 +547,7 @@ struct TextDocumentItem {
* The version number of this document (it will increase after each
* change, including undo/redo).
*/
- int version;
+ int version = 0;
/**
* The content of the opened text document.
@@ -584,7 +584,7 @@ struct TextDocumentContentChangeEvent {
/**
* The length of the range that got replaced.
*/
- int rangeLength;
+ int rangeLength = 0;
/**
* The new text of the range/document.
@@ -656,12 +656,12 @@ struct Diagnostic {
* The diagnostic's severity. Can be omitted. If omitted it is up to the
* client to interpret diagnostics as error, warning, info or hint.
*/
- int severity;
+ int severity = 0;
/**
* The diagnostic's code, which might appear in the user interface.
*/
- int code;
+ int code = 0;
/**
* A human-readable string describing the source of this
@@ -833,7 +833,7 @@ struct CompletionItem {
* an icon is chosen by the editor. The standardized set
* of available values is defined in `CompletionItemKind`.
*/
- int kind;
+ int kind = 0;
/**
* A human-readable string with additional information
@@ -891,7 +891,7 @@ struct CompletionItem {
* The format of the insert text. The format applies to both the `insertText` property
* and the `newText` property of a provided `textEdit`.
*/
- int insertTextFormat;
+ int insertTextFormat = 0;
/**
* An edit which is applied to a document when selecting this completion. When an edit is provided the value of
@@ -1003,7 +1003,7 @@ struct CompletionList {
* This list it not complete. Further typing should result in recomputing
* this list.
*/
- bool isIncomplete;
+ bool isIncomplete = false;
/**
* The completion items.
@@ -1661,7 +1661,7 @@ struct ServerCapabilities {
signatureHelpProvider.triggerCharacters.push_back(",");
signatureHelpProvider.triggerCharacters.push_back("(");
dict["signatureHelpProvider"] = signatureHelpProvider.to_json();
- dict["codeLensProvider"] = false; // codeLensProvider.to_json();
+ //dict["codeLensProvider"] = codeLensProvider.to_json();
dict["documentOnTypeFormattingProvider"] = documentOnTypeFormattingProvider.to_json();
dict["renameProvider"] = renameProvider.to_json();
dict["documentLinkProvider"] = documentLinkProvider.to_json();
diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp
index e90475a60e..93b709a613 100644
--- a/modules/gdscript/register_types.cpp
+++ b/modules/gdscript/register_types.cpp
@@ -85,7 +85,7 @@ public:
return;
}
- // TODO: Readd compiled GDScript on export.
+ // TODO: Re-add compiled GDScript on export.
return;
}
};
diff --git a/modules/gdscript/tests/test_gdscript.cpp b/modules/gdscript/tests/test_gdscript.cpp
index 898ac653f5..3cc0eee672 100644
--- a/modules/gdscript/tests/test_gdscript.cpp
+++ b/modules/gdscript/tests/test_gdscript.cpp
@@ -118,10 +118,10 @@ static void test_parser(const String &p_code, const String &p_script_path, const
print_line(vformat("%02d:%02d: %s", error.line, error.column, error.message));
}
}
-
+#ifdef TOOLS_ENABLED
GDScriptParser::TreePrinter printer;
-
printer.print_tree(parser);
+#endif
}
static void test_compiler(const String &p_code, const String &p_script_path, const Vector<String> &p_lines) {
@@ -175,8 +175,9 @@ static void test_compiler(const String &p_code, const String &p_script_path, con
signature += func->get_argument_name(i);
}
print_line(signature + ")");
-
+#ifdef TOOLS_ENABLED
func->disassemble(p_lines);
+#endif
print_line("");
print_line("");
}
diff --git a/modules/gltf/config.py b/modules/gltf/config.py
index 1505a456d7..a4ee871eff 100644
--- a/modules/gltf/config.py
+++ b/modules/gltf/config.py
@@ -4,3 +4,27 @@ def can_build(env, platform):
def configure(env):
pass
+
+
+def get_doc_classes():
+ return [
+ "EditorSceneImporterGLTF",
+ "GLTFAccessor",
+ "GLTFAnimation",
+ "GLTFBufferView",
+ "GLTFCamera",
+ "GLTFDocument",
+ "GLTFLight",
+ "GLTFMesh",
+ "GLTFNode",
+ "GLTFSkeleton",
+ "GLTFSkin",
+ "GLTFSpecGloss",
+ "GLTFState",
+ "GLTFTexture",
+ "PackedSceneGLTF",
+ ]
+
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/doc/classes/EditorSceneImporterGLTF.xml b/modules/gltf/doc_classes/EditorSceneImporterGLTF.xml
index e717b30f73..e717b30f73 100644
--- a/doc/classes/EditorSceneImporterGLTF.xml
+++ b/modules/gltf/doc_classes/EditorSceneImporterGLTF.xml
diff --git a/doc/classes/GLTFAccessor.xml b/modules/gltf/doc_classes/GLTFAccessor.xml
index a1f596f7dd..a1f596f7dd 100644
--- a/doc/classes/GLTFAccessor.xml
+++ b/modules/gltf/doc_classes/GLTFAccessor.xml
diff --git a/doc/classes/GLTFAnimation.xml b/modules/gltf/doc_classes/GLTFAnimation.xml
index 5c1fa02f11..5c1fa02f11 100644
--- a/doc/classes/GLTFAnimation.xml
+++ b/modules/gltf/doc_classes/GLTFAnimation.xml
diff --git a/doc/classes/GLTFBufferView.xml b/modules/gltf/doc_classes/GLTFBufferView.xml
index edaad85e0a..edaad85e0a 100644
--- a/doc/classes/GLTFBufferView.xml
+++ b/modules/gltf/doc_classes/GLTFBufferView.xml
diff --git a/doc/classes/GLTFCamera.xml b/modules/gltf/doc_classes/GLTFCamera.xml
index 0b95f2c802..0b95f2c802 100644
--- a/doc/classes/GLTFCamera.xml
+++ b/modules/gltf/doc_classes/GLTFCamera.xml
diff --git a/doc/classes/GLTFDocument.xml b/modules/gltf/doc_classes/GLTFDocument.xml
index 04c40dd752..04c40dd752 100644
--- a/doc/classes/GLTFDocument.xml
+++ b/modules/gltf/doc_classes/GLTFDocument.xml
diff --git a/doc/classes/GLTFLight.xml b/modules/gltf/doc_classes/GLTFLight.xml
index bfeaf9a86e..bfeaf9a86e 100644
--- a/doc/classes/GLTFLight.xml
+++ b/modules/gltf/doc_classes/GLTFLight.xml
diff --git a/doc/classes/GLTFMesh.xml b/modules/gltf/doc_classes/GLTFMesh.xml
index 55f79d2c55..55f79d2c55 100644
--- a/doc/classes/GLTFMesh.xml
+++ b/modules/gltf/doc_classes/GLTFMesh.xml
diff --git a/doc/classes/GLTFNode.xml b/modules/gltf/doc_classes/GLTFNode.xml
index 5b7d4fadec..5b7d4fadec 100644
--- a/doc/classes/GLTFNode.xml
+++ b/modules/gltf/doc_classes/GLTFNode.xml
diff --git a/doc/classes/GLTFSkeleton.xml b/modules/gltf/doc_classes/GLTFSkeleton.xml
index e27c838648..9680c27705 100644
--- a/doc/classes/GLTFSkeleton.xml
+++ b/modules/gltf/doc_classes/GLTFSkeleton.xml
@@ -10,7 +10,7 @@
<method name="get_bone_attachment">
<return type="BoneAttachment3D">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="idx" type="int">
</argument>
<description>
</description>
diff --git a/doc/classes/GLTFSkin.xml b/modules/gltf/doc_classes/GLTFSkin.xml
index 5a80c7097a..5a80c7097a 100644
--- a/doc/classes/GLTFSkin.xml
+++ b/modules/gltf/doc_classes/GLTFSkin.xml
diff --git a/doc/classes/GLTFSpecGloss.xml b/modules/gltf/doc_classes/GLTFSpecGloss.xml
index 68cc7c845d..68cc7c845d 100644
--- a/doc/classes/GLTFSpecGloss.xml
+++ b/modules/gltf/doc_classes/GLTFSpecGloss.xml
diff --git a/doc/classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml
index f7763efdb1..8255cd73d0 100644
--- a/doc/classes/GLTFState.xml
+++ b/modules/gltf/doc_classes/GLTFState.xml
@@ -16,7 +16,7 @@
<method name="get_animation_player">
<return type="AnimationPlayer">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="idx" type="int">
</argument>
<description>
</description>
@@ -24,7 +24,7 @@
<method name="get_animation_players_count">
<return type="int">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="idx" type="int">
</argument>
<description>
</description>
@@ -80,7 +80,7 @@
<method name="get_scene_node">
<return type="Node">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="idx" type="int">
</argument>
<description>
</description>
@@ -109,6 +109,12 @@
<description>
</description>
</method>
+ <method name="get_unique_animation_names">
+ <return type="Array">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_unique_names">
<return type="Array">
</return>
@@ -219,6 +225,14 @@
<description>
</description>
</method>
+ <method name="set_unique_animation_names">
+ <return type="void">
+ </return>
+ <argument index="0" name="unique_animation_names" type="Array">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_unique_names">
<return type="void">
</return>
diff --git a/doc/classes/GLTFTexture.xml b/modules/gltf/doc_classes/GLTFTexture.xml
index c7f94ab0da..ece5cf3fe3 100644
--- a/doc/classes/GLTFTexture.xml
+++ b/modules/gltf/doc_classes/GLTFTexture.xml
@@ -9,7 +9,7 @@
<methods>
</methods>
<members>
- <member name="src_image" type="int" setter="set_src_image" getter="get_src_image" default="4">
+ <member name="src_image" type="int" setter="set_src_image" getter="get_src_image" default="212600976">
</member>
</members>
<constants>
diff --git a/doc/classes/PackedSceneGLTF.xml b/modules/gltf/doc_classes/PackedSceneGLTF.xml
index a04c6ef0b6..a04c6ef0b6 100644
--- a/doc/classes/PackedSceneGLTF.xml
+++ b/modules/gltf/doc_classes/PackedSceneGLTF.xml
diff --git a/modules/gltf/editor_scene_importer_gltf.cpp b/modules/gltf/editor_scene_importer_gltf.cpp
index 6ea722a216..35f44ca122 100644
--- a/modules/gltf/editor_scene_importer_gltf.cpp
+++ b/modules/gltf/editor_scene_importer_gltf.cpp
@@ -99,7 +99,9 @@ Node *PackedSceneGLTF::import_scene(const String &p_path, uint32_t p_flags,
Ref<GLTFDocument> gltf_document;
gltf_document.instance();
Error err = gltf_document->parse(r_state, p_path);
- *r_err = err;
+ if (r_err) {
+ *r_err = err;
+ }
ERR_FAIL_COND_V(err != Error::OK, nullptr);
Node3D *root = memnew(Node3D);
diff --git a/modules/gltf/gltf_camera.h b/modules/gltf/gltf_camera.h
index e5c2041793..bf94b80bef 100644
--- a/modules/gltf/gltf_camera.h
+++ b/modules/gltf/gltf_camera.h
@@ -38,8 +38,8 @@ class GLTFCamera : public Resource {
private:
bool perspective = true;
- float fov_size = 75;
- float zfar = 4000;
+ float fov_size = 75.0;
+ float zfar = 4000.0;
float znear = 0.05;
protected:
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index cce0740121..7ea0aa8ba2 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -63,7 +63,6 @@
#ifdef MODULE_GRIDMAP_ENABLED
#include "modules/gridmap/grid_map.h"
#endif // MODULE_GRIDMAP_ENABLED
-#include "modules/regex/regex.h"
#include "scene/2d/node_2d.h"
#include "scene/3d/bone_attachment_3d.h"
#include "scene/3d/camera_3d.h"
@@ -72,6 +71,7 @@
#include "scene/3d/node_3d.h"
#include "scene/3d/skeleton_3d.h"
#include "scene/animation/animation_player.h"
+#include "scene/main/node.h"
#include "scene/resources/surface_tool.h"
#include <limits>
@@ -449,14 +449,8 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) {
return OK;
}
-String GLTFDocument::_sanitize_scene_name(const String &name) {
- RegEx regex("([^a-zA-Z0-9_ -]+)");
- String p_name = regex.sub(name, "", true);
- return p_name;
-}
-
String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name) {
- const String s_name = _sanitize_scene_name(p_name);
+ const String s_name = p_name.validate_node_name();
String name;
int index = 1;
@@ -464,7 +458,7 @@ String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name
name = s_name;
if (index > 1) {
- name += " " + itos(index);
+ name += itos(index);
}
if (!state->unique_names.has(name)) {
break;
@@ -477,25 +471,44 @@ String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name
return name;
}
-String GLTFDocument::_sanitize_bone_name(const String &name) {
- String p_name = name.camelcase_to_underscore(true);
+String GLTFDocument::_sanitize_animation_name(const String &p_name) {
+ // Animations disallow the normal node invalid characters as well as "," and "["
+ // (See animation/animation_player.cpp::add_animation)
+
+ // TODO: Consider adding invalid_characters or a validate_animation_name to animation_player to mirror Node.
+ String name = p_name.validate_node_name();
+ name = name.replace(",", "");
+ name = name.replace("[", "");
+ return name;
+}
- RegEx pattern_nocolon(":");
- p_name = pattern_nocolon.sub(p_name, "_", true);
+String GLTFDocument::_gen_unique_animation_name(Ref<GLTFState> state, const String &p_name) {
+ const String s_name = _sanitize_animation_name(p_name);
- RegEx pattern_noslash("/");
- p_name = pattern_noslash.sub(p_name, "_", true);
+ String name;
+ int index = 1;
+ while (true) {
+ name = s_name;
- RegEx pattern_nospace(" +");
- p_name = pattern_nospace.sub(p_name, "_", true);
+ if (index > 1) {
+ name += itos(index);
+ }
+ if (!state->unique_animation_names.has(name)) {
+ break;
+ }
+ index++;
+ }
- RegEx pattern_multiple("_+");
- p_name = pattern_multiple.sub(p_name, "_", true);
+ state->unique_animation_names.insert(name);
- RegEx pattern_padded("0+(\\d+)");
- p_name = pattern_padded.sub(p_name, "$1", true);
+ return name;
+}
- return p_name;
+String GLTFDocument::_sanitize_bone_name(const String &p_name) {
+ String name = p_name;
+ name = name.replace(":", "_");
+ name = name.replace("/", "_");
+ return name;
}
String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> state, const GLTFSkeletonIndex skel_i, const String &p_name) {
@@ -2391,7 +2404,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
e["targetNames"] = target_names;
for (int j = 0; j < target_names.size(); j++) {
- real_t weight = 0;
+ real_t weight = 0.0;
if (j < state->meshes.write[gltf_mesh_i]->get_blend_weights().size()) {
weight = state->meshes.write[gltf_mesh_i]->get_blend_weights()[j];
}
@@ -4729,7 +4742,7 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) {
if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
animation->set_loop(true);
}
- animation->set_name(_sanitize_scene_name(name));
+ animation->set_name(_gen_unique_animation_name(state, name));
}
for (int j = 0; j < channels.size(); j++) {
@@ -5569,7 +5582,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
animation->set_loop(true);
}
- float length = 0;
+ float length = 0.0;
for (Map<int, GLTFAnimation::Track>::Element *track_i = anim->get_tracks().front(); track_i; track_i = track_i->next()) {
const GLTFAnimation::Track &track = track_i->get();
@@ -5620,8 +5633,8 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
animation->track_set_path(track_idx, node_path);
//first determine animation length
- const float increment = 1.0 / float(bake_fps);
- float time = 0.0;
+ const double increment = 1.0 / bake_fps;
+ double time = 0.0;
Vector3 base_pos;
Quat base_rot;
@@ -5711,8 +5724,8 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
} else {
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
- const float increment = 1.0 / float(bake_fps);
- float time = 0.0;
+ const double increment = 1.0 / bake_fps;
+ double time = 0.0;
bool last = false;
while (true) {
_interpolate_track<float>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp);
diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h
index ddf307e6a7..bda1ce87d6 100644
--- a/modules/gltf/gltf_document.h
+++ b/modules/gltf/gltf_document.h
@@ -162,8 +162,9 @@ private:
Error _parse_nodes(Ref<GLTFState> state);
String _get_type_name(const GLTFType p_component);
String _get_accessor_type_name(const GLTFDocument::GLTFType p_type);
- String _sanitize_scene_name(const String &name);
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,
diff --git a/modules/gltf/gltf_skeleton.cpp b/modules/gltf/gltf_skeleton.cpp
index 739779d3bd..d6c7a25eaf 100644
--- a/modules/gltf/gltf_skeleton.cpp
+++ b/modules/gltf/gltf_skeleton.cpp
@@ -41,7 +41,7 @@ void GLTFSkeleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_godot_bone_node"), &GLTFSkeleton::get_godot_bone_node);
ClassDB::bind_method(D_METHOD("set_godot_bone_node", "godot_bone_node"), &GLTFSkeleton::set_godot_bone_node);
ClassDB::bind_method(D_METHOD("get_bone_attachment_count"), &GLTFSkeleton::get_bone_attachment_count);
- ClassDB::bind_method(D_METHOD("get_bone_attachment"), &GLTFSkeleton::get_bone_attachment);
+ ClassDB::bind_method(D_METHOD("get_bone_attachment", "idx"), &GLTFSkeleton::get_bone_attachment);
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "joints"), "set_joints", "get_joints"); // Vector<GLTFNodeIndex>
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "roots"), "set_roots", "get_roots"); // Vector<GLTFNodeIndex>
diff --git a/modules/gltf/gltf_skin.cpp b/modules/gltf/gltf_skin.cpp
index fd39e4f45a..5a61e5778c 100644
--- a/modules/gltf/gltf_skin.cpp
+++ b/modules/gltf/gltf_skin.cpp
@@ -142,7 +142,7 @@ void GLTFSkin::set_joint_i_to_name(Dictionary p_joint_i_to_name) {
joint_i_to_name = Map<int, StringName>();
Array keys = p_joint_i_to_name.keys();
for (int i = 0; i < keys.size(); i++) {
- joint_i_to_name[keys[i]] = joint_i_to_name[keys[i]];
+ joint_i_to_name[keys[i]] = p_joint_i_to_name[keys[i]];
}
}
diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp
index eedc743330..ff9778e7d8 100644
--- a/modules/gltf/gltf_state.cpp
+++ b/modules/gltf/gltf_state.cpp
@@ -51,8 +51,8 @@ void GLTFState::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_accessors", "accessors"), &GLTFState::set_accessors);
ClassDB::bind_method(D_METHOD("get_meshes"), &GLTFState::get_meshes);
ClassDB::bind_method(D_METHOD("set_meshes", "meshes"), &GLTFState::set_meshes);
- ClassDB::bind_method(D_METHOD("get_animation_players_count"), &GLTFState::get_animation_players_count);
- ClassDB::bind_method(D_METHOD("get_animation_player"), &GLTFState::get_animation_player);
+ ClassDB::bind_method(D_METHOD("get_animation_players_count", "idx"), &GLTFState::get_animation_players_count);
+ ClassDB::bind_method(D_METHOD("get_animation_player", "idx"), &GLTFState::get_animation_player);
ClassDB::bind_method(D_METHOD("get_materials"), &GLTFState::get_materials);
ClassDB::bind_method(D_METHOD("set_materials", "materials"), &GLTFState::set_materials);
ClassDB::bind_method(D_METHOD("get_scene_name"), &GLTFState::get_scene_name);
@@ -71,13 +71,15 @@ void GLTFState::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lights", "lights"), &GLTFState::set_lights);
ClassDB::bind_method(D_METHOD("get_unique_names"), &GLTFState::get_unique_names);
ClassDB::bind_method(D_METHOD("set_unique_names", "unique_names"), &GLTFState::set_unique_names);
+ ClassDB::bind_method(D_METHOD("get_unique_animation_names"), &GLTFState::get_unique_animation_names);
+ ClassDB::bind_method(D_METHOD("set_unique_animation_names", "unique_animation_names"), &GLTFState::set_unique_animation_names);
ClassDB::bind_method(D_METHOD("get_skeletons"), &GLTFState::get_skeletons);
ClassDB::bind_method(D_METHOD("set_skeletons", "skeletons"), &GLTFState::set_skeletons);
ClassDB::bind_method(D_METHOD("get_skeleton_to_node"), &GLTFState::get_skeleton_to_node);
ClassDB::bind_method(D_METHOD("set_skeleton_to_node", "skeleton_to_node"), &GLTFState::set_skeleton_to_node);
ClassDB::bind_method(D_METHOD("get_animations"), &GLTFState::get_animations);
ClassDB::bind_method(D_METHOD("set_animations", "animations"), &GLTFState::set_animations);
- ClassDB::bind_method(D_METHOD("get_scene_node"), &GLTFState::get_scene_node);
+ ClassDB::bind_method(D_METHOD("get_scene_node", "idx"), &GLTFState::get_scene_node);
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "json"), "set_json", "get_json"); // Dictionary
ADD_PROPERTY(PropertyInfo(Variant::INT, "major_version"), "set_major_version", "get_major_version"); // int
@@ -98,6 +100,7 @@ void GLTFState::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "cameras", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_cameras", "get_cameras"); // Vector<Ref<GLTFCamera>>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "lights", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_lights", "get_lights"); // Vector<Ref<GLTFLight>>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_names", "get_unique_names"); // Set<String>
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_animation_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_animation_names", "get_unique_animation_names"); // Set<String>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skeletons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeletons", "get_skeletons"); // Vector<Ref<GLTFSkeleton>>
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "skeleton_to_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeleton_to_node", "get_skeleton_to_node"); // Map<GLTFSkeletonIndex,
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_animations", "get_animations"); // Vector<Ref<GLTFAnimation>>
@@ -255,6 +258,14 @@ void GLTFState::set_unique_names(Array p_unique_names) {
GLTFDocument::set_from_array(unique_names, p_unique_names);
}
+Array GLTFState::get_unique_animation_names() {
+ return GLTFDocument::to_array(unique_animation_names);
+}
+
+void GLTFState::set_unique_animation_names(Array p_unique_animation_names) {
+ GLTFDocument::set_from_array(unique_animation_names, p_unique_animation_names);
+}
+
Array GLTFState::get_skeletons() {
return GLTFDocument::to_array(skeletons);
}
diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h
index 4ce5aa9491..9030962b03 100644
--- a/modules/gltf/gltf_state.h
+++ b/modules/gltf/gltf_state.h
@@ -80,6 +80,7 @@ class GLTFState : public Resource {
Vector<Ref<GLTFCamera>> cameras;
Vector<Ref<GLTFLight>> lights;
Set<String> unique_names;
+ Set<String> unique_animation_names;
Vector<Ref<GLTFSkeleton>> skeletons;
Map<GLTFSkeletonIndex, GLTFNodeIndex> skeleton_to_node;
@@ -147,6 +148,9 @@ public:
Array get_unique_names();
void set_unique_names(Array p_unique_names);
+ Array get_unique_animation_names();
+ void set_unique_animation_names(Array p_unique_names);
+
Array get_skeletons();
void set_skeletons(Array p_skeletons);
diff --git a/modules/gltf/gltf_texture.h b/modules/gltf/gltf_texture.h
index e1d0407fb4..4659725502 100644
--- a/modules/gltf/gltf_texture.h
+++ b/modules/gltf/gltf_texture.h
@@ -38,7 +38,7 @@ class GLTFTexture : public Resource {
GDCLASS(GLTFTexture, Resource);
private:
- GLTFImageIndex src_image;
+ GLTFImageIndex src_image = 0;
protected:
static void _bind_methods();
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 4dccb03369..9b6fa138e5 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -8,6 +8,7 @@
GridMaps use a [MeshLibrary] which contains a list of tiles. Each tile is a mesh with materials plus optional collision and navigation shapes.
A GridMap contains a collection of cells. Each grid cell refers to a tile in the [MeshLibrary]. All cells in the map have the same dimensions.
Internally, a GridMap is split into a sparse collection of octants for efficient rendering and physics processing. Every octant has the same dimensions and can contain several cells.
+ [b]Note:[/b] GridMap doesn't extend [VisualInstance3D] and therefore can't be hidden or cull masked based on [member VisualInstance3D.layers]. If you make a light not affect the first layer, the whole GridMap won't be lit by the light in question.
</description>
<tutorials>
<link title="Using gridmaps">https://docs.godotengine.org/en/latest/tutorials/3d/using_gridmaps.html</link>
@@ -40,6 +41,7 @@
<return type="Array">
</return>
<description>
+ Returns an array of [ArrayMesh]es and [Transform] references of all bake meshes that exist within the current GridMap.
</description>
</method>
<method name="get_cell_item" qualifiers="const">
@@ -182,6 +184,9 @@
</method>
</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.
+ </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.
</member>
@@ -212,6 +217,9 @@
<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">
+ The navigation layers the GridMap generates its navigable regions in.
+ </member>
</members>
<signals>
<signal name="cell_size_changed">
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 5a17541075..4e4f88ed6a 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -179,6 +179,24 @@ bool GridMap::get_collision_layer_bit(int p_bit) const {
return get_collision_layer() & (1 << p_bit);
}
+void GridMap::set_bake_navigation(bool p_bake_navigation) {
+ bake_navigation = p_bake_navigation;
+ _recreate_octant_data();
+}
+
+bool GridMap::is_baking_navigation() {
+ return bake_navigation;
+}
+
+void GridMap::set_navigation_layers(uint32_t p_layers) {
+ navigation_layers = p_layers;
+ _recreate_octant_data();
+}
+
+uint32_t GridMap::get_navigation_layers() {
+ return navigation_layers;
+}
+
void GridMap::set_mesh_library(const Ref<MeshLibrary> &p_mesh_library) {
if (!mesh_library.is_null()) {
mesh_library->unregister_owner(this);
@@ -189,7 +207,6 @@ void GridMap::set_mesh_library(const Ref<MeshLibrary> &p_mesh_library) {
}
_recreate_octant_data();
- _change_notify("mesh_library");
}
Ref<MeshLibrary> GridMap::get_mesh_library() const {
@@ -286,7 +303,8 @@ void GridMap::set_cell_item(const Vector3i &p_position, int p_item, int p_rot) {
//create octant because it does not exist
Octant *g = memnew(Octant);
g->dirty = true;
- g->static_body = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC);
+ g->static_body = PhysicsServer3D::get_singleton()->body_create();
+ PhysicsServer3D::get_singleton()->body_set_mode(g->static_body, PhysicsServer3D::BODY_MODE_STATIC);
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);
@@ -474,13 +492,15 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
Octant::NavMesh nm;
nm.xform = xform * mesh_library->get_item_navmesh_transform(c.item);
- if (navigation) {
+ if (bake_navigation) {
RID region = NavigationServer3D::get_singleton()->region_create();
+ NavigationServer3D::get_singleton()->region_set_layers(region, navigation_layers);
NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh);
- NavigationServer3D::get_singleton()->region_set_transform(region, navigation->get_global_transform() * nm.xform);
- NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid());
+ NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * mesh_library->get_item_navmesh_transform(c.item));
+ NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
nm.region = region;
}
+
g.navmesh_ids[E->get()] = nm;
}
}
@@ -491,7 +511,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
Octant::MultimeshInstance mmi;
RID mm = RS::get_singleton()->multimesh_create();
- RS::get_singleton()->multimesh_allocate(mm, E->get().size(), RS::MULTIMESH_TRANSFORM_3D);
+ RS::get_singleton()->multimesh_allocate_data(mm, E->get().size(), RS::MULTIMESH_TRANSFORM_3D);
RS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E->key())->get_rid());
int idx = 0;
@@ -564,15 +584,17 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
RS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform());
}
- if (navigation && mesh_library.is_valid()) {
+ if (bake_navigation && mesh_library.is_valid()) {
for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) {
if (cell_map.has(F->key()) && F->get().region.is_valid() == false) {
Ref<NavigationMesh> nm = mesh_library->get_item_navmesh(cell_map[F->key()].item);
if (nm.is_valid()) {
RID region = NavigationServer3D::get_singleton()->region_create();
+ NavigationServer3D::get_singleton()->region_set_layers(region, navigation_layers);
NavigationServer3D::get_singleton()->region_set_navmesh(region, nm);
- NavigationServer3D::get_singleton()->region_set_transform(region, navigation->get_global_transform() * F->get().xform);
- NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid());
+ NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * F->get().xform);
+ NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
+
F->get().region = region;
}
}
@@ -594,12 +616,10 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
RS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, RID());
}
- if (navigation) {
- for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) {
- if (F->get().region.is_valid()) {
- NavigationServer3D::get_singleton()->free(F->get().region);
- F->get().region = RID();
- }
+ for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) {
+ if (F->get().region.is_valid()) {
+ NavigationServer3D::get_singleton()->free(F->get().region);
+ F->get().region = RID();
}
}
}
@@ -635,16 +655,6 @@ void GridMap::_octant_clean_up(const OctantKey &p_key) {
void GridMap::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_WORLD: {
- Node3D *c = this;
- while (c) {
- navigation = Object::cast_to<Navigation3D>(c);
- if (navigation) {
- break;
- }
-
- c = Object::cast_to<Node3D>(c->get_parent());
- }
-
last_transform = get_global_transform();
for (Map<OctantKey, Octant *>::Element *E = octant_map.front(); E; E = E->next()) {
@@ -679,8 +689,6 @@ void GridMap::_notification(int p_what) {
_octant_exit_world(E->key());
}
- navigation = nullptr;
-
//_queue_octants_dirty(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS);
//_update_octants_callback();
//_update_area_instances();
@@ -700,8 +708,6 @@ void GridMap::_update_visibility() {
return;
}
- _change_notify("visible");
-
for (Map<OctantKey, Octant *>::Element *e = octant_map.front(); e; e = e->next()) {
Octant *octant = e->value();
for (int i = 0; i < octant->multimesh_instances.size(); i++) {
@@ -709,6 +715,10 @@ void GridMap::_update_visibility() {
RS::get_singleton()->instance_set_visible(mi.instance, is_visible_in_tree());
}
}
+
+ for (int i = 0; i < baked_meshes.size(); i++) {
+ RS::get_singleton()->instance_set_visible(baked_meshes[i].instance, is_visible_in_tree());
+ }
}
void GridMap::_queue_octants_dirty() {
@@ -787,6 +797,12 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &GridMap::set_collision_layer_bit);
ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &GridMap::get_collision_layer_bit);
+ ClassDB::bind_method(D_METHOD("set_bake_navigation", "bake_navigation"), &GridMap::set_bake_navigation);
+ ClassDB::bind_method(D_METHOD("is_baking_navigation"), &GridMap::is_baking_navigation);
+
+ 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_mesh_library", "mesh_library"), &GridMap::set_mesh_library);
ClassDB::bind_method(D_METHOD("get_mesh_library"), &GridMap::get_mesh_library);
@@ -840,6 +856,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_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);
@@ -1046,26 +1065,7 @@ RID GridMap::get_bake_mesh_instance(int p_idx) {
}
GridMap::GridMap() {
- collision_layer = 1;
- collision_mask = 1;
-
- cell_size = Vector3(2, 2, 2);
- octant_size = 8;
- awaiting_update = false;
- _in_tree = false;
- center_x = true;
- center_y = true;
- center_z = true;
-
- clip = false;
- clip_floor = 0;
- clip_axis = Vector3::AXIS_Z;
- clip_above = true;
- cell_scale = 1.0;
-
- navigation = nullptr;
set_notify_transform(true);
- recreating_octants = false;
}
GridMap::~GridMap() {
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index 48ad95f9ff..4c04d492f7 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -31,7 +31,6 @@
#ifndef GRID_MAP_H
#define GRID_MAP_H
-#include "scene/3d/navigation_3d.h"
#include "scene/3d/node_3d.h"
#include "scene/resources/mesh_library.h"
#include "scene/resources/multimesh.h"
@@ -53,7 +52,7 @@ class GridMap : public Node3D {
int16_t y;
int16_t z;
};
- uint64_t key;
+ uint64_t key = 0;
_FORCE_INLINE_ bool operator<(const IndexKey &p_key) const {
return key < p_key.key;
@@ -68,7 +67,7 @@ class GridMap : public Node3D {
y = (int16_t)p_vector.y;
z = (int16_t)p_vector.z;
}
- IndexKey() { key = 0; }
+ IndexKey() {}
};
/**
@@ -80,13 +79,7 @@ class GridMap : public Node3D {
unsigned int rot : 5;
unsigned int layer : 8;
};
- uint32_t cell;
-
- Cell() {
- item = 0;
- rot = 0;
- layer = 0;
- }
+ uint32_t cell = 0;
};
/**
@@ -103,7 +96,7 @@ class GridMap : public Node3D {
RID instance;
RID multimesh;
struct Item {
- int index;
+ int index = 0;
Transform transform;
IndexKey key;
};
@@ -116,7 +109,7 @@ class GridMap : public Node3D {
RID collision_debug;
RID collision_debug_instance;
- bool dirty;
+ bool dirty = false;
RID static_body;
Map<IndexKey, NavMesh> navmesh_ids;
};
@@ -129,35 +122,38 @@ class GridMap : public Node3D {
int16_t empty;
};
- uint64_t key;
+ uint64_t key = 0;
_FORCE_INLINE_ bool operator<(const OctantKey &p_key) const {
return key < p_key.key;
}
//OctantKey(const IndexKey& p_k, int p_item) { indexkey=p_k.key; item=p_item; }
- OctantKey() { key = 0; }
+ OctantKey() {}
};
- uint32_t collision_layer;
- uint32_t collision_mask;
+ uint32_t collision_layer = 1;
+ uint32_t collision_mask = 1;
+ bool bake_navigation = false;
+ uint32_t navigation_layers = 1;
Transform last_transform;
- bool _in_tree;
- Vector3 cell_size;
- int octant_size;
- bool center_x, center_y, center_z;
- float cell_scale;
- Navigation3D *navigation;
+ bool _in_tree = false;
+ Vector3 cell_size = Vector3(2, 2, 2);
+ int octant_size = 8;
+ bool center_x = true;
+ bool center_y = true;
+ bool center_z = true;
+ float cell_scale = 1.0;
- bool clip;
- bool clip_above;
- int clip_floor;
+ bool clip = false;
+ bool clip_above = true;
+ int clip_floor = 0;
- bool recreating_octants;
+ bool recreating_octants = false;
- Vector3::Axis clip_axis;
+ Vector3::Axis clip_axis = Vector3::AXIS_Z;
Ref<MeshLibrary> mesh_library;
@@ -167,10 +163,10 @@ class GridMap : public Node3D {
void _recreate_octant_data();
struct BakeLight {
- RS::LightType type;
+ RS::LightType type = RS::LightType::LIGHT_DIRECTIONAL;
Vector3 pos;
Vector3 dir;
- float param[RS::LIGHT_PARAM_MAX];
+ float param[RS::LIGHT_PARAM_MAX] = {};
};
_FORCE_INLINE_ Vector3 _octant_get_offset(const OctantKey &p_key) const {
@@ -183,7 +179,7 @@ class GridMap : public Node3D {
bool _octant_update(const OctantKey &p_key);
void _octant_clean_up(const OctantKey &p_key);
void _octant_transform(const OctantKey &p_key);
- bool awaiting_update;
+ bool awaiting_update = false;
void _queue_octants_dirty();
void _update_octants_callback();
@@ -227,6 +223,12 @@ public:
void set_collision_mask_bit(int p_bit, bool p_value);
bool get_collision_mask_bit(int p_bit) const;
+ void set_bake_navigation(bool p_bake_navigation);
+ bool is_baking_navigation();
+
+ void set_navigation_layers(uint32_t p_layers);
+ uint32_t get_navigation_layers();
+
void set_mesh_library(const Ref<MeshLibrary> &p_mesh_library);
Ref<MeshLibrary> get_mesh_library() const;
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index 4732a3f62d..74ae45a46e 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -386,13 +386,13 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b
}
int cell[3];
- float cell_size[3] = { node->get_cell_size().x, node->get_cell_size().y, node->get_cell_size().z };
+ Vector3 cell_size = node->get_cell_size();
for (int i = 0; i < 3; i++) {
if (i == edit_axis) {
cell[i] = edit_floor[i];
} else {
- cell[i] = inters[i] / node->get_cell_size()[i];
+ cell[i] = inters[i] / cell_size[i];
if (inters[i] < 0) {
cell[i] -= 1; // Compensate negative.
}
@@ -436,6 +436,7 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b
}
return true;
}
+
if (input_action == INPUT_PAINT) {
SetItem si;
si.position = Vector3i(cell[0], cell[1], cell[2]);
@@ -545,7 +546,7 @@ void GridMapEditor::_update_paste_indicator() {
return;
}
- Vector3 center = 0.5 * Vector3(float(node->get_center_x()), float(node->get_center_y()), float(node->get_center_z()));
+ Vector3 center = 0.5 * Vector3(real_t(node->get_center_x()), real_t(node->get_center_y()), real_t(node->get_center_z()));
Vector3 scale = (Vector3(1, 1, 1) + (paste_indicator.end - paste_indicator.begin)) * node->get_cell_size();
Transform xf;
xf.scale(scale);
@@ -614,13 +615,13 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_WHEEL_UP && (mb->get_command() || mb->get_shift())) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && (mb->get_command() || mb->get_shift())) {
if (mb->is_pressed()) {
floor->set_value(floor->get_value() + mb->get_factor());
}
return true; // Eaten.
- } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && (mb->get_command() || mb->get_shift())) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && (mb->get_command() || mb->get_shift())) {
if (mb->is_pressed()) {
floor->set_value(floor->get_value() - mb->get_factor());
}
@@ -631,7 +632,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
Node3DEditorViewport::NavigationScheme nav_scheme = (Node3DEditorViewport::NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
if ((nav_scheme == Node3DEditorViewport::NAVIGATION_MAYA || nav_scheme == Node3DEditorViewport::NAVIGATION_MODO) && mb->get_alt()) {
input_action = INPUT_NONE;
- } else if (mb->get_button_index() == BUTTON_LEFT) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
bool can_edit = (node && node->get_mesh_library().is_valid());
if (input_action == INPUT_PASTE) {
_do_paste();
@@ -646,7 +647,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
input_action = INPUT_PAINT;
set_items.clear();
}
- } else if (mb->get_button_index() == BUTTON_RIGHT) {
+ } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
if (input_action == INPUT_PASTE) {
_clear_clipboard_data();
input_action = INPUT_NONE;
@@ -665,7 +666,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
return do_input_action(p_camera, Point2(mb->get_position().x, mb->get_position().y), true);
} else {
- if ((mb->get_button_index() == BUTTON_RIGHT && input_action == INPUT_ERASE) || (mb->get_button_index() == BUTTON_LEFT && input_action == INPUT_PAINT)) {
+ if ((mb->get_button_index() == MOUSE_BUTTON_RIGHT && input_action == INPUT_ERASE) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && input_action == INPUT_PAINT)) {
if (set_items.size()) {
undo_redo->create_action(TTR("GridMap Paint"));
for (List<SetItem>::Element *E = set_items.front(); E; E = E->next()) {
@@ -684,19 +685,19 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
return set_items.size() > 0;
}
- if (mb->get_button_index() == BUTTON_LEFT && input_action == INPUT_SELECT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT && input_action == INPUT_SELECT) {
undo_redo->create_action("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);
undo_redo->commit_action();
}
- if (mb->get_button_index() == BUTTON_LEFT && input_action != INPUT_NONE) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT && input_action != INPUT_NONE) {
set_items.clear();
input_action = INPUT_NONE;
return true;
}
- if (mb->get_button_index() == BUTTON_RIGHT && (input_action == INPUT_ERASE || input_action == INPUT_PASTE)) {
+ if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && (input_action == INPUT_ERASE || input_action == INPUT_PASTE)) {
input_action = INPUT_NONE;
return true;
}
@@ -769,7 +770,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
struct _CGMEItemSort {
String name;
- int id;
+ int id = 0;
_FORCE_INLINE_ bool operator<(const _CGMEItemSort &r_it) const { return name < r_it.name; }
};
@@ -810,11 +811,11 @@ void GridMapEditor::_mesh_library_palette_input(const Ref<InputEvent> &p_ie) {
// Zoom in/out using Ctrl + mouse wheel
if (mb.is_valid() && mb->is_pressed() && mb->get_command()) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
size_slider->set_value(size_slider->get_value() + 0.2);
}
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
size_slider->set_value(size_slider->get_value() - 0.2);
}
}
@@ -1151,7 +1152,6 @@ void GridMapEditor::_bind_methods() {
}
GridMapEditor::GridMapEditor(EditorNode *p_editor) {
- input_action = INPUT_NONE;
editor = p_editor;
undo_redo = p_editor->get_undo_redo();
@@ -1173,7 +1173,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
floor->set_min(-32767);
floor->set_max(32767);
floor->set_step(1);
- floor->get_line_edit()->add_theme_constant_override("minimum_spaces", 16);
+ floor->get_line_edit()->add_theme_constant_override("minimum_character_width", 16);
spatial_editor_hb->add_child(floor);
floor->connect("value_changed", callable_mp(this, &GridMapEditor::_floor_changed));
@@ -1234,7 +1234,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
settings_pick_distance->set_value(EDITOR_DEF("editors/grid_map/pick_distance", 5000.0));
settings_vbc->add_margin_child(TTR("Pick Distance:"), settings_pick_distance);
- clip_mode = CLIP_DISABLED;
options->get_popup()->connect("id_pressed", callable_mp(this, &GridMapEditor::_menu_option));
HBoxContainer *hb = memnew(HBoxContainer);
@@ -1275,8 +1274,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
EDITOR_DEF("editors/grid_map/preview_size", 64);
- display_mode = DISPLAY_THUMBNAIL;
-
mesh_library_palette = memnew(ItemList);
add_child(mesh_library_palette);
mesh_library_palette->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -1296,11 +1293,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
edit_floor[1] = -1;
edit_floor[2] = -1;
- cursor_visible = false;
- selected_palette = -1;
- lock_view = false;
- cursor_rot = 0;
-
selection_mesh = RenderingServer::get_singleton()->mesh_create();
paste_mesh = RenderingServer::get_singleton()->mesh_create();
@@ -1418,8 +1410,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
}
_set_selection(false);
- updating = false;
- accumulated_floor_delta = 0.0;
indicator_mat.instance();
indicator_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index 0c0ec64680..6c7f0bedf6 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -65,11 +65,11 @@ class GridMapEditor : public VBoxContainer {
};
UndoRedo *undo_redo;
- InputAction input_action;
+ InputAction input_action = INPUT_NONE;
Panel *panel;
MenuButton *options;
SpinBox *floor;
- double accumulated_floor_delta;
+ double accumulated_floor_delta = 0.0;
Button *mode_thumbnail;
Button *mode_list;
LineEdit *search_box;
@@ -82,19 +82,19 @@ class GridMapEditor : public VBoxContainer {
struct SetItem {
Vector3i position;
- int new_value;
- int new_orientation;
- int old_value;
- int old_orientation;
+ int new_value = 0;
+ int new_orientation = 0;
+ int old_value = 0;
+ int old_orientation = 0;
};
List<SetItem> set_items;
GridMap *node = nullptr;
MeshLibrary *last_mesh_library;
- ClipMode clip_mode;
+ ClipMode clip_mode = CLIP_DISABLED;
- bool lock_view;
+ bool lock_view = false;
Transform grid_xform;
Transform edit_grid_xform;
Vector3::Axis edit_axis;
@@ -112,9 +112,9 @@ class GridMapEditor : public VBoxContainer {
RID paste_instance;
struct ClipboardItem {
- int cell_item;
+ int cell_item = 0;
Vector3 grid_offset;
- int orientation;
+ int orientation = 0;
RID instance;
};
@@ -125,14 +125,14 @@ class GridMapEditor : public VBoxContainer {
Ref<StandardMaterial3D> outer_mat;
Ref<StandardMaterial3D> selection_floor_mat;
- bool updating;
+ bool updating = false;
struct Selection {
Vector3 click;
Vector3 current;
Vector3 begin;
Vector3 end;
- bool active;
+ bool active = false;
} selection;
Selection last_selection;
@@ -141,18 +141,18 @@ class GridMapEditor : public VBoxContainer {
Vector3 current;
Vector3 begin;
Vector3 end;
- int orientation;
+ int orientation = 0;
};
PasteIndicator paste_indicator;
- bool cursor_visible;
+ bool cursor_visible = false;
Transform cursor_transform;
Vector3 cursor_origin;
- int display_mode;
- int selected_palette;
- int cursor_rot;
+ int display_mode = DISPLAY_THUMBNAIL;
+ int selected_palette = -1;
+ int cursor_rot = 0;
enum Menu {
MENU_OPTION_NEXT_LEVEL,
diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp
index f31eb3f066..61ebabdfb6 100644
--- a/modules/lightmapper_rd/lightmapper_rd.cpp
+++ b/modules/lightmapper_rd/lightmapper_rd.cpp
@@ -93,8 +93,8 @@ void LightmapperRD::add_spot_light(bool p_static, const Vector3 &p_position, con
l.direction[2] = p_direction.z;
l.range = p_range;
l.attenuation = p_attenuation;
- l.spot_angle = Math::deg2rad(p_spot_angle);
- l.spot_attenuation = p_spot_attenuation;
+ l.cos_spot_angle = Math::cos(Math::deg2rad(p_spot_angle));
+ l.inv_spot_attenuation = 1.0f / p_spot_attenuation;
l.color[0] = p_color.r;
l.color[1] = p_color.g;
l.color[2] = p_color.b;
@@ -1225,23 +1225,23 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
switch (p_quality) {
case BAKE_QUALITY_LOW: {
- push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/low_quality_ray_count");
+ push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/low_quality_ray_count");
} break;
case BAKE_QUALITY_MEDIUM: {
- push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/medium_quality_ray_count");
+ push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/medium_quality_ray_count");
} break;
case BAKE_QUALITY_HIGH: {
- push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/high_quality_ray_count");
+ push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/high_quality_ray_count");
} break;
case BAKE_QUALITY_ULTRA: {
- push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/ultra_quality_ray_count");
+ push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/ultra_quality_ray_count");
} break;
}
push_constant.ray_count = CLAMP(push_constant.ray_count, 16, 8192);
- int max_region_size = nearest_power_of_2_templated(int(GLOBAL_GET("rendering/gpu_lightmapper/performance/region_size")));
- int max_rays = GLOBAL_GET("rendering/gpu_lightmapper/performance/max_rays_per_pass");
+ int max_region_size = nearest_power_of_2_templated(int(GLOBAL_GET("rendering/lightmapping/bake_performance/region_size")));
+ int max_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_rays_per_pass");
int x_regions = (atlas_size.width - 1) / max_region_size + 1;
int y_regions = (atlas_size.height - 1) / max_region_size + 1;
@@ -1347,23 +1347,23 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
switch (p_quality) {
case BAKE_QUALITY_LOW: {
- push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/low_quality_probe_ray_count");
+ push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/low_quality_probe_ray_count");
} break;
case BAKE_QUALITY_MEDIUM: {
- push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/medium_quality_probe_ray_count");
+ push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/medium_quality_probe_ray_count");
} break;
case BAKE_QUALITY_HIGH: {
- push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/high_quality_probe_ray_count");
+ push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/high_quality_probe_ray_count");
} break;
case BAKE_QUALITY_ULTRA: {
- push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/ultra_quality_probe_ray_count");
+ push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count");
} break;
}
push_constant.atlas_size[0] = probe_positions.size();
push_constant.ray_count = CLAMP(push_constant.ray_count, 16, 8192);
- int max_rays = GLOBAL_GET("rendering/gpu_lightmapper/performance/max_rays_per_probe_pass");
+ int max_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_rays_per_probe_pass");
int ray_iterations = (push_constant.ray_count - 1) / max_rays + 1;
for (int i = 0; i < ray_iterations; i++) {
diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h
index bb735baf6c..f2a826a447 100644
--- a/modules/lightmapper_rd/lightmapper_rd.h
+++ b/modules/lightmapper_rd/lightmapper_rd.h
@@ -46,18 +46,18 @@ class LightmapperRD : public Lightmapper {
};
struct Light {
- float position[3];
+ float position[3] = {};
uint32_t type = LIGHT_TYPE_DIRECTIONAL;
- float direction[3];
- float energy;
- float color[3];
- float size;
- float range;
- float attenuation;
- float spot_angle;
- float spot_attenuation;
- uint32_t static_bake;
- uint32_t pad[3];
+ float direction[3] = {};
+ float energy = 0.0;
+ float color[3] = {};
+ float size = 0.0;
+ float range = 0.0;
+ float attenuation = 0.0;
+ float cos_spot_angle = 0.0;
+ float inv_spot_attenuation = 0.0;
+ uint32_t static_bake = 0;
+ uint32_t pad[3] = {};
bool operator<(const Light &p_light) const {
return type < p_light.type;
@@ -65,10 +65,10 @@ class LightmapperRD : public Lightmapper {
};
struct Vertex {
- float position[3];
- float normal_z;
- float uv[2];
- float normal_xy[2];
+ float position[3] = {};
+ float normal_z = 0.0;
+ float uv[2] = {};
+ float normal_xy[2] = {};
bool operator==(const Vertex &p_vtx) const {
return (position[0] == p_vtx.position[0]) &&
@@ -102,7 +102,7 @@ class LightmapperRD : public Lightmapper {
};
struct Probe {
- float position[4];
+ float position[4] = {};
};
Vector<Probe> probe_positions;
@@ -158,15 +158,15 @@ class LightmapperRD : public Lightmapper {
};
struct Box {
- float min_bounds[3];
- float pad0;
- float max_bounds[3];
- float pad1;
+ float min_bounds[3] = {};
+ float pad0 = 0.0;
+ float max_bounds[3] = {};
+ float pad1 = 0.0;
};
struct Triangle {
- uint32_t indices[3];
- uint32_t slice;
+ uint32_t indices[3] = {};
+ uint32_t slice = 0;
bool operator<(const Triangle &p_triangle) const {
return slice < p_triangle.slice;
}
@@ -177,8 +177,8 @@ class LightmapperRD : public Lightmapper {
Vector<Light> lights;
struct TriangleSort {
- uint32_t cell_index;
- uint32_t triangle_index;
+ uint32_t cell_index = 0;
+ uint32_t triangle_index = 0;
bool operator<(const TriangleSort &p_triangle_sort) const {
return cell_index < p_triangle_sort.cell_index; //sorting by triangle index in this case makes no sense
}
@@ -187,44 +187,44 @@ class LightmapperRD : public Lightmapper {
void _plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[], uint32_t p_triangle_index, LocalVector<TriangleSort> &triangles, uint32_t p_grid_size);
struct RasterPushConstant {
- float atlas_size[2];
- float uv_offset[2];
- float to_cell_size[3];
- uint32_t base_triangle;
- float to_cell_offset[3];
- float bias;
- int32_t grid_size[3];
- uint32_t pad2;
+ float atlas_size[2] = {};
+ float uv_offset[2] = {};
+ float to_cell_size[3] = {};
+ uint32_t base_triangle = 0;
+ float to_cell_offset[3] = {};
+ float bias = 0.0;
+ int32_t grid_size[3] = {};
+ uint32_t pad2 = 0;
};
struct RasterSeamsPushConstant {
- uint32_t base_index;
- uint32_t slice;
- float uv_offset[2];
- uint32_t debug;
- float blend;
- uint32_t pad[2];
+ uint32_t base_index = 0;
+ uint32_t slice = 0;
+ float uv_offset[2] = {};
+ uint32_t debug = 0;
+ float blend = 0.0;
+ uint32_t pad[2] = {};
};
struct PushConstant {
- int32_t atlas_size[2];
- uint32_t ray_count;
- uint32_t ray_to;
+ int32_t atlas_size[2] = {};
+ uint32_t ray_count = 0;
+ uint32_t ray_to = 0;
- float world_size[3];
- float bias;
+ float world_size[3] = {};
+ float bias = 0.0;
- float to_cell_offset[3];
- uint32_t ray_from;
+ float to_cell_offset[3] = {};
+ uint32_t ray_from = 0;
- float to_cell_size[3];
- uint32_t light_count;
+ float to_cell_size[3] = {};
+ uint32_t light_count = 0;
- int32_t grid_size;
- int32_t atlas_slice;
- int32_t region_ofs[2];
+ int32_t grid_size = 0;
+ int32_t atlas_slice = 0;
+ int32_t region_ofs[2] = {};
- float environment_xform[12];
+ float environment_xform[12] = {};
};
Vector<Ref<Image>> bake_textures;
diff --git a/modules/lightmapper_rd/lm_common_inc.glsl b/modules/lightmapper_rd/lm_common_inc.glsl
index 0ff455936e..f8a0cd16de 100644
--- a/modules/lightmapper_rd/lm_common_inc.glsl
+++ b/modules/lightmapper_rd/lm_common_inc.glsl
@@ -56,8 +56,8 @@ struct Light {
float range;
float attenuation;
- float spot_angle;
- float spot_attenuation;
+ float cos_spot_angle;
+ float inv_spot_attenuation;
bool static_bake;
uint pad[3];
diff --git a/modules/lightmapper_rd/lm_compute.glsl b/modules/lightmapper_rd/lm_compute.glsl
index 8a9adbc5cc..eb9d817f99 100644
--- a/modules/lightmapper_rd/lm_compute.glsl
+++ b/modules/lightmapper_rd/lm_compute.glsl
@@ -313,13 +313,16 @@ void main() {
if (lights.data[i].type == LIGHT_TYPE_SPOT) {
vec3 rel = normalize(position - light_pos);
- float angle = acos(dot(rel, lights.data[i].direction));
- if (angle > lights.data[i].spot_angle) {
+ float cos_spot_angle = lights.data[i].cos_spot_angle;
+ float cos_angle = dot(rel, lights.data[i].direction);
+
+ if (cos_angle < cos_spot_angle) {
continue; //invisible, dont try
}
- float d = clamp(angle / lights.data[i].spot_angle, 0, 1);
- attenuation *= pow(1.0 - d, lights.data[i].spot_attenuation);
+ float scos = max(cos_angle, cos_spot_angle);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle));
+ attenuation *= 1.0 - pow(spot_rim, lights.data[i].inv_spot_attenuation);
}
}
diff --git a/modules/lightmapper_rd/register_types.cpp b/modules/lightmapper_rd/register_types.cpp
index a7b8c063fd..191bb3d765 100644
--- a/modules/lightmapper_rd/register_types.cpp
+++ b/modules/lightmapper_rd/register_types.cpp
@@ -41,18 +41,18 @@ static Lightmapper *create_lightmapper_rd() {
#endif
void register_lightmapper_rd_types() {
- GLOBAL_DEF("rendering/gpu_lightmapper/quality/low_quality_ray_count", 16);
- GLOBAL_DEF("rendering/gpu_lightmapper/quality/medium_quality_ray_count", 64);
- GLOBAL_DEF("rendering/gpu_lightmapper/quality/high_quality_ray_count", 256);
- GLOBAL_DEF("rendering/gpu_lightmapper/quality/ultra_quality_ray_count", 1024);
- GLOBAL_DEF("rendering/gpu_lightmapper/performance/max_rays_per_pass", 32);
- GLOBAL_DEF("rendering/gpu_lightmapper/performance/region_size", 512);
+ GLOBAL_DEF("rendering/lightmapping/bake_quality/low_quality_ray_count", 16);
+ GLOBAL_DEF("rendering/lightmapping/bake_quality/medium_quality_ray_count", 64);
+ GLOBAL_DEF("rendering/lightmapping/bake_quality/high_quality_ray_count", 256);
+ GLOBAL_DEF("rendering/lightmapping/bake_quality/ultra_quality_ray_count", 1024);
+ GLOBAL_DEF("rendering/lightmapping/bake_performance/max_rays_per_pass", 32);
+ GLOBAL_DEF("rendering/lightmapping/bake_performance/region_size", 512);
- GLOBAL_DEF("rendering/gpu_lightmapper/quality/low_quality_probe_ray_count", 64);
- GLOBAL_DEF("rendering/gpu_lightmapper/quality/medium_quality_probe_ray_count", 256);
- GLOBAL_DEF("rendering/gpu_lightmapper/quality/high_quality_probe_ray_count", 512);
- GLOBAL_DEF("rendering/gpu_lightmapper/quality/ultra_quality_probe_ray_count", 2048);
- GLOBAL_DEF("rendering/gpu_lightmapper/performance/max_rays_per_probe_pass", 64);
+ GLOBAL_DEF("rendering/lightmapping/bake_quality/low_quality_probe_ray_count", 64);
+ GLOBAL_DEF("rendering/lightmapping/bake_quality/medium_quality_probe_ray_count", 256);
+ 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);
#ifndef _3D_DISABLED
ClassDB::register_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 b2f8d668bf..8a6cdfb131 100644
--- a/modules/mbedtls/packet_peer_mbed_dtls.cpp
+++ b/modules/mbedtls/packet_peer_mbed_dtls.cpp
@@ -246,7 +246,6 @@ int PacketPeerMbedDTLS::get_max_packet_size() const {
PacketPeerMbedDTLS::PacketPeerMbedDTLS() {
ssl_ctx.instance();
- status = STATUS_DISCONNECTED;
}
PacketPeerMbedDTLS::~PacketPeerMbedDTLS() {
diff --git a/modules/mbedtls/packet_peer_mbed_dtls.h b/modules/mbedtls/packet_peer_mbed_dtls.h
index 0feec04c6e..6554c74a21 100644
--- a/modules/mbedtls/packet_peer_mbed_dtls.h
+++ b/modules/mbedtls/packet_peer_mbed_dtls.h
@@ -44,7 +44,7 @@ private:
uint8_t packet_buffer[PACKET_BUFFER_SIZE];
- Status status;
+ Status status = STATUS_DISCONNECTED;
String hostname;
Ref<PacketPeerUDP> base;
diff --git a/modules/mbedtls/ssl_context_mbedtls.cpp b/modules/mbedtls/ssl_context_mbedtls.cpp
index 046f30588a..cbb532587f 100644
--- a/modules/mbedtls/ssl_context_mbedtls.cpp
+++ b/modules/mbedtls/ssl_context_mbedtls.cpp
@@ -76,7 +76,6 @@ void CookieContextMbedTLS::clear() {
}
CookieContextMbedTLS::CookieContextMbedTLS() {
- inited = false;
}
CookieContextMbedTLS::~CookieContextMbedTLS() {
@@ -205,7 +204,6 @@ mbedtls_ssl_context *SSLContextMbedTLS::get_context() {
}
SSLContextMbedTLS::SSLContextMbedTLS() {
- inited = false;
}
SSLContextMbedTLS::~SSLContextMbedTLS() {
diff --git a/modules/mbedtls/ssl_context_mbedtls.h b/modules/mbedtls/ssl_context_mbedtls.h
index d243185726..30632018a8 100644
--- a/modules/mbedtls/ssl_context_mbedtls.h
+++ b/modules/mbedtls/ssl_context_mbedtls.h
@@ -50,7 +50,7 @@ class CookieContextMbedTLS : public Reference {
friend class SSLContextMbedTLS;
protected:
- bool inited;
+ bool inited = false;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_cookie_ctx cookie_ctx;
@@ -65,7 +65,7 @@ public:
class SSLContextMbedTLS : public Reference {
protected:
- bool inited;
+ bool inited = false;
static PackedByteArray _read_file(String p_path);
diff --git a/modules/mbedtls/stream_peer_mbedtls.cpp b/modules/mbedtls/stream_peer_mbedtls.cpp
index 1332d0923c..b39a6ecc2f 100644
--- a/modules/mbedtls/stream_peer_mbedtls.cpp
+++ b/modules/mbedtls/stream_peer_mbedtls.cpp
@@ -242,7 +242,7 @@ void StreamPeerMbedTLS::poll() {
return;
}
- // We could pass NULL as second parameter, but some behaviour sanitizers doesn't seem to like that.
+ // We could pass NULL as second parameter, but some behaviour sanitizers don't seem to like that.
// Passing a 1 byte buffer to workaround it.
uint8_t byte;
int ret = mbedtls_ssl_read(ssl_ctx->get_context(), &byte, 0);
@@ -274,7 +274,6 @@ int StreamPeerMbedTLS::get_available_bytes() const {
StreamPeerMbedTLS::StreamPeerMbedTLS() {
ssl_ctx.instance();
- status = STATUS_DISCONNECTED;
}
StreamPeerMbedTLS::~StreamPeerMbedTLS() {
diff --git a/modules/mbedtls/stream_peer_mbedtls.h b/modules/mbedtls/stream_peer_mbedtls.h
index ccbbebe4f8..b89d7fb238 100644
--- a/modules/mbedtls/stream_peer_mbedtls.h
+++ b/modules/mbedtls/stream_peer_mbedtls.h
@@ -36,7 +36,7 @@
class StreamPeerMbedTLS : public StreamPeerSSL {
private:
- Status status;
+ Status status = STATUS_DISCONNECTED;
String hostname;
Ref<StreamPeer> base;
diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp
index 8627f71987..b128b81000 100644
--- a/modules/minimp3/audio_stream_mp3.cpp
+++ b/modules/minimp3/audio_stream_mp3.cpp
@@ -159,7 +159,8 @@ void AudioStreamMP3::set_data(const Vector<uint8_t> &p_data) {
const uint8_t *src_datar = p_data.ptr();
mp3dec_ex_t mp3d;
- mp3dec_ex_open_buf(&mp3d, src_datar, src_data_len, MP3D_SEEK_TO_SAMPLE);
+ int err = mp3dec_ex_open_buf(&mp3d, src_datar, src_data_len, MP3D_SEEK_TO_SAMPLE);
+ ERR_FAIL_COND(err != 0);
channels = mp3d.info.channels;
sample_rate = mp3d.info.hz;
diff --git a/modules/minimp3/audio_stream_mp3.h b/modules/minimp3/audio_stream_mp3.h
index de02ba6003..ce001fc418 100644
--- a/modules/minimp3/audio_stream_mp3.h
+++ b/modules/minimp3/audio_stream_mp3.h
@@ -78,11 +78,11 @@ class AudioStreamMP3 : public AudioStream {
void *data = nullptr;
uint32_t data_len = 0;
- float sample_rate = 1;
+ float sample_rate = 1.0;
int channels = 1;
- float length = 0;
+ float length = 0.0;
bool loop = false;
- float loop_offset = 0;
+ float loop_offset = 0.0;
void clear_data();
protected:
diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp
index a9073ea4a0..5140cfbbaf 100644
--- a/modules/mobile_vr/mobile_vr_interface.cpp
+++ b/modules/mobile_vr/mobile_vr_interface.cpp
@@ -153,8 +153,8 @@ void MobileVRInterface::set_position_from_sensors() {
last_magnetometer_data = magneto;
if (grav.length() < 0.1) {
- // not ideal but use our accelerometer, this will contain shakey shakey user behaviour
- // maybe look into some math but I'm guessing that if this isn't available, its because we lack the gyro sensor to actually work out
+ // not ideal but use our accelerometer, this will contain shaky user behaviour
+ // maybe look into some math but I'm guessing that if this isn't available, it's because we lack the gyro sensor to actually work out
// what a stable gravity vector is
grav = acc;
if (grav.length() > 0.1) {
@@ -181,8 +181,8 @@ void MobileVRInterface::set_position_from_sensors() {
tracking_state = XRInterface::XR_NORMAL_TRACKING;
};
- ///@TODO improve this, the magnetometer is very fidgity sometimes flipping the axis for no apparent reason (probably a bug on my part)
- // if you have a gyro + accelerometer that combo tends to be better then combining all three but without a gyro you need the magnetometer..
+ ///@TODO improve this, the magnetometer is very fidgety sometimes flipping the axis for no apparent reason (probably a bug on my part)
+ // if you have a gyro + accelerometer that combo tends to be better than combining all three but without a gyro you need the magnetometer..
if (has_magneto && has_grav && !has_gyro) {
// convert to quaternions, easier to smooth those out
Quat transform_quat(orientation);
@@ -372,7 +372,7 @@ Transform MobileVRInterface::get_transform_for_eye(XRInterface::Eyes p_eye, cons
if (initialized) {
float world_scale = xr_server->get_world_scale();
- // we don't need to check for the existence of our HMD, doesn't effect our values...
+ // we don't need to check for the existence of our HMD, doesn't affect our values...
// note * 0.01 to convert cm to m and * 0.5 as we're moving half in each direction...
if (p_eye == XRInterface::EYE_LEFT) {
transform_for_eye.origin.x = -(intraocular_dist * 0.01 * 0.5 * world_scale);
@@ -402,7 +402,7 @@ CameraMatrix MobileVRInterface::get_projection_for_eye(XRInterface::Eyes p_eye,
CameraMatrix eye;
if (p_eye == XRInterface::EYE_MONO) {
- ///@TODO for now hardcode some of this, what is really needed here is that this needs to be in sync with the real cameras properties
+ ///@TODO for now hardcode some of this, what is really needed here is that this needs to be in sync with the real camera's properties
// which probably means implementing a specific class for iOS and Android. For now this is purely here as an example.
// Note also that if you use a normal viewport with AR/VR turned off you can still use the tracker output of this interface
// to position a stock standard Godot camera and have control over this.
@@ -448,19 +448,7 @@ void MobileVRInterface::process() {
};
};
-MobileVRInterface::MobileVRInterface() {
- initialized = false;
-
- // Just set some defaults for these. At some point we need to look at adding a lookup table for common device + headset combos and/or support reading cardboard QR codes
- eye_height = 1.85;
- intraocular_dist = 6.0;
- display_width = 14.5;
- display_to_lens = 4.0;
- oversample = 1.5;
- k1 = 0.215;
- k2 = 0.215;
- last_ticks = 0;
-};
+MobileVRInterface::MobileVRInterface() {}
MobileVRInterface::~MobileVRInterface() {
// and make sure we cleanup if we haven't already
diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h
index 1afa6c39b6..d28c2196af 100644
--- a/modules/mobile_vr/mobile_vr_interface.h
+++ b/modules/mobile_vr/mobile_vr_interface.h
@@ -51,19 +51,21 @@ class MobileVRInterface : public XRInterface {
GDCLASS(MobileVRInterface, XRInterface);
private:
- bool initialized;
+ bool initialized = false;
Basis orientation;
- float eye_height;
- uint64_t last_ticks;
- real_t intraocular_dist;
- real_t display_width;
- real_t display_to_lens;
- real_t oversample;
+ // Just set some defaults for these. At some point we need to look at adding a lookup table for common device + headset combos and/or support reading cardboard QR codes
+ float eye_height = 1.85;
+ uint64_t last_ticks = 0;
+
+ real_t intraocular_dist = 6.0;
+ real_t display_width = 14.5;
+ real_t display_to_lens = 4.0;
+ real_t oversample = 1.5;
//@TODO not yet used, these are needed in our distortion shader...
- real_t k1;
- real_t k2;
+ real_t k1 = 0.215;
+ real_t k2 = 0.215;
/*
logic for processing our sensor data, this was originally in our positional tracker logic but I think
@@ -73,9 +75,9 @@ private:
Vector3 scale_magneto(const Vector3 &p_magnetometer);
Basis combine_acc_mag(const Vector3 &p_grav, const Vector3 &p_magneto);
- int mag_count;
- bool has_gyro;
- bool sensor_first;
+ int mag_count = 0;
+ bool has_gyro = false;
+ bool sensor_first = false;
Vector3 last_accerometer_data;
Vector3 last_magnetometer_data;
Vector3 mag_current_min;
diff --git a/modules/mono/Directory.Build.props b/modules/mono/Directory.Build.props
new file mode 100644
index 0000000000..fbf864b11b
--- /dev/null
+++ b/modules/mono/Directory.Build.props
@@ -0,0 +1,3 @@
+<Project>
+ <Import Project="$(MSBuildThisFileDirectory)\SdkPackageVersions.props" />
+</Project>
diff --git a/modules/mono/SdkPackageVersions.props b/modules/mono/SdkPackageVersions.props
new file mode 100644
index 0000000000..df3ebe581c
--- /dev/null
+++ b/modules/mono/SdkPackageVersions.props
@@ -0,0 +1,6 @@
+<Project>
+ <PropertyGroup>
+ <PackageVersion_Godot_NET_Sdk>4.0.0-dev5</PackageVersion_Godot_NET_Sdk>
+ <PackageVersion_Godot_SourceGenerators>4.0.0-dev2</PackageVersion_Godot_SourceGenerators>
+ </PropertyGroup>
+</Project>
diff --git a/modules/mono/build_scripts/godot_net_sdk_build.py b/modules/mono/build_scripts/godot_net_sdk_build.py
index 3bfba0f0f6..8c5a60d2db 100644
--- a/modules/mono/build_scripts/godot_net_sdk_build.py
+++ b/modules/mono/build_scripts/godot_net_sdk_build.py
@@ -21,6 +21,18 @@ def build_godot_net_sdk(source, target, env):
# No need to copy targets. The Godot.NET.Sdk csproj takes care of copying them.
+def get_nupkgs_versions(props_file):
+ import xml.etree.ElementTree as ET
+
+ tree = ET.parse(props_file)
+ root = tree.getroot()
+
+ return {
+ "Godot.NET.Sdk": root.find("./PropertyGroup/PackageVersion_Godot_NET_Sdk").text.strip(),
+ "Godot.SourceGenerators": root.find("./PropertyGroup/PackageVersion_Godot_SourceGenerators").text.strip(),
+ }
+
+
def build(env_mono):
assert env_mono["tools"]
@@ -30,14 +42,12 @@ def build(env_mono):
module_dir = os.getcwd()
- package_version_file = os.path.join(
- module_dir, "editor", "Godot.NET.Sdk", "Godot.NET.Sdk", "Godot.NET.Sdk_PackageVersion.txt"
- )
-
- with open(package_version_file, mode="r") as f:
- version = f.read().strip()
+ nupkgs_versions = get_nupkgs_versions(os.path.join(module_dir, "SdkPackageVersions.props"))
- target_filenames = ["Godot.NET.Sdk.%s.nupkg" % version]
+ target_filenames = [
+ "Godot.NET.Sdk.%s.nupkg" % nupkgs_versions["Godot.NET.Sdk"],
+ "Godot.SourceGenerators.%s.nupkg" % nupkgs_versions["Godot.SourceGenerators"],
+ ]
targets = [os.path.join(nupkgs_dir, filename) for filename in target_filenames]
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index bd29dc1876..43f57a7caa 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -31,6 +31,7 @@
#include "csharp_script.h"
#include <mono/metadata/threads.h>
+#include <mono/metadata/tokentype.h>
#include <stdint.h>
#include "core/config/project_settings.h"
@@ -327,7 +328,7 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin
String script_template = "using " BINDINGS_NAMESPACE ";\n"
"using System;\n"
"\n"
- "public class %CLASS% : %BASE%\n"
+ "public partial class %CLASS% : %BASE%\n"
"{\n"
" // Declare member variables here. Examples:\n"
" // private int a = 2;\n"
@@ -1182,46 +1183,56 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
}
#endif
-void CSharpLanguage::_load_scripts_metadata() {
- scripts_metadata.clear();
+void CSharpLanguage::lookup_script_for_class(GDMonoClass *p_class) {
+ if (!p_class->has_attribute(CACHED_CLASS(ScriptPathAttribute))) {
+ return;
+ }
- String scripts_metadata_filename = "scripts_metadata.";
+ MonoObject *attr = p_class->get_attribute(CACHED_CLASS(ScriptPathAttribute));
+ String path = CACHED_FIELD(ScriptPathAttribute, path)->get_string_value(attr);
-#ifdef TOOLS_ENABLED
- scripts_metadata_filename += Engine::get_singleton()->is_editor_hint() ? "editor" : "editor_player";
-#else
-#ifdef DEBUG_ENABLED
- scripts_metadata_filename += "debug";
-#else
- scripts_metadata_filename += "release";
-#endif
-#endif
+ dotnet_script_lookup_map[path] = DotNetScriptLookupInfo(
+ p_class->get_namespace(), p_class->get_name(), p_class);
+}
- String scripts_metadata_path = GodotSharpDirs::get_res_metadata_dir().plus_file(scripts_metadata_filename);
+void CSharpLanguage::lookup_scripts_in_assembly(GDMonoAssembly *p_assembly) {
+ if (p_assembly->has_attribute(CACHED_CLASS(AssemblyHasScriptsAttribute))) {
+ MonoObject *attr = p_assembly->get_attribute(CACHED_CLASS(AssemblyHasScriptsAttribute));
+ bool requires_lookup = CACHED_FIELD(AssemblyHasScriptsAttribute, requiresLookup)->get_bool_value(attr);
- if (FileAccess::exists(scripts_metadata_path)) {
- String old_json;
+ if (requires_lookup) {
+ // This is supported for scenarios where specifying all types would be cumbersome,
+ // such as when disabling C# source generators (for whatever reason) or when using a
+ // language other than C# that has nothing similar to source generators to automate it.
+ MonoImage *image = p_assembly->get_image();
- Error ferr = read_all_file_utf8(scripts_metadata_path, old_json);
+ int rows = mono_image_get_table_rows(image, MONO_TABLE_TYPEDEF);
- ERR_FAIL_COND(ferr != OK);
+ for (int i = 1; i < rows; i++) {
+ // We don't search inner classes, only top-level.
+ MonoClass *mono_class = mono_class_get(image, (i + 1) | MONO_TOKEN_TYPE_DEF);
- Variant old_dict_var;
- String err_str;
- int err_line;
- Error json_err = JSON::parse(old_json, old_dict_var, err_str, err_line);
- if (json_err != OK) {
- ERR_PRINT("Failed to parse metadata file: '" + err_str + "' (" + String::num_int64(err_line) + ").");
- return;
- }
+ if (!mono_class_is_assignable_from(CACHED_CLASS_RAW(GodotObject), mono_class)) {
+ continue;
+ }
- scripts_metadata = old_dict_var.operator Dictionary();
- scripts_metadata_invalidated = false;
+ GDMonoClass *current = p_assembly->get_class(mono_class);
+ if (current) {
+ lookup_script_for_class(current);
+ }
+ }
+ } else {
+ // This is the most likely scenario as we use C# source generators
+ MonoArray *script_types = (MonoArray *)CACHED_FIELD(AssemblyHasScriptsAttribute, scriptTypes)->get_value(attr);
- print_verbose("Successfully loaded scripts metadata");
- } else {
- if (!Engine::get_singleton()->is_editor_hint()) {
- ERR_PRINT("Missing scripts metadata file.");
+ int length = mono_array_length(script_types);
+
+ for (int i = 0; i < length; i++) {
+ MonoReflectionType *reftype = mono_array_get(script_types, MonoReflectionType *, i);
+ ManagedType type = ManagedType::from_reftype(reftype);
+ ERR_CONTINUE(!type.type_class);
+ lookup_script_for_class(type.type_class);
+ }
}
}
}
@@ -1300,7 +1311,7 @@ void CSharpLanguage::_on_scripts_domain_unloaded() {
}
#endif
- scripts_metadata_invalidated = true;
+ dotnet_script_lookup_map.clear();
}
#ifdef TOOLS_ENABLED
@@ -2007,22 +2018,20 @@ void CSharpInstance::connect_event_signals() {
// TODO: Use pooling for ManagedCallable instances.
auto event_signal_callable = memnew(EventSignalCallable(owner, &event_signal));
- owner->connect(signal_name, Callable(event_signal_callable));
+ Callable callable(event_signal_callable);
+ connected_event_signals.push_back(callable);
+ owner->connect(signal_name, callable);
}
}
void CSharpInstance::disconnect_event_signals() {
- for (const Map<StringName, CSharpScript::EventSignal>::Element *E = script->event_signals.front(); E; E = E->next()) {
- const CSharpScript::EventSignal &event_signal = E->value();
-
- StringName signal_name = event_signal.field->get_name();
-
- // TODO: It would be great if we could store this EventSignalCallable on the stack.
- // The problem is that Callable memdeletes it when it's destructed...
- auto event_signal_callable = memnew(EventSignalCallable(owner, &event_signal));
-
- owner->disconnect(signal_name, Callable(event_signal_callable));
+ for (const List<Callable>::Element *E = connected_event_signals.front(); E; E = E->next()) {
+ const Callable &callable = E->get();
+ auto event_signal_callable = static_cast<const EventSignalCallable *>(callable.get_custom());
+ owner->disconnect(event_signal_callable->get_signal(), callable);
}
+
+ connected_event_signals.clear();
}
void CSharpInstance::refcount_incremented() {
@@ -3356,45 +3365,34 @@ Error CSharpScript::reload(bool p_keep_state) {
GD_MONO_SCOPE_THREAD_ATTACH;
- GDMonoAssembly *project_assembly = GDMono::get_singleton()->get_project_assembly();
-
- if (project_assembly) {
- const Variant *script_metadata_var = CSharpLanguage::get_singleton()->get_scripts_metadata().getptr(get_path());
- if (script_metadata_var) {
- Dictionary script_metadata = script_metadata_var->operator Dictionary()["class"];
- const Variant *namespace_ = script_metadata.getptr("namespace");
- const Variant *class_name = script_metadata.getptr("class_name");
- ERR_FAIL_NULL_V(namespace_, ERR_BUG);
- ERR_FAIL_NULL_V(class_name, ERR_BUG);
- GDMonoClass *klass = project_assembly->get_class(namespace_->operator String(), class_name->operator String());
- if (klass && CACHED_CLASS(GodotObject)->is_assignable_from(klass)) {
- script_class = klass;
- }
- } else {
- // Missing script metadata. Fallback to legacy method
- script_class = project_assembly->get_object_derived_class(name);
+ const DotNetScriptLookupInfo *lookup_info =
+ CSharpLanguage::get_singleton()->lookup_dotnet_script(get_path());
+
+ if (lookup_info) {
+ GDMonoClass *klass = lookup_info->script_class;
+ if (klass) {
+ ERR_FAIL_COND_V(!CACHED_CLASS(GodotObject)->is_assignable_from(klass), FAILED);
+ script_class = klass;
}
+ }
- valid = script_class != nullptr;
+ valid = script_class != nullptr;
- if (script_class) {
+ if (script_class) {
#ifdef DEBUG_ENABLED
- print_verbose("Found class " + script_class->get_full_name() + " for script " + get_path());
+ print_verbose("Found class " + script_class->get_full_name() + " for script " + get_path());
#endif
- native = GDMonoUtils::get_class_native_base(script_class);
-
- CRASH_COND(native == nullptr);
+ native = GDMonoUtils::get_class_native_base(script_class);
- update_script_class_info(this);
+ CRASH_COND(native == nullptr);
- _update_exports();
- }
+ update_script_class_info(this);
- return OK;
+ _update_exports();
}
- return ERR_FILE_MISSING_DEPENDENCIES;
+ return OK;
}
ScriptLanguage *CSharpScript::get_language() const {
@@ -3644,7 +3642,7 @@ void CSharpScript::get_members(Set<StringName> *p_members) {
/*************** RESOURCE ***************/
-RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
}
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 85edd8b9c6..dd93a86d7a 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -66,6 +66,18 @@ TScriptInstance *cast_script_instance(ScriptInstance *p_inst) {
#define CAST_CSHARP_INSTANCE(m_inst) (cast_script_instance<CSharpInstance, CSharpLanguage>(m_inst))
+struct DotNetScriptLookupInfo {
+ String class_namespace;
+ String class_name;
+ GDMonoClass *script_class = nullptr;
+
+ DotNetScriptLookupInfo() {} // Required by HashMap...
+
+ DotNetScriptLookupInfo(const String &p_class_namespace, const String &p_class_name, GDMonoClass *p_script_class) :
+ class_namespace(p_class_namespace), class_name(p_class_name), script_class(p_script_class) {
+ }
+};
+
class CSharpScript : public Script {
GDCLASS(CSharpScript, Script);
@@ -259,6 +271,8 @@ class CSharpInstance : public ScriptInstance {
Ref<CSharpScript> script;
MonoGCHandleData gchandle;
+ List<Callable> connected_event_signals;
+
bool _reference_owner_unsafe();
/*
@@ -390,16 +404,15 @@ class CSharpLanguage : public ScriptLanguage {
int lang_idx = -1;
- Dictionary scripts_metadata;
- bool scripts_metadata_invalidated = true;
+ HashMap<String, DotNetScriptLookupInfo> dotnet_script_lookup_map;
+
+ void lookup_script_for_class(GDMonoClass *p_class);
// For debug_break and debug_break_parse
int _debug_parse_err_line = -1;
String _debug_parse_err_file;
String _debug_error;
- void _load_scripts_metadata();
-
friend class GDMono;
void _on_scripts_domain_unloaded();
@@ -436,18 +449,13 @@ public:
void reload_assemblies(bool p_soft_reload);
#endif
- _FORCE_INLINE_ Dictionary get_scripts_metadata_or_nothing() {
- return scripts_metadata_invalidated ? Dictionary() : scripts_metadata;
- }
+ _FORCE_INLINE_ ManagedCallableMiddleman *get_managed_callable_middleman() const { return managed_callable_middleman; }
- _FORCE_INLINE_ const Dictionary &get_scripts_metadata() {
- if (scripts_metadata_invalidated) {
- _load_scripts_metadata();
- }
- return scripts_metadata;
- }
+ void lookup_scripts_in_assembly(GDMonoAssembly *p_assembly);
- _FORCE_INLINE_ ManagedCallableMiddleman *get_managed_callable_middleman() const { return managed_callable_middleman; }
+ const DotNetScriptLookupInfo *lookup_dotnet_script(const String &p_script_path) const {
+ return dotnet_script_lookup_map.getptr(p_script_path);
+ }
String get_name() const override;
@@ -542,7 +550,7 @@ public:
class ResourceFormatLoaderCSharpScript : public ResourceFormatLoader {
public:
- RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false) override;
+ RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
void get_recognized_extensions(List<String> *p_extensions) const override;
bool handles_type(const String &p_type) const override;
String get_resource_type(const String &p_path) const override;
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln
index 56c0cb7703..d1868f52ef 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln
@@ -2,6 +2,12 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.NET.Sdk", "Godot.NET.Sdk\Godot.NET.Sdk.csproj", "{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.SourceGenerators", "Godot.SourceGenerators\Godot.SourceGenerators.csproj", "{32D31B23-2A45-4099-B4F5-95B4C8FF7D9F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.SourceGenerators.Sample", "Godot.SourceGenerators.Sample\Godot.SourceGenerators.Sample.csproj", "{7297A614-8DF5-43DE-9EAD-99671B26BD1F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharp", "..\..\glue\GodotSharp\GodotSharp\GodotSharp.csproj", "{AEBF0036-DA76-4341-B651-A3F2856AB2FA}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -12,5 +18,17 @@ Global
{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {32D31B23-2A45-4099-B4F5-95B4C8FF7D9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {32D31B23-2A45-4099-B4F5-95B4C8FF7D9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {32D31B23-2A45-4099-B4F5-95B4C8FF7D9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {32D31B23-2A45-4099-B4F5-95B4C8FF7D9F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7297A614-8DF5-43DE-9EAD-99671B26BD1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7297A614-8DF5-43DE-9EAD-99671B26BD1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7297A614-8DF5-43DE-9EAD-99671B26BD1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7297A614-8DF5-43DE-9EAD-99671B26BD1F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
index 8304d9e321..4e9e7184da 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
@@ -8,43 +8,34 @@
<PackageId>Godot.NET.Sdk</PackageId>
<Version>4.0.0</Version>
- <PackageProjectUrl>https://github.com/godotengine/godot/tree/master/modules/mono/editor/Godot.NET.Sdk</PackageProjectUrl>
+ <PackageVersion>$(PackageVersion_Godot_NET_Sdk)</PackageVersion>
+ <RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/editor/Godot.NET.Sdk</RepositoryUrl>
+ <PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
<PackageType>MSBuildSdk</PackageType>
<PackageTags>MSBuildSdk</PackageTags>
+ <PackageLicenseExpression>MIT</PackageLicenseExpression>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
- </PropertyGroup>
- <PropertyGroup>
- <NuspecFile>Godot.NET.Sdk.nuspec</NuspecFile>
- <GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);SetNuSpecProperties</GenerateNuspecDependsOn>
+ <!-- Exclude target framework from the package dependencies as we don't include the build output -->
+ <SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
+ <IncludeBuildOutput>false</IncludeBuildOutput>
</PropertyGroup>
- <Target Name="ReadGodotNETSdkVersion" BeforeTargets="BeforeBuild;BeforeRebuild;CoreCompile">
- <PropertyGroup>
- <PackageVersion>$([System.IO.File]::ReadAllText('$(ProjectDir)Godot.NET.Sdk_PackageVersion.txt').Trim())</PackageVersion>
- </PropertyGroup>
- </Target>
-
- <Target Name="SetNuSpecProperties" Condition=" Exists('$(NuspecFile)') " DependsOnTargets="ReadGodotNETSdkVersion">
- <PropertyGroup>
- <NuspecProperties>
- id=$(PackageId);
- description=$(Description);
- authors=$(Authors);
- version=$(PackageVersion);
- packagetype=$(PackageType);
- tags=$(PackageTags);
- projecturl=$(PackageProjectUrl)
- </NuspecProperties>
- </PropertyGroup>
- </Target>
+ <ItemGroup>
+ <!-- Package Sdk\Sdk.props and Sdk\Sdk.targets file -->
+ <None Include="Sdk\Sdk.props" Pack="true" PackagePath="Sdk" />
+ <None Include="Sdk\Sdk.targets" Pack="true" PackagePath="Sdk" />
+ <!-- SdkPackageVersions.props -->
+ <None Include="..\..\..\SdkPackageVersions.props" Pack="true" PackagePath="Sdk">
+ <Link>Sdk\SdkPackageVersions.props</Link>
+ </None>
+ </ItemGroup>
<Target Name="CopyNupkgToSConsOutputDir" AfterTargets="Pack">
<PropertyGroup>
<GodotSourceRootPath>$(SolutionDir)\..\..\..\..\</GodotSourceRootPath>
<GodotOutputDataDir>$(GodotSourceRootPath)\bin\GodotSharp\</GodotOutputDataDir>
</PropertyGroup>
- <Copy SourceFiles="$(OutputPath)$(PackageId).$(PackageVersion).nupkg"
- DestinationFolder="$(GodotOutputDataDir)Tools\nupkgs\" />
+ <Copy SourceFiles="$(PackageOutputPath)$(PackageId).$(PackageVersion).nupkg" DestinationFolder="$(GodotOutputDataDir)Tools\nupkgs\" />
</Target>
</Project>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec
deleted file mode 100644
index ba68a4da43..0000000000
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<package xmlns="http://schemas.microsoft.com/packaging/2011/10/nuspec.xsd">
- <metadata>
- <id>$id$</id>
- <version>$version$</version>
- <description>$description$</description>
- <authors>$authors$</authors>
- <owners>$authors$</owners>
- <projectUrl>$projecturl$</projectUrl>
- <requireLicenseAcceptance>false</requireLicenseAcceptance>
- <license type="expression">MIT</license>
- <licenseUrl>https://licenses.nuget.org/MIT</licenseUrl>
- <tags>$tags$</tags>
- <packageTypes>
- <packageType name="$packagetype$" />
- </packageTypes>
- <repository url="$projecturl$" />
- </metadata>
- <files>
- <file src="Sdk\**" target="Sdk" />
- </files>
-</package>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt
deleted file mode 100644
index 34749489b9..0000000000
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt
+++ /dev/null
@@ -1 +0,0 @@
-4.0.0-dev3
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 5febcf3175..0128f5c706 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
@@ -1,4 +1,6 @@
<Project>
+ <Import Project="$(MSBuildThisFileDirectory)\SdkPackageVersions.props" />
+
<PropertyGroup>
<!-- Determines if we should import Microsoft.NET.Sdk, if it wasn't already imported. -->
<GodotSdkImportsMicrosoftNetSdk Condition=" '$(UsingMicrosoftNETSdk)' != 'true' ">true</GodotSdkImportsMicrosoftNetSdk>
@@ -94,6 +96,7 @@
<DefineConstants>$(GodotDefineConstants);$(DefineConstants)</DefineConstants>
</PropertyGroup>
+ <!-- Godot API references -->
<ItemGroup>
<!--
TODO:
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets
index f5afd75505..92e299d2f3 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets
@@ -14,4 +14,9 @@
-->
<DefineConstants Condition=" '$(GodotRealTIsDouble)' == 'true' ">GODOT_REAL_T_IS_DOUBLE;$(DefineConstants)</DefineConstants>
</PropertyGroup>
+
+ <!-- C# source generators -->
+ <ItemGroup Condition=" '$(DisableImplicitGodotGeneratorReferences)' != 'true' ">
+ <PackageReference Include="Godot.SourceGenerators" Version="$(PackageVersion_Godot_SourceGenerators)" />
+ </ItemGroup>
</Project>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs
new file mode 100644
index 0000000000..5eaebc4474
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs
@@ -0,0 +1,15 @@
+namespace Godot.SourceGenerators.Sample
+{
+ partial class Bar : Godot.Object
+ {
+ }
+
+ // Foo in another file
+ partial class Foo
+ {
+ }
+
+ partial class NotSameNameAsFile : Godot.Object
+ {
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs
new file mode 100644
index 0000000000..21a5bfe560
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs
@@ -0,0 +1,11 @@
+namespace Godot.SourceGenerators.Sample
+{
+ partial class Foo : Godot.Object
+ {
+ }
+
+ // Foo again in the same file
+ partial class Foo
+ {
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj
new file mode 100644
index 0000000000..24f7909861
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj
@@ -0,0 +1,31 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>netstandard2.1</TargetFramework>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <!-- $(GodotProjectDir) would normally be defined by the Godot.NET.Sdk -->
+ <GodotProjectDir>$(MSBuildProjectDirectory)</GodotProjectDir>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <!-- The emitted files are not part of the compilation nor design.
+ They're only for peeking at the generated sources. Sometimes the
+ emitted files get corrupted, but that won't break anything. -->
+ <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
+ <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\glue\GodotSharp\GodotSharp\GodotSharp.csproj">
+ <Private>False</Private>
+ </ProjectReference>
+ <ProjectReference Include="..\Godot.SourceGenerators\Godot.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
+ </ItemGroup>
+
+ <!-- This file is imported automatically when using PackageReference to
+ reference Godot.SourceGenerators, but not when using ProjectReference -->
+ <Import Project="..\Godot.SourceGenerators\Godot.SourceGenerators.props" />
+
+</Project>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
new file mode 100644
index 0000000000..4867c986e6
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
@@ -0,0 +1,33 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Godot.SourceGenerators
+{
+ public static class Common
+ {
+ public static void ReportNonPartialGodotScriptClass(
+ GeneratorExecutionContext context,
+ ClassDeclarationSyntax cds, INamedTypeSymbol symbol
+ )
+ {
+ string message =
+ "Missing partial modifier on declaration of type '" +
+ $"{symbol.FullQualifiedName()}' which is a subclass of '{GodotClasses.Object}'";
+
+ string description = $"{message}. Subclasses of '{GodotClasses.Object}' must be " +
+ "declared with the partial modifier or annotated with the " +
+ $"attribute '{GodotClasses.DisableGodotGeneratorsAttr}'.";
+
+ context.ReportDiagnostic(Diagnostic.Create(
+ new DiagnosticDescriptor(id: "GODOT-G0001",
+ title: message,
+ messageFormat: message,
+ category: "Usage",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true,
+ description),
+ cds.GetLocation(),
+ cds.SyntaxTree.FilePath));
+ }
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
new file mode 100644
index 0000000000..e16f72f43a
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
@@ -0,0 +1,89 @@
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Godot.SourceGenerators
+{
+ static class ExtensionMethods
+ {
+ public static bool TryGetGlobalAnalyzerProperty(
+ this GeneratorExecutionContext context, string property, out string? value
+ ) => context.AnalyzerConfigOptions.GlobalOptions
+ .TryGetValue("build_property." + property, out value);
+
+ private static bool InheritsFrom(this INamedTypeSymbol? symbol, string baseName)
+ {
+ if (symbol == null)
+ return false;
+
+ while (true)
+ {
+ if (symbol.ToString() == baseName)
+ {
+ return true;
+ }
+
+ if (symbol.BaseType != null)
+ {
+ symbol = symbol.BaseType;
+ continue;
+ }
+
+ break;
+ }
+
+ return false;
+ }
+
+ private static bool IsGodotScriptClass(
+ this ClassDeclarationSyntax cds, Compilation compilation,
+ out INamedTypeSymbol? symbol
+ )
+ {
+ var sm = compilation.GetSemanticModel(cds.SyntaxTree);
+
+ var classTypeSymbol = sm.GetDeclaredSymbol(cds);
+
+ if (classTypeSymbol?.BaseType == null
+ || !classTypeSymbol.BaseType.InheritsFrom(GodotClasses.Object))
+ {
+ symbol = null;
+ return false;
+ }
+
+ symbol = classTypeSymbol;
+ return true;
+ }
+
+ public static IEnumerable<(ClassDeclarationSyntax cds, INamedTypeSymbol symbol)> SelectGodotScriptClasses(
+ this IEnumerable<ClassDeclarationSyntax> source,
+ Compilation compilation
+ )
+ {
+ foreach (var cds in source)
+ {
+ if (cds.IsGodotScriptClass(compilation, out var symbol))
+ yield return (cds, symbol!);
+ }
+ }
+
+ public static bool IsPartial(this ClassDeclarationSyntax cds)
+ => cds.Modifiers.Any(SyntaxKind.PartialKeyword);
+
+ public static bool HasDisableGeneratorsAttribute(this INamedTypeSymbol symbol)
+ => symbol.GetAttributes().Any(attr =>
+ attr.AttributeClass?.ToString() == GodotClasses.DisableGodotGeneratorsAttr);
+
+ private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } =
+ SymbolDisplayFormat.FullyQualifiedFormat
+ .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted);
+
+ public static string FullQualifiedName(this INamedTypeSymbol symbol)
+ => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal);
+
+ public static string FullQualifiedName(this INamespaceSymbol namespaceSymbol)
+ => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj
new file mode 100644
index 0000000000..224d7e5b5a
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj
@@ -0,0 +1,40 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ <LangVersion>8.0</LangVersion>
+ <Nullable>enable</Nullable>
+ </PropertyGroup>
+ <PropertyGroup>
+ <Description>Core C# source generator for Godot projects.</Description>
+ <Authors>Godot Engine contributors</Authors>
+
+ <PackageId>Godot.SourceGenerators</PackageId>
+ <Version>4.0.0</Version>
+ <PackageVersion>$(PackageVersion_Godot_SourceGenerators)</PackageVersion>
+ <RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators</RepositoryUrl>
+ <PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
+ <PackageLicenseExpression>MIT</PackageLicenseExpression>
+
+ <GeneratePackageOnBuild>true</GeneratePackageOnBuild> <!-- Generates a package at build -->
+ <IncludeBuildOutput>false</IncludeBuildOutput> <!-- Do not include the generator as a lib dependency -->
+ </PropertyGroup>
+ <ItemGroup>
+ <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" PrivateAssets="all" />
+ <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.1" PrivateAssets="all" />
+ </ItemGroup>
+ <ItemGroup>
+ <!-- Package the generator in the analyzer directory of the nuget package -->
+ <None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
+
+ <!-- Package the props file -->
+ <None Include="Godot.SourceGenerators.props" Pack="true" PackagePath="build" Visible="false" />
+ </ItemGroup>
+
+ <Target Name="CopyNupkgToSConsOutputDir" AfterTargets="Pack">
+ <PropertyGroup>
+ <GodotSourceRootPath>$(SolutionDir)\..\..\..\..\</GodotSourceRootPath>
+ <GodotOutputDataDir>$(GodotSourceRootPath)\bin\GodotSharp\</GodotOutputDataDir>
+ </PropertyGroup>
+ <Copy SourceFiles="$(PackageOutputPath)$(PackageId).$(PackageVersion).nupkg" DestinationFolder="$(GodotOutputDataDir)Tools\nupkgs\" />
+ </Target>
+</Project>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props
new file mode 100644
index 0000000000..f9b47ad5b1
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props
@@ -0,0 +1,7 @@
+<Project>
+ <ItemGroup>
+ <!-- $(GodotProjectDir) is defined by Godot.NET.Sdk -->
+ <CompilerVisibleProperty Include="GodotProjectDir" />
+ <CompilerVisibleProperty Include="GodotScriptPathAttributeGenerator" />
+ </ItemGroup>
+</Project>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs
new file mode 100644
index 0000000000..29e41d155a
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs
@@ -0,0 +1,9 @@
+namespace Godot.SourceGenerators
+{
+ public static class GodotClasses
+ {
+ public const string Object = "Godot.Object";
+ public const string DisableGodotGeneratorsAttr = "Godot.DisableGodotGeneratorsAttribute";
+ public const string AssemblyHasScriptsAttr = "Godot.AssemblyHasScriptsAttribute";
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs
new file mode 100644
index 0000000000..a51728e221
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs
@@ -0,0 +1,182 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Text;
+
+namespace Godot.SourceGenerators
+{
+ [Generator]
+ public class ScriptPathAttributeGenerator : ISourceGenerator
+ {
+ public void Execute(GeneratorExecutionContext context)
+ {
+ if (context.TryGetGlobalAnalyzerProperty("GodotScriptPathAttributeGenerator", out string? toggle)
+ && toggle == "disabled")
+ {
+ return;
+ }
+
+ // NOTE: IsNullOrEmpty doesn't work well with nullable checks
+ // ReSharper disable once ReplaceWithStringIsNullOrEmpty
+ if (!context.TryGetGlobalAnalyzerProperty("GodotProjectDir", out string? godotProjectDir)
+ || godotProjectDir!.Length == 0)
+ {
+ throw new InvalidOperationException("Property 'GodotProjectDir' is null or empty.");
+ }
+
+ var godotClasses = context.Compilation.SyntaxTrees
+ .SelectMany(tree =>
+ tree.GetRoot().DescendantNodes()
+ .OfType<ClassDeclarationSyntax>()
+ // Ignore inner classes
+ .Where(cds => !(cds.Parent is ClassDeclarationSyntax))
+ .SelectGodotScriptClasses(context.Compilation)
+ // Report and skip non-partial classes
+ .Where(x =>
+ {
+ if (x.cds.IsPartial() || x.symbol.HasDisableGeneratorsAttribute())
+ return true;
+ Common.ReportNonPartialGodotScriptClass(context, x.cds, x.symbol);
+ 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)
+ .GroupBy(x => x.symbol)
+ .ToDictionary(g => g.Key, g => g.Select(x => x.cds));
+
+ foreach (var godotClass in godotClasses)
+ {
+ VisitGodotScriptClass(context, godotProjectDir,
+ symbol: godotClass.Key,
+ classDeclarations: godotClass.Value);
+ }
+
+ if (godotClasses.Count <= 0)
+ return;
+
+ AddScriptTypesAssemblyAttr(context, godotClasses);
+ }
+
+ private static void VisitGodotScriptClass(
+ GeneratorExecutionContext context,
+ string godotProjectDir,
+ INamedTypeSymbol symbol,
+ IEnumerable<ClassDeclarationSyntax> classDeclarations
+ )
+ {
+ var attributes = new StringBuilder();
+
+ // Remember syntax trees for which we already added an attribute, to prevent unnecessary duplicates.
+ var attributedTrees = new List<SyntaxTree>();
+
+ foreach (var cds in classDeclarations)
+ {
+ if (attributedTrees.Contains(cds.SyntaxTree))
+ continue;
+
+ attributedTrees.Add(cds.SyntaxTree);
+
+ if (attributes.Length != 0)
+ attributes.Append("\n");
+
+ attributes.Append(@"[ScriptPathAttribute(""res://");
+ attributes.Append(RelativeToDir(cds.SyntaxTree.FilePath, godotProjectDir));
+ attributes.Append(@""")]");
+ }
+
+ string className = symbol.Name;
+
+ INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
+ string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
+ namespaceSymbol.FullQualifiedName() :
+ string.Empty;
+ bool hasNamespace = classNs.Length != 0;
+
+ string uniqueName = hasNamespace ?
+ classNs + "." + className + "_ScriptPath_Generated" :
+ className + "_ScriptPath_Generated";
+
+ var source = new StringBuilder();
+
+ // using Godot;
+ // namespace {classNs} {
+ // {attributesBuilder}
+ // partial class {className} { }
+ // }
+
+ source.Append("using Godot;\n");
+
+ if (hasNamespace)
+ {
+ source.Append("namespace ");
+ source.Append(classNs);
+ source.Append(" {\n\n");
+ }
+
+ source.Append(attributes);
+ source.Append("\n partial class ");
+ source.Append(className);
+ source.Append("\n{\n}\n");
+
+ if (hasNamespace)
+ {
+ source.Append("\n}\n");
+ }
+
+ context.AddSource(uniqueName, SourceText.From(source.ToString(), Encoding.UTF8));
+ }
+
+ private static void AddScriptTypesAssemblyAttr(GeneratorExecutionContext context,
+ Dictionary<INamedTypeSymbol, IEnumerable<ClassDeclarationSyntax>> godotClasses)
+ {
+ var sourceBuilder = new StringBuilder();
+
+ sourceBuilder.Append("[assembly:");
+ sourceBuilder.Append(GodotClasses.AssemblyHasScriptsAttr);
+ sourceBuilder.Append("(new System.Type[] {");
+
+ bool first = true;
+
+ foreach (var godotClass in godotClasses)
+ {
+ var qualifiedName = godotClass.Key.ToDisplayString(
+ NullableFlowState.NotNull, SymbolDisplayFormat.FullyQualifiedFormat);
+ if (!first)
+ sourceBuilder.Append(", ");
+ first = false;
+ sourceBuilder.Append("typeof(");
+ sourceBuilder.Append(qualifiedName);
+ sourceBuilder.Append(")");
+ }
+
+ sourceBuilder.Append("})]\n");
+
+ context.AddSource("AssemblyScriptTypes_Generated",
+ SourceText.From(sourceBuilder.ToString(), Encoding.UTF8));
+ }
+
+ public void Initialize(GeneratorInitializationContext context)
+ {
+ }
+
+ private static string RelativeToDir(string path, string dir)
+ {
+ // Make sure the directory ends with a path separator
+ dir = Path.Combine(dir, " ").TrimEnd();
+
+ if (Path.DirectorySeparatorChar == '\\')
+ dir = dir.Replace("/", "\\") + "\\";
+
+ var fullPath = new Uri(Path.GetFullPath(path), UriKind.Absolute);
+ var relRoot = new Uri(Path.GetFullPath(dir), UriKind.Absolute);
+
+ // MakeRelativeUri converts spaces to %20, hence why we need UnescapeDataString
+ return Uri.UnescapeDataString(relRoot.MakeRelativeUri(fullPath).ToString());
+ }
+ }
+}
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
index 4e2c0f17cc..cdac9acb25 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
@@ -1,11 +1,5 @@
using System;
-using GodotTools.Core;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
using Microsoft.Build.Construction;
-using Microsoft.Build.Globbing;
namespace GodotTools.ProjectEditor
{
@@ -31,47 +25,6 @@ namespace GodotTools.ProjectEditor
return root != null ? new MSBuildProject(root) : null;
}
- private static List<string> GetAllFilesRecursive(string rootDirectory, string mask)
- {
- string[] files = Directory.GetFiles(rootDirectory, mask, SearchOption.AllDirectories);
-
- // We want relative paths
- for (int i = 0; i < files.Length; i++)
- {
- files[i] = files[i].RelativeToPath(rootDirectory);
- }
-
- return new List<string>(files);
- }
-
- // NOTE: Assumes auto-including items. Only used by the scripts metadata generator, which will be replaced with source generators in the future.
- public static IEnumerable<string> GetIncludeFiles(string projectPath, string itemType)
- {
- var excluded = new List<string>();
- var includedFiles = GetAllFilesRecursive(Path.GetDirectoryName(projectPath), "*.cs");
-
- var root = ProjectRootElement.Open(projectPath);
- Debug.Assert(root != null);
-
- foreach (var item in root.Items)
- {
- if (string.IsNullOrEmpty(item.Condition))
- continue;
-
- if (item.ItemType != itemType)
- continue;
-
- string normalizedRemove = item.Remove.NormalizePath();
-
- var glob = MSBuildGlob.Parse(normalizedRemove);
- excluded.AddRange(includedFiles.Where(includedFile => glob.IsMatch(includedFile)));
- }
-
- includedFiles.RemoveAll(f => excluded.Contains(f));
-
- return includedFiles;
- }
-
public static void MigrateToProjectSdksStyle(MSBuildProject project, string projectName)
{
var origRoot = project.Root;
diff --git a/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets b/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets
index 1d382dcb43..aab2d73bdd 100644
--- a/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets
+++ b/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets
@@ -3,7 +3,6 @@
<Target Name="SetPropertiesForGenerateGodotNupkgsVersions">
<PropertyGroup>
- <GodotNETSdkPackageVersionFile>$(SolutionDir)..\Godot.NET.Sdk\Godot.NET.Sdk\Godot.NET.Sdk_PackageVersion.txt</GodotNETSdkPackageVersionFile>
<GeneratedGodotNupkgsVersionsFile>$(IntermediateOutputPath)GodotNupkgsVersions.g.cs</GeneratedGodotNupkgsVersionsFile>
</PropertyGroup>
</Target>
@@ -18,13 +17,14 @@
</Target>
<Target Name="_GenerateGodotNupkgsVersionsFile"
DependsOnTargets="SetPropertiesForGenerateGodotNupkgsVersions"
- Inputs="$(MSBuildProjectFile);@(GodotNETSdkPackageVersionFile)"
+ Inputs="$(MSBuildProjectFile);$(MSBuildThisFileDirectory);$(MSBuildProjectFile)\..\..\..\SdkPackageVersions.props"
Outputs="$(GeneratedGodotNupkgsVersionsFile)">
<PropertyGroup>
<GenerateGodotNupkgsVersionsCode><![CDATA[
namespace $(RootNamespace) {
public class GeneratedGodotNupkgsVersions {
- public const string GodotNETSdk = "$([System.IO.File]::ReadAllText('$(GodotNETSdkPackageVersionFile)').Trim())"%3b
+ public const string GodotNETSdk = "$(PackageVersion_Godot_NET_Sdk)"%3b
+ public const string GodotSourceGenerators = "$(PackageVersion_Godot_SourceGenerators)"%3b
}
}
]]></GenerateGodotNupkgsVersionsCode>
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
index b96b0c8175..2b6f972529 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
@@ -218,43 +218,12 @@ namespace GodotTools.Build
Godot.GD.PushError("Failed to setup Godot NuGet Offline Packages: " + e.Message);
}
- GenerateEditorScriptMetadata();
-
if (GodotSharpEditor.Instance.SkipBuildBeforePlaying)
return true; // Requested play from an external editor/IDE which already built the project
return BuildProjectBlocking("Debug");
}
- // NOTE: This will be replaced with C# source generators in 4.0
- public static void GenerateEditorScriptMetadata()
- {
- string editorScriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, "scripts_metadata.editor");
- string playerScriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, "scripts_metadata.editor_player");
-
- CsProjOperations.GenerateScriptsMetadata(GodotSharpDirs.ProjectCsProjPath, editorScriptsMetadataPath);
-
- if (!File.Exists(editorScriptsMetadataPath))
- return;
-
- try
- {
- File.Copy(editorScriptsMetadataPath, playerScriptsMetadataPath);
- }
- catch (IOException e)
- {
- throw new IOException("Failed to copy scripts metadata file.", innerException: e);
- }
- }
-
- // NOTE: This will be replaced with C# source generators in 4.0
- public static string GenerateExportedGameScriptMetadata(bool isDebug)
- {
- string scriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, $"scripts_metadata.{(isDebug ? "debug" : "release")}");
- CsProjOperations.GenerateScriptsMetadata(GodotSharpDirs.ProjectCsProjPath, scriptsMetadataPath);
- return scriptsMetadataPath;
- }
-
public static void Initialize()
{
// Build tool settings
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
index 708ec73454..ed69c2b833 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
@@ -43,8 +43,6 @@ namespace GodotTools.Build
GD.PushError("Failed to setup Godot NuGet Offline Packages: " + e.Message);
}
- BuildManager.GenerateEditorScriptMetadata();
-
if (!BuildManager.BuildProjectBlocking("Debug"))
return; // Build failed
@@ -74,8 +72,6 @@ namespace GodotTools.Build
GD.PushError("Failed to setup Godot NuGet Offline Packages: " + e.Message);
}
- BuildManager.GenerateEditorScriptMetadata();
-
if (!BuildManager.BuildProjectBlocking("Debug", targets: new[] {"Rebuild"}))
return; // Build failed
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
index 5ef55fea49..774c49e705 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
@@ -86,7 +86,7 @@ namespace GodotTools.Build
{
case BuildTool.DotnetCli:
{
- string dotnetCliPath = OS.PathWhich("dotnet");
+ string dotnetCliPath = FindBuildEngineOnUnix("dotnet");
if (!string.IsNullOrEmpty(dotnetCliPath))
return (dotnetCliPath, BuildTool.DotnetCli);
GD.PushError($"Cannot find executable for '{BuildManager.PropNameDotnetCli}'. Fallback to MSBuild from Mono.");
@@ -122,7 +122,11 @@ namespace GodotTools.Build
if (OS.IsMacOS)
{
result.Add("/Library/Frameworks/Mono.framework/Versions/Current/bin/");
+ result.Add("/opt/local/bin/");
result.Add("/usr/local/var/homebrew/linked/mono/bin/");
+ result.Add("/usr/local/bin/");
+ result.Add("/usr/local/bin/dotnet/");
+ result.Add("/usr/local/share/dotnet/");
}
result.Add("/opt/novell/mono/bin/");
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs
index 793ef7fd71..16dd1c8c6b 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs
@@ -290,7 +290,8 @@ namespace GodotTools.Build
private static readonly (string packageId, string packageVersion)[] PackagesToAdd =
{
- ("Godot.NET.Sdk", GeneratedGodotNupkgsVersions.GodotNETSdk)
+ ("Godot.NET.Sdk", GeneratedGodotNupkgsVersions.GodotNETSdk),
+ ("Godot.SourceGenerators", GeneratedGodotNupkgsVersions.GodotSourceGenerators),
};
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs b/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs
index 1d800b8151..e43f10804d 100644
--- a/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs
@@ -1,11 +1,6 @@
using Godot;
using System;
-using System.Linq;
-using Godot.Collections;
-using GodotTools.Internals;
using GodotTools.ProjectEditor;
-using File = GodotTools.Utils.File;
-using Directory = GodotTools.Utils.Directory;
namespace GodotTools
{
@@ -23,86 +18,5 @@ namespace GodotTools
return string.Empty;
}
}
-
- private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
-
- private static ulong ConvertToTimestamp(this DateTime value)
- {
- TimeSpan elapsedTime = value - Epoch;
- return (ulong)elapsedTime.TotalSeconds;
- }
-
- private static bool TryParseFileMetadata(string includeFile, ulong modifiedTime, out Dictionary fileMetadata)
- {
- fileMetadata = null;
-
- var parseError = ScriptClassParser.ParseFile(includeFile, out var classes, out string errorStr);
-
- if (parseError != Error.Ok)
- {
- GD.PushError($"Failed to determine namespace and class for script: {includeFile}. Parse error: {errorStr ?? parseError.ToString()}");
- return false;
- }
-
- string searchName = System.IO.Path.GetFileNameWithoutExtension(includeFile);
-
- var firstMatch = classes.FirstOrDefault(classDecl =>
- classDecl.BaseCount != 0 && // If it doesn't inherit anything, it can't be a Godot.Object.
- classDecl.SearchName == searchName // Filter by the name we're looking for
- );
-
- if (firstMatch == null)
- return false; // Not found
-
- fileMetadata = new Dictionary
- {
- ["modified_time"] = $"{modifiedTime}",
- ["class"] = new Dictionary
- {
- ["namespace"] = firstMatch.Namespace,
- ["class_name"] = firstMatch.Name,
- ["nested"] = firstMatch.Nested
- }
- };
-
- return true;
- }
-
- public static void GenerateScriptsMetadata(string projectPath, string outputPath)
- {
- var metadataDict = Internal.GetScriptsMetadataOrNothing().Duplicate();
-
- bool IsUpToDate(string includeFile, ulong modifiedTime)
- {
- return metadataDict.TryGetValue(includeFile, out var oldFileVar) &&
- ulong.TryParse(((Dictionary)oldFileVar)["modified_time"] as string,
- out ulong storedModifiedTime) && storedModifiedTime == modifiedTime;
- }
-
- var outdatedFiles = ProjectUtils.GetIncludeFiles(projectPath, "Compile")
- .Select(path => ("res://" + path).SimplifyGodotPath())
- .ToDictionary(path => path, path => File.GetLastWriteTime(path).ConvertToTimestamp())
- .Where(pair => !IsUpToDate(includeFile: pair.Key, modifiedTime: pair.Value))
- .ToArray();
-
- foreach (var pair in outdatedFiles)
- {
- metadataDict.Remove(pair.Key);
-
- string includeFile = pair.Key;
-
- if (TryParseFileMetadata(includeFile, modifiedTime: pair.Value, out var fileMetadata))
- metadataDict[includeFile] = fileMetadata;
- }
-
- string json = metadataDict.Count <= 0 ? "{}" : JSON.Print(metadataDict);
-
- string baseDir = outputPath.GetBaseDir();
-
- if (!Directory.Exists(baseDir))
- Directory.CreateDirectory(baseDir);
-
- File.WriteAllText(outputPath, json);
- }
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
index e9bb701562..270be8b6bf 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
@@ -157,9 +157,6 @@ namespace GodotTools.Export
string buildConfig = isDebug ? "ExportDebug" : "ExportRelease";
- string scriptsMetadataPath = BuildManager.GenerateExportedGameScriptMetadata(isDebug);
- AddFile(scriptsMetadataPath, scriptsMetadataPath);
-
if (!BuildManager.BuildProjectBlocking(buildConfig, platform: platform))
throw new Exception("Failed to build project");
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
index 7e5049e4b7..77370090ec 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
@@ -1,7 +1,5 @@
-using System;
using System.Runtime.CompilerServices;
using Godot;
-using Godot.Collections;
using GodotTools.IdeMessaging.Requests;
namespace GodotTools.Internals
@@ -42,9 +40,6 @@ namespace GodotTools.Internals
public static void EditorNodeShowScriptScreen() => internal_EditorNodeShowScriptScreen();
- public static Dictionary<string, object> GetScriptsMetadataOrNothing() =>
- internal_GetScriptsMetadataOrNothing(typeof(Dictionary<string, object>));
-
public static string MonoWindowsInstallRoot => internal_MonoWindowsInstallRoot();
public static void EditorRunPlay() => internal_EditorRunPlay();
@@ -101,9 +96,6 @@ namespace GodotTools.Internals
private static extern void internal_EditorNodeShowScriptScreen();
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern Dictionary<string, object> internal_GetScriptsMetadataOrNothing(Type dictType);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_MonoWindowsInstallRoot();
[MethodImpl(MethodImplOptions.InternalCall)]
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs
deleted file mode 100644
index c72a84c513..0000000000
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using Godot;
-using Godot.Collections;
-
-namespace GodotTools.Internals
-{
- public static class ScriptClassParser
- {
- public class ClassDecl
- {
- public string Name { get; }
- public string Namespace { get; }
- public bool Nested { get; }
- public long BaseCount { get; }
-
- public string SearchName => Nested ?
- Name.Substring(Name.LastIndexOf(".", StringComparison.Ordinal) + 1) :
- Name;
-
- public ClassDecl(string name, string @namespace, bool nested, long baseCount)
- {
- Name = name;
- Namespace = @namespace;
- Nested = nested;
- BaseCount = baseCount;
- }
- }
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern Error internal_ParseFile(string filePath, Array<Dictionary> classes, out string errorStr);
-
- public static Error ParseFile(string filePath, out IEnumerable<ClassDecl> classes, out string errorStr)
- {
- var classesArray = new Array<Dictionary>();
- var error = internal_ParseFile(filePath, classesArray, out errorStr);
- if (error != Error.Ok)
- {
- classes = null;
- return error;
- }
-
- var classesList = new List<ClassDecl>();
-
- foreach (var classDeclDict in classesArray)
- {
- classesList.Add(new ClassDecl(
- (string)classDeclDict["name"],
- (string)classDeclDict["namespace"],
- (bool)classDeclDict["nested"],
- (long)classDeclDict["base_count"]
- ));
- }
-
- classes = classesList;
-
- return Error.Ok;
- }
- }
-}
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 38e403b2e1..b48e5df9eb 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -39,6 +39,7 @@
#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/string/ucaps.h"
+#include "main/main.h"
#include "../glue/cs_glue_version.gen.h"
#include "../godotsharp_defs.h"
@@ -783,6 +784,72 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
}
}
+void BindingsGenerator::_generate_array_extensions(StringBuilder &p_output) {
+ p_output.append("using System;\n\n");
+ p_output.append("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
+ // The class where we put the extensions doesn't matter, so just use "GD".
+ p_output.append(INDENT1 "public static partial class " BINDINGS_GLOBAL_SCOPE_CLASS "\n" INDENT1 "{");
+
+#define ARRAY_IS_EMPTY(m_type) \
+ p_output.append("\n" INDENT2 "/// <summary>\n"); \
+ p_output.append(INDENT2 "/// Returns true if this " #m_type " array is empty or doesn't exist.\n"); \
+ p_output.append(INDENT2 "/// </summary>\n"); \
+ p_output.append(INDENT2 "/// <param name=\"instance\">The " #m_type " array check.</param>\n"); \
+ p_output.append(INDENT2 "/// <returns>Whether or not the array is empty.</returns>\n"); \
+ p_output.append(INDENT2 "public static bool IsEmpty(this " #m_type "[] instance)\n"); \
+ p_output.append(INDENT2 OPEN_BLOCK); \
+ p_output.append(INDENT3 "return instance == null || instance.Length == 0;\n"); \
+ p_output.append(INDENT2 CLOSE_BLOCK);
+
+#define ARRAY_JOIN(m_type) \
+ p_output.append("\n" INDENT2 "/// <summary>\n"); \
+ p_output.append(INDENT2 "/// Converts this " #m_type " array to a string delimited by the given string.\n"); \
+ p_output.append(INDENT2 "/// </summary>\n"); \
+ p_output.append(INDENT2 "/// <param name=\"instance\">The " #m_type " array to convert.</param>\n"); \
+ p_output.append(INDENT2 "/// <param name=\"delimiter\">The delimiter to use between items.</param>\n"); \
+ p_output.append(INDENT2 "/// <returns>A single string with all items.</returns>\n"); \
+ p_output.append(INDENT2 "public static string Join(this " #m_type "[] instance, string delimiter = \", \")\n"); \
+ p_output.append(INDENT2 OPEN_BLOCK); \
+ p_output.append(INDENT3 "return String.Join(delimiter, instance);\n"); \
+ p_output.append(INDENT2 CLOSE_BLOCK);
+
+#define ARRAY_STRINGIFY(m_type) \
+ p_output.append("\n" INDENT2 "/// <summary>\n"); \
+ p_output.append(INDENT2 "/// Converts this " #m_type " array to a string with brackets.\n"); \
+ p_output.append(INDENT2 "/// </summary>\n"); \
+ p_output.append(INDENT2 "/// <param name=\"instance\">The " #m_type " array to convert.</param>\n"); \
+ p_output.append(INDENT2 "/// <returns>A single string with all items.</returns>\n"); \
+ p_output.append(INDENT2 "public static string Stringify(this " #m_type "[] instance)\n"); \
+ p_output.append(INDENT2 OPEN_BLOCK); \
+ p_output.append(INDENT3 "return \"[\" + instance.Join() + \"]\";\n"); \
+ p_output.append(INDENT2 CLOSE_BLOCK);
+
+#define ARRAY_ALL(m_type) \
+ ARRAY_IS_EMPTY(m_type) \
+ ARRAY_JOIN(m_type) \
+ ARRAY_STRINGIFY(m_type)
+
+ ARRAY_ALL(byte);
+ ARRAY_ALL(int);
+ ARRAY_ALL(long);
+ ARRAY_ALL(float);
+ ARRAY_ALL(double);
+ ARRAY_ALL(string);
+ ARRAY_ALL(Color);
+ ARRAY_ALL(Vector2);
+ ARRAY_ALL(Vector2i);
+ ARRAY_ALL(Vector3);
+ ARRAY_ALL(Vector3i);
+
+#undef ARRAY_ALL
+#undef ARRAY_IS_EMPTY
+#undef ARRAY_JOIN
+#undef ARRAY_STRINGIFY
+
+ p_output.append(INDENT1 CLOSE_BLOCK); // End of GD class.
+ p_output.append(CLOSE_BLOCK); // End of namespace.
+}
+
void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
// Constants (in partial GD class)
@@ -926,6 +993,19 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
compile_items.push_back(output_file);
}
+ // Generate source file for array extensions
+ {
+ StringBuilder extensions_source;
+ _generate_array_extensions(extensions_source);
+ String output_file = path::join(base_gen_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_extensions.cs");
+ Error save_err = _save_file(output_file, extensions_source);
+ if (save_err != OK) {
+ return save_err;
+ }
+
+ compile_items.push_back(output_file);
+ }
+
for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
const TypeInterface &itype = E.get();
@@ -1479,6 +1559,12 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
ERR_FAIL_COND_V_MSG(prop_itype->is_singleton, ERR_BUG,
"Property type is a singleton: '" + p_itype.name + "." + String(p_iprop.cname) + "'.");
+ if (p_itype.api_type == ClassDB::API_CORE) {
+ ERR_FAIL_COND_V_MSG(prop_itype->api_type == ClassDB::API_EDITOR, ERR_BUG,
+ "Property '" + p_itype.name + "." + String(p_iprop.cname) + "' has type '" + prop_itype->name +
+ "' from the editor API. Core API cannot have dependencies on the editor API.");
+ }
+
if (p_iprop.prop_doc && p_iprop.prop_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(p_iprop.prop_doc->description), &p_itype);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
@@ -1575,6 +1661,12 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
ERR_FAIL_COND_V_MSG(return_type->is_singleton, ERR_BUG,
"Method return type is a singleton: '" + p_itype.name + "." + p_imethod.name + "'.");
+ if (p_itype.api_type == ClassDB::API_CORE) {
+ ERR_FAIL_COND_V_MSG(return_type->api_type == ClassDB::API_EDITOR, ERR_BUG,
+ "Method '" + p_itype.name + "." + p_imethod.name + "' has return type '" + return_type->name +
+ "' from the editor API. Core API cannot have dependencies on the editor API.");
+ }
+
String method_bind_field = "__method_bind_" + itos(p_method_bind_count);
String arguments_sig;
@@ -1593,6 +1685,12 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG,
"Argument type is a singleton: '" + iarg.name + "' of method '" + p_itype.name + "." + p_imethod.name + "'.");
+ if (p_itype.api_type == ClassDB::API_CORE) {
+ ERR_FAIL_COND_V_MSG(arg_type->api_type == ClassDB::API_EDITOR, ERR_BUG,
+ "Argument '" + iarg.name + "' of method '" + p_itype.name + "." + p_imethod.name + "' has type '" +
+ arg_type->name + "' from the editor API. Core API cannot have dependencies on the editor API.");
+ }
+
if (iarg.default_argument.size()) {
CRASH_COND_MSG(!_arg_default_value_is_assignable_to_type(iarg.def_param_value, *arg_type),
"Invalid default value for parameter '" + iarg.name + "' of method '" + p_itype.name + "." + p_imethod.name + "'.");
@@ -1806,7 +1904,13 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type);
ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG,
- "Argument type is a singleton: '" + iarg.name + "' of signal" + p_itype.name + "." + p_isignal.name + "'.");
+ "Argument type is a singleton: '" + iarg.name + "' of signal '" + p_itype.name + "." + p_isignal.name + "'.");
+
+ if (p_itype.api_type == ClassDB::API_CORE) {
+ ERR_FAIL_COND_V_MSG(arg_type->api_type == ClassDB::API_EDITOR, ERR_BUG,
+ "Argument '" + iarg.name + "' of signal '" + p_itype.name + "." + p_isignal.name + "' has type '" +
+ arg_type->name + "' from the editor API. Core API cannot have dependencies on the editor API.");
+ }
// Add the current arguments to the signature
@@ -2932,9 +3036,9 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
}
break;
case Variant::FLOAT:
-#ifndef REAL_T_IS_DOUBLE
- r_iarg.default_argument += "f";
-#endif
+ if (r_iarg.type.cname == name_cache.type_float) {
+ r_iarg.default_argument += "f";
+ }
break;
case Variant::STRING:
case Variant::STRING_NAME:
@@ -2947,23 +3051,32 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
r_iarg.default_argument = "\"" + r_iarg.default_argument + "\"";
}
break;
- case Variant::TRANSFORM:
- if (p_val.operator Transform() == Transform()) {
- r_iarg.default_argument.clear();
- }
- r_iarg.default_argument = "new %s(" + r_iarg.default_argument + ")";
+ case Variant::PLANE: {
+ Plane plane = p_val.operator Plane();
+ r_iarg.default_argument = "new Plane(new Vector3(" + plane.normal.operator String() + "), " + rtos(plane.d) + ")";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
- break;
- case Variant::PLANE:
- case Variant::AABB:
+ } break;
+ case Variant::AABB: {
+ AABB aabb = p_val.operator ::AABB();
+ r_iarg.default_argument = "new AABB(new Vector3(" + aabb.position.operator String() + "), new Vector3(" + aabb.position.operator String() + "))";
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ } break;
+ case Variant::RECT2: {
+ Rect2 rect = p_val.operator Rect2();
+ r_iarg.default_argument = "new Rect2(new Vector2(" + rect.position.operator String() + "), new Vector2(" + rect.position.operator String() + "))";
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ } break;
+ case Variant::RECT2I: {
+ Rect2i rect = p_val.operator Rect2i();
+ r_iarg.default_argument = "new Rect2i(new Vector2i(" + rect.position.operator String() + "), new Vector2i(" + rect.position.operator String() + "))";
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ } break;
case Variant::COLOR:
- r_iarg.default_argument = "new Color(1, 1, 1, 1)";
+ r_iarg.default_argument = "new %s(" + r_iarg.default_argument + ")";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
break;
case Variant::VECTOR2:
case Variant::VECTOR2I:
- case Variant::RECT2:
- case Variant::RECT2I:
case Variant::VECTOR3:
case Variant::VECTOR3I:
r_iarg.default_argument = "new %s" + r_iarg.default_argument;
@@ -3001,12 +3114,43 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
r_iarg.default_argument = "new %s {}";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
break;
- case Variant::TRANSFORM2D:
- case Variant::BASIS:
- case Variant::QUAT:
- r_iarg.default_argument = Variant::get_type_name(p_val.get_type()) + ".Identity";
+ case Variant::TRANSFORM2D: {
+ Transform2D transform = p_val.operator Transform2D();
+ if (transform == Transform2D()) {
+ r_iarg.default_argument = "Transform2D.Identity";
+ } else {
+ r_iarg.default_argument = "new Transform2D(new Vector2" + transform.elements[0].operator String() + ", new Vector2" + transform.elements[1].operator String() + ", new Vector2" + transform.elements[2].operator String() + ")";
+ }
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
- break;
+ } break;
+ case Variant::TRANSFORM: {
+ Transform transform = p_val.operator Transform();
+ if (transform == Transform()) {
+ r_iarg.default_argument = "Transform.Identity";
+ } else {
+ Basis basis = transform.basis;
+ r_iarg.default_argument = "new Transform(new Vector3" + basis.get_column(0).operator String() + ", new Vector3" + basis.get_column(1).operator String() + ", new Vector3" + basis.get_column(2).operator String() + ", new Vector3" + transform.origin.operator String() + ")";
+ }
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ } break;
+ case Variant::BASIS: {
+ Basis basis = p_val.operator Basis();
+ if (basis == Basis()) {
+ r_iarg.default_argument = "Basis.Identity";
+ } else {
+ r_iarg.default_argument = "new Basis(new Vector3" + basis.get_column(0).operator String() + ", new Vector3" + basis.get_column(1).operator String() + ", new Vector3" + basis.get_column(2).operator String() + ")";
+ }
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ } break;
+ case Variant::QUAT: {
+ Quat quat = p_val.operator Quat();
+ if (quat == Quat()) {
+ r_iarg.default_argument = "Quat.Identity";
+ } else {
+ r_iarg.default_argument = "new Quat" + quat.operator String();
+ }
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ } break;
case Variant::CALLABLE:
case Variant::SIGNAL:
CRASH_NOW_MSG("Parameter of type '" + String(r_iarg.type.cname) + "' cannot have a default value.");
@@ -3487,11 +3631,44 @@ void BindingsGenerator::_initialize() {
initialized = true;
}
+static String generate_all_glue_option = "--generate-mono-glue";
+static String generate_cs_glue_option = "--generate-mono-cs-glue";
+static String generate_cpp_glue_option = "--generate-mono-cpp-glue";
+
+static void handle_cmdline_options(String glue_dir_path, String cs_dir_path, String cpp_dir_path) {
+ BindingsGenerator bindings_generator;
+ bindings_generator.set_log_print_enabled(true);
+
+ if (!bindings_generator.is_initialized()) {
+ ERR_PRINT("Failed to initialize the bindings generator");
+ return;
+ }
+
+ if (glue_dir_path.length()) {
+ if (bindings_generator.generate_glue(glue_dir_path) != OK) {
+ ERR_PRINT(generate_all_glue_option + ": Failed to generate the C++ glue.");
+ }
+
+ if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK) {
+ ERR_PRINT(generate_all_glue_option + ": Failed to generate the C# API.");
+ }
+ }
+
+ if (cs_dir_path.length()) {
+ if (bindings_generator.generate_cs_api(cs_dir_path) != OK) {
+ ERR_PRINT(generate_cs_glue_option + ": Failed to generate the C# API.");
+ }
+ }
+
+ if (cpp_dir_path.length()) {
+ if (bindings_generator.generate_glue(cpp_dir_path) != OK) {
+ ERR_PRINT(generate_cpp_glue_option + ": Failed to generate the C++ glue.");
+ }
+ }
+}
+
void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
const int NUM_OPTIONS = 2;
- String generate_all_glue_option = "--generate-mono-glue";
- String generate_cs_glue_option = "--generate-mono-cs-glue";
- String generate_cpp_glue_option = "--generate-mono-cpp-glue";
String glue_dir_path;
String cs_dir_path;
@@ -3499,6 +3676,8 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
int options_left = NUM_OPTIONS;
+ bool exit_godot = false;
+
const List<String>::Element *elem = p_cmdline_args.front();
while (elem && options_left) {
@@ -3510,6 +3689,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
elem = elem->next();
} else {
ERR_PRINT(generate_all_glue_option + ": No output directory specified (expected path to '{GODOT_ROOT}/modules/mono/glue').");
+ exit_godot = true;
}
--options_left;
@@ -3521,6 +3701,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
elem = elem->next();
} else {
ERR_PRINT(generate_cs_glue_option + ": No output directory specified.");
+ exit_godot = true;
}
--options_left;
@@ -3532,6 +3713,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
elem = elem->next();
} else {
ERR_PRINT(generate_cpp_glue_option + ": No output directory specified.");
+ exit_godot = true;
}
--options_left;
@@ -3541,37 +3723,13 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
}
if (glue_dir_path.length() || cs_dir_path.length() || cpp_dir_path.length()) {
- BindingsGenerator bindings_generator;
- bindings_generator.set_log_print_enabled(true);
-
- if (!bindings_generator.initialized) {
- ERR_PRINT("Failed to initialize the bindings generator");
- ::exit(0);
- }
-
- if (glue_dir_path.length()) {
- if (bindings_generator.generate_glue(glue_dir_path) != OK) {
- ERR_PRINT(generate_all_glue_option + ": Failed to generate the C++ glue.");
- }
-
- if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK) {
- ERR_PRINT(generate_all_glue_option + ": Failed to generate the C# API.");
- }
- }
-
- if (cs_dir_path.length()) {
- if (bindings_generator.generate_cs_api(cs_dir_path) != OK) {
- ERR_PRINT(generate_cs_glue_option + ": Failed to generate the C# API.");
- }
- }
-
- if (cpp_dir_path.length()) {
- if (bindings_generator.generate_glue(cpp_dir_path) != OK) {
- ERR_PRINT(generate_cpp_glue_option + ": Failed to generate the C++ glue.");
- }
- }
+ handle_cmdline_options(glue_dir_path, cs_dir_path, cpp_dir_path);
+ exit_godot = true;
+ }
+ if (exit_godot) {
// Exit once done
+ Main::cleanup(true);
::exit(0);
}
}
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index b18dfb0ec4..876046176b 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -661,6 +661,7 @@ class BindingsGenerator {
Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output);
Error _generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output);
+ void _generate_array_extensions(StringBuilder &p_output);
void _generate_global_constants(StringBuilder &p_output);
Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, StringBuilder &p_output);
diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp
index 667e4a3879..21efd58938 100644
--- a/modules/mono/editor/editor_internal_calls.cpp
+++ b/modules/mono/editor/editor_internal_calls.cpp
@@ -49,7 +49,6 @@
#include "../utils/osx_utils.h"
#include "code_completion.h"
#include "godotsharp_export.h"
-#include "script_class_parser.h"
MonoString *godot_icall_GodotSharpDirs_ResDataDir() {
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_data_dir());
@@ -172,36 +171,6 @@ MonoBoolean godot_icall_EditorProgress_Step(MonoString *p_task, MonoString *p_st
return EditorNode::progress_task_step(task, state, p_step, (bool)p_force_refresh);
}
-int32_t godot_icall_ScriptClassParser_ParseFile(MonoString *p_filepath, MonoObject *p_classes, MonoString **r_error_str) {
- *r_error_str = nullptr;
-
- String filepath = GDMonoMarshal::mono_string_to_godot(p_filepath);
-
- ScriptClassParser scp;
- Error err = scp.parse_file(filepath);
- if (err == OK) {
- Array classes = GDMonoMarshal::mono_object_to_variant(p_classes);
- const Vector<ScriptClassParser::ClassDecl> &class_decls = scp.get_classes();
-
- for (int i = 0; i < class_decls.size(); i++) {
- const ScriptClassParser::ClassDecl &classDecl = class_decls[i];
-
- Dictionary classDeclDict;
- classDeclDict["name"] = classDecl.name;
- classDeclDict["namespace"] = classDecl.namespace_;
- classDeclDict["nested"] = classDecl.nested;
- classDeclDict["base_count"] = classDecl.base.size();
- classes.push_back(classDeclDict);
- }
- } else {
- String error_str = scp.get_error();
- if (!error_str.is_empty()) {
- *r_error_str = GDMonoMarshal::mono_string_from_godot(error_str);
- }
- }
- return err;
-}
-
uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_assemblies,
MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_assembly_dependencies) {
Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_assemblies);
@@ -289,18 +258,6 @@ void godot_icall_Internal_EditorNodeShowScriptScreen() {
EditorNode::get_singleton()->call("_editor_select", EditorNode::EDITOR_SCRIPT);
}
-MonoObject *godot_icall_Internal_GetScriptsMetadataOrNothing(MonoReflectionType *p_dict_reftype) {
- Dictionary maybe_metadata = CSharpLanguage::get_singleton()->get_scripts_metadata_or_nothing();
-
- MonoType *dict_type = mono_reflection_type_get_type(p_dict_reftype);
-
- int type_encoding = mono_type_get_type(dict_type);
- MonoClass *type_class_raw = mono_class_from_mono_type(dict_type);
- GDMonoClass *type_class = GDMono::get_singleton()->get_class(type_class_raw);
-
- return GDMonoMarshal::variant_to_mono_object(maybe_metadata, ManagedType(type_encoding, type_class));
-}
-
MonoString *godot_icall_Internal_MonoWindowsInstallRoot() {
#ifdef WINDOWS_ENABLED
String install_root_dir = GDMono::get_singleton()->get_mono_reg_info().install_root_dir;
@@ -395,9 +352,6 @@ void register_editor_internal_calls() {
GDMonoUtils::add_internal_call("GodotTools.Internals.EditorProgress::internal_Dispose", godot_icall_EditorProgress_Dispose);
GDMonoUtils::add_internal_call("GodotTools.Internals.EditorProgress::internal_Step", godot_icall_EditorProgress_Step);
- // ScriptClassParser
- GDMonoUtils::add_internal_call("GodotTools.Internals.ScriptClassParser::internal_ParseFile", godot_icall_ScriptClassParser_ParseFile);
-
// ExportPlugin
GDMonoUtils::add_internal_call("GodotTools.Export.ExportPlugin::internal_GetExportedAssemblyDependencies", godot_icall_ExportPlugin_GetExportedAssemblyDependencies);
@@ -416,7 +370,6 @@ void register_editor_internal_calls() {
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorDebuggerNodeReloadScripts", godot_icall_Internal_EditorDebuggerNodeReloadScripts);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_ScriptEditorEdit", godot_icall_Internal_ScriptEditorEdit);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorNodeShowScriptScreen", godot_icall_Internal_EditorNodeShowScriptScreen);
- GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GetScriptsMetadataOrNothing", godot_icall_Internal_GetScriptsMetadataOrNothing);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_MonoWindowsInstallRoot", godot_icall_Internal_MonoWindowsInstallRoot);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorRunPlay", godot_icall_Internal_EditorRunPlay);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorRunStop", godot_icall_Internal_EditorRunStop);
diff --git a/modules/mono/editor/script_class_parser.cpp b/modules/mono/editor/script_class_parser.cpp
deleted file mode 100644
index e81cbe4ebd..0000000000
--- a/modules/mono/editor/script_class_parser.cpp
+++ /dev/null
@@ -1,753 +0,0 @@
-/*************************************************************************/
-/* script_class_parser.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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 "script_class_parser.h"
-
-#include "core/os/os.h"
-#include "core/templates/map.h"
-
-#include "../utils/string_utils.h"
-
-const char *ScriptClassParser::token_names[ScriptClassParser::TK_MAX] = {
- "[",
- "]",
- "{",
- "}",
- ".",
- ":",
- ",",
- "Symbol",
- "Identifier",
- "String",
- "Number",
- "<",
- ">",
- "EOF",
- "Error"
-};
-
-String ScriptClassParser::get_token_name(ScriptClassParser::Token p_token) {
- ERR_FAIL_INDEX_V(p_token, TK_MAX, "<error>");
- return token_names[p_token];
-}
-
-ScriptClassParser::Token ScriptClassParser::get_token() {
- while (true) {
- switch (code[idx]) {
- case '\n': {
- line++;
- idx++;
- break;
- };
- case 0: {
- return TK_EOF;
- } break;
- case '{': {
- idx++;
- return TK_CURLY_BRACKET_OPEN;
- };
- case '}': {
- idx++;
- return TK_CURLY_BRACKET_CLOSE;
- };
- case '[': {
- idx++;
- return TK_BRACKET_OPEN;
- };
- case ']': {
- idx++;
- return TK_BRACKET_CLOSE;
- };
- case '<': {
- idx++;
- return TK_OP_LESS;
- };
- case '>': {
- idx++;
- return TK_OP_GREATER;
- };
- case ':': {
- idx++;
- return TK_COLON;
- };
- case ',': {
- idx++;
- return TK_COMMA;
- };
- case '.': {
- idx++;
- return TK_PERIOD;
- };
- case '#': {
- //compiler directive
- while (code[idx] != '\n' && code[idx] != 0) {
- idx++;
- }
- continue;
- } break;
- case '/': {
- switch (code[idx + 1]) {
- case '*': { // block comment
- idx += 2;
- while (true) {
- if (code[idx] == 0) {
- error_str = "Unterminated comment";
- error = true;
- return TK_ERROR;
- } else if (code[idx] == '*' && code[idx + 1] == '/') {
- idx += 2;
- break;
- } else if (code[idx] == '\n') {
- line++;
- }
-
- idx++;
- }
-
- } break;
- case '/': { // line comment skip
- while (code[idx] != '\n' && code[idx] != 0) {
- idx++;
- }
-
- } break;
- default: {
- value = "/";
- idx++;
- return TK_SYMBOL;
- }
- }
-
- continue; // a comment
- } break;
- case '\'':
- case '"': {
- bool verbatim = idx != 0 && code[idx - 1] == '@';
-
- char32_t begin_str = code[idx];
- idx++;
- String tk_string = String();
- while (true) {
- if (code[idx] == 0) {
- error_str = "Unterminated String";
- error = true;
- return TK_ERROR;
- } else if (code[idx] == begin_str) {
- if (verbatim && code[idx + 1] == '"') { // '""' is verbatim string's '\"'
- idx += 2; // skip next '"' as well
- continue;
- }
-
- idx += 1;
- break;
- } else if (code[idx] == '\\' && !verbatim) {
- //escaped characters...
- idx++;
- char32_t next = code[idx];
- if (next == 0) {
- error_str = "Unterminated String";
- error = true;
- return TK_ERROR;
- }
- char32_t res = 0;
-
- switch (next) {
- case 'b':
- res = 8;
- break;
- case 't':
- res = 9;
- break;
- case 'n':
- res = 10;
- break;
- case 'f':
- res = 12;
- break;
- case 'r':
- res = 13;
- break;
- case '\"':
- res = '\"';
- break;
- case '\\':
- res = '\\';
- break;
- default: {
- res = next;
- } break;
- }
-
- tk_string += res;
-
- } else {
- if (code[idx] == '\n') {
- line++;
- }
- tk_string += code[idx];
- }
- idx++;
- }
-
- value = tk_string;
-
- return TK_STRING;
- } break;
- default: {
- if (code[idx] <= 32) {
- idx++;
- break;
- }
-
- if ((code[idx] >= 33 && code[idx] <= 47) || (code[idx] >= 58 && code[idx] <= 63) || (code[idx] >= 91 && code[idx] <= 94) || code[idx] == 96 || (code[idx] >= 123 && code[idx] <= 127)) {
- value = String::chr(code[idx]);
- idx++;
- return TK_SYMBOL;
- }
-
- if (code[idx] == '-' || (code[idx] >= '0' && code[idx] <= '9')) {
- //a number
- const char32_t *rptr;
- double number = String::to_float(&code[idx], &rptr);
- idx += (rptr - &code[idx]);
- value = number;
- return TK_NUMBER;
-
- } else if ((code[idx] == '@' && code[idx + 1] != '"') || code[idx] == '_' || (code[idx] >= 'A' && code[idx] <= 'Z') || (code[idx] >= 'a' && code[idx] <= 'z') || code[idx] > 127) {
- String id;
-
- id += code[idx];
- idx++;
-
- while (code[idx] == '_' || (code[idx] >= 'A' && code[idx] <= 'Z') || (code[idx] >= 'a' && code[idx] <= 'z') || (code[idx] >= '0' && code[idx] <= '9') || code[idx] > 127) {
- id += code[idx];
- idx++;
- }
-
- value = id;
- return TK_IDENTIFIER;
- } else if (code[idx] == '@' && code[idx + 1] == '"') {
- // begin of verbatim string
- idx++;
- } else {
- error_str = "Unexpected character.";
- error = true;
- return TK_ERROR;
- }
- }
- }
- }
-}
-
-Error ScriptClassParser::_skip_generic_type_params() {
- Token tk;
-
- while (true) {
- tk = get_token();
-
- if (tk == TK_IDENTIFIER) {
- tk = get_token();
- // Type specifications can end with "?" to denote nullable types, such as IList<int?>
- if (tk == TK_SYMBOL) {
- tk = get_token();
- if (value.operator String() != "?") {
- error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found unexpected symbol '" + value + "'";
- error = true;
- return ERR_PARSE_ERROR;
- }
- if (tk != TK_OP_GREATER && tk != TK_COMMA) {
- error_str = "Nullable type symbol '?' is only allowed after an identifier, but found " + get_token_name(tk) + " next.";
- error = true;
- return ERR_PARSE_ERROR;
- }
- }
-
- if (tk == TK_PERIOD) {
- while (true) {
- tk = get_token();
-
- if (tk != TK_IDENTIFIER) {
- error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- tk = get_token();
-
- if (tk != TK_PERIOD) {
- break;
- }
- }
- }
-
- if (tk == TK_OP_LESS) {
- Error err = _skip_generic_type_params();
- if (err) {
- return err;
- }
- tk = get_token();
- }
-
- if (tk == TK_OP_GREATER) {
- return OK;
- } else if (tk != TK_COMMA) {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
- } else if (tk == TK_OP_LESS) {
- error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found " + get_token_name(TK_OP_LESS);
- error = true;
- return ERR_PARSE_ERROR;
- } else if (tk == TK_OP_GREATER) {
- return OK;
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
- }
-}
-
-Error ScriptClassParser::_parse_type_full_name(String &r_full_name) {
- Token tk = get_token();
-
- if (tk != TK_IDENTIFIER) {
- error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- r_full_name += String(value);
-
- if (code[idx] == '<') {
- idx++;
-
- // We don't mind if the base is generic, but we skip it any ways since this information is not needed
- Error err = _skip_generic_type_params();
- if (err) {
- return err;
- }
- }
-
- if (code[idx] != '.') { // We only want to take the next token if it's a period
- return OK;
- }
-
- tk = get_token();
-
- CRASH_COND(tk != TK_PERIOD); // Assertion
-
- r_full_name += ".";
-
- return _parse_type_full_name(r_full_name);
-}
-
-Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) {
- String name;
-
- Error err = _parse_type_full_name(name);
- if (err) {
- return err;
- }
-
- Token tk = get_token();
-
- if (tk == TK_COMMA) {
- err = _parse_class_base(r_base);
- if (err) {
- return err;
- }
- } else if (tk == TK_IDENTIFIER && String(value) == "where") {
- err = _parse_type_constraints();
- if (err) {
- return err;
- }
-
- // An open curly bracket was parsed by _parse_type_constraints, so we can exit
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- // we are finished when we hit the open curly bracket
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- r_base.push_back(name);
-
- return OK;
-}
-
-Error ScriptClassParser::_parse_type_constraints() {
- Token tk = get_token();
- if (tk != TK_IDENTIFIER) {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- tk = get_token();
- if (tk != TK_COLON) {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- while (true) {
- tk = get_token();
- if (tk == TK_IDENTIFIER) {
- if (String(value) == "where") {
- return _parse_type_constraints();
- }
-
- tk = get_token();
- if (tk == TK_PERIOD) {
- while (true) {
- tk = get_token();
-
- if (tk != TK_IDENTIFIER) {
- error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- tk = get_token();
-
- if (tk != TK_PERIOD) {
- break;
- }
- }
- }
- }
-
- if (tk == TK_COMMA) {
- continue;
- } else if (tk == TK_IDENTIFIER && String(value) == "where") {
- return _parse_type_constraints();
- } else if (tk == TK_SYMBOL && String(value) == "(") {
- tk = get_token();
- if (tk != TK_SYMBOL || String(value) != ")") {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
- } else if (tk == TK_OP_LESS) {
- Error err = _skip_generic_type_params();
- if (err) {
- return err;
- }
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- return OK;
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
- }
-}
-
-Error ScriptClassParser::_parse_namespace_name(String &r_name, int &r_curly_stack) {
- Token tk = get_token();
-
- if (tk == TK_IDENTIFIER) {
- r_name += String(value);
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- tk = get_token();
-
- if (tk == TK_PERIOD) {
- r_name += ".";
- return _parse_namespace_name(r_name, r_curly_stack);
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- r_curly_stack++;
- return OK;
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
-}
-
-Error ScriptClassParser::parse(const String &p_code) {
- code = p_code;
- idx = 0;
- line = 0;
- error_str = String();
- error = false;
- value = Variant();
- classes.clear();
-
- Token tk = get_token();
-
- Map<int, NameDecl> name_stack;
- int curly_stack = 0;
- int type_curly_stack = 0;
-
- while (!error && tk != TK_EOF) {
- String identifier = value;
- if (tk == TK_IDENTIFIER && (identifier == "class" || identifier == "struct")) {
- bool is_class = identifier == "class";
-
- tk = get_token();
-
- if (tk == TK_IDENTIFIER) {
- String name = value;
- int at_level = curly_stack;
-
- ClassDecl class_decl;
-
- for (Map<int, NameDecl>::Element *E = name_stack.front(); E; E = E->next()) {
- const NameDecl &name_decl = E->value();
-
- if (name_decl.type == NameDecl::NAMESPACE_DECL) {
- if (E != name_stack.front()) {
- class_decl.namespace_ += ".";
- }
- class_decl.namespace_ += name_decl.name;
- } else {
- class_decl.name += name_decl.name + ".";
- }
- }
-
- class_decl.name += name;
- class_decl.nested = type_curly_stack > 0;
-
- bool generic = false;
-
- while (true) {
- tk = get_token();
-
- if (tk == TK_COLON) {
- Error err = _parse_class_base(class_decl.base);
- if (err) {
- return err;
- }
-
- curly_stack++;
- type_curly_stack++;
-
- break;
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- curly_stack++;
- type_curly_stack++;
- break;
- } else if (tk == TK_OP_LESS && !generic) {
- generic = true;
-
- Error err = _skip_generic_type_params();
- if (err) {
- return err;
- }
- } else if (tk == TK_IDENTIFIER && String(value) == "where") {
- Error err = _parse_type_constraints();
- if (err) {
- return err;
- }
-
- // An open curly bracket was parsed by _parse_type_constraints, so we can exit
- curly_stack++;
- type_curly_stack++;
- break;
- } else {
- error_str = "Unexpected token: " + get_token_name(tk);
- error = true;
- return ERR_PARSE_ERROR;
- }
- }
-
- NameDecl name_decl;
- name_decl.name = name;
- name_decl.type = is_class ? NameDecl::CLASS_DECL : NameDecl::STRUCT_DECL;
- name_stack[at_level] = name_decl;
-
- if (is_class) {
- if (!generic) { // no generics, thanks
- classes.push_back(class_decl);
- } else if (OS::get_singleton()->is_stdout_verbose()) {
- String full_name = class_decl.namespace_;
- if (full_name.length()) {
- full_name += ".";
- }
- full_name += class_decl.name;
- OS::get_singleton()->print("Ignoring generic class declaration: %s\n", full_name.utf8().get_data());
- }
- }
- }
- } else if (tk == TK_IDENTIFIER && identifier == "namespace") {
- if (type_curly_stack > 0) {
- error_str = "Found namespace nested inside type.";
- error = true;
- return ERR_PARSE_ERROR;
- }
-
- String name;
- int at_level = curly_stack;
-
- Error err = _parse_namespace_name(name, curly_stack);
- if (err) {
- return err;
- }
-
- NameDecl name_decl;
- name_decl.name = name;
- name_decl.type = NameDecl::NAMESPACE_DECL;
- name_stack[at_level] = name_decl;
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- curly_stack++;
- } else if (tk == TK_CURLY_BRACKET_CLOSE) {
- curly_stack--;
- if (name_stack.has(curly_stack)) {
- if (name_stack[curly_stack].type != NameDecl::NAMESPACE_DECL) {
- type_curly_stack--;
- }
- name_stack.erase(curly_stack);
- }
- }
-
- tk = get_token();
- }
-
- if (!error && tk == TK_EOF && curly_stack > 0) {
- error_str = "Reached EOF with missing close curly brackets.";
- error = true;
- }
-
- if (error) {
- return ERR_PARSE_ERROR;
- }
-
- return OK;
-}
-
-static String get_preprocessor_directive(const String &p_line, int p_from) {
- CRASH_COND(p_line[p_from] != '#');
- p_from++;
- int i = p_from;
- while (i < p_line.length() && (p_line[i] == '_' || (p_line[i] >= 'A' && p_line[i] <= 'Z') ||
- (p_line[i] >= 'a' && p_line[i] <= 'z') || p_line[i] > 127)) {
- i++;
- }
- return p_line.substr(p_from, i - p_from);
-}
-
-static void run_dummy_preprocessor(String &r_source, const String &p_filepath) {
- Vector<String> lines = r_source.split("\n", /* p_allow_empty: */ true);
-
- bool *include_lines = memnew_arr(bool, lines.size());
-
- int if_level = -1;
- Vector<bool> is_branch_being_compiled;
-
- for (int i = 0; i < lines.size(); i++) {
- const String &line = lines[i];
-
- const int line_len = line.length();
-
- int j;
- for (j = 0; j < line_len; j++) {
- if (line[j] != ' ' && line[j] != '\t') {
- if (line[j] == '#') {
- // First non-whitespace char of the line is '#'
- include_lines[i] = false;
-
- String directive = get_preprocessor_directive(line, j);
-
- if (directive == "if") {
- if_level++;
- is_branch_being_compiled.push_back(if_level == 0 || is_branch_being_compiled[if_level - 1]);
- } else if (directive == "elif") {
- ERR_CONTINUE_MSG(if_level == -1, "Found unexpected '#elif' directive. File: '" + p_filepath + "'.");
- is_branch_being_compiled.write[if_level] = false;
- } else if (directive == "else") {
- ERR_CONTINUE_MSG(if_level == -1, "Found unexpected '#else' directive. File: '" + p_filepath + "'.");
- is_branch_being_compiled.write[if_level] = false;
- } else if (directive == "endif") {
- ERR_CONTINUE_MSG(if_level == -1, "Found unexpected '#endif' directive. File: '" + p_filepath + "'.");
- is_branch_being_compiled.remove(if_level);
- if_level--;
- }
-
- break;
- } else {
- // First non-whitespace char of the line is not '#'
- include_lines[i] = if_level == -1 || is_branch_being_compiled[if_level];
- break;
- }
- }
- }
-
- if (j == line_len) {
- // Loop ended without finding a non-whitespace character.
- // Either the line was empty or it only contained whitespaces.
- include_lines[i] = if_level == -1 || is_branch_being_compiled[if_level];
- }
- }
-
- r_source.clear();
-
- // Custom join ignoring lines removed by the preprocessor
- for (int i = 0; i < lines.size(); i++) {
- if (i > 0 && include_lines[i - 1]) {
- r_source += '\n';
- }
-
- if (include_lines[i]) {
- r_source += lines[i];
- }
- }
-}
-
-Error ScriptClassParser::parse_file(const String &p_filepath) {
- String source;
-
- Error ferr = read_all_file_utf8(p_filepath, source);
-
- ERR_FAIL_COND_V_MSG(ferr != OK, ferr,
- ferr == ERR_INVALID_DATA ?
- "File '" + p_filepath + "' contains invalid unicode (UTF-8), so it was not loaded."
- " Please ensure that scripts are saved in valid UTF-8 unicode." :
- "Failed to read file: '" + p_filepath + "'.");
-
- run_dummy_preprocessor(source, p_filepath);
-
- return parse(source);
-}
-
-String ScriptClassParser::get_error() {
- return error_str;
-}
-
-Vector<ScriptClassParser::ClassDecl> ScriptClassParser::get_classes() {
- return classes;
-}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
new file mode 100644
index 0000000000..ef135da51a
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Godot
+{
+ [AttributeUsage(AttributeTargets.Assembly)]
+ public class AssemblyHasScriptsAttribute : Attribute
+ {
+ private readonly bool requiresLookup;
+ private readonly System.Type[] scriptTypes;
+
+ public AssemblyHasScriptsAttribute()
+ {
+ requiresLookup = true;
+ }
+
+ public AssemblyHasScriptsAttribute(System.Type[] scriptTypes)
+ {
+ requiresLookup = false;
+ this.scriptTypes = scriptTypes;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs
new file mode 100644
index 0000000000..ac6cffceb2
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Godot
+{
+ [AttributeUsage(AttributeTargets.Class)]
+ public class DisableGodotGeneratorsAttribute : Attribute
+ {
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
new file mode 100644
index 0000000000..12eb1035c3
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Godot
+{
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public class ScriptPathAttribute : Attribute
+ {
+ private string path;
+
+ public ScriptPathAttribute(string path)
+ {
+ this.path = path;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs
new file mode 100644
index 0000000000..763f470504
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs
@@ -0,0 +1,27 @@
+namespace Godot
+{
+ public partial class PackedScene
+ {
+ /// <summary>
+ /// Instantiates the scene's node hierarchy, erroring on failure.
+ /// Triggers child scene instantiation(s). Triggers a
+ /// `Node.NotificationInstanced` notification on the root node.
+ /// </summary>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of Node.</typeparam>
+ public T Instance<T>(PackedScene.GenEditState editState = (PackedScene.GenEditState)0) where T : class
+ {
+ return (T)(object)Instance(editState);
+ }
+
+ /// <summary>
+ /// Instantiates the scene's node hierarchy, returning null on failure.
+ /// Triggers child scene instantiation(s). Triggers a
+ /// `Node.NotificationInstanced` notification on the root node.
+ /// </summary>
+ /// <typeparam name="T">The type to cast to. Should be a descendant of Node.</typeparam>
+ public T InstanceOrNull<T>(PackedScene.GenEditState editState = (PackedScene.GenEditState)0) where T : class
+ {
+ return Instance(editState) as T;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs
index 5f64c09a89..74fa05d1fd 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs
@@ -2,7 +2,7 @@ namespace Godot
{
public static partial class ResourceLoader
{
- public static T Load<T>(string path, string typeHint = null, bool noCache = false) where T : class
+ public static T Load<T>(string path, string typeHint = null, CacheMode noCache = CacheMode.Reuse) where T : class
{
return (T)(object)Load(path, typeHint, noCache);
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs
new file mode 100644
index 0000000000..702a6c76ba
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Godot
+{
+ public static partial class GD
+ {
+ /// <summary>
+ /// Fires when an unhandled exception occurs, regardless of project settings.
+ /// </summary>
+ public static event EventHandler<UnhandledExceptionArgs> UnhandledException;
+
+ private static void OnUnhandledException(Exception e)
+ {
+ UnhandledException?.Invoke(null, new UnhandledExceptionArgs(e));
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs
new file mode 100644
index 0000000000..be01674568
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Godot
+{
+ /// <summary>
+ /// Event arguments for when unhandled exceptions occur.
+ /// </summary>
+ public class UnhandledExceptionArgs
+ {
+ /// <summary>
+ /// Exception object
+ /// </summary>
+ public Exception Exception { get; private set; }
+
+ internal UnhandledExceptionArgs(Exception exception)
+ {
+ Exception = exception;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
index 42dbdf25c3..3b895bbbf6 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -111,10 +111,10 @@ namespace Godot
}
/// <summary>
- /// Returns the minimum angle to the given vector, in radians.
+ /// Returns the unsigned minimum angle to the given vector, in radians.
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
- /// <returns>The angle between the two vectors, in radians.</returns>
+ /// <returns>The unsigned angle between the two vectors, in radians.</returns>
public real_t AngleTo(Vector3 to)
{
return Mathf.Atan2(Cross(to).Length(), Dot(to));
@@ -469,6 +469,23 @@ namespace Godot
}
/// <summary>
+ /// Returns the signed angle to the given vector, in radians.
+ /// The sign of the angle is positive in a counter-clockwise
+ /// direction and negative in a clockwise direction when viewed
+ /// from the side specified by the `axis`.
+ /// </summary>
+ /// <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)
+ {
+ Vector3 crossTo = Cross(to);
+ real_t unsignedAngle = Mathf.Atan2(crossTo.Length(), Dot(to));
+ real_t sign = crossTo.Dot(axis);
+ return (sign < 0) ? -unsignedAngle : unsignedAngle;
+ }
+
+ /// <summary>
/// Returns the result of the spherical linear interpolation between
/// this vector and `to` by amount `weight`.
///
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
index 86a16c17f1..54aaaf1f92 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
@@ -14,9 +14,12 @@
<ItemGroup>
<Compile Include="Core\AABB.cs" />
<Compile Include="Core\Array.cs" />
+ <Compile Include="Core\Attributes\AssemblyHasScriptsAttribute.cs" />
+ <Compile Include="Core\Attributes\DisableGodotGeneratorsAttribute.cs" />
<Compile Include="Core\Attributes\ExportAttribute.cs" />
<Compile Include="Core\Attributes\GodotMethodAttribute.cs" />
<Compile Include="Core\Attributes\RPCAttributes.cs" />
+ <Compile Include="Core\Attributes\ScriptPathAttribute.cs" />
<Compile Include="Core\Attributes\SignalAttribute.cs" />
<Compile Include="Core\Attributes\ToolAttribute.cs" />
<Compile Include="Core\Basis.cs" />
@@ -30,12 +33,14 @@
<Compile Include="Core\DynamicObject.cs" />
<Compile Include="Core\Extensions\NodeExtensions.cs" />
<Compile Include="Core\Extensions\ObjectExtensions.cs" />
+ <Compile Include="Core\Extensions\PackedSceneExtensions.cs" />
<Compile Include="Core\Extensions\ResourceLoaderExtensions.cs" />
<Compile Include="Core\Extensions\SceneTreeExtensions.cs" />
<Compile Include="Core\GD.cs" />
<Compile Include="Core\GodotSynchronizationContext.cs" />
<Compile Include="Core\GodotTaskScheduler.cs" />
<Compile Include="Core\GodotTraceListener.cs" />
+ <Compile Include="Core\GodotUnhandledExceptionEvent.cs" />
<Compile Include="Core\Interfaces\IAwaitable.cs" />
<Compile Include="Core\Interfaces\IAwaiter.cs" />
<Compile Include="Core\Interfaces\ISerializationListener.cs" />
@@ -55,6 +60,7 @@
<Compile Include="Core\StringName.cs" />
<Compile Include="Core\Transform.cs" />
<Compile Include="Core\Transform2D.cs" />
+ <Compile Include="Core\UnhandledExceptionArgs.cs" />
<Compile Include="Core\Vector2.cs" />
<Compile Include="Core\Vector2i.cs" />
<Compile Include="Core\Vector3.cs" />
diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
index a39a6fe381..020a40575c 100644
--- a/modules/mono/godotsharp_dirs.cpp
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -179,16 +179,16 @@ private:
#ifdef OSX_ENABLED
if (!DirAccess::exists(data_editor_tools_dir)) {
- data_editor_tools_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Tools");
+ data_editor_tools_dir = exe_dir.plus_file("../Resources/GodotSharp/Tools");
}
if (!DirAccess::exists(data_editor_prebuilt_api_dir)) {
- data_editor_prebuilt_api_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Api");
+ data_editor_prebuilt_api_dir = exe_dir.plus_file("../Resources/GodotSharp/Api");
}
if (!DirAccess::exists(data_mono_root_dir)) {
data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc");
- data_mono_lib_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/lib");
+ data_mono_lib_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/lib");
}
#endif
@@ -218,11 +218,11 @@ private:
#ifdef OSX_ENABLED
if (!DirAccess::exists(data_mono_root_dir)) {
data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc");
- data_mono_lib_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/lib");
+ data_mono_lib_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/lib");
}
if (!DirAccess::exists(data_game_assemblies_dir)) {
- data_game_assemblies_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Assemblies");
+ data_game_assemblies_dir = exe_dir.plus_file("../Resources/GodotSharp/Assemblies");
}
#endif
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 43a39a4966..560788fb3a 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -1006,6 +1006,7 @@ bool GDMono::_load_project_assembly() {
if (success) {
mono_assembly_set_main(project_assembly->get_assembly());
+ CSharpLanguage::get_singleton()->lookup_scripts_in_assembly(project_assembly);
}
return success;
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 1fe06bfbee..a1556bace5 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -345,6 +345,45 @@ String GDMonoAssembly::get_path() const {
return String::utf8(mono_image_get_filename(image));
}
+bool GDMonoAssembly::has_attribute(GDMonoClass *p_attr_class) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_NULL_V(p_attr_class, false);
+#endif
+
+ if (!attrs_fetched) {
+ fetch_attributes();
+ }
+
+ if (!attributes) {
+ return false;
+ }
+
+ return mono_custom_attrs_has_attr(attributes, p_attr_class->get_mono_ptr());
+}
+
+MonoObject *GDMonoAssembly::get_attribute(GDMonoClass *p_attr_class) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_NULL_V(p_attr_class, nullptr);
+#endif
+
+ if (!attrs_fetched) {
+ fetch_attributes();
+ }
+
+ if (!attributes) {
+ return nullptr;
+ }
+
+ return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr());
+}
+
+void GDMonoAssembly::fetch_attributes() {
+ ERR_FAIL_COND(attributes != nullptr);
+
+ attributes = mono_custom_attrs_from_assembly(assembly);
+ attrs_fetched = true;
+}
+
GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const StringName &p_name) {
ERR_FAIL_NULL_V(image, nullptr);
@@ -390,70 +429,6 @@ GDMonoClass *GDMonoAssembly::get_class(MonoClass *p_mono_class) {
return wrapped_class;
}
-GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) {
- GDMonoClass *match = nullptr;
-
- if (gdobject_class_cache_updated) {
- Map<StringName, GDMonoClass *>::Element *result = gdobject_class_cache.find(p_class);
-
- if (result) {
- match = result->get();
- }
- } else {
- List<GDMonoClass *> nested_classes;
-
- int rows = mono_image_get_table_rows(image, MONO_TABLE_TYPEDEF);
-
- for (int i = 1; i < rows; i++) {
- MonoClass *mono_class = mono_class_get(image, (i + 1) | MONO_TOKEN_TYPE_DEF);
-
- if (!mono_class_is_assignable_from(CACHED_CLASS_RAW(GodotObject), mono_class)) {
- continue;
- }
-
- GDMonoClass *current = get_class(mono_class);
-
- if (!current) {
- continue;
- }
-
- nested_classes.push_back(current);
-
- if (!match && current->get_name() == p_class) {
- match = current;
- }
-
- while (!nested_classes.is_empty()) {
- GDMonoClass *current_nested = nested_classes.front()->get();
- nested_classes.pop_front();
-
- void *iter = nullptr;
-
- while (true) {
- MonoClass *raw_nested = mono_class_get_nested_types(current_nested->get_mono_ptr(), &iter);
-
- if (!raw_nested) {
- break;
- }
-
- GDMonoClass *nested_class = get_class(raw_nested);
-
- if (nested_class) {
- gdobject_class_cache.insert(nested_class->get_name(), nested_class);
- nested_classes.push_back(nested_class);
- }
- }
- }
-
- gdobject_class_cache.insert(current->get_name(), current);
- }
-
- gdobject_class_cache_updated = true;
- }
-
- return match;
-}
-
GDMonoAssembly *GDMonoAssembly::load(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs) {
if (GDMono::get_singleton()->get_corlib_assembly() && (p_name == "mscorlib" || p_name == "mscorlib.dll")) {
return GDMono::get_singleton()->get_corlib_assembly();
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
index 350fcf3210..6191c491f4 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.h
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -71,13 +71,13 @@ class GDMonoAssembly {
MonoImage *image;
MonoAssembly *assembly;
+ bool attrs_fetched = false;
+ MonoCustomAttrInfo *attributes = nullptr;
+
#ifdef GD_MONO_HOT_RELOAD
uint64_t modified_time = 0;
#endif
- bool gdobject_class_cache_updated = false;
- Map<StringName, GDMonoClass *> gdobject_class_cache;
-
HashMap<ClassKey, GDMonoClass *, ClassKey::Hasher> cached_classes;
Map<MonoClass *, GDMonoClass *> cached_raw;
@@ -111,11 +111,14 @@ public:
String get_path() const;
+ bool has_attribute(GDMonoClass *p_attr_class);
+ MonoObject *get_attribute(GDMonoClass *p_attr_class);
+
+ void fetch_attributes();
+
GDMonoClass *get_class(const StringName &p_namespace, const StringName &p_name);
GDMonoClass *get_class(MonoClass *p_mono_class);
- GDMonoClass *get_object_derived_class(const StringName &p_class);
-
static String find_assembly(const String &p_name);
static void fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config = String(), const String &p_custom_bcl_dir = String());
diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp
index aea467660f..d66cc29b9a 100644
--- a/modules/mono/mono_gd/gd_mono_cache.cpp
+++ b/modules/mono/mono_gd/gd_mono_cache.cpp
@@ -148,6 +148,11 @@ void CachedData::clear_godot_api_cache() {
class_PuppetSyncAttribute = nullptr;
class_GodotMethodAttribute = nullptr;
field_GodotMethodAttribute_methodName = nullptr;
+ class_ScriptPathAttribute = nullptr;
+ field_ScriptPathAttribute_path = nullptr;
+ class_AssemblyHasScriptsAttribute = nullptr;
+ field_AssemblyHasScriptsAttribute_requiresLookup = nullptr;
+ field_AssemblyHasScriptsAttribute_scriptTypes = nullptr;
field_GodotObject_ptr = nullptr;
field_StringName_ptr = nullptr;
@@ -272,6 +277,11 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(PuppetSyncAttribute, GODOT_API_CLASS(PuppetSyncAttribute));
CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute));
CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName"));
+ CACHE_CLASS_AND_CHECK(ScriptPathAttribute, GODOT_API_CLASS(ScriptPathAttribute));
+ CACHE_FIELD_AND_CHECK(ScriptPathAttribute, path, CACHED_CLASS(ScriptPathAttribute)->get_field("path"));
+ CACHE_CLASS_AND_CHECK(AssemblyHasScriptsAttribute, GODOT_API_CLASS(AssemblyHasScriptsAttribute));
+ CACHE_FIELD_AND_CHECK(AssemblyHasScriptsAttribute, requiresLookup, CACHED_CLASS(AssemblyHasScriptsAttribute)->get_field("requiresLookup"));
+ CACHE_FIELD_AND_CHECK(AssemblyHasScriptsAttribute, scriptTypes, CACHED_CLASS(AssemblyHasScriptsAttribute)->get_field("scriptTypes"));
CACHE_FIELD_AND_CHECK(GodotObject, ptr, CACHED_CLASS(GodotObject)->get_field(BINDINGS_PTR_FIELD));
CACHE_FIELD_AND_CHECK(StringName, ptr, CACHED_CLASS(StringName)->get_field(BINDINGS_PTR_FIELD));
diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h
index fb75cb4b1c..51370da452 100644
--- a/modules/mono/mono_gd/gd_mono_cache.h
+++ b/modules/mono/mono_gd/gd_mono_cache.h
@@ -119,6 +119,11 @@ struct CachedData {
GDMonoClass *class_PuppetSyncAttribute;
GDMonoClass *class_GodotMethodAttribute;
GDMonoField *field_GodotMethodAttribute_methodName;
+ GDMonoClass *class_ScriptPathAttribute;
+ GDMonoField *field_ScriptPathAttribute_path;
+ GDMonoClass *class_AssemblyHasScriptsAttribute;
+ GDMonoField *field_AssemblyHasScriptsAttribute_requiresLookup;
+ GDMonoField *field_AssemblyHasScriptsAttribute_scriptTypes;
GDMonoField *field_GodotObject_ptr;
GDMonoField *field_StringName_ptr;
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index 65e2680905..fa93c6533a 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -43,7 +43,6 @@
#include <mono/metadata/exception.h>
namespace GDMonoInternals {
-
void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
// This method should not fail
@@ -113,9 +112,11 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
void unhandled_exception(MonoException *p_exc) {
mono_print_unhandled_exception((MonoObject *)p_exc);
+ gd_unhandled_exception_event(p_exc);
if (GDMono::get_singleton()->get_unhandled_exception_policy() == GDMono::POLICY_TERMINATE_APP) {
// Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders
+ mono_unhandled_exception((MonoObject *)p_exc);
GDMono::unhandled_exception_hook((MonoObject *)p_exc, nullptr);
GD_UNREACHABLE();
} else {
@@ -127,4 +128,14 @@ void unhandled_exception(MonoException *p_exc) {
#endif
}
}
+
+void gd_unhandled_exception_event(MonoException *p_exc) {
+ MonoImage *mono_image = GDMono::get_singleton()->get_core_api_assembly()->get_image();
+
+ MonoClass *gd_klass = mono_class_from_name(mono_image, "Godot", "GD");
+ MonoMethod *unhandled_exception_method = mono_class_get_method_from_name(gd_klass, "OnUnhandledException", -1);
+ void *args[1];
+ args[0] = p_exc;
+ mono_runtime_invoke(unhandled_exception_method, nullptr, (void **)args, nullptr);
+}
} // namespace GDMonoInternals
diff --git a/modules/mono/mono_gd/gd_mono_internals.h b/modules/mono/mono_gd/gd_mono_internals.h
index 34d2d35b2d..26eb270eee 100644
--- a/modules/mono/mono_gd/gd_mono_internals.h
+++ b/modules/mono/mono_gd/gd_mono_internals.h
@@ -38,7 +38,6 @@
#include "core/object/class_db.h"
namespace GDMonoInternals {
-
void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged);
/**
@@ -46,6 +45,8 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged);
* Use GDMonoUtils::debug_unhandled_exception(MonoException *) instead.
*/
void unhandled_exception(MonoException *p_exc);
+
+void gd_unhandled_exception_event(MonoException *p_exc);
} // namespace GDMonoInternals
#endif // GD_MONO_INTERNALS_H
diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp
index e1d283242c..dafd36c36b 100644
--- a/modules/mono/mono_gd/gd_mono_log.cpp
+++ b/modules/mono/mono_gd/gd_mono_log.cpp
@@ -189,8 +189,6 @@ void GDMonoLog::initialize() {
GDMonoLog::GDMonoLog() {
singleton = this;
-
- log_level_id = -1;
}
GDMonoLog::~GDMonoLog() {
diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h
index 9a95e3cb0a..f7a53156ab 100644
--- a/modules/mono/mono_gd/gd_mono_log.h
+++ b/modules/mono/mono_gd/gd_mono_log.h
@@ -46,9 +46,9 @@
class GDMonoLog {
#ifdef GD_MONO_LOG_ENABLED
- int log_level_id;
+ int log_level_id = -1;
- FileAccess *log_file;
+ FileAccess *log_file = nullptr;
String log_file_path;
bool _try_create_logs_dir(const String &p_logs_dir);
diff --git a/modules/mono/mono_gd/support/android_support.cpp b/modules/mono/mono_gd/support/android_support.cpp
index cba29d63cd..c65353dfd1 100644
--- a/modules/mono/mono_gd/support/android_support.cpp
+++ b/modules/mono/mono_gd/support/android_support.cpp
@@ -415,8 +415,7 @@ GD_PINVOKE_EXPORT int32_t monodroid_get_system_property(const char *p_name, char
if (r_value) {
if (len >= 0) {
*r_value = (char *)malloc(len + 1);
- if (!*r_value)
- return -1;
+ ERR_FAIL_NULL_V_MSG(*r_value, -1, "Out of memory.");
memcpy(*r_value, prop_value_str, len);
(*r_value)[len] = '\0';
} else {
@@ -637,6 +636,7 @@ GD_PINVOKE_EXPORT int32_t _monodroid_get_dns_servers(void **r_dns_servers_array)
if (dns_servers_count > 0) {
size_t ret_size = sizeof(char *) * (size_t)dns_servers_count;
*r_dns_servers_array = malloc(ret_size); // freed by the BCL
+ ERR_FAIL_NULL_V_MSG(*r_dns_servers_array, -1, "Out of memory.");
memcpy(*r_dns_servers_array, dns_servers, ret_size);
}
diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml
index 7df261d2ba..86e7f9cc08 100644
--- a/modules/opensimplex/doc_classes/NoiseTexture.xml
+++ b/modules/opensimplex/doc_classes/NoiseTexture.xml
@@ -32,6 +32,7 @@
</member>
<member name="seamless" type="bool" setter="set_seamless" getter="get_seamless" default="false">
Whether the texture can be tiled without visible seams or not. Seamless textures take longer to generate.
+ [b]Note:[/b] Seamless noise has a lower contrast compared to non-seamless noise. This is due to the way noise uses higher dimensions for generating seamless noise.
</member>
<member name="width" type="int" setter="set_width" getter="get_width" default="512">
Width of the generated texture.
diff --git a/modules/opensimplex/doc_classes/OpenSimplexNoise.xml b/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
index dcda5c2324..ad82f87213 100644
--- a/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
+++ b/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
@@ -109,6 +109,7 @@
</argument>
<description>
Generate a tileable noise image in [constant Image.FORMAT_L8] format, based on the current noise parameters. Generated seamless images are always square ([code]size[/code] × [code]size[/code]).
+ [b]Note:[/b] Seamless noise has a lower contrast compared to non-seamless noise. This is due to the way noise uses higher dimensions for generating seamless noise.
</description>
</method>
</methods>
diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp
index 30a0ca3464..f5d401b058 100644
--- a/modules/opensimplex/noise_texture.cpp
+++ b/modules/opensimplex/noise_texture.cpp
@@ -33,15 +33,6 @@
#include "core/core_string_names.h"
NoiseTexture::NoiseTexture() {
- update_queued = false;
- regen_queued = false;
- first_time = true;
-
- size = Vector2i(512, 512);
- seamless = false;
- as_normal_map = false;
- bump_strength = 8.0;
-
noise = Ref<OpenSimplexNoise>();
_queue_update();
@@ -225,7 +216,7 @@ void NoiseTexture::set_as_normal_map(bool p_as_normal_map) {
}
as_normal_map = p_as_normal_map;
_queue_update();
- _change_notify();
+ notify_property_list_changed();
}
bool NoiseTexture::is_normal_map() {
diff --git a/modules/opensimplex/noise_texture.h b/modules/opensimplex/noise_texture.h
index 170275bd2e..e89479d962 100644
--- a/modules/opensimplex/noise_texture.h
+++ b/modules/opensimplex/noise_texture.h
@@ -47,18 +47,18 @@ private:
Thread noise_thread;
- bool first_time;
- bool update_queued;
- bool regen_queued;
+ bool first_time = true;
+ bool update_queued = false;
+ bool regen_queued = false;
mutable RID texture;
- uint32_t flags;
+ uint32_t flags = 0;
Ref<OpenSimplexNoise> noise;
- Vector2i size;
- bool seamless;
- bool as_normal_map;
- float bump_strength;
+ Vector2i size = Vector2i(512, 512);
+ bool seamless = false;
+ bool as_normal_map = false;
+ float bump_strength = 8.0;
void _thread_done(const Ref<Image> &p_image);
static void _thread_function(void *p_ud);
diff --git a/modules/opensimplex/open_simplex_noise.cpp b/modules/opensimplex/open_simplex_noise.cpp
index a823bcf3b8..3773946112 100644
--- a/modules/opensimplex/open_simplex_noise.cpp
+++ b/modules/opensimplex/open_simplex_noise.cpp
@@ -33,12 +33,6 @@
#include "core/core_string_names.h"
OpenSimplexNoise::OpenSimplexNoise() {
- seed = 0;
- persistence = 0.5;
- octaves = 3;
- period = 64;
- lacunarity = 2.0;
-
_init_seeds();
}
diff --git a/modules/opensimplex/open_simplex_noise.h b/modules/opensimplex/open_simplex_noise.h
index f18dd4d798..847c157409 100644
--- a/modules/opensimplex/open_simplex_noise.h
+++ b/modules/opensimplex/open_simplex_noise.h
@@ -48,11 +48,11 @@ class OpenSimplexNoise : public Resource {
osn_context contexts[MAX_OCTAVES];
- int seed;
- float persistence; // Controls details, value in [0,1]. Higher increases grain, lower increases smoothness.
- int octaves; // Number of noise layers
- float period; // Distance above which we start to see similarities. The higher, the longer "hills" will be on a terrain.
- float lacunarity; // Controls period change across octaves. 2 is usually a good value to address all detail levels.
+ int seed = 0;
+ float persistence = 0.5; // Controls details, value in [0,1]. Higher increases grain, lower increases smoothness.
+ int octaves = 3; // Number of noise layers
+ float period = 64.0; // Distance above which we start to see similarities. The higher, the longer "hills" will be on a terrain.
+ float lacunarity = 2.0; // Controls period change across octaves. 2 is usually a good value to address all detail levels.
public:
OpenSimplexNoise();
diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp
index 70a3c8b5a9..83f032ca2b 100644
--- a/modules/pvr/texture_loader_pvr.cpp
+++ b/modules/pvr/texture_loader_pvr.cpp
@@ -46,7 +46,7 @@ enum PVRFLags {
PVR_VFLIP = 0x00010000
};
-RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
@@ -207,7 +207,7 @@ ResourceFormatPVR::ResourceFormatPVR() {
struct PVRTCBlock {
//blocks are 64 bits
- uint32_t data[2];
+ uint32_t data[2] = {};
};
_FORCE_INLINE_ bool is_po2(uint32_t p_input) {
diff --git a/modules/pvr/texture_loader_pvr.h b/modules/pvr/texture_loader_pvr.h
index da425c3237..26071ce30f 100644
--- a/modules/pvr/texture_loader_pvr.h
+++ b/modules/pvr/texture_loader_pvr.h
@@ -36,7 +36,7 @@
class ResourceFormatPVR : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp
index fe8136ef35..6bae12e7e6 100644
--- a/modules/regex/regex.cpp
+++ b/modules/regex/regex.cpp
@@ -365,12 +365,10 @@ Array RegEx::get_names() const {
RegEx::RegEx() {
general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr);
- code = nullptr;
}
RegEx::RegEx(const String &p_pattern) {
general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr);
- code = nullptr;
compile(p_pattern);
}
diff --git a/modules/regex/regex.h b/modules/regex/regex.h
index 46505855d7..f5773042fb 100644
--- a/modules/regex/regex.h
+++ b/modules/regex/regex.h
@@ -42,8 +42,8 @@ class RegExMatch : public Reference {
GDCLASS(RegExMatch, Reference);
struct Range {
- int start;
- int end;
+ int start = 0;
+ int end = 0;
};
String subject;
@@ -72,7 +72,7 @@ class RegEx : public Reference {
GDCLASS(RegEx, Reference);
void *general_ctx;
- void *code;
+ void *code = nullptr;
String pattern;
void _pattern_info(uint32_t what, void *where) const;
diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
index 4b2be47e74..6732078efc 100644
--- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
@@ -47,7 +47,7 @@ void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fra
int mixed = stb_vorbis_get_samples_float_interleaved(ogg_stream, 2, buffer, todo * 2);
if (vorbis_stream->channels == 1 && mixed > 0) {
//mix mono to stereo
- for (int i = start_buffer; i < mixed; i++) {
+ for (int i = start_buffer; i < start_buffer + mixed; i++) {
p_buffer[i].r = p_buffer[i].l;
}
}
@@ -263,16 +263,7 @@ void AudioStreamOGGVorbis::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "loop_offset"), "set_loop_offset", "get_loop_offset");
}
-AudioStreamOGGVorbis::AudioStreamOGGVorbis() {
- data = nullptr;
- data_len = 0;
- length = 0;
- sample_rate = 1;
- channels = 1;
- loop_offset = 0;
- decode_mem_size = 0;
- loop = false;
-}
+AudioStreamOGGVorbis::AudioStreamOGGVorbis() {}
AudioStreamOGGVorbis::~AudioStreamOGGVorbis() {
clear_data();
diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.h b/modules/stb_vorbis/audio_stream_ogg_vorbis.h
index efc8fc6c27..2bd70a2722 100644
--- a/modules/stb_vorbis/audio_stream_ogg_vorbis.h
+++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.h
@@ -41,11 +41,11 @@ class AudioStreamOGGVorbis;
class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled {
GDCLASS(AudioStreamPlaybackOGGVorbis, AudioStreamPlaybackResampled);
- stb_vorbis *ogg_stream;
+ stb_vorbis *ogg_stream = nullptr;
stb_vorbis_alloc ogg_alloc;
- uint32_t frames_mixed;
- bool active;
- int loops;
+ uint32_t frames_mixed = 0;
+ bool active = false;
+ int loops = 0;
friend class AudioStreamOGGVorbis;
@@ -76,15 +76,15 @@ class AudioStreamOGGVorbis : public AudioStream {
friend class AudioStreamPlaybackOGGVorbis;
- void *data;
- uint32_t data_len;
+ void *data = nullptr;
+ uint32_t data_len = 0;
- int decode_mem_size;
- float sample_rate;
- int channels;
- float length;
- bool loop;
- float loop_offset;
+ int decode_mem_size = 0;
+ float sample_rate = 1.0;
+ int channels = 1;
+ float length = 0.0;
+ bool loop = false;
+ float loop_offset = 0.0;
void clear_data();
protected:
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index 3589c8546d..e7863f88a3 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -38,6 +38,7 @@ def make_icu_data(target, source, env):
# Thirdparty source files
thirdparty_obj = []
+freetype_enabled = env.module_check_dependencies("text_server_adv", ["freetype"])
if env["builtin_harfbuzz"]:
env_harfbuzz = env_modules.Clone()
@@ -57,11 +58,9 @@ if env["builtin_harfbuzz"]:
"src/hb-face.cc",
"src/hb-fallback-shape.cc",
"src/hb-font.cc",
- "src/hb-ft.cc",
#'src/hb-gdi.cc',
#'src/hb-glib.cc',
#'src/hb-gobject-structs.cc',
- "src/hb-graphite2.cc",
"src/hb-icu.cc",
"src/hb-map.cc",
"src/hb-number.cc",
@@ -84,8 +83,8 @@ if env["builtin_harfbuzz"]:
"src/hb-ot-shape-complex-indic.cc",
"src/hb-ot-shape-complex-khmer.cc",
"src/hb-ot-shape-complex-myanmar.cc",
+ "src/hb-ot-shape-complex-syllabic.cc",
"src/hb-ot-shape-complex-thai.cc",
- "src/hb-ot-shape-complex-use-table.cc",
"src/hb-ot-shape-complex-use.cc",
"src/hb-ot-shape-complex-vowel-constraints.cc",
"src/hb-ot-shape-fallback.cc",
@@ -109,17 +108,29 @@ if env["builtin_harfbuzz"]:
"src/hb-unicode.cc",
#'src/hb-uniscribe.cc'
]
+
+ if freetype_enabled:
+ thirdparty_sources += [
+ "src/hb-ft.cc",
+ "src/hb-graphite2.cc",
+ ]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_harfbuzz.Append(
CPPPATH=[
"#thirdparty/harfbuzz/src",
- "#thirdparty/freetype/include",
- "#thirdparty/graphite/include",
"#thirdparty/icu4c/common/",
]
)
+ if freetype_enabled:
+ env_harfbuzz.Append(
+ CPPPATH=[
+ "#thirdparty/freetype/include",
+ "#thirdparty/graphite/include",
+ ]
+ )
+
if env["platform"] == "android" or env["platform"] == "linuxbsd" or env["platform"] == "server":
env_harfbuzz.Append(CCFLAGS=["-DHAVE_PTHREAD"])
@@ -133,12 +144,18 @@ if env["builtin_harfbuzz"]:
CCFLAGS=[
"-DHAVE_ICU_BUILTIN",
"-DHAVE_ICU",
- "-DHAVE_FREETYPE",
- "-DHAVE_GRAPHITE2",
- "-DGRAPHITE2_STATIC",
]
)
+ if freetype_enabled:
+ env_harfbuzz.Append(
+ CCFLAGS=[
+ "-DHAVE_FREETYPE",
+ "-DHAVE_GRAPHITE2",
+ "-DGRAPHITE2_STATIC",
+ ]
+ )
+
lib = env_harfbuzz.add_library("harfbuzz_builtin", thirdparty_sources)
thirdparty_obj += lib
@@ -156,7 +173,7 @@ if env["builtin_harfbuzz"]:
env.Append(LIBS=[lib])
-if env["builtin_graphite"]:
+if env["builtin_graphite"] and freetype_enabled:
env_graphite = env_modules.Clone()
env_graphite.disable_warnings()
@@ -488,12 +505,18 @@ if env_text_server_adv["tools"]:
env_text_server_adv.Append(
CPPPATH=[
"#thirdparty/harfbuzz/src",
- "#thirdparty/freetype/include",
- "#thirdparty/graphite/include",
"#thirdparty/icu4c/common/",
]
)
+if freetype_enabled:
+ env_text_server_adv.Append(
+ CPPPATH=[
+ "#thirdparty/freetype/include",
+ "#thirdparty/graphite/include",
+ ]
+ )
+
env_text_server_adv.add_source_files(module_obj, "*.cpp")
env.modules_sources += module_obj
diff --git a/modules/text_server_adv/bitmap_font_adv.cpp b/modules/text_server_adv/bitmap_font_adv.cpp
index 51cc242348..df7b42eac6 100644
--- a/modules/text_server_adv/bitmap_font_adv.cpp
+++ b/modules/text_server_adv/bitmap_font_adv.cpp
@@ -36,7 +36,7 @@
struct hb_bmp_font_t {
BitmapFontDataAdvanced *face = nullptr;
- float font_size = 0;
+ float font_size = 0.0;
bool unref = false; /* Whether to destroy bm_face when done. */
};
@@ -340,7 +340,7 @@ Error BitmapFontDataAdvanced::load_from_file(const String &p_filename, int p_bas
char_map[idx] = c;
} else if (type == "kerning") {
KerningPairKey kpk;
- float k = 0;
+ float k = 0.0;
if (keys.has("first")) {
kpk.A = keys["first"].to_int();
}
@@ -361,67 +361,71 @@ Error BitmapFontDataAdvanced::load_from_file(const String &p_filename, int p_bas
base_size = height;
}
+ if (hb_handle) {
+ hb_font_destroy(hb_handle);
+ }
+ hb_handle = hb_bmp_font_create(this, base_size, nullptr);
valid = true;
memdelete(f);
return OK;
}
-Error BitmapFontDataAdvanced::load_from_memory(const uint8_t *p_data, size_t p_size, int p_base_size) {
- _THREAD_SAFE_METHOD_
- ERR_FAIL_COND_V(p_data == nullptr, ERR_CANT_CREATE);
- ERR_FAIL_COND_V(p_size != sizeof(TextServer::BitmapFontData), ERR_CANT_CREATE);
-
- const TextServer::BitmapFontData *data = (const TextServer::BitmapFontData *)p_data;
-
- if (RenderingServer::get_singleton() != nullptr) {
- Ref<Image> image = memnew(Image(data->img));
- Ref<ImageTexture> tex = memnew(ImageTexture);
- tex->create_from_image(image);
+Error BitmapFontDataAdvanced::bitmap_new(float p_height, float p_ascent, int p_base_size) {
+ height = p_height;
+ ascent = p_ascent;
- textures.push_back(tex);
+ base_size = p_base_size;
+ if (base_size == 0) {
+ base_size = height;
}
- for (int i = 0; i < data->charcount; i++) {
- const int *c = &data->char_rects[i * 8];
-
- Character chr;
- chr.rect.position.x = c[1];
- chr.rect.position.y = c[2];
- chr.rect.size.x = c[3];
- chr.rect.size.y = c[4];
- if (c[7] < 0) {
- chr.advance.x = c[3];
- } else {
- chr.advance.x = c[7];
- }
- chr.align = Vector2(c[6], c[5]);
- char_map[c[0]] = chr;
+ char_map.clear();
+ textures.clear();
+ kerning_map.clear();
+ if (hb_handle) {
+ hb_font_destroy(hb_handle);
}
+ hb_handle = hb_bmp_font_create(this, base_size, nullptr);
+ valid = true;
- for (int i = 0; i < data->kerning_count; i++) {
- KerningPairKey kpk;
- kpk.A = data->kernings[i * 3 + 0];
- kpk.B = data->kernings[i * 3 + 1];
+ return OK;
+}
- if (data->kernings[i * 3 + 2] == 0 && kerning_map.has(kpk)) {
- kerning_map.erase(kpk);
- } else {
- kerning_map[kpk] = data->kernings[i * 3 + 2];
- }
- }
+void BitmapFontDataAdvanced::bitmap_add_texture(const Ref<Texture> &p_texture) {
+ ERR_FAIL_COND(!valid);
+ ERR_FAIL_COND_MSG(p_texture.is_null(), "It's not a reference to a valid Texture object.");
- height = data->height;
- ascent = data->ascent;
+ textures.push_back(p_texture);
+}
- base_size = p_base_size;
- if (base_size == 0) {
- base_size = height;
+void BitmapFontDataAdvanced::bitmap_add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) {
+ ERR_FAIL_COND(!valid);
+
+ Character chr;
+ chr.rect = p_rect;
+ chr.texture_idx = p_texture_idx;
+ if (p_advance < 0) {
+ chr.advance.x = chr.rect.size.x;
+ } else {
+ chr.advance.x = p_advance;
}
+ chr.align = p_align;
+ char_map[p_char] = chr;
+}
- valid = true;
+void BitmapFontDataAdvanced::bitmap_add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) {
+ ERR_FAIL_COND(!valid);
- return OK;
+ KerningPairKey kpk;
+ kpk.A = p_A;
+ kpk.B = p_B;
+
+ if (p_kerning == 0 && kerning_map.has(kpk)) {
+ kerning_map.erase(kpk);
+ } else {
+ kerning_map[kpk] = p_kerning;
+ }
}
float BitmapFontDataAdvanced::get_height(int p_size) const {
@@ -464,10 +468,7 @@ float BitmapFontDataAdvanced::get_base_size() const {
hb_font_t *BitmapFontDataAdvanced::get_hb_handle(int p_size) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!valid, nullptr);
- if (!cache.has(p_size)) {
- cache[p_size] = hb_bmp_font_create(this, p_size, nullptr);
- }
- return cache[p_size];
+ return hb_handle;
}
bool BitmapFontDataAdvanced::has_char(char32_t p_char) const {
@@ -514,6 +515,10 @@ Vector2 BitmapFontDataAdvanced::get_size(uint32_t p_char, int p_size) const {
return c->rect.size * (float(p_size) / float(base_size));
}
+float BitmapFontDataAdvanced::get_font_scale(int p_size) const {
+ return float(p_size) / float(base_size);
+}
+
Vector2 BitmapFontDataAdvanced::get_kerning(uint32_t p_char, uint32_t p_next, int p_size) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!valid, Vector2());
@@ -541,13 +546,13 @@ Vector2 BitmapFontDataAdvanced::draw_glyph(RID p_canvas, int p_size, const Vecto
ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), Vector2());
if (c->texture_idx != -1) {
Point2i cpos = p_pos;
- cpos += c->align * (float(p_size) / float(base_size));
- cpos.y -= ascent * (float(p_size) / float(base_size));
+ cpos += (c->align + Vector2(0, -ascent)) * (float(p_size) / float(base_size));
+ Size2i csize = c->rect.size * (float(p_size) / float(base_size));
if (RenderingServer::get_singleton() != nullptr) {
//if (distance_field_hint) { // Not implemented.
// RenderingServer::get_singleton()->canvas_item_set_distance_field_mode(p_canvas, true);
//}
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, c->rect.size * (float(p_size) / float(base_size))), textures[c->texture_idx]->get_rid(), c->rect, p_color, false, false);
+ RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), textures[c->texture_idx]->get_rid(), c->rect, p_color, false, false);
//if (distance_field_hint) {
// RenderingServer::get_singleton()->canvas_item_set_distance_field_mode(p_canvas, false);
//}
@@ -574,7 +579,7 @@ Vector2 BitmapFontDataAdvanced::draw_glyph_outline(RID p_canvas, int p_size, int
}
BitmapFontDataAdvanced::~BitmapFontDataAdvanced() {
- for (Map<float, hb_font_t *>::Element *E = cache.front(); E; E = E->next()) {
- hb_font_destroy(E->get());
+ if (hb_handle) {
+ hb_font_destroy(hb_handle);
}
}
diff --git a/modules/text_server_adv/bitmap_font_adv.h b/modules/text_server_adv/bitmap_font_adv.h
index c314f1b087..7b620021e1 100644
--- a/modules/text_server_adv/bitmap_font_adv.h
+++ b/modules/text_server_adv/bitmap_font_adv.h
@@ -63,18 +63,22 @@ private:
HashMap<uint32_t, Character> char_map;
Map<KerningPairKey, int> kerning_map;
- Map<float, hb_font_t *> cache;
+ hb_font_t *hb_handle = nullptr;
float height = 0.f;
float ascent = 0.f;
- float base_size = 0.f;
+ int base_size = 0;
bool distance_field_hint = false;
public:
virtual void clear_cache() override{};
virtual Error load_from_file(const String &p_filename, int p_base_size) override;
- virtual Error load_from_memory(const uint8_t *p_data, size_t p_size, int p_base_size) override;
+ virtual Error bitmap_new(float p_height, float p_ascent, int p_base_size) override;
+
+ virtual void bitmap_add_texture(const Ref<Texture> &p_texture) override;
+ virtual void bitmap_add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) override;
+ virtual void bitmap_add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) override;
virtual float get_height(int p_size) const override;
virtual float get_ascent(int p_size) const override;
@@ -97,6 +101,7 @@ public:
virtual bool has_outline() const override { return false; };
virtual float get_base_size() const override;
+ virtual float get_font_scale(int p_size) const override;
virtual hb_font_t *get_hb_handle(int p_size) override;
diff --git a/modules/text_server_adv/config.py b/modules/text_server_adv/config.py
index 22482fce24..d22f9454ed 100644
--- a/modules/text_server_adv/config.py
+++ b/modules/text_server_adv/config.py
@@ -1,5 +1,5 @@
def can_build(env, platform):
- return env.module_check_dependencies("text_server_adv", ["freetype"])
+ return True
def configure(env):
diff --git a/modules/text_server_adv/dynamic_font_adv.cpp b/modules/text_server_adv/dynamic_font_adv.cpp
index 5a16158c0f..2521e68dda 100644
--- a/modules/text_server_adv/dynamic_font_adv.cpp
+++ b/modules/text_server_adv/dynamic_font_adv.cpp
@@ -30,6 +30,8 @@
#include "dynamic_font_adv.h"
+#ifdef MODULE_FREETYPE_ENABLED
+
#include FT_STROKER_H
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
@@ -124,10 +126,10 @@ DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(
fds->size = p_size;
fds->ascent = (fds->face->size->metrics.ascender / 64.0) / oversampling * fds->scale_color_font;
fds->descent = (-fds->face->size->metrics.descender / 64.0) / oversampling * fds->scale_color_font;
- fds->underline_position = -fds->face->underline_position / 64.0 / oversampling * fds->scale_color_font;
- fds->underline_thickness = fds->face->underline_thickness / 64.0 / oversampling * fds->scale_color_font;
+ fds->underline_position = (-FT_MulFix(fds->face->underline_position, fds->face->size->metrics.y_scale) / 64.0) / oversampling * fds->scale_color_font;
+ fds->underline_thickness = (FT_MulFix(fds->face->underline_thickness, fds->face->size->metrics.y_scale) / 64.0) / oversampling * fds->scale_color_font;
- //Load os2 TTF pable
+ //Load os2 TTF table
fds->os2 = (TT_OS2 *)FT_Get_Sfnt_Table(fds->face, FT_SFNT_OS2);
fds->hb_handle = hb_ft_font_create(fds->face, nullptr);
@@ -1001,3 +1003,5 @@ DynamicFontDataAdvanced::~DynamicFontDataAdvanced() {
FT_Done_FreeType(library);
}
}
+
+#endif // MODULE_FREETYPE_ENABLED
diff --git a/modules/text_server_adv/dynamic_font_adv.h b/modules/text_server_adv/dynamic_font_adv.h
index c35dd9390b..d69a30b321 100644
--- a/modules/text_server_adv/dynamic_font_adv.h
+++ b/modules/text_server_adv/dynamic_font_adv.h
@@ -33,6 +33,10 @@
#include "font_adv.h"
+#include "modules/modules_enabled.gen.h"
+
+#ifdef MODULE_FREETYPE_ENABLED
+
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TRUETYPE_TABLES_H
@@ -74,14 +78,11 @@ private:
uint32_t size : 16;
uint32_t outline_size : 16;
};
- uint32_t key;
+ uint32_t key = 0;
};
bool operator<(CacheID right) const {
return key < right.key;
}
- CacheID() {
- key = 0;
- }
};
struct DataAtSize {
@@ -91,10 +92,10 @@ private:
int size = 0;
float scale_color_font = 1.f;
- float ascent = 0;
- float descent = 0;
- float underline_position = 0;
- float underline_thickness = 0;
+ float ascent = 0.0;
+ float descent = 0.0;
+ float underline_position = 0.0;
+ float underline_thickness = 0.0;
Vector<CharTexture> textures;
HashMap<uint32_t, Character> glyph_map;
@@ -188,4 +189,6 @@ public:
virtual ~DynamicFontDataAdvanced() override;
};
+#endif // MODULE_FREETYPE_ENABLED
+
#endif // DYNAMIC_FONT_ADV_H
diff --git a/modules/text_server_adv/font_adv.h b/modules/text_server_adv/font_adv.h
index 4bbd2dd4bf..2b6d977451 100644
--- a/modules/text_server_adv/font_adv.h
+++ b/modules/text_server_adv/font_adv.h
@@ -39,11 +39,18 @@ struct FontDataAdvanced {
Map<String, bool> lang_support_overrides;
Map<String, bool> script_support_overrides;
bool valid = false;
+ int spacing_space = 0;
+ int spacing_glyph = 0;
virtual void clear_cache() = 0;
- virtual Error load_from_file(const String &p_filename, int p_base_size) = 0;
- virtual Error load_from_memory(const uint8_t *p_data, size_t p_size, int p_base_size) = 0;
+ virtual Error load_from_file(const String &p_filename, int p_base_size) { return ERR_CANT_CREATE; };
+ virtual Error load_from_memory(const uint8_t *p_data, size_t p_size, int p_base_size) { return ERR_CANT_CREATE; };
+ virtual Error bitmap_new(float p_height, float p_ascent, int p_base_size) { return ERR_CANT_CREATE; };
+
+ virtual void bitmap_add_texture(const Ref<Texture> &p_texture) { ERR_FAIL_MSG("Not supported."); };
+ virtual void bitmap_add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) { ERR_FAIL_MSG("Not supported."); };
+ virtual void bitmap_add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) { ERR_FAIL_MSG("Not supported."); };
virtual float get_height(int p_size) const = 0;
virtual float get_ascent(int p_size) const = 0;
@@ -58,6 +65,18 @@ struct FontDataAdvanced {
virtual float get_underline_position(int p_size) const = 0;
virtual float get_underline_thickness(int p_size) const = 0;
+ virtual int get_spacing_space() const { return spacing_space; };
+ virtual void set_spacing_space(int p_value) {
+ spacing_space = p_value;
+ clear_cache();
+ };
+
+ virtual int get_spacing_glyph() const { return spacing_glyph; };
+ virtual void set_spacing_glyph(int p_value) {
+ spacing_glyph = p_value;
+ clear_cache();
+ };
+
virtual void set_antialiased(bool p_antialiased) = 0;
virtual bool get_antialiased() const = 0;
diff --git a/modules/text_server_adv/script_iterator.h b/modules/text_server_adv/script_iterator.h
index ad476f7c75..896a0e5c15 100644
--- a/modules/text_server_adv/script_iterator.h
+++ b/modules/text_server_adv/script_iterator.h
@@ -45,9 +45,9 @@
class ScriptIterator {
public:
struct ScriptRange {
- int start;
- int end;
- hb_script_t script;
+ int start = 0;
+ int end = 0;
+ hb_script_t script = HB_SCRIPT_COMMON;
};
Vector<ScriptRange> script_ranges;
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 8e4771685d..43b8f18101 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -166,7 +166,7 @@ bool TextServerAdvanced::load_support_data(const String &p_filename) {
#ifdef ICU_STATIC_DATA
if (icu_data == nullptr) {
UErrorCode err = U_ZERO_ERROR;
- u_init(&err); // Do not check for errors, since we only load part the of data.
+ u_init(&err); // Do not check for errors, since we only load part of the data.
icu_data = (uint8_t *)&U_ICUDATA_ENTRY_POINT;
}
#else
@@ -244,7 +244,7 @@ struct FeatureInfo {
};
static FeatureInfo feature_set[] = {
- // Registred OpenType feature tags.
+ // Registered OpenType feature tags.
{ HB_TAG('a', 'a', 'l', 't'), "access_all_alternates" },
{ HB_TAG('a', 'b', 'v', 'f'), "above_base_forms" },
{ HB_TAG('a', 'b', 'v', 'm'), "above_base_mark_positioning" },
@@ -484,7 +484,7 @@ static FeatureInfo feature_set[] = {
{ HB_TAG('v', 'r', 't', '2'), "vertical_alternates_and_rotation" },
{ HB_TAG('v', 'r', 't', 'r'), "vertical_alternates_for_rotation" },
{ HB_TAG('z', 'e', 'r', 'o'), "slashed_zero" },
- // Registred OpenType variation tags.
+ // Registered OpenType variation tags.
{ HB_TAG('i', 't', 'a', 'l'), "italic" },
{ HB_TAG('o', 'p', 's', 'z'), "optical_size" },
{ HB_TAG('s', 'l', 'n', 't'), "slant" },
@@ -529,10 +529,12 @@ RID TextServerAdvanced::create_font_system(const String &p_name, int p_base_size
RID TextServerAdvanced::create_font_resource(const String &p_filename, int p_base_size) {
_THREAD_SAFE_METHOD_
FontDataAdvanced *fd = nullptr;
- if (p_filename.get_extension() == "ttf" || p_filename.get_extension() == "otf" || p_filename.get_extension() == "woff") {
- fd = memnew(DynamicFontDataAdvanced);
- } else if (p_filename.get_extension() == "fnt" || p_filename.get_extension() == "font") {
+ if (p_filename.get_extension() == "fnt" || p_filename.get_extension() == "font") {
fd = memnew(BitmapFontDataAdvanced);
+#ifdef MODULE_FREETYPE_ENABLED
+ } else if (p_filename.get_extension() == "ttf" || p_filename.get_extension() == "otf" || p_filename.get_extension() == "woff") {
+ fd = memnew(DynamicFontDataAdvanced);
+#endif
} else {
return RID();
}
@@ -549,10 +551,12 @@ RID TextServerAdvanced::create_font_resource(const String &p_filename, int p_bas
RID TextServerAdvanced::create_font_memory(const uint8_t *p_data, size_t p_size, const String &p_type, int p_base_size) {
_THREAD_SAFE_METHOD_
FontDataAdvanced *fd = nullptr;
- if (p_type == "ttf" || p_type == "otf" || p_type == "woff") {
- fd = memnew(DynamicFontDataAdvanced);
- } else if (p_type == "fnt" || p_type == "font") {
+ if (p_type == "fnt" || p_type == "font") {
fd = memnew(BitmapFontDataAdvanced);
+#ifdef MODULE_FREETYPE_ENABLED
+ } else if (p_type == "ttf" || p_type == "otf" || p_type == "woff") {
+ fd = memnew(DynamicFontDataAdvanced);
+#endif
} else {
return RID();
}
@@ -566,6 +570,39 @@ RID TextServerAdvanced::create_font_memory(const uint8_t *p_data, size_t p_size,
return font_owner.make_rid(fd);
}
+RID TextServerAdvanced::create_font_bitmap(float p_height, float p_ascent, int p_base_size) {
+ _THREAD_SAFE_METHOD_
+ FontDataAdvanced *fd = memnew(BitmapFontDataAdvanced);
+ Error err = fd->bitmap_new(p_height, p_ascent, p_base_size);
+ if (err != OK) {
+ memdelete(fd);
+ return RID();
+ }
+
+ return font_owner.make_rid(fd);
+}
+
+void TextServerAdvanced::font_bitmap_add_texture(RID p_font, const Ref<Texture> &p_texture) {
+ _THREAD_SAFE_METHOD_
+ FontDataAdvanced *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND(!fd);
+ fd->bitmap_add_texture(p_texture);
+}
+
+void TextServerAdvanced::font_bitmap_add_char(RID p_font, char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) {
+ _THREAD_SAFE_METHOD_
+ FontDataAdvanced *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND(!fd);
+ fd->bitmap_add_char(p_char, p_texture_idx, p_rect, p_align, p_advance);
+}
+
+void TextServerAdvanced::font_bitmap_add_kerning_pair(RID p_font, char32_t p_A, char32_t p_B, int p_kerning) {
+ _THREAD_SAFE_METHOD_
+ FontDataAdvanced *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND(!fd);
+ fd->bitmap_add_kerning_pair(p_A, p_B, p_kerning);
+}
+
float TextServerAdvanced::font_get_height(RID p_font, int p_size) const {
_THREAD_SAFE_METHOD_
const FontDataAdvanced *fd = font_owner.getornull(p_font);
@@ -601,6 +638,34 @@ float TextServerAdvanced::font_get_underline_thickness(RID p_font, int p_size) c
return fd->get_underline_thickness(p_size);
}
+int TextServerAdvanced::font_get_spacing_space(RID p_font) const {
+ _THREAD_SAFE_METHOD_
+ const FontDataAdvanced *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND_V(!fd, 0);
+ return fd->get_spacing_space();
+}
+
+void TextServerAdvanced::font_set_spacing_space(RID p_font, int p_value) {
+ _THREAD_SAFE_METHOD_
+ FontDataAdvanced *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND(!fd);
+ fd->set_spacing_space(p_value);
+}
+
+int TextServerAdvanced::font_get_spacing_glyph(RID p_font) const {
+ _THREAD_SAFE_METHOD_
+ const FontDataAdvanced *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND_V(!fd, 0);
+ return fd->get_spacing_glyph();
+}
+
+void TextServerAdvanced::font_set_spacing_glyph(RID p_font, int p_value) {
+ _THREAD_SAFE_METHOD_
+ FontDataAdvanced *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND(!fd);
+ fd->set_spacing_glyph(p_value);
+}
+
void TextServerAdvanced::font_set_antialiased(RID p_font, bool p_antialiased) {
_THREAD_SAFE_METHOD_
FontDataAdvanced *fd = font_owner.getornull(p_font);
@@ -1595,7 +1660,7 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) {
}
if (sd->line_breaks_valid) {
- return true; // Noting to do.
+ return true; // Nothing to do.
}
const UChar *data = sd->utf16.ptr();
@@ -1780,7 +1845,7 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) {
}
if (sd->justification_ops_valid) {
- return true; // Noting to do.
+ return true; // Nothing to do.
}
const UChar *data = sd->utf16.ptr();
@@ -2049,6 +2114,11 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
gl.x_off = Math::round(glyph_pos[i].x_offset / (64.0 / fd->get_font_scale(fs)));
gl.y_off = -Math::round(glyph_pos[i].y_offset / (64.0 / fd->get_font_scale(fs)));
}
+ if (fd->get_spacing_space() && is_whitespace(p_sd->text[glyph_info[i].cluster])) {
+ gl.advance += fd->get_spacing_space();
+ } else {
+ gl.advance += fd->get_spacing_glyph();
+ }
if (p_sd->preserve_control) {
last_cluster_valid = last_cluster_valid && ((glyph_info[i].codepoint != 0) || is_whitespace(p_sd->text[glyph_info[i].cluster]) || is_linebreak(p_sd->text[glyph_info[i].cluster]));
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 89fae477f9..b53b5716e5 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -126,6 +126,11 @@ public:
virtual RID create_font_system(const String &p_name, int p_base_size = 16) override;
virtual RID create_font_resource(const String &p_filename, int p_base_size = 16) override;
virtual RID create_font_memory(const uint8_t *p_data, size_t p_size, const String &p_type, int p_base_size = 16) override;
+ virtual RID create_font_bitmap(float p_height, float p_ascent, int p_base_size = 16) override;
+
+ virtual void font_bitmap_add_texture(RID p_font, const Ref<Texture> &p_texture) override;
+ virtual void font_bitmap_add_char(RID p_font, char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) override;
+ virtual void font_bitmap_add_kerning_pair(RID p_font, char32_t p_A, char32_t p_B, int p_kerning) override;
virtual float font_get_height(RID p_font, int p_size) const override;
virtual float font_get_ascent(RID p_font, int p_size) const override;
@@ -134,6 +139,12 @@ public:
virtual float font_get_underline_position(RID p_font, int p_size) const override;
virtual float font_get_underline_thickness(RID p_font, int p_size) const override;
+ virtual int font_get_spacing_space(RID p_font) const override;
+ virtual void font_set_spacing_space(RID p_font, int p_value) override;
+
+ virtual int font_get_spacing_glyph(RID p_font) const override;
+ virtual void font_set_spacing_glyph(RID p_font, int p_value) override;
+
virtual void font_set_antialiased(RID p_font, bool p_antialiased) override;
virtual bool font_get_antialiased(RID p_font) const override;
diff --git a/modules/text_server_fb/bitmap_font_fb.cpp b/modules/text_server_fb/bitmap_font_fb.cpp
index 6bc838bd6a..313f170f04 100644
--- a/modules/text_server_fb/bitmap_font_fb.cpp
+++ b/modules/text_server_fb/bitmap_font_fb.cpp
@@ -148,7 +148,7 @@ Error BitmapFontDataFallback::load_from_file(const String &p_filename, int p_bas
char_map[idx] = c;
} else if (type == "kerning") {
KerningPairKey kpk;
- float k = 0;
+ float k = 0.0;
if (keys.has("first")) {
kpk.A = keys["first"].to_int();
}
@@ -175,61 +175,58 @@ Error BitmapFontDataFallback::load_from_file(const String &p_filename, int p_bas
return OK;
}
-Error BitmapFontDataFallback::load_from_memory(const uint8_t *p_data, size_t p_size, int p_base_size) {
- _THREAD_SAFE_METHOD_
- ERR_FAIL_COND_V(p_data == nullptr, ERR_CANT_CREATE);
- ERR_FAIL_COND_V(p_size != sizeof(TextServer::BitmapFontData), ERR_CANT_CREATE);
+Error BitmapFontDataFallback::bitmap_new(float p_height, float p_ascent, int p_base_size) {
+ height = p_height;
+ ascent = p_ascent;
- const TextServer::BitmapFontData *data = (const TextServer::BitmapFontData *)p_data;
+ base_size = p_base_size;
+ if (base_size == 0) {
+ base_size = height;
+ }
- if (RenderingServer::get_singleton() != nullptr) {
- Ref<Image> image = memnew(Image(data->img));
- Ref<ImageTexture> tex = memnew(ImageTexture);
- tex->create_from_image(image);
+ char_map.clear();
+ textures.clear();
+ kerning_map.clear();
- textures.push_back(tex);
- }
+ valid = true;
- for (int i = 0; i < data->charcount; i++) {
- const int *c = &data->char_rects[i * 8];
-
- Character chr;
- chr.rect.position.x = c[1];
- chr.rect.position.y = c[2];
- chr.rect.size.x = c[3];
- chr.rect.size.y = c[4];
- if (c[7] < 0) {
- chr.advance.x = c[3];
- } else {
- chr.advance.x = c[7];
- }
- chr.align = Vector2(c[6], c[5]);
- char_map[c[0]] = chr;
- }
+ return OK;
+}
- for (int i = 0; i < data->kerning_count; i++) {
- KerningPairKey kpk;
- kpk.A = data->kernings[i * 3 + 0];
- kpk.B = data->kernings[i * 3 + 1];
+void BitmapFontDataFallback::bitmap_add_texture(const Ref<Texture> &p_texture) {
+ ERR_FAIL_COND(!valid);
+ ERR_FAIL_COND_MSG(p_texture.is_null(), "It's not a reference to a valid Texture object.");
- if (data->kernings[i * 3 + 2] == 0 && kerning_map.has(kpk)) {
- kerning_map.erase(kpk);
- } else {
- kerning_map[kpk] = data->kernings[i * 3 + 2];
- }
- }
+ textures.push_back(p_texture);
+}
- height = data->height;
- ascent = data->ascent;
+void BitmapFontDataFallback::bitmap_add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) {
+ ERR_FAIL_COND(!valid);
- base_size = p_base_size;
- if (base_size == 0) {
- base_size = height;
+ Character chr;
+ chr.rect = p_rect;
+ chr.texture_idx = p_texture_idx;
+ if (p_advance < 0) {
+ chr.advance.x = chr.rect.size.x;
+ } else {
+ chr.advance.x = p_advance;
}
+ chr.align = p_align;
+ char_map[p_char] = chr;
+}
- valid = true;
+void BitmapFontDataFallback::bitmap_add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) {
+ ERR_FAIL_COND(!valid);
- return OK;
+ KerningPairKey kpk;
+ kpk.A = p_A;
+ kpk.B = p_B;
+
+ if (p_kerning == 0 && kerning_map.has(kpk)) {
+ kerning_map.erase(kpk);
+ } else {
+ kerning_map[kpk] = p_kerning;
+ }
}
float BitmapFontDataFallback::get_height(int p_size) const {
@@ -322,14 +319,13 @@ Vector2 BitmapFontDataFallback::draw_glyph(RID p_canvas, int p_size, const Vecto
ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), Vector2());
if (c->texture_idx != -1) {
Point2i cpos = p_pos;
- cpos += c->align * (float(p_size) / float(base_size));
- cpos.y -= ascent * (float(p_size) / float(base_size));
-
+ cpos += (c->align + Vector2(0, -ascent)) * (float(p_size) / float(base_size));
+ Size2i csize = c->rect.size * (float(p_size) / float(base_size));
if (RenderingServer::get_singleton() != nullptr) {
//if (distance_field_hint) { // Not implemented.
// RenderingServer::get_singleton()->canvas_item_set_distance_field_mode(p_canvas, true);
//}
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, c->rect.size * (float(p_size) / float(base_size))), textures[c->texture_idx]->get_rid(), c->rect, p_color, false, false);
+ RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), textures[c->texture_idx]->get_rid(), c->rect, p_color, false, false);
//if (distance_field_hint) {
// RenderingServer::get_singleton()->canvas_item_set_distance_field_mode(p_canvas, false);
//}
diff --git a/modules/text_server_fb/bitmap_font_fb.h b/modules/text_server_fb/bitmap_font_fb.h
index 33401b85fa..7cd7507ebc 100644
--- a/modules/text_server_fb/bitmap_font_fb.h
+++ b/modules/text_server_fb/bitmap_font_fb.h
@@ -70,7 +70,11 @@ public:
virtual void clear_cache() override{};
virtual Error load_from_file(const String &p_filename, int p_base_size) override;
- virtual Error load_from_memory(const uint8_t *p_data, size_t p_size, int p_base_size) override;
+ virtual Error bitmap_new(float p_height, float p_ascent, int p_base_size) override;
+
+ virtual void bitmap_add_texture(const Ref<Texture> &p_texture) override;
+ virtual void bitmap_add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) override;
+ virtual void bitmap_add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) override;
virtual float get_height(int p_size) const override;
virtual float get_ascent(int p_size) const override;
diff --git a/modules/text_server_fb/config.py b/modules/text_server_fb/config.py
index 491377a369..7a73080ae9 100644
--- a/modules/text_server_fb/config.py
+++ b/modules/text_server_fb/config.py
@@ -1,5 +1,5 @@
def can_build(env, platform):
- return env.module_check_dependencies("text_server_fb", ["freetype"])
+ return True
def configure(env):
diff --git a/modules/text_server_fb/dynamic_font_fb.cpp b/modules/text_server_fb/dynamic_font_fb.cpp
index df7756cbd0..66d36bc885 100644
--- a/modules/text_server_fb/dynamic_font_fb.cpp
+++ b/modules/text_server_fb/dynamic_font_fb.cpp
@@ -30,6 +30,8 @@
#include "dynamic_font_fb.h"
+#ifdef MODULE_FREETYPE_ENABLED
+
#include FT_STROKER_H
#include FT_ADVANCES_H
@@ -124,8 +126,9 @@ DynamicFontDataFallback::DataAtSize *DynamicFontDataFallback::get_data_for_size(
fds->size = p_size;
fds->ascent = (fds->face->size->metrics.ascender / 64.0) / oversampling * fds->scale_color_font;
fds->descent = (-fds->face->size->metrics.descender / 64.0) / oversampling * fds->scale_color_font;
- fds->underline_position = -fds->face->underline_position / 64.0 / oversampling * fds->scale_color_font;
- fds->underline_thickness = fds->face->underline_thickness / 64.0 / oversampling * fds->scale_color_font;
+ fds->underline_position = (-FT_MulFix(fds->face->underline_position, fds->face->size->metrics.y_scale) / 64.0) / oversampling * fds->scale_color_font;
+ fds->underline_thickness = (FT_MulFix(fds->face->underline_thickness, fds->face->size->metrics.y_scale) / 64.0) / oversampling * fds->scale_color_font;
+
if (p_outline_size != 0) {
size_cache_outline[id] = fds;
} else {
@@ -683,3 +686,5 @@ DynamicFontDataFallback::~DynamicFontDataFallback() {
FT_Done_FreeType(library);
}
}
+
+#endif // MODULE_FREETYPE_ENABLED
diff --git a/modules/text_server_fb/dynamic_font_fb.h b/modules/text_server_fb/dynamic_font_fb.h
index f1cd758f2c..eb70f46666 100644
--- a/modules/text_server_fb/dynamic_font_fb.h
+++ b/modules/text_server_fb/dynamic_font_fb.h
@@ -33,6 +33,10 @@
#include "font_fb.h"
+#include "modules/modules_enabled.gen.h"
+
+#ifdef MODULE_FREETYPE_ENABLED
+
#include <ft2build.h>
#include FT_FREETYPE_H
@@ -70,14 +74,11 @@ private:
uint32_t size : 16;
uint32_t outline_size : 16;
};
- uint32_t key;
+ uint32_t key = 0;
};
bool operator<(CacheID right) const {
return key < right.key;
}
- CacheID() {
- key = 0;
- }
};
struct DataAtSize {
@@ -86,10 +87,10 @@ private:
int size = 0;
float scale_color_font = 1.f;
- float ascent = 0;
- float descent = 0;
- float underline_position = 0;
- float underline_thickness = 0;
+ float ascent = 0.0;
+ float descent = 0.0;
+ float underline_position = 0.0;
+ float underline_thickness = 0.0;
Vector<CharTexture> textures;
HashMap<char32_t, Character> char_map;
@@ -166,4 +167,6 @@ public:
virtual ~DynamicFontDataFallback() override;
};
+#endif // MODULE_FREETYPE_ENABLED
+
#endif // DYNAMIC_FONT_FALLBACK_H
diff --git a/modules/text_server_fb/font_fb.h b/modules/text_server_fb/font_fb.h
index cc72919542..218f3df03a 100644
--- a/modules/text_server_fb/font_fb.h
+++ b/modules/text_server_fb/font_fb.h
@@ -37,11 +37,18 @@ struct FontDataFallback {
Map<String, bool> lang_support_overrides;
Map<String, bool> script_support_overrides;
bool valid = false;
+ int spacing_space = 0;
+ int spacing_glyph = 0;
virtual void clear_cache() = 0;
- virtual Error load_from_file(const String &p_filename, int p_base_size) = 0;
- virtual Error load_from_memory(const uint8_t *p_data, size_t p_size, int p_base_size) = 0;
+ virtual Error load_from_file(const String &p_filename, int p_base_size) { return ERR_CANT_CREATE; };
+ virtual Error load_from_memory(const uint8_t *p_data, size_t p_size, int p_base_size) { return ERR_CANT_CREATE; };
+ virtual Error bitmap_new(float p_height, float p_ascent, int p_base_size) { return ERR_CANT_CREATE; };
+
+ virtual void bitmap_add_texture(const Ref<Texture> &p_texture) { ERR_FAIL_MSG("Not supported."); };
+ virtual void bitmap_add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) { ERR_FAIL_MSG("Not supported."); };
+ virtual void bitmap_add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) { ERR_FAIL_MSG("Not supported."); };
virtual float get_height(int p_size) const = 0;
virtual float get_ascent(int p_size) const = 0;
@@ -50,6 +57,18 @@ struct FontDataFallback {
virtual float get_underline_position(int p_size) const = 0;
virtual float get_underline_thickness(int p_size) const = 0;
+ virtual int get_spacing_space() const { return spacing_space; };
+ virtual void set_spacing_space(int p_value) {
+ spacing_space = p_value;
+ clear_cache();
+ };
+
+ virtual int get_spacing_glyph() const { return spacing_glyph; };
+ virtual void set_spacing_glyph(int p_value) {
+ spacing_glyph = p_value;
+ clear_cache();
+ };
+
virtual void set_antialiased(bool p_antialiased) = 0;
virtual bool get_antialiased() const = 0;
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index e60d269408..f46f96d30d 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -107,10 +107,12 @@ RID TextServerFallback::create_font_system(const String &p_name, int p_base_size
RID TextServerFallback::create_font_resource(const String &p_filename, int p_base_size) {
_THREAD_SAFE_METHOD_
FontDataFallback *fd = nullptr;
- if (p_filename.get_extension() == "ttf" || p_filename.get_extension() == "otf" || p_filename.get_extension() == "woff") {
- fd = memnew(DynamicFontDataFallback);
- } else if (p_filename.get_extension() == "fnt" || p_filename.get_extension() == "font") {
+ if (p_filename.get_extension() == "fnt" || p_filename.get_extension() == "font") {
fd = memnew(BitmapFontDataFallback);
+#ifdef MODULE_FREETYPE_ENABLED
+ } else if (p_filename.get_extension() == "ttf" || p_filename.get_extension() == "otf" || p_filename.get_extension() == "woff") {
+ fd = memnew(DynamicFontDataFallback);
+#endif
} else {
return RID();
}
@@ -127,10 +129,12 @@ RID TextServerFallback::create_font_resource(const String &p_filename, int p_bas
RID TextServerFallback::create_font_memory(const uint8_t *p_data, size_t p_size, const String &p_type, int p_base_size) {
_THREAD_SAFE_METHOD_
FontDataFallback *fd = nullptr;
- if (p_type == "ttf" || p_type == "otf" || p_type == "woff") {
- fd = memnew(DynamicFontDataFallback);
- } else if (p_type == "fnt" || p_type == "font") {
+ if (p_type == "fnt" || p_type == "font") {
fd = memnew(BitmapFontDataFallback);
+#ifdef MODULE_FREETYPE_ENABLED
+ } else if (p_type == "ttf" || p_type == "otf" || p_type == "woff") {
+ fd = memnew(DynamicFontDataFallback);
+#endif
} else {
return RID();
}
@@ -144,6 +148,39 @@ RID TextServerFallback::create_font_memory(const uint8_t *p_data, size_t p_size,
return font_owner.make_rid(fd);
}
+RID TextServerFallback::create_font_bitmap(float p_height, float p_ascent, int p_base_size) {
+ _THREAD_SAFE_METHOD_
+ FontDataFallback *fd = memnew(BitmapFontDataFallback);
+ Error err = fd->bitmap_new(p_height, p_ascent, p_base_size);
+ if (err != OK) {
+ memdelete(fd);
+ return RID();
+ }
+
+ return font_owner.make_rid(fd);
+}
+
+void TextServerFallback::font_bitmap_add_texture(RID p_font, const Ref<Texture> &p_texture) {
+ _THREAD_SAFE_METHOD_
+ FontDataFallback *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND(!fd);
+ fd->bitmap_add_texture(p_texture);
+}
+
+void TextServerFallback::font_bitmap_add_char(RID p_font, char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) {
+ _THREAD_SAFE_METHOD_
+ FontDataFallback *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND(!fd);
+ fd->bitmap_add_char(p_char, p_texture_idx, p_rect, p_align, p_advance);
+}
+
+void TextServerFallback::font_bitmap_add_kerning_pair(RID p_font, char32_t p_A, char32_t p_B, int p_kerning) {
+ _THREAD_SAFE_METHOD_
+ FontDataFallback *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND(!fd);
+ fd->bitmap_add_kerning_pair(p_A, p_B, p_kerning);
+}
+
float TextServerFallback::font_get_height(RID p_font, int p_size) const {
_THREAD_SAFE_METHOD_
const FontDataFallback *fd = font_owner.getornull(p_font);
@@ -179,6 +216,34 @@ float TextServerFallback::font_get_underline_thickness(RID p_font, int p_size) c
return fd->get_underline_thickness(p_size);
}
+int TextServerFallback::font_get_spacing_space(RID p_font) const {
+ _THREAD_SAFE_METHOD_
+ const FontDataFallback *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND_V(!fd, 0);
+ return fd->get_spacing_space();
+}
+
+void TextServerFallback::font_set_spacing_space(RID p_font, int p_value) {
+ _THREAD_SAFE_METHOD_
+ FontDataFallback *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND(!fd);
+ fd->set_spacing_space(p_value);
+}
+
+int TextServerFallback::font_get_spacing_glyph(RID p_font) const {
+ _THREAD_SAFE_METHOD_
+ const FontDataFallback *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND_V(!fd, 0);
+ return fd->get_spacing_glyph();
+}
+
+void TextServerFallback::font_set_spacing_glyph(RID p_font, int p_value) {
+ _THREAD_SAFE_METHOD_
+ FontDataFallback *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND(!fd);
+ fd->set_spacing_glyph(p_value);
+}
+
void TextServerFallback::font_set_antialiased(RID p_font, bool p_antialiased) {
_THREAD_SAFE_METHOD_
FontDataFallback *fd = font_owner.getornull(p_font);
@@ -1026,7 +1091,7 @@ bool TextServerFallback::shaped_text_update_breaks(RID p_shaped) {
}
if (sd->line_breaks_valid) {
- return true; // Noting to do.
+ return true; // Nothing to do.
}
int sd_size = sd->glyphs.size();
@@ -1184,6 +1249,11 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
sd->descent = MAX(sd->descent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5));
}
}
+ if (fd->get_spacing_space() && is_whitespace(sd->text[j])) {
+ gl.advance += fd->get_spacing_space();
+ } else {
+ gl.advance += fd->get_spacing_glyph();
+ }
sd->upos = MAX(sd->upos, fd->get_underline_position(gl.font_size));
sd->uthk = MAX(sd->uthk, fd->get_underline_thickness(gl.font_size));
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index d142b320e4..b10369d172 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -81,6 +81,11 @@ public:
virtual RID create_font_system(const String &p_name, int p_base_size = 16) override;
virtual RID create_font_resource(const String &p_filename, int p_base_size = 16) override;
virtual RID create_font_memory(const uint8_t *p_data, size_t p_size, const String &p_type, int p_base_size = 16) override;
+ virtual RID create_font_bitmap(float p_height, float p_ascent, int p_base_size = 16) override;
+
+ virtual void font_bitmap_add_texture(RID p_font, const Ref<Texture> &p_texture) override;
+ virtual void font_bitmap_add_char(RID p_font, char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) override;
+ virtual void font_bitmap_add_kerning_pair(RID p_font, char32_t p_A, char32_t p_B, int p_kerning) override;
virtual float font_get_height(RID p_font, int p_size) const override;
virtual float font_get_ascent(RID p_font, int p_size) const override;
@@ -89,6 +94,12 @@ public:
virtual float font_get_underline_position(RID p_font, int p_size) const override;
virtual float font_get_underline_thickness(RID p_font, int p_size) const override;
+ virtual int font_get_spacing_space(RID p_font) const override;
+ virtual void font_set_spacing_space(RID p_font, int p_value) override;
+
+ virtual int font_get_spacing_glyph(RID p_font) const override;
+ virtual void font_set_spacing_glyph(RID p_font, int p_value) override;
+
virtual void font_set_antialiased(RID p_font, bool p_antialiased) override;
virtual bool font_get_antialiased(RID p_font) const override;
diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp
index 2da9159228..ef53661557 100644
--- a/modules/tga/image_loader_tga.cpp
+++ b/modules/tga/image_loader_tga.cpp
@@ -56,6 +56,10 @@ Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t
compressed_pos += 1;
count = (c & 0x7f) + 1;
+ if (output_pos + count * p_pixel_size > output_pos) {
+ return ERR_PARSE_ERROR;
+ }
+
if (c & 0x80) {
for (size_t i = 0; i < p_pixel_size; i++) {
pixels_w[i] = p_compressed_buffer[compressed_pos];
@@ -79,7 +83,7 @@ Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t
return OK;
}
-Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome) {
+Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome, size_t p_output_size) {
#define TGA_PUT_PIXEL(r, g, b, a) \
int image_data_ofs = ((y * width) + x); \
image_data_w[image_data_ofs * 4 + 0] = r; \
@@ -130,6 +134,9 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
if (p_is_monochrome) {
while (y != y_end) {
while (x != x_end) {
+ if (i > p_output_size) {
+ return ERR_PARSE_ERROR;
+ }
uint8_t shade = p_buffer[i];
TGA_PUT_PIXEL(shade, shade, shade, 0xff)
@@ -143,6 +150,9 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
} else {
while (y != y_end) {
while (x != x_end) {
+ if (i > p_output_size) {
+ return ERR_PARSE_ERROR;
+ }
uint8_t index = p_buffer[i];
uint8_t r = 0x00;
uint8_t g = 0x00;
@@ -171,6 +181,10 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
} else if (p_header.pixel_depth == 24) {
while (y != y_end) {
while (x != x_end) {
+ if (i + 2 > p_output_size) {
+ return ERR_PARSE_ERROR;
+ }
+
uint8_t r = p_buffer[i + 2];
uint8_t g = p_buffer[i + 1];
uint8_t b = p_buffer[i + 0];
@@ -186,6 +200,10 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
} else if (p_header.pixel_depth == 32) {
while (y != y_end) {
while (x != x_end) {
+ if (i + 3 > p_output_size) {
+ return ERR_PARSE_ERROR;
+ }
+
uint8_t a = p_buffer[i + 3];
uint8_t r = p_buffer[i + 2];
uint8_t g = p_buffer[i + 1];
@@ -279,7 +297,7 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
const uint8_t *src_image_r = src_image.ptr();
const size_t pixel_size = tga_header.pixel_depth >> 3;
- const size_t buffer_size = (tga_header.image_width * tga_header.image_height) * pixel_size;
+ size_t buffer_size = (tga_header.image_width * tga_header.image_height) * pixel_size;
Vector<uint8_t> uncompressed_buffer;
uncompressed_buffer.resize(buffer_size);
@@ -297,11 +315,12 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
}
} else {
buffer = src_image_r;
+ buffer_size = src_image_len;
};
if (err == OK) {
const uint8_t *palette_r = palette.ptr();
- err = convert_to_image(p_image, buffer, tga_header, palette_r, is_monochrome);
+ err = convert_to_image(p_image, buffer, tga_header, palette_r, is_monochrome, buffer_size);
}
}
diff --git a/modules/tga/image_loader_tga.h b/modules/tga/image_loader_tga.h
index 249e33411e..cb2ce07edd 100644
--- a/modules/tga/image_loader_tga.h
+++ b/modules/tga/image_loader_tga.h
@@ -57,23 +57,23 @@ class ImageLoaderTGA : public ImageFormatLoader {
};
struct tga_header_s {
- uint8_t id_length;
- uint8_t color_map_type;
+ uint8_t id_length = 0;
+ uint8_t color_map_type = 0;
tga_type_e image_type;
- uint16_t first_color_entry;
- uint16_t color_map_length;
- uint8_t color_map_depth;
+ uint16_t first_color_entry = 0;
+ uint16_t color_map_length = 0;
+ uint8_t color_map_depth = 0;
- uint16_t x_origin;
- uint16_t y_origin;
- uint16_t image_width;
- uint16_t image_height;
- uint8_t pixel_depth;
- uint8_t image_descriptor;
+ uint16_t x_origin = 0;
+ uint16_t y_origin = 0;
+ uint16_t image_width = 0;
+ uint16_t image_height = 0;
+ uint8_t pixel_depth = 0;
+ uint8_t image_descriptor = 0;
};
static Error decode_tga_rle(const uint8_t *p_compressed_buffer, size_t p_pixel_size, uint8_t *p_uncompressed_buffer, size_t p_output_size);
- static Error convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome);
+ static Error convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome, size_t p_output_size);
public:
virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale);
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index 1026d58b85..c5f6dc0d99 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -554,7 +554,7 @@ void VideoStreamPlaybackTheora::play() {
}
playing = true;
- delay_compensation = ProjectSettings::get_singleton()->get("audio/video_delay_compensation_ms");
+ delay_compensation = ProjectSettings::get_singleton()->get("audio/video/video_delay_compensation_ms");
delay_compensation /= 1000.0;
};
@@ -645,30 +645,13 @@ void VideoStreamPlaybackTheora::_streaming_thread(void *ud) {
#endif
VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() {
- file = nullptr;
- theora_p = 0;
- vorbis_p = 0;
- videobuf_ready = 0;
- playing = false;
- frames_pending = 0;
- videobuf_time = 0;
- paused = false;
-
- buffering = false;
texture = Ref<ImageTexture>(memnew(ImageTexture));
- mix_callback = nullptr;
- mix_udata = nullptr;
- audio_track = 0;
- delay_compensation = 0;
- audio_frames_wrote = 0;
#ifdef THEORA_USE_THREAD_STREAMING
int rb_power = nearest_shift(RB_SIZE_KB * 1024);
ring_buffer.resize(rb_power);
read_buffer.resize(RB_SIZE_KB * 1024);
thread_sem = Semaphore::create();
- thread_exit = false;
- thread_eof = false;
#endif
};
@@ -694,7 +677,7 @@ void VideoStreamTheora::_bind_methods() {
////////////
-RES ResourceFormatLoaderTheora::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderTheora::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) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
if (r_error) {
diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h
index c315d682da..2685a8a013 100644
--- a/modules/theora/video_stream_theora.h
+++ b/modules/theora/video_stream_theora.h
@@ -36,6 +36,7 @@
#include "core/os/semaphore.h"
#include "core/os/thread.h"
#include "core/templates/ring_buffer.h"
+#include "core/templates/safe_refcount.h"
#include "scene/resources/video_stream.h"
#include "servers/audio_server.h"
@@ -52,12 +53,12 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
};
//Image frames[MAX_FRAMES];
- Image::Format format;
+ Image::Format format = Image::Format::FORMAT_L8;
Vector<uint8_t> frame_data;
- int frames_pending;
- FileAccess *file;
+ int frames_pending = 0;
+ FileAccess *file = nullptr;
String file_name;
- int audio_frames_wrote;
+ int audio_frames_wrote = 0;
Point2i size;
int buffer_data();
@@ -65,8 +66,8 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
void video_write();
float get_time() const;
- bool theora_eos;
- bool vorbis_eos;
+ bool theora_eos = false;
+ bool vorbis_eos = false;
ogg_sync_state oy;
ogg_page og;
@@ -74,33 +75,33 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
ogg_stream_state to;
th_info ti;
th_comment tc;
- th_dec_ctx *td;
+ th_dec_ctx *td = nullptr;
vorbis_info vi;
vorbis_dsp_state vd;
vorbis_block vb;
vorbis_comment vc;
th_pixel_fmt px_fmt;
- double videobuf_time;
- int pp_inc;
+ double videobuf_time = 0;
+ int pp_inc = 0;
- int theora_p;
- int vorbis_p;
- int pp_level_max;
- int pp_level;
- int videobuf_ready;
+ int theora_p = 0;
+ int vorbis_p = 0;
+ int pp_level_max = 0;
+ int pp_level = 0;
+ int videobuf_ready = 0;
- bool playing;
- bool buffering;
+ bool playing = false;
+ bool buffering = false;
- double last_update_time;
- double time;
- double delay_compensation;
+ double last_update_time = 0;
+ double time = 0;
+ double delay_compensation = 0;
Ref<ImageTexture> texture;
AudioMixCallback mix_callback;
- void *mix_udata;
- bool paused;
+ void *mix_udata = nullptr;
+ bool paused = false;
#ifdef THEORA_USE_THREAD_STREAMING
@@ -110,16 +111,16 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
RingBuffer<uint8_t> ring_buffer;
Vector<uint8_t> read_buffer;
- bool thread_eof;
+ bool thread_eof = false;
Semaphore *thread_sem;
Thread thread;
- volatile bool thread_exit;
+ SafeFlag thread_exit;
static void _streaming_thread(void *ud);
#endif
- int audio_track;
+ int audio_track = 0;
protected:
void clear();
@@ -185,7 +186,7 @@ public:
class ResourceFormatLoaderTheora : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/upnp/SCsub b/modules/upnp/SCsub
index bc0b215be3..b2fed0cb23 100644
--- a/modules/upnp/SCsub
+++ b/modules/upnp/SCsub
@@ -12,18 +12,19 @@ thirdparty_obj = []
if env["builtin_miniupnpc"]:
thirdparty_dir = "#thirdparty/miniupnpc/"
thirdparty_sources = [
+ "igd_desc_parse.c",
"miniupnpc.c",
- "upnpcommands.c",
+ "minixml.c",
+ "minisoap.c",
+ "minissdpc.c",
"miniwget.c",
+ "upnpcommands.c",
"upnpdev.c",
- "igd_desc_parse.c",
- "minissdpc.c",
- "minisoap.c",
- "minixml.c",
+ "upnpreplyparse.c",
"connecthostport.c",
- "receivedata.c",
"portlistingparse.c",
- "upnpreplyparse.c",
+ "receivedata.c",
+ "addr_is_reserved.c",
]
thirdparty_sources = [thirdparty_dir + "miniupnpc/" + file for file in thirdparty_sources]
diff --git a/modules/upnp/upnp.cpp b/modules/upnp/upnp.cpp
index 8c3be884bd..8e4e833d45 100644
--- a/modules/upnp/upnp.cpp
+++ b/modules/upnp/upnp.cpp
@@ -52,10 +52,12 @@ int UPNP::discover(int timeout, int ttl, const String &device_filter) {
int error = 0;
struct UPNPDev *devlist;
+ CharString cs = discover_multicast_if.utf8();
+ const char *m_if = cs.length() ? cs.get_data() : nullptr;
if (is_common_device(device_filter)) {
- devlist = upnpDiscover(timeout, discover_multicast_if.utf8().get_data(), nullptr, discover_local_port, discover_ipv6, ttl, &error);
+ devlist = upnpDiscover(timeout, m_if, nullptr, discover_local_port, discover_ipv6, ttl, &error);
} else {
- devlist = upnpDiscoverAll(timeout, discover_multicast_if.utf8().get_data(), nullptr, discover_local_port, discover_ipv6, ttl, &error);
+ devlist = upnpDiscoverAll(timeout, m_if, nullptr, discover_local_port, discover_ipv6, ttl, &error);
}
if (error != UPNPDISCOVER_SUCCESS) {
@@ -393,9 +395,6 @@ void UPNP::_bind_methods() {
}
UPNP::UPNP() {
- discover_multicast_if = "";
- discover_local_port = 0;
- discover_ipv6 = false;
}
UPNP::~UPNP() {
diff --git a/modules/upnp/upnp.h b/modules/upnp/upnp.h
index 9dfa907476..a0cca96bc8 100644
--- a/modules/upnp/upnp.h
+++ b/modules/upnp/upnp.h
@@ -41,9 +41,9 @@ class UPNP : public Reference {
GDCLASS(UPNP, Reference);
private:
- String discover_multicast_if;
- int discover_local_port;
- bool discover_ipv6;
+ String discover_multicast_if = "";
+ int discover_local_port = 0;
+ bool discover_ipv6 = false;
Vector<Ref<UPNPDevice>> devices;
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index fe92f59179..e91ae46a57 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -137,7 +137,6 @@ Ref<VisualScript> VisualScriptNode::get_visual_script() const {
}
VisualScriptNode::VisualScriptNode() {
- breakpoint = false;
}
////////////////
@@ -145,8 +144,6 @@ VisualScriptNode::VisualScriptNode() {
/////////////////////
VisualScriptNodeInstance::VisualScriptNodeInstance() {
- sequence_outputs = nullptr;
- input_ports = nullptr;
}
VisualScriptNodeInstance::~VisualScriptNodeInstance() {
@@ -1372,7 +1369,7 @@ void VisualScriptInstance::_dependency_step(VisualScriptNodeInstance *node, int
// Is a default value (unassigned input port).
input_args[i] = &default_values[index];
} else {
- // Rregular temporary in stack.
+ // Regular temporary in stack.
input_args[i] = &variant_stack[index];
}
}
@@ -1394,7 +1391,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p
ERR_FAIL_COND_V(!F, Variant());
Function *f = &F->get();
- // This call goes separate, so it can e yielded and suspended.
+ // This call goes separate, so it can be yielded and suspended.
Variant *variant_stack = (Variant *)p_stack;
bool *sequence_bits = (bool *)(variant_stack + f->max_stack);
const Variant **input_args = (const Variant **)(sequence_bits + f->node_count);
@@ -2623,14 +2620,8 @@ void VisualScriptLanguage::get_registered_node_names(List<String> *r_names) {
}
VisualScriptLanguage::VisualScriptLanguage() {
- notification = "_notification";
- _step = "_step";
- _subcall = "_subcall";
singleton = this;
- _debug_parse_err_node = -1;
- _debug_parse_err_file = "";
- _debug_call_stack_pos = 0;
int dmcs = GLOBAL_DEF("debug/settings/visual_script/max_call_stack", 1024);
ProjectSettings::get_singleton()->set_custom_property_info("debug/settings/visual_script/max_call_stack", PropertyInfo(Variant::INT, "debug/settings/visual_script/max_call_stack", PROPERTY_HINT_RANGE, "1024,4096,1,or_greater")); //minimum is 1024
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index bdb3c3a16b..72362e0ef4 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -49,7 +49,7 @@ class VisualScriptNode : public Resource {
Ref<VisualScript> script_used;
Array default_input_values;
- bool breakpoint;
+ bool breakpoint = false;
void _set_default_input_values(Array p_values);
Array _get_default_input_values() const;
@@ -90,13 +90,9 @@ public:
virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance) = 0;
struct TypeGuess {
- Variant::Type type;
+ Variant::Type type = Variant::NIL;
StringName gdclass;
Ref<Script> script;
-
- TypeGuess() {
- type = Variant::NIL;
- }
};
virtual TypeGuess guess_output_type(TypeGuess *p_inputs, int p_output) const;
@@ -114,19 +110,19 @@ class VisualScriptNodeInstance {
INPUT_DEFAULT_VALUE_BIT = INPUT_SHIFT, // from unassigned input port, using default value (edited by user)
};
- int id;
- int sequence_index;
- VisualScriptNodeInstance **sequence_outputs;
- int sequence_output_count;
+ int id = 0;
+ int sequence_index = 0;
+ VisualScriptNodeInstance **sequence_outputs = nullptr;
+ int sequence_output_count = 0;
Vector<VisualScriptNodeInstance *> dependencies;
- int *input_ports;
- int input_port_count;
- int *output_ports;
- int output_port_count;
- int working_mem_idx;
- int pass_idx;
+ int *input_ports = nullptr;
+ int input_port_count = 0;
+ int *output_ports = nullptr;
+ int output_port_count = 0;
+ int working_mem_idx = 0;
+ int pass_idx = 0;
- VisualScriptNode *base;
+ VisualScriptNode *base = nullptr;
public:
enum StartMode {
@@ -178,7 +174,7 @@ public:
uint64_t from_output : 16;
uint64_t to_node : 24;
};
- uint64_t id;
+ uint64_t id = 0;
};
bool operator<(const SequenceConnection &p_connection) const {
@@ -194,7 +190,7 @@ public:
uint64_t to_node : 24;
uint64_t to_port : 8;
};
- uint64_t id;
+ uint64_t id = 0;
};
bool operator<(const DataConnection &p_connection) const {
@@ -208,7 +204,7 @@ private:
StringName base_type;
struct Argument {
String name;
- Variant::Type type;
+ Variant::Type type = Variant::Type::NIL;
};
struct NodeData {
@@ -231,7 +227,7 @@ private:
struct Variable {
PropertyInfo info;
Variant default_value;
- bool _export;
+ bool _export = false;
// Add getter & setter options here.
};
@@ -388,26 +384,27 @@ public:
};
class VisualScriptInstance : public ScriptInstance {
- Object *owner;
+ Object *owner = nullptr;
Ref<VisualScript> script;
Map<StringName, Variant> variables; // Using variable path, not script.
Map<int, VisualScriptNodeInstance *> instances;
struct Function {
- int node;
- int max_stack;
- int trash_pos;
- int flow_stack_size;
- int pass_stack_size;
- int node_count;
- int argument_count;
+ int node = 0;
+ int max_stack = 0;
+ int trash_pos = 0;
+ int flow_stack_size = 0;
+ int pass_stack_size = 0;
+ int node_count = 0;
+ int argument_count = 0;
};
Map<StringName, Function> functions;
Vector<Variant> default_values;
- int max_input_args, max_output_args;
+ int max_input_args = 0;
+ int max_output_args = 0;
StringName source;
@@ -479,14 +476,14 @@ class VisualScriptFunctionState : public Reference {
ObjectID instance_id;
ObjectID script_id;
- VisualScriptInstance *instance;
+ VisualScriptInstance *instance = nullptr;
StringName function;
Vector<uint8_t> stack;
- int working_mem_index;
- int variant_stack_size;
- VisualScriptNodeInstance *node;
- int flow_stack_pos;
- int pass;
+ int working_mem_index = 0;
+ int variant_stack_size = 0;
+ VisualScriptNodeInstance *node = nullptr;
+ int flow_stack_pos = 0;
+ int pass = 0;
Variant _signal_callback(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
@@ -507,25 +504,25 @@ class VisualScriptLanguage : public ScriptLanguage {
Map<String, VisualScriptNodeRegisterFunc> register_funcs;
struct CallLevel {
- Variant *stack;
- Variant **work_mem;
- const StringName *function;
- VisualScriptInstance *instance;
- int *current_id;
+ Variant *stack = nullptr;
+ Variant **work_mem = nullptr;
+ const StringName *function = nullptr;
+ VisualScriptInstance *instance = nullptr;
+ int *current_id = nullptr;
};
- int _debug_parse_err_node;
- String _debug_parse_err_file;
+ int _debug_parse_err_node = -1;
+ String _debug_parse_err_file = "";
String _debug_error;
- int _debug_call_stack_pos;
+ int _debug_call_stack_pos = 0;
int _debug_max_call_stack;
CallLevel *_call_stack;
public:
- StringName notification;
+ StringName notification = "_notification";
StringName _get_output_port_unsequenced;
- StringName _step;
- StringName _subcall;
+ StringName _step = "_step";
+ StringName _subcall = "_subcall";
static VisualScriptLanguage *singleton;
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index b96311ba6c..7ca14fbca8 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -647,7 +647,7 @@ String VisualScriptBuiltinFunc::get_caption() const {
void VisualScriptBuiltinFunc::set_func(BuiltinFunc p_which) {
ERR_FAIL_INDEX(p_which, FUNC_MAX);
func = p_which;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 78e4a7f113..d520837d43 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -61,7 +61,7 @@ protected:
}
void _sig_changed() {
- _change_notify();
+ notify_property_list_changed();
emit_signal("changed");
}
@@ -172,7 +172,7 @@ protected:
public:
void edit(const StringName &p_sig) {
sig = p_sig;
- _change_notify();
+ notify_property_list_changed();
}
VisualScriptEditorSignalEdit() { undo_redo = nullptr; }
@@ -195,11 +195,10 @@ protected:
}
void _var_changed() {
- _change_notify();
+ notify_property_list_changed();
emit_signal("changed");
}
void _var_value_changed() {
- _change_notify("value"); // So the whole tree is not redrawn, makes editing smoother in general.
emit_signal("changed");
}
@@ -331,7 +330,7 @@ protected:
public:
void edit(const StringName &p_var) {
var = p_var;
- _change_notify();
+ notify_property_list_changed();
}
VisualScriptEditorVariableEdit() { undo_redo = nullptr; }
@@ -1838,7 +1837,7 @@ void VisualScriptEditor::_input(const Ref<InputEvent> &p_event) {
void VisualScriptEditor::_graph_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> key = p_event;
- if (key.is_valid() && key->is_pressed() && key->get_button_mask() == BUTTON_RIGHT) {
+ if (key.is_valid() && key->is_pressed() && key->get_button_mask() == MOUSE_BUTTON_RIGHT) {
saved_position = graph->get_local_mouse_position();
Point2 gpos = Input::get_singleton()->get_mouse_position();
@@ -3689,16 +3688,23 @@ void VisualScriptEditor::_comment_node_resized(const Vector2 &p_new_size, int p_
return;
}
+ Vector2 new_size = p_new_size;
+ if (graph->is_using_snap()) {
+ Vector2 snap = Vector2(graph->get_snap(), graph->get_snap());
+ Vector2 min_size = (gn->get_minimum_size() + (snap * 0.5)).snapped(snap);
+ new_size = new_size.snapped(snap).max(min_size);
+ }
+
updating_graph = true;
graph->set_block_minimum_size_adjust(true); //faster resize
undo_redo->create_action(TTR("Resize Comment"), UndoRedo::MERGE_ENDS);
- undo_redo->add_do_method(vsc.ptr(), "set_size", p_new_size / EDSCALE);
+ undo_redo->add_do_method(vsc.ptr(), "set_size", new_size / EDSCALE);
undo_redo->add_undo_method(vsc.ptr(), "set_size", vsc->get_size());
undo_redo->commit_action();
- gn->set_custom_minimum_size(p_new_size);
+ gn->set_custom_minimum_size(new_size);
gn->set_size(Size2(1, 1));
graph->set_block_minimum_size_adjust(false);
updating_graph = false;
@@ -3952,7 +3958,7 @@ void VisualScriptEditor::_menu_option(int p_what) {
if (start_node == -1) {
// If we still don't have a start node then,
// run through the nodes and select the first tree node,
- // ie node without any input sequence but output sequence.
+ // i.e. node without any input sequence but output sequence.
for (Set<int>::Element *E = nodes_from.front(); E; E = E->next()) {
if (!nodes_to.has(E->get())) {
start_node = E->get();
@@ -4268,13 +4274,13 @@ VisualScriptEditor::VisualScriptEditor() {
edit_menu->set_shortcut_context(this);
edit_menu->set_text(TTR("Edit"));
edit_menu->set_switch_on_hover(true);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/delete_selected"), EDIT_DELETE_NODES);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_graph_delete"), EDIT_DELETE_NODES);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/toggle_breakpoint"), EDIT_TOGGLE_BREAKPOINT);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/find_node_type"), EDIT_FIND_NODE_TYPE);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/copy_nodes"), EDIT_COPY_NODES);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/cut_nodes"), EDIT_CUT_NODES);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/paste_nodes"), EDIT_PASTE_NODES);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_copy"), EDIT_COPY_NODES);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_cut"), EDIT_CUT_NODES);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_paste"), EDIT_PASTE_NODES);
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/create_function"), EDIT_CREATE_FUNCTION);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/refresh_nodes"), REFRESH_GRAPH);
@@ -4514,12 +4520,8 @@ void VisualScriptEditor::free_clipboard() {
static void register_editor_callback() {
ScriptEditor::register_create_script_editor_function(create_editor);
- ED_SHORTCUT("visual_script_editor/delete_selected", TTR("Delete Selected"), KEY_DELETE);
ED_SHORTCUT("visual_script_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9);
ED_SHORTCUT("visual_script_editor/find_node_type", TTR("Find Node Type"), KEY_MASK_CMD + KEY_F);
- ED_SHORTCUT("visual_script_editor/copy_nodes", TTR("Copy Nodes"), KEY_MASK_CMD + KEY_C);
- ED_SHORTCUT("visual_script_editor/cut_nodes", TTR("Cut Nodes"), KEY_MASK_CMD + KEY_X);
- ED_SHORTCUT("visual_script_editor/paste_nodes", TTR("Paste Nodes"), KEY_MASK_CMD + KEY_V);
ED_SHORTCUT("visual_script_editor/create_function", TTR("Make Function"), KEY_MASK_CMD + KEY_G);
ED_SHORTCUT("visual_script_editor/refresh_nodes", TTR("Refresh Graph"), KEY_MASK_CMD + KEY_R);
ED_SHORTCUT("visual_script_editor/edit_member", TTR("Edit Member"), KEY_MASK_CMD + KEY_E);
diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp
index 9596fda95c..cb4230bea9 100644
--- a/modules/visual_script/visual_script_expression.cpp
+++ b/modules/visual_script/visual_script_expression.cpp
@@ -63,7 +63,7 @@ bool VisualScriptExpression::_set(const StringName &p_name, const Variant &p_val
}
expression_dirty = true;
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
return true;
}
@@ -1054,7 +1054,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() {
}
}
- /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */
+ /* Reduce the set of expressions and place them in an operator tree, respecting precedence */
while (expression.size() > 1) {
int next_op = -1;
@@ -1506,13 +1506,20 @@ VisualScriptNodeInstance *VisualScriptExpression::instance(VisualScriptInstance
return instance;
}
+void VisualScriptExpression::reset_state() {
+ if (nodes) {
+ memdelete(nodes);
+ nodes = nullptr;
+ root = nullptr;
+ }
+
+ error_str = String();
+ error_set = false;
+ str_ofs = 0;
+ inputs.clear();
+}
+
VisualScriptExpression::VisualScriptExpression() {
- output_type = Variant::NIL;
- expression_dirty = true;
- error_set = true;
- root = nullptr;
- nodes = nullptr;
- sequenced = false;
}
VisualScriptExpression::~VisualScriptExpression() {
diff --git a/modules/visual_script/visual_script_expression.h b/modules/visual_script/visual_script_expression.h
index 7fe665769d..c35075ea53 100644
--- a/modules/visual_script/visual_script_expression.h
+++ b/modules/visual_script/visual_script_expression.h
@@ -39,20 +39,18 @@ class VisualScriptExpression : public VisualScriptNode {
friend class VisualScriptNodeInstanceExpression;
struct Input {
- Variant::Type type;
+ Variant::Type type = Variant::NIL;
String name;
-
- Input() { type = Variant::NIL; }
};
Vector<Input> inputs;
- Variant::Type output_type;
+ Variant::Type output_type = Variant::NIL;
String expression;
- bool sequenced;
- int str_ofs;
- bool expression_dirty;
+ bool sequenced = false;
+ int str_ofs = 0;
+ bool expression_dirty = true;
bool _compile_expression();
@@ -114,7 +112,7 @@ class VisualScriptExpression : public VisualScriptNode {
Error _get_token(Token &r_token);
String error_str;
- bool error_set;
+ bool error_set = true;
struct ENode {
enum Type {
@@ -131,11 +129,10 @@ class VisualScriptExpression : public VisualScriptNode {
TYPE_CALL
};
- ENode *next;
+ ENode *next = nullptr;
- Type type;
+ Type type = Type::TYPE_SELF;
- ENode() { next = nullptr; }
virtual ~ENode() {
if (next) {
memdelete(next);
@@ -144,17 +141,17 @@ class VisualScriptExpression : public VisualScriptNode {
};
struct Expression {
- bool is_op;
+ bool is_op = false;
union {
Variant::Operator op;
- ENode *node;
+ ENode *node = nullptr;
};
};
ENode *_parse_expression();
struct InputNode : public ENode {
- int index;
+ int index = 0;
InputNode() {
type = TYPE_INPUT;
}
@@ -168,9 +165,9 @@ class VisualScriptExpression : public VisualScriptNode {
};
struct OperatorNode : public ENode {
- Variant::Operator op;
+ Variant::Operator op = Variant::Operator::OP_ADD;
- ENode *nodes[2];
+ ENode *nodes[2] = { nullptr, nullptr };
OperatorNode() {
type = TYPE_OPERATOR;
@@ -184,8 +181,8 @@ class VisualScriptExpression : public VisualScriptNode {
};
struct IndexNode : public ENode {
- ENode *base;
- ENode *index;
+ ENode *base = nullptr;
+ ENode *index = nullptr;
IndexNode() {
type = TYPE_INDEX;
@@ -193,7 +190,7 @@ class VisualScriptExpression : public VisualScriptNode {
};
struct NamedIndexNode : public ENode {
- ENode *base;
+ ENode *base = nullptr;
StringName name;
NamedIndexNode() {
@@ -202,7 +199,7 @@ class VisualScriptExpression : public VisualScriptNode {
};
struct ConstructorNode : public ENode {
- Variant::Type data_type;
+ Variant::Type data_type = Variant::Type::NIL;
Vector<ENode *> arguments;
ConstructorNode() {
@@ -211,7 +208,7 @@ class VisualScriptExpression : public VisualScriptNode {
};
struct CallNode : public ENode {
- ENode *base;
+ ENode *base = nullptr;
StringName method;
Vector<ENode *> arguments;
@@ -235,7 +232,7 @@ class VisualScriptExpression : public VisualScriptNode {
};
struct BuiltinFuncNode : public ENode {
- VisualScriptBuiltinFunc::BuiltinFunc func;
+ VisualScriptBuiltinFunc::BuiltinFunc func = VisualScriptBuiltinFunc::BuiltinFunc::BYTES_TO_VAR;
Vector<ENode *> arguments;
BuiltinFuncNode() {
type = TYPE_BUILTIN_FUNC;
@@ -250,8 +247,8 @@ class VisualScriptExpression : public VisualScriptNode {
return node;
}
- ENode *root;
- ENode *nodes;
+ ENode *root = nullptr;
+ ENode *nodes = nullptr;
protected:
bool _set(const StringName &p_name, const Variant &p_value);
@@ -259,6 +256,8 @@ protected:
void _get_property_list(List<PropertyInfo> *p_list) const;
public:
+ virtual void reset_state() override;
+
virtual int get_output_sequence_port_count() const override;
virtual bool has_input_sequence_port() const override;
diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp
index 0049e254c4..e977f9c96b 100644
--- a/modules/visual_script/visual_script_flow_control.cpp
+++ b/modules/visual_script/visual_script_flow_control.cpp
@@ -628,7 +628,7 @@ VisualScriptNodeInstance *VisualScriptSwitch::instance(VisualScriptInstance *p_i
bool VisualScriptSwitch::_set(const StringName &p_name, const Variant &p_value) {
if (String(p_name) == "case_count") {
case_values.resize(p_value);
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
return true;
}
@@ -638,7 +638,7 @@ bool VisualScriptSwitch::_set(const StringName &p_name, const Variant &p_value)
ERR_FAIL_INDEX_V(idx, case_values.size(), false);
case_values.write[idx].type = Variant::Type(int(p_value));
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
return true;
@@ -677,6 +677,10 @@ void VisualScriptSwitch::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
+void VisualScriptSwitch::reset_state() {
+ case_values.clear();
+}
+
void VisualScriptSwitch::_bind_methods() {
}
@@ -733,7 +737,7 @@ void VisualScriptTypeCast::set_base_type(const StringName &p_type) {
}
base_type = p_type;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -747,7 +751,7 @@ void VisualScriptTypeCast::set_base_script(const String &p_path) {
}
script = p_path;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -796,7 +800,7 @@ public:
}
if (!ResourceCache::has(script)) {
- //if the script is not in use by anyone, we can safely assume whathever we got is not casting to it.
+ //if the script is not in use by anyone, we can safely assume whatever we got is not casting to it.
return 1;
}
Ref<Script> cast_script = Ref<Resource>(ResourceCache::get(script));
diff --git a/modules/visual_script/visual_script_flow_control.h b/modules/visual_script/visual_script_flow_control.h
index 46a72bb92d..d9c4dedafd 100644
--- a/modules/visual_script/visual_script_flow_control.h
+++ b/modules/visual_script/visual_script_flow_control.h
@@ -202,6 +202,8 @@ protected:
static void _bind_methods();
public:
+ virtual void reset_state() override;
+
virtual int get_output_sequence_port_count() const override;
virtual bool has_input_sequence_port() const override;
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index d016b938de..9310b86627 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -281,7 +281,7 @@ void VisualScriptFunctionCall::set_basic_type(Variant::Type p_type) {
}
basic_type = p_type;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -295,7 +295,7 @@ void VisualScriptFunctionCall::set_base_type(const StringName &p_type) {
}
base_type = p_type;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -309,7 +309,7 @@ void VisualScriptFunctionCall::set_base_script(const String &p_path) {
}
base_script = p_path;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -328,7 +328,7 @@ void VisualScriptFunctionCall::set_singleton(const StringName &p_type) {
base_type = obj->get_class();
}
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -425,7 +425,7 @@ void VisualScriptFunctionCall::set_function(const StringName &p_type) {
_update_method_cache();
}
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -439,7 +439,7 @@ void VisualScriptFunctionCall::set_base_path(const NodePath &p_type) {
}
base_path = p_type;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -453,7 +453,7 @@ void VisualScriptFunctionCall::set_call_mode(CallMode p_mode) {
}
call_mode = p_mode;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -476,7 +476,7 @@ void VisualScriptFunctionCall::set_rpc_call_mode(VisualScriptFunctionCall::RPCCa
}
rpc_call_mode = p_mode;
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
}
VisualScriptFunctionCall::RPCCallMode VisualScriptFunctionCall::get_rpc_call_mode() const {
@@ -547,7 +547,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const
} else {
Node *bnode = _get_base_node();
if (bnode) {
- property.hint_string = bnode->get_path(); //convert to loong string
+ property.hint_string = bnode->get_path(); //convert to long string
}
}
}
@@ -1067,7 +1067,7 @@ void VisualScriptPropertySet::set_basic_type(Variant::Type p_type) {
}
basic_type = p_type;
- _change_notify();
+ notify_property_list_changed();
_update_base_type();
ports_changed_notify();
}
@@ -1082,7 +1082,7 @@ void VisualScriptPropertySet::set_base_type(const StringName &p_type) {
}
base_type = p_type;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1096,7 +1096,7 @@ void VisualScriptPropertySet::set_base_script(const String &p_path) {
}
base_script = p_path;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1191,7 +1191,7 @@ void VisualScriptPropertySet::set_property(const StringName &p_type) {
property = p_type;
index = StringName();
_update_cache();
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1206,7 +1206,7 @@ void VisualScriptPropertySet::set_base_path(const NodePath &p_type) {
base_path = p_type;
_update_base_type();
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1221,7 +1221,7 @@ void VisualScriptPropertySet::set_call_mode(CallMode p_mode) {
call_mode = p_mode;
_update_base_type();
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1243,7 +1243,7 @@ void VisualScriptPropertySet::set_index(const StringName &p_type) {
}
index = p_type;
_update_cache();
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1259,7 +1259,7 @@ void VisualScriptPropertySet::set_assign_op(AssignOp p_op) {
assign_op = p_op;
_update_cache();
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1292,7 +1292,7 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const {
} else {
Node *bnode = _get_base_node();
if (bnode) {
- property.hint_string = bnode->get_path(); //convert to loong string
+ property.hint_string = bnode->get_path(); //convert to long string
}
}
}
@@ -1760,7 +1760,7 @@ void VisualScriptPropertyGet::set_base_type(const StringName &p_type) {
}
base_type = p_type;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1774,7 +1774,7 @@ void VisualScriptPropertyGet::set_base_script(const String &p_path) {
}
base_script = p_path;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1871,7 +1871,7 @@ void VisualScriptPropertyGet::set_property(const StringName &p_type) {
property = p_type;
_update_cache();
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1885,7 +1885,7 @@ void VisualScriptPropertyGet::set_base_path(const NodePath &p_type) {
}
base_path = p_type;
- _change_notify();
+ notify_property_list_changed();
_update_base_type();
ports_changed_notify();
}
@@ -1900,7 +1900,7 @@ void VisualScriptPropertyGet::set_call_mode(CallMode p_mode) {
}
call_mode = p_mode;
- _change_notify();
+ notify_property_list_changed();
_update_base_type();
ports_changed_notify();
}
@@ -1915,7 +1915,7 @@ void VisualScriptPropertyGet::set_basic_type(Variant::Type p_type) {
}
basic_type = p_type;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1937,7 +1937,7 @@ void VisualScriptPropertyGet::set_index(const StringName &p_type) {
}
index = p_type;
_update_cache();
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1970,7 +1970,7 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const {
} else {
Node *bnode = _get_base_node();
if (bnode) {
- property.hint_string = bnode->get_path(); //convert to loong string
+ property.hint_string = bnode->get_path(); //convert to long string
}
}
}
@@ -2261,7 +2261,7 @@ void VisualScriptEmitSignal::set_signal(const StringName &p_type) {
name = p_type;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index ae2b548f21..fed6637acb 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -57,7 +57,7 @@ bool VisualScriptFunction::_set(const StringName &p_name, const Variant &p_value
arguments.write[i].type = Variant::NIL;
}
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
return true;
}
if (String(p_name).begins_with("argument_")) {
@@ -303,6 +303,14 @@ VisualScriptNodeInstance *VisualScriptFunction::instance(VisualScriptInstance *p
return instance;
}
+void VisualScriptFunction::reset_state() {
+ arguments.clear();
+ stack_size = 256;
+ stack_less = false;
+ sequenced = true;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
+}
+
VisualScriptFunction::VisualScriptFunction() {
stack_size = 256;
stack_less = false;
@@ -312,7 +320,7 @@ VisualScriptFunction::VisualScriptFunction() {
void VisualScriptFunction::set_stack_less(bool p_enable) {
stack_less = p_enable;
- _change_notify();
+ notify_property_list_changed();
}
bool VisualScriptFunction::is_stack_less() const {
@@ -421,7 +429,7 @@ bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) {
inputports.write[i].type = Variant::NIL;
}
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
return true;
}
if (String(p_name).begins_with("input_") && is_input_port_editable()) {
@@ -457,7 +465,7 @@ bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) {
outputports.write[i].type = Variant::NIL;
}
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
return true;
}
if (String(p_name).begins_with("output_") && is_output_port_editable()) {
@@ -578,7 +586,7 @@ void VisualScriptLists::add_input_data_port(Variant::Type p_type, const String &
}
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
}
void VisualScriptLists::set_input_data_port_type(int p_idx, Variant::Type p_type) {
@@ -590,7 +598,7 @@ void VisualScriptLists::set_input_data_port_type(int p_idx, Variant::Type p_type
inputports.write[p_idx].type = p_type;
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
}
void VisualScriptLists::set_input_data_port_name(int p_idx, const String &p_name) {
@@ -602,7 +610,7 @@ void VisualScriptLists::set_input_data_port_name(int p_idx, const String &p_name
inputports.write[p_idx].name = p_name;
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
}
void VisualScriptLists::remove_input_data_port(int p_argidx) {
@@ -615,7 +623,7 @@ void VisualScriptLists::remove_input_data_port(int p_argidx) {
inputports.remove(p_argidx);
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
}
// output data port interaction
@@ -634,7 +642,7 @@ void VisualScriptLists::add_output_data_port(Variant::Type p_type, const String
}
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
}
void VisualScriptLists::set_output_data_port_type(int p_idx, Variant::Type p_type) {
@@ -646,7 +654,7 @@ void VisualScriptLists::set_output_data_port_type(int p_idx, Variant::Type p_typ
outputports.write[p_idx].type = p_type;
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
}
void VisualScriptLists::set_output_data_port_name(int p_idx, const String &p_name) {
@@ -658,7 +666,7 @@ void VisualScriptLists::set_output_data_port_name(int p_idx, const String &p_nam
outputports.write[p_idx].name = p_name;
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
}
void VisualScriptLists::remove_output_data_port(int p_argidx) {
@@ -671,7 +679,7 @@ void VisualScriptLists::remove_output_data_port(int p_argidx) {
outputports.remove(p_argidx);
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
}
// sequences
@@ -687,6 +695,13 @@ bool VisualScriptLists::is_sequenced() const {
return sequenced;
}
+void VisualScriptLists::reset_state() {
+ inputports.clear();
+ outputports.clear();
+ sequenced = false;
+ flags = 0;
+}
+
VisualScriptLists::VisualScriptLists() {
// initialize
sequenced = false;
@@ -1433,7 +1448,7 @@ void VisualScriptConstant::set_constant_type(Variant::Type p_type) {
Callable::CallError ce;
Variant::construct(type, value, nullptr, 0, ce);
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
}
Variant::Type VisualScriptConstant::get_constant_type() const {
@@ -1764,7 +1779,7 @@ String VisualScriptGlobalConstant::get_caption() const {
void VisualScriptGlobalConstant::set_global_constant(int p_which) {
index = p_which;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1850,7 +1865,7 @@ String VisualScriptClassConstant::get_caption() const {
void VisualScriptClassConstant::set_class_constant(const StringName &p_which) {
name = p_which;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1876,7 +1891,7 @@ void VisualScriptClassConstant::set_base_type(const StringName &p_which) {
} else {
name = "";
}
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -1983,7 +1998,7 @@ String VisualScriptBasicTypeConstant::get_text() const {
void VisualScriptBasicTypeConstant::set_basic_type_constant(const StringName &p_which) {
name = p_which;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -2010,7 +2025,7 @@ void VisualScriptBasicTypeConstant::set_basic_type(Variant::Type p_which) {
} else {
name = "";
}
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -2140,7 +2155,7 @@ String VisualScriptMathConstant::get_caption() const {
void VisualScriptMathConstant::set_math_constant(MathConstant p_which) {
constant = p_which;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -2233,7 +2248,7 @@ String VisualScriptEngineSingleton::get_caption() const {
void VisualScriptEngineSingleton::set_singleton(const String &p_string) {
singleton = p_string;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -2342,7 +2357,7 @@ String VisualScriptSceneNode::get_caption() const {
void VisualScriptSceneNode::set_node_path(const NodePath &p_path) {
path = p_path;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -2620,7 +2635,7 @@ String VisualScriptResourcePath::get_caption() const {
void VisualScriptResourcePath::set_resource_path(const String &p_path) {
path = p_path;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -3748,7 +3763,7 @@ void VisualScriptDeconstruct::set_deconstruct_type(Variant::Type p_type) {
type = p_type;
_update_elements();
ports_changed_notify();
- _change_notify(); //to make input appear/disappear
+ notify_property_list_changed(); //to make input appear/disappear
}
Variant::Type VisualScriptDeconstruct::get_deconstruct_type() const {
diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h
index ae5e04d096..7392443e4e 100644
--- a/modules/visual_script/visual_script_nodes.h
+++ b/modules/visual_script/visual_script_nodes.h
@@ -99,6 +99,8 @@ public:
virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance) override;
+ virtual void reset_state() override;
+
VisualScriptFunction();
};
@@ -134,6 +136,8 @@ protected:
static void _bind_methods();
public:
+ virtual void reset_state() override;
+
virtual bool is_output_port_editable() const;
virtual bool is_output_port_name_editable() const;
virtual bool is_output_port_type_editable() const;
diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp
index 6c9af4e600..52fe659983 100644
--- a/modules/visual_script/visual_script_yield_nodes.cpp
+++ b/modules/visual_script/visual_script_yield_nodes.cpp
@@ -152,7 +152,7 @@ void VisualScriptYield::set_yield_mode(YieldMode p_mode) {
}
yield_mode = p_mode;
ports_changed_notify();
- _change_notify();
+ notify_property_list_changed();
}
VisualScriptYield::YieldMode VisualScriptYield::get_yield_mode() {
@@ -359,7 +359,7 @@ void VisualScriptYieldSignal::set_base_type(const StringName &p_type) {
base_type = p_type;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -374,7 +374,7 @@ void VisualScriptYieldSignal::set_signal(const StringName &p_type) {
signal = p_type;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -389,7 +389,7 @@ void VisualScriptYieldSignal::set_base_path(const NodePath &p_type) {
base_path = p_type;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -404,7 +404,7 @@ void VisualScriptYieldSignal::set_call_mode(CallMode p_mode) {
call_mode = p_mode;
- _change_notify();
+ notify_property_list_changed();
ports_changed_notify();
}
@@ -425,7 +425,7 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const {
} else {
Node *bnode = _get_base_node();
if (bnode) {
- property.hint_string = bnode->get_path(); //convert to loong string
+ property.hint_string = bnode->get_path(); //convert to long string
}
}
}
diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp
index 5d8245c64c..101001cba0 100644
--- a/modules/webm/video_stream_webm.cpp
+++ b/modules/webm/video_stream_webm.cpp
@@ -156,7 +156,7 @@ void VideoStreamPlaybackWebm::stop() {
void VideoStreamPlaybackWebm::play() {
stop();
- delay_compensation = ProjectSettings::get_singleton()->get("audio/video_delay_compensation_ms");
+ delay_compensation = ProjectSettings::get_singleton()->get("audio/video/video_delay_compensation_ms");
delay_compensation /= 1000.0;
playing = true;
@@ -429,7 +429,7 @@ void VideoStreamWebm::set_audio_track(int p_track) {
////////////
-RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderWebm::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) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
if (r_error) {
diff --git a/modules/webm/video_stream_webm.h b/modules/webm/video_stream_webm.h
index cb3cf58850..60e02ab38b 100644
--- a/modules/webm/video_stream_webm.h
+++ b/modules/webm/video_stream_webm.h
@@ -126,7 +126,7 @@ public:
class ResourceFormatLoaderWebm : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/webrtc/webrtc_data_channel_js.cpp b/modules/webrtc/webrtc_data_channel_js.cpp
index 9f2b084cb1..dfbec80c86 100644
--- a/modules/webrtc/webrtc_data_channel_js.cpp
+++ b/modules/webrtc/webrtc_data_channel_js.cpp
@@ -182,16 +182,9 @@ bool WebRTCDataChannelJS::is_negotiated() const {
}
WebRTCDataChannelJS::WebRTCDataChannelJS() {
- queue_count = 0;
- _was_string = false;
- _write_mode = WRITE_MODE_BINARY;
- _js_id = 0;
}
WebRTCDataChannelJS::WebRTCDataChannelJS(int js_id) {
- queue_count = 0;
- _was_string = false;
- _write_mode = WRITE_MODE_BINARY;
_js_id = js_id;
godot_js_rtc_datachannel_connect(js_id, this, &_on_open, &_on_message, &_on_error, &_on_close);
diff --git a/modules/webrtc/webrtc_data_channel_js.h b/modules/webrtc/webrtc_data_channel_js.h
index 8c56b62303..db58ebccff 100644
--- a/modules/webrtc/webrtc_data_channel_js.h
+++ b/modules/webrtc/webrtc_data_channel_js.h
@@ -42,16 +42,16 @@ private:
String _label;
String _protocol;
- bool _was_string;
- WriteMode _write_mode;
+ bool _was_string = false;
+ WriteMode _write_mode = WRITE_MODE_BINARY;
enum {
PACKET_BUFFER_SIZE = 65536 - 5 // 4 bytes for the size, 1 for for type
};
- int _js_id;
+ int _js_id = 0;
RingBuffer<uint8_t> in_buffer;
- int queue_count;
+ int queue_count = 0;
uint8_t packet_buffer[PACKET_BUFFER_SIZE];
static void _on_open(void *p_obj);
diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp
index aec01a1eea..25b6d6ef0e 100644
--- a/modules/websocket/emws_client.cpp
+++ b/modules/websocket/emws_client.cpp
@@ -140,11 +140,7 @@ Error EMWSClient::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffe
}
EMWSClient::EMWSClient() {
- _in_buf_size = DEF_BUF_SHIFT;
- _in_pkt_size = DEF_PKT_SHIFT;
- _is_connecting = false;
_peer = Ref<EMWSPeer>(memnew(EMWSPeer));
- _js_id = 0;
}
EMWSClient::~EMWSClient() {
diff --git a/modules/websocket/emws_client.h b/modules/websocket/emws_client.h
index fdf7a231d2..2ab7dc83d0 100644
--- a/modules/websocket/emws_client.h
+++ b/modules/websocket/emws_client.h
@@ -41,10 +41,10 @@ class EMWSClient : public WebSocketClient {
GDCIIMPL(EMWSClient, WebSocketClient);
private:
- int _js_id;
- bool _is_connecting;
- int _in_buf_size;
- int _in_pkt_size;
+ int _js_id = 0;
+ bool _is_connecting = false;
+ int _in_buf_size = DEF_BUF_SHIFT;
+ int _in_pkt_size = DEF_PKT_SHIFT;
static void _esws_on_connect(void *obj, char *proto);
static void _esws_on_message(void *obj, const uint8_t *p_data, int p_data_size, int p_is_string);
diff --git a/modules/websocket/emws_peer.cpp b/modules/websocket/emws_peer.cpp
index 496c1edc04..5e75e10d68 100644
--- a/modules/websocket/emws_peer.cpp
+++ b/modules/websocket/emws_peer.cpp
@@ -106,8 +106,6 @@ void EMWSPeer::set_no_delay(bool p_enabled) {
}
EMWSPeer::EMWSPeer() {
- peer_sock = -1;
- write_mode = WRITE_MODE_BINARY;
close();
};
diff --git a/modules/websocket/emws_peer.h b/modules/websocket/emws_peer.h
index 07f61b62a0..abe5bf2bdb 100644
--- a/modules/websocket/emws_peer.h
+++ b/modules/websocket/emws_peer.h
@@ -56,12 +56,12 @@ class EMWSPeer : public WebSocketPeer {
GDCIIMPL(EMWSPeer, WebSocketPeer);
private:
- int peer_sock;
- WriteMode write_mode;
+ int peer_sock = -1;
+ WriteMode write_mode = WRITE_MODE_BINARY;
Vector<uint8_t> _packet_buffer;
PacketBuffer<uint8_t> _in_buffer;
- uint8_t _is_string;
+ uint8_t _is_string = 0;
public:
Error read_msg(const uint8_t *p_data, uint32_t p_size, bool p_is_string);
diff --git a/modules/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp
index eb0252e6d1..425013f811 100644
--- a/modules/websocket/websocket_client.cpp
+++ b/modules/websocket/websocket_client.cpp
@@ -33,7 +33,6 @@
GDCINULL(WebSocketClient);
WebSocketClient::WebSocketClient() {
- verify_ssl = true;
}
WebSocketClient::~WebSocketClient() {
diff --git a/modules/websocket/websocket_client.h b/modules/websocket/websocket_client.h
index 78b77b89cd..0225c9b3d3 100644
--- a/modules/websocket/websocket_client.h
+++ b/modules/websocket/websocket_client.h
@@ -42,7 +42,7 @@ class WebSocketClient : public WebSocketMultiplayerPeer {
protected:
Ref<WebSocketPeer> _peer;
- bool verify_ssl;
+ bool verify_ssl = true;
Ref<X509Certificate> ssl_cert;
static void _bind_methods();
diff --git a/modules/websocket/websocket_multiplayer_peer.cpp b/modules/websocket/websocket_multiplayer_peer.cpp
index f94642475c..758ed66c80 100644
--- a/modules/websocket/websocket_multiplayer_peer.cpp
+++ b/modules/websocket/websocket_multiplayer_peer.cpp
@@ -33,15 +33,6 @@
#include "core/os/os.h"
WebSocketMultiplayerPeer::WebSocketMultiplayerPeer() {
- _is_multiplayer = false;
- _peer_id = 0;
- _target_peer = 0;
- _refusing = false;
-
- _current_packet.source = 0;
- _current_packet.destination = 0;
- _current_packet.size = 0;
- _current_packet.data = nullptr;
}
WebSocketMultiplayerPeer::~WebSocketMultiplayerPeer() {
@@ -62,7 +53,7 @@ int WebSocketMultiplayerPeer::_gen_unique_id() const {
(uint32_t)((uint64_t)this), hash); //rely on aslr heap
hash = hash_djb2_one_32(
(uint32_t)((uint64_t)&hash), hash); //rely on aslr stack
- hash = hash & 0x7FFFFFFF; // make it compatible with unsigned, since negatie id is used for exclusion
+ hash = hash & 0x7FFFFFFF; // make it compatible with unsigned, since negative id is used for exclusion
}
return hash;
@@ -195,7 +186,7 @@ void WebSocketMultiplayerPeer::_send_add(int32_t p_peer_id) {
for (Map<int, Ref<WebSocketPeer>>::Element *E = _peer_map.front(); E; E = E->next()) {
int32_t id = E->key();
if (p_peer_id == id) {
- continue; // Skip the newwly added peer (already confirmed)
+ continue; // Skip the newly added peer (already confirmed)
}
// Send new peer to others
@@ -323,7 +314,7 @@ void WebSocketMultiplayerPeer::_process_multiplayer(Ref<WebSocketPeer> p_peer, u
_peer_map.erase(id);
emit_signal("peer_disconnected", id);
break;
- case SYS_ID: // Helo, server assigned ID
+ case SYS_ID: // Hello, server assigned ID
_peer_id = id;
break;
default:
diff --git a/modules/websocket/websocket_multiplayer_peer.h b/modules/websocket/websocket_multiplayer_peer.h
index e593163b7c..48a6607d89 100644
--- a/modules/websocket/websocket_multiplayer_peer.h
+++ b/modules/websocket/websocket_multiplayer_peer.h
@@ -55,20 +55,20 @@ protected:
};
struct Packet {
- int source;
- int destination;
- uint8_t *data;
- uint32_t size;
+ int source = 0;
+ int destination = 0;
+ uint8_t *data = nullptr;
+ uint32_t size = 0;
};
List<Packet> _incoming_packets;
Map<int, Ref<WebSocketPeer>> _peer_map;
Packet _current_packet;
- bool _is_multiplayer;
- int _target_peer;
- int _peer_id;
- int _refusing;
+ bool _is_multiplayer = false;
+ int _target_peer = 0;
+ int _peer_id = 0;
+ int _refusing = false;
static void _bind_methods();
diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp
index 3e2f48e9b3..a075ae3982 100644
--- a/modules/websocket/wsl_client.cpp
+++ b/modules/websocket/wsl_client.cpp
@@ -337,11 +337,6 @@ Error WSLClient::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer
}
WSLClient::WSLClient() {
- _in_buf_size = DEF_BUF_SHIFT;
- _in_pkt_size = DEF_PKT_SHIFT;
- _out_buf_size = DEF_BUF_SHIFT;
- _out_pkt_size = DEF_PKT_SHIFT;
-
_peer.instance();
_tcp.instance();
disconnect_from_host();
diff --git a/modules/websocket/wsl_client.h b/modules/websocket/wsl_client.h
index 8712b57f2c..e7c91ed333 100644
--- a/modules/websocket/wsl_client.h
+++ b/modules/websocket/wsl_client.h
@@ -44,27 +44,27 @@ class WSLClient : public WebSocketClient {
GDCIIMPL(WSLClient, WebSocketClient);
private:
- int _in_buf_size;
- int _in_pkt_size;
- int _out_buf_size;
- int _out_pkt_size;
+ int _in_buf_size = DEF_BUF_SHIFT;
+ int _in_pkt_size = DEF_PKT_SHIFT;
+ int _out_buf_size = DEF_BUF_SHIFT;
+ int _out_pkt_size = DEF_PKT_SHIFT;
Ref<WSLPeer> _peer;
Ref<StreamPeerTCP> _tcp;
Ref<StreamPeer> _connection;
CharString _request;
- int _requested;
+ int _requested = 0;
uint8_t _resp_buf[WSL_MAX_HEADER_SIZE];
- int _resp_pos;
+ int _resp_pos = 0;
String _response;
String _key;
String _host;
Vector<String> _protocols;
- bool _use_ssl;
+ bool _use_ssl = false;
void _do_handshake();
bool _verify_headers(String &r_protocol);
diff --git a/modules/websocket/wsl_peer.cpp b/modules/websocket/wsl_peer.cpp
index 9d016e1139..dbbf86d0da 100644
--- a/modules/websocket/wsl_peer.cpp
+++ b/modules/websocket/wsl_peer.cpp
@@ -329,10 +329,6 @@ void WSLPeer::invalidate() {
}
WSLPeer::WSLPeer() {
- _data = nullptr;
- _is_string = 0;
- close_code = -1;
- write_mode = WRITE_MODE_BINARY;
}
WSLPeer::~WSLPeer() {
diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h
index 01efa4b21e..5e6a7e8554 100644
--- a/modules/websocket/wsl_peer.h
+++ b/modules/websocket/wsl_peer.h
@@ -48,29 +48,17 @@ class WSLPeer : public WebSocketPeer {
public:
struct PeerData {
- bool polling;
- bool destroy;
- bool valid;
- bool is_server;
- bool closing;
- void *obj;
- void *peer;
+ bool polling = false;
+ bool destroy = false;
+ bool valid = false;
+ bool is_server = false;
+ bool closing = false;
+ void *obj = nullptr;
+ void *peer = nullptr;
Ref<StreamPeer> conn;
Ref<StreamPeerTCP> tcp;
- int id;
- wslay_event_context_ptr ctx;
-
- PeerData() {
- polling = false;
- destroy = false;
- valid = false;
- is_server = false;
- id = 1;
- ctx = nullptr;
- obj = nullptr;
- closing = false;
- peer = nullptr;
- }
+ int id = 1;
+ wslay_event_context_ptr ctx = nullptr;
};
static String compute_key_response(String p_key);
@@ -80,17 +68,17 @@ private:
static bool _wsl_poll(struct PeerData *p_data);
static void _wsl_destroy(struct PeerData **p_data);
- struct PeerData *_data;
- uint8_t _is_string;
+ struct PeerData *_data = nullptr;
+ uint8_t _is_string = 0;
// Our packet info is just a boolean (is_string), using uint8_t for it.
PacketBuffer<uint8_t> _in_buffer;
Vector<uint8_t> _packet_buffer;
- WriteMode write_mode;
+ WriteMode write_mode = WRITE_MODE_BINARY;
public:
- int close_code;
+ int close_code = -1;
String close_reason;
void poll(); // Used by client and server.
diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp
index 9df076bf3f..437eb2061b 100644
--- a/modules/websocket/wsl_server.cpp
+++ b/modules/websocket/wsl_server.cpp
@@ -34,15 +34,6 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
-WSLServer::PendingPeer::PendingPeer() {
- use_ssl = false;
- time = 0;
- has_request = false;
- response_sent = 0;
- req_pos = 0;
- memset(req_buf, 0, sizeof(req_buf));
-}
-
bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols) {
Vector<String> psa = String((char *)req_buf).split("\r\n");
int len = psa.size();
@@ -310,10 +301,6 @@ Error WSLServer::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer
}
WSLServer::WSLServer() {
- _in_buf_size = DEF_BUF_SHIFT;
- _in_pkt_size = DEF_PKT_SHIFT;
- _out_buf_size = DEF_BUF_SHIFT;
- _out_pkt_size = DEF_PKT_SHIFT;
_server.instance();
}
diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h
index 8b2d4d3a04..75669e12ee 100644
--- a/modules/websocket/wsl_server.h
+++ b/modules/websocket/wsl_server.h
@@ -53,26 +53,24 @@ private:
public:
Ref<StreamPeerTCP> tcp;
Ref<StreamPeer> connection;
- bool use_ssl;
+ bool use_ssl = false;
- int time;
- uint8_t req_buf[WSL_MAX_HEADER_SIZE];
- int req_pos;
+ int time = 0;
+ uint8_t req_buf[WSL_MAX_HEADER_SIZE] = {};
+ int req_pos = 0;
String key;
String protocol;
- bool has_request;
+ bool has_request = false;
CharString response;
- int response_sent;
-
- PendingPeer();
+ int response_sent = 0;
Error do_handshake(const Vector<String> p_protocols);
};
- int _in_buf_size;
- int _in_pkt_size;
- int _out_buf_size;
- int _out_pkt_size;
+ int _in_buf_size = DEF_BUF_SHIFT;
+ int _in_pkt_size = DEF_PKT_SHIFT;
+ int _out_buf_size = DEF_BUF_SHIFT;
+ int _out_pkt_size = DEF_PKT_SHIFT;
List<Ref<PendingPeer>> _pending;
Ref<TCP_Server> _server;
diff --git a/modules/webxr/native/webxr.externs.js b/modules/webxr/native/webxr.externs.js
index 03dc05bc83..9ea105aa93 100644
--- a/modules/webxr/native/webxr.externs.js
+++ b/modules/webxr/native/webxr.externs.js
@@ -33,7 +33,7 @@ XR.prototype.ondevicechanged;
*
* @return {!Promise<boolean>}
*/
-XR.prototype.isSessionSupported = function(mode) {}
+XR.prototype.isSessionSupported = function(mode) {};
/**
* @param {string} mode
@@ -41,7 +41,7 @@ XR.prototype.isSessionSupported = function(mode) {}
*
* @return {!Promise<XRSession>}
*/
-XR.prototype.requestSession = function(mode, options) {}
+XR.prototype.requestSession = function(mode, options) {};
/**
* @constructor
diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp
index 74789fc98e..10076327e2 100644
--- a/modules/webxr/webxr_interface_js.cpp
+++ b/modules/webxr/webxr_interface_js.cpp
@@ -416,7 +416,7 @@ void WebXRInterfaceJS::_update_tracker(int p_controller_id) {
int *axes = godot_webxr_get_controller_axes(p_controller_id);
if (axes) {
for (int i = 0; i < axes[0]; i++) {
- Input::JoyAxis joy_axis;
+ Input::JoyAxisValue joy_axis;
joy_axis.min = -1;
joy_axis.value = *((float *)axes + (i + 1));
input->joy_axis(p_controller_id + 100, i, joy_axis);
diff --git a/modules/xatlas_unwrap/register_types.cpp b/modules/xatlas_unwrap/register_types.cpp
index 9f6e7efb27..e1f9521a48 100644
--- a/modules/xatlas_unwrap/register_types.cpp
+++ b/modules/xatlas_unwrap/register_types.cpp
@@ -154,17 +154,21 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver
float h = *r_size_hint_y;
if (w == 0 || h == 0) {
+ xatlas::Destroy(atlas);
return false; //could not bake because there is no area
}
const xatlas::Mesh &output = atlas->meshes[0];
*r_vertices = (int *)malloc(sizeof(int) * output.vertexCount);
+ ERR_FAIL_NULL_V_MSG(*r_vertices, false, "Out of memory.");
*r_uvs = (float *)malloc(sizeof(float) * output.vertexCount * 2);
+ ERR_FAIL_NULL_V_MSG(*r_uvs, false, "Out of memory.");
*r_indices = (int *)malloc(sizeof(int) * output.indexCount);
+ ERR_FAIL_NULL_V_MSG(*r_indices, false, "Out of memory.");
- float max_x = 0;
- float max_y = 0;
+ float max_x = 0.0;
+ float max_y = 0.0;
for (uint32_t i = 0; i < output.vertexCount; i++) {
(*r_vertices)[i] = output.vertexArray[i].xref;
(*r_uvs)[i * 2 + 0] = output.vertexArray[i].uv[0] / w;
diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp
index ee28959adc..3a2ccac481 100644
--- a/platform/android/audio_driver_jandroid.cpp
+++ b/platform/android/audio_driver_jandroid.cpp
@@ -73,9 +73,9 @@ Error AudioDriverAndroid::init() {
// __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
JNIEnv *env = get_jni_env();
- int mix_rate = GLOBAL_GET("audio/mix_rate");
+ int mix_rate = GLOBAL_GET("audio/driver/mix_rate");
- int latency = GLOBAL_GET("audio/output_latency");
+ int latency = GLOBAL_GET("audio/driver/output_latency");
unsigned int buffer_size = next_power_of_2(latency * mix_rate / 1000);
print_verbose("Audio buffer size: " + itos(buffer_size));
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 650606ff8b..996b6dcf41 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -13,7 +13,7 @@ def get_name():
def can_build():
- return "ANDROID_NDK_ROOT" in os.environ
+ return ("ANDROID_SDK_ROOT" in os.environ) or ("ANDROID_HOME" in os.environ)
def get_platform(platform):
@@ -24,13 +24,33 @@ def get_opts():
from SCons.Variables import BoolVariable, EnumVariable
return [
- ("ANDROID_NDK_ROOT", "Path to the Android NDK", os.environ.get("ANDROID_NDK_ROOT", 0)),
+ ("ANDROID_NDK_ROOT", "Path to the Android NDK", get_android_ndk_root()),
+ ("ANDROID_SDK_ROOT", "Path to the Android SDK", get_android_sdk_root()),
("ndk_platform", 'Target platform (android-<api>, e.g. "android-24")', "android-24"),
EnumVariable("android_arch", "Target architecture", "armv7", ("armv7", "arm64v8", "x86", "x86_64")),
BoolVariable("android_neon", "Enable NEON support (armv7 only)", True),
]
+# Return the ANDROID_SDK_ROOT environment variable.
+# While ANDROID_HOME has been deprecated, it's used as a fallback for backward
+# compatibility purposes.
+def get_android_sdk_root():
+ if "ANDROID_SDK_ROOT" in os.environ:
+ return os.environ.get("ANDROID_SDK_ROOT", 0)
+ else:
+ return os.environ.get("ANDROID_HOME", 0)
+
+
+# Return the ANDROID_NDK_ROOT environment variable.
+# We generate one for this build using the ANDROID_SDK_ROOT env
+# variable and the project ndk version.
+# If the env variable is already defined, we override it with
+# our own to match what the project expects.
+def get_android_ndk_root():
+ return get_android_sdk_root() + "/ndk/" + get_project_ndk_version()
+
+
def get_flags():
return [
("tools", False),
@@ -47,7 +67,31 @@ def create(env):
return env.Clone(tools=tools)
+# Check if ANDROID_NDK_ROOT is valid.
+# If not, install the ndk using ANDROID_SDK_ROOT and sdkmanager.
+def install_ndk_if_needed(env):
+ print("Checking for Android NDK...")
+ env_ndk_version = get_env_ndk_version(env["ANDROID_NDK_ROOT"])
+ if env_ndk_version is None:
+ # Reinstall the ndk and update ANDROID_NDK_ROOT.
+ print("Installing Android NDK...")
+ if env["ANDROID_SDK_ROOT"] is None:
+ raise Exception("Invalid ANDROID_SDK_ROOT environment variable.")
+
+ import subprocess
+
+ extension = ".bat" if os.name == "nt" else ""
+ sdkmanager_path = env["ANDROID_SDK_ROOT"] + "/cmdline-tools/latest/bin/sdkmanager" + extension
+ ndk_download_args = "ndk;" + get_project_ndk_version()
+ subprocess.check_call([sdkmanager_path, ndk_download_args])
+
+ env["ANDROID_NDK_ROOT"] = env["ANDROID_SDK_ROOT"] + "/ndk/" + get_project_ndk_version()
+ print("ANDROID_NDK_ROOT: " + env["ANDROID_NDK_ROOT"])
+
+
def configure(env):
+ install_ndk_if_needed(env)
+
# Workaround for MinGW. See:
# http://www.scons.org/wiki/LongCmdLinesOnWin32
if os.name == "nt":
@@ -153,12 +197,11 @@ def configure(env):
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(LINKFLAGS=["-O2"])
env.Append(CCFLAGS=["-O2", "-fomit-frame-pointer"])
- env.Append(CPPDEFINES=["NDEBUG"])
- else: # optimize for size
+ elif env["optimize"] == "size": # optimize for size
env.Append(CCFLAGS=["-Os"])
- env.Append(CPPDEFINES=["NDEBUG"])
env.Append(LINKFLAGS=["-Os"])
+ env.Append(CPPDEFINES=["NDEBUG"])
if can_vectorize:
env.Append(CCFLAGS=["-ftree-vectorize"])
if env["target"] == "release_debug":
@@ -270,7 +313,7 @@ def configure(env):
# Link flags
- ndk_version = get_ndk_version(env["ANDROID_NDK_ROOT"])
+ ndk_version = get_env_ndk_version(env["ANDROID_NDK_ROOT"])
if ndk_version != None and LooseVersion(ndk_version) >= LooseVersion("17.1.4828580"):
env.Append(LINKFLAGS=["-Wl,--exclude-libs,libgcc.a", "-Wl,--exclude-libs,libatomic.a", "-nostdlib++"])
else:
@@ -323,8 +366,14 @@ def configure(env):
env.Append(LIBS=["OpenSLES", "EGL", "GLESv2", "vulkan", "android", "log", "z", "dl"])
+# Return the project NDK version.
+# This is kept in sync with the value in 'platform/android/java/app/config.gradle'.
+def get_project_ndk_version():
+ return "21.4.7075529"
+
+
# Return NDK version string in source.properties (adapted from the Chromium project).
-def get_ndk_version(path):
+def get_env_ndk_version(path):
if path is None:
return None
prop_file_path = os.path.join(path, "source.properties")
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 5f7e5eaa83..dd001baba9 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -477,7 +477,7 @@ void DisplayServerAndroid::process_joy_event(DisplayServerAndroid::JoypadEvent p
Input::get_singleton()->joy_button(p_event.device, p_event.index, p_event.pressed);
break;
case JOY_EVENT_AXIS:
- Input::JoyAxis value;
+ Input::JoyAxisValue value;
value.min = -1;
value.value = p_event.value;
Input::get_singleton()->joy_axis(p_event.device, p_event.index, value);
@@ -741,15 +741,15 @@ void DisplayServerAndroid::process_mouse_event(int input_device, int event_actio
ev->set_pressed(true);
buttons_state = event_buttons_mask;
if (event_vertical_factor > 0) {
- _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_UP, event_vertical_factor);
+ _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_UP, event_vertical_factor);
} else if (event_vertical_factor < 0) {
- _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_DOWN, -event_vertical_factor);
+ _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_DOWN, -event_vertical_factor);
}
if (event_horizontal_factor > 0) {
- _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_RIGHT, event_horizontal_factor);
+ _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_RIGHT, event_horizontal_factor);
} else if (event_horizontal_factor < 0) {
- _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_LEFT, -event_horizontal_factor);
+ _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_LEFT, -event_horizontal_factor);
}
} break;
}
@@ -784,16 +784,16 @@ void DisplayServerAndroid::process_double_tap(int event_android_button_mask, Poi
int DisplayServerAndroid::_button_index_from_mask(int button_mask) {
switch (button_mask) {
- case BUTTON_MASK_LEFT:
- return BUTTON_LEFT;
- case BUTTON_MASK_RIGHT:
- return BUTTON_RIGHT;
- case BUTTON_MASK_MIDDLE:
- return BUTTON_MIDDLE;
- case BUTTON_MASK_XBUTTON1:
- return BUTTON_XBUTTON1;
- case BUTTON_MASK_XBUTTON2:
- return BUTTON_XBUTTON2;
+ case MOUSE_BUTTON_MASK_LEFT:
+ return MOUSE_BUTTON_LEFT;
+ case MOUSE_BUTTON_MASK_RIGHT:
+ return MOUSE_BUTTON_RIGHT;
+ case MOUSE_BUTTON_MASK_MIDDLE:
+ return MOUSE_BUTTON_MIDDLE;
+ case MOUSE_BUTTON_MASK_XBUTTON1:
+ return MOUSE_BUTTON_XBUTTON1;
+ case MOUSE_BUTTON_MASK_XBUTTON2:
+ return MOUSE_BUTTON_XBUTTON2;
default:
return 0;
}
@@ -854,19 +854,19 @@ int DisplayServerAndroid::mouse_get_button_state() const {
int DisplayServerAndroid::_android_button_mask_to_godot_button_mask(int android_button_mask) {
int godot_button_mask = 0;
if (android_button_mask & AMOTION_EVENT_BUTTON_PRIMARY) {
- godot_button_mask |= BUTTON_MASK_LEFT;
+ godot_button_mask |= MOUSE_BUTTON_MASK_LEFT;
}
if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) {
- godot_button_mask |= BUTTON_MASK_RIGHT;
+ godot_button_mask |= MOUSE_BUTTON_MASK_RIGHT;
}
if (android_button_mask & AMOTION_EVENT_BUTTON_TERTIARY) {
- godot_button_mask |= BUTTON_MASK_MIDDLE;
+ godot_button_mask |= MOUSE_BUTTON_MASK_MIDDLE;
}
if (android_button_mask & AMOTION_EVENT_BUTTON_BACK) {
- godot_button_mask |= BUTTON_MASK_XBUTTON1;
+ godot_button_mask |= MOUSE_BUTTON_MASK_XBUTTON1;
}
if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) {
- godot_button_mask |= BUTTON_MASK_XBUTTON2;
+ godot_button_mask |= MOUSE_BUTTON_MASK_XBUTTON2;
}
return godot_button_mask;
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index a963c5a741..326e513261 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -37,6 +37,7 @@
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
+#include "core/templates/safe_refcount.h"
#include "core/version.h"
#include "drivers/png/png_driver_common.h"
#include "editor/editor_export.h"
@@ -202,6 +203,19 @@ static const char *android_perms[] = {
static const char *SPLASH_IMAGE_EXPORT_PATH = "res/drawable/splash.png";
static const char *SPLASH_BG_COLOR_PATH = "res/drawable/splash_bg_color.png";
+static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash_drawable.xml";
+
+const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/splash_bg_color" />
+ <item>
+ <bitmap
+ android:gravity="%s"
+ android:filter="%s"
+ android:src="@drawable/splash" />
+ </item>
+</layer-list>
+)SPLASH";
struct LauncherIcon {
const char *export_path;
@@ -264,38 +278,38 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
Vector<PluginConfigAndroid> plugins;
String last_plugin_names;
uint64_t last_custom_build_time = 0;
- volatile bool plugins_changed;
+ SafeFlag plugins_changed;
Mutex plugins_lock;
Vector<Device> devices;
- volatile bool devices_changed;
+ SafeFlag devices_changed;
Mutex device_lock;
Thread check_for_changes_thread;
- volatile bool quit_request;
+ SafeFlag quit_request;
static void _check_for_changes_poll_thread(void *ud) {
EditorExportPlatformAndroid *ea = (EditorExportPlatformAndroid *)ud;
- while (!ea->quit_request) {
+ while (!ea->quit_request.is_set()) {
// Check for plugins updates
{
// Nothing to do if we already know the plugins have changed.
- if (!ea->plugins_changed) {
+ if (!ea->plugins_changed.is_set()) {
Vector<PluginConfigAndroid> loaded_plugins = get_plugins();
MutexLock lock(ea->plugins_lock);
if (ea->plugins.size() != loaded_plugins.size()) {
- ea->plugins_changed = true;
+ ea->plugins_changed.set();
} else {
for (int i = 0; i < ea->plugins.size(); i++) {
if (ea->plugins[i].name != loaded_plugins[i].name) {
- ea->plugins_changed = true;
+ ea->plugins_changed.set();
break;
}
}
}
- if (ea->plugins_changed) {
+ if (ea->plugins_changed.is_set()) {
ea->plugins = loaded_plugins;
}
}
@@ -409,7 +423,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
}
ea->devices = ndevices;
- ea->devices_changed = true;
+ ea->devices_changed.set();
}
}
@@ -418,7 +432,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
uint64_t time = OS::get_singleton()->get_ticks_usec();
while (OS::get_singleton()->get_ticks_usec() - time < wait) {
OS::get_singleton()->delay_usec(1000 * sleep);
- if (ea->quit_request) {
+ if (ea->quit_request.is_set()) {
break;
}
}
@@ -775,6 +789,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
}
void _write_tmp_manifest(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, bool p_debug) {
+ 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"
@@ -791,10 +806,11 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
manifest_text += _get_xr_features_tag(p_preset);
manifest_text += _get_instrumentation_tag(p_preset);
- String plugins_names = get_plugins_names(get_enabled_plugins(p_preset));
- manifest_text += _get_application_tag(p_preset, plugins_names);
+ manifest_text += _get_application_tag(p_preset);
manifest_text += "</manifest>\n";
String manifest_path = vformat("res://android/build/src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release"));
+
+ print_verbose("Storing manifest into " + manifest_path + ": " + "\n" + manifest_text);
store_string_at_path(manifest_path, manifest_text);
}
@@ -839,8 +855,6 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
int xr_mode_index = p_preset->get("xr_features/xr_mode");
bool focus_awareness = p_preset->get("xr_features/focus_awareness");
- String plugins_names = get_plugins_names(get_enabled_plugins(p_preset));
-
Vector<String> perms;
// Write permissions into the perms variable.
_get_permissions(p_preset, p_give_internet, perms);
@@ -978,11 +992,6 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
encode_uint32(xr_mode_index == /* XRMode.OVR */ 1 && focus_awareness ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]);
}
- if (tname == "meta-data" && attrname == "value" && value == "plugins_value" && !plugins_names.is_empty()) {
- // Update the meta-data 'android:value' attribute with the list of enabled plugins.
- string_table.write[attr_value] = plugins_names;
- }
-
is_focus_aware_metadata = tname == "meta-data" && attrname == "name" && value == "com.oculus.vr.focusaware";
iofs += 20;
}
@@ -1470,20 +1479,26 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
}
}
- void load_splash_refs(Ref<Image> &splash_image, Ref<Image> &splash_bg_color_image) {
- // TODO: Figure out how to handle remaining boot splash parameters (e.g: fullsize, filter)
+ String load_splash_refs(Ref<Image> &splash_image, Ref<Image> &splash_bg_color_image) {
+ bool scale_splash = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize");
+ bool apply_filter = ProjectSettings::get_singleton()->get("application/boot_splash/use_filter");
String project_splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image");
if (!project_splash_path.is_empty()) {
splash_image.instance();
+ print_verbose("Loading splash image: " + project_splash_path);
const Error err = ImageLoader::load_image(project_splash_path, splash_image);
if (err) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ print_error("- unable to load splash image from " + project_splash_path + " (" + itos(err) + ")");
+ }
splash_image.unref();
}
}
if (splash_image.is_null()) {
// Use the default
+ print_verbose("Using default splash image.");
splash_image = Ref<Image>(memnew(Image(boot_splash_png)));
}
@@ -1494,9 +1509,14 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
bg_color = boot_splash_bg_color;
}
+ print_verbose("Creating splash background color image.");
splash_bg_color_image.instance();
splash_bg_color_image->create(splash_image->get_width(), splash_image->get_height(), false, splash_image->get_format());
splash_bg_color_image->fill(bg_color);
+
+ String gravity = scale_splash ? "fill" : "center";
+ String processed_splash_config_xml = vformat(SPLASH_CONFIG_XML_CONTENT, gravity, bool_to_string(apply_filter));
+ return processed_splash_config_xml;
}
void load_icon_refs(const Ref<EditorExportPreset> &p_preset, Ref<Image> &icon, Ref<Image> &foreground, Ref<Image> &background) {
@@ -1508,19 +1528,24 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
// Regular icon: user selection -> project icon -> default.
String path = static_cast<String>(p_preset->get(launcher_icon_option)).strip_edges();
+ print_verbose("Loading regular icon from " + path);
if (path.is_empty() || ImageLoader::load_image(path, icon) != OK) {
+ print_verbose("- falling back to project icon: " + project_icon_path);
ImageLoader::load_image(project_icon_path, icon);
}
// Adaptive foreground: user selection -> regular icon (user selection -> project icon -> default).
path = static_cast<String>(p_preset->get(launcher_adaptive_icon_foreground_option)).strip_edges();
+ print_verbose("Loading adaptive foreground icon from " + path);
if (path.is_empty() || ImageLoader::load_image(path, foreground) != OK) {
+ print_verbose("- falling back to using the regular icon");
foreground = icon;
}
// Adaptive background: user selection -> default.
path = static_cast<String>(p_preset->get(launcher_adaptive_icon_background_option)).strip_edges();
if (!path.is_empty()) {
+ print_verbose("Loading adaptive background icon from " + path);
ImageLoader::load_image(path, background);
}
}
@@ -1535,13 +1560,21 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
}
void _copy_icons_to_gradle_project(const Ref<EditorExportPreset> &p_preset,
+ const String &processed_splash_config_xml,
const Ref<Image> &splash_image,
const Ref<Image> &splash_bg_color_image,
const Ref<Image> &main_image,
const Ref<Image> &foreground,
const Ref<Image> &background) {
+ // Store the splash configuration
+ if (!processed_splash_config_xml.is_empty()) {
+ print_verbose("Storing processed splash configuration: " + String("\n") + processed_splash_config_xml);
+ store_string_at_path(SPLASH_CONFIG_PATH, processed_splash_config_xml);
+ }
+
// Store the splash image
if (splash_image.is_valid() && !splash_image->is_empty()) {
+ print_verbose("Storing splash image in " + String(SPLASH_IMAGE_EXPORT_PATH));
Vector<uint8_t> data;
_load_image_data(splash_image, data);
store_image(SPLASH_IMAGE_EXPORT_PATH, data);
@@ -1549,6 +1582,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
// Store the splash bg color image
if (splash_bg_color_image.is_valid() && !splash_bg_color_image->is_empty()) {
+ print_verbose("Storing splash background image in " + String(SPLASH_BG_COLOR_PATH));
Vector<uint8_t> data;
_load_image_data(splash_bg_color_image, data);
store_image(SPLASH_BG_COLOR_PATH, data);
@@ -1559,12 +1593,14 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
for (int i = 0; i < icon_densities_count; ++i) {
if (main_image.is_valid() && !main_image->is_empty()) {
+ print_verbose("Processing launcher icon for dimension " + itos(launcher_icons[i].dimensions) + " into " + launcher_icons[i].export_path);
Vector<uint8_t> data;
_process_launcher_icons(launcher_icons[i].export_path, main_image, launcher_icons[i].dimensions, data);
store_image(launcher_icons[i], data);
}
if (foreground.is_valid() && !foreground->is_empty()) {
+ print_verbose("Processing launcher adaptive icon foreground for dimension " + itos(launcher_adaptive_icon_foregrounds[i].dimensions) + " into " + launcher_adaptive_icon_foregrounds[i].export_path);
Vector<uint8_t> data;
_process_launcher_icons(launcher_adaptive_icon_foregrounds[i].export_path, foreground,
launcher_adaptive_icon_foregrounds[i].dimensions, data);
@@ -1572,6 +1608,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
}
if (background.is_valid() && !background->is_empty()) {
+ print_verbose("Processing launcher adaptive icon background for dimension " + itos(launcher_adaptive_icon_backgrounds[i].dimensions) + " into " + launcher_adaptive_icon_backgrounds[i].export_path);
Vector<uint8_t> data;
_process_launcher_icons(launcher_adaptive_icon_backgrounds[i].export_path, background,
launcher_adaptive_icon_backgrounds[i].dimensions, data);
@@ -1597,7 +1634,7 @@ public:
public:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override {
- String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name");
+ String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
if (driver == "GLES2") {
r_features->push_back("etc");
}
@@ -1623,7 +1660,7 @@ public:
print_verbose("Found Android plugin " + plugins_configs[i].name);
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + plugins_configs[i].name), false));
}
- plugins_changed = false;
+ plugins_changed.clear();
Vector<String> abis = get_abis();
for (int i = 0; i < abis.size(); ++i) {
@@ -1693,19 +1730,19 @@ public:
}
virtual bool should_update_export_options() override {
- bool export_options_changed = plugins_changed;
+ bool export_options_changed = plugins_changed.is_set();
if (export_options_changed) {
// don't clear unless we're reporting true, to avoid race
- plugins_changed = false;
+ plugins_changed.clear();
}
return export_options_changed;
}
virtual bool poll_export() override {
- bool dc = devices_changed;
+ bool dc = devices_changed.is_set();
if (dc) {
// don't clear unless we're reporting true, to avoid race
- devices_changed = false;
+ devices_changed.clear();
}
return dc;
}
@@ -1958,6 +1995,7 @@ public:
String template_err;
bool dvalid = false;
bool rvalid = false;
+ bool has_export_templates = false;
if (p_preset->get("custom_template/debug") != "") {
dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
@@ -1965,7 +2003,7 @@ public:
template_err += TTR("Custom debug template not found.") + "\n";
}
} else {
- dvalid = exists_export_template("android_debug.apk", &template_err);
+ has_export_templates |= exists_export_template("android_debug.apk", &template_err);
}
if (p_preset->get("custom_template/release") != "") {
@@ -1974,22 +2012,24 @@ public:
template_err += TTR("Custom release template not found.") + "\n";
}
} else {
- rvalid = exists_export_template("android_release.apk", &template_err);
+ has_export_templates |= exists_export_template("android_release.apk", &template_err);
}
- valid = dvalid || rvalid;
+ r_missing_templates = !has_export_templates;
+ valid = dvalid || rvalid || has_export_templates;
if (!valid) {
err += template_err;
}
} else {
- valid = exists_export_template("android_source.zip", &err);
+ r_missing_templates = !exists_export_template("android_source.zip", &err);
- if (!FileAccess::exists("res://android/build/build.gradle")) {
+ bool installed_android_build_template = FileAccess::exists("res://android/build/build.gradle");
+ if (!installed_android_build_template) {
err += TTR("Android build template not installed in the project. Install it from the Project menu.") + "\n";
- valid = false;
}
+
+ valid = installed_android_build_template && !r_missing_templates;
}
- r_missing_templates = !valid;
// Validate the rest of the configuration.
@@ -2239,6 +2279,7 @@ public:
String release_password = p_preset->get("keystore/release_password");
String apksigner = get_apksigner_path();
+ print_verbose("Starting signing of the " + export_label + " binary using " + apksigner);
if (!FileAccess::exists(apksigner)) {
EditorNode::add_io_error("'apksigner' could not be found.\nPlease check the command is available in the Android SDK build-tools directory.\nThe resulting " + export_label + " is unsigned.");
return OK;
@@ -2287,6 +2328,10 @@ public:
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.
+ print_verbose("Signing debug binary using: " + String("\n") + apksigner + " " + join_list(args, String(" ")));
+ }
int retval;
OS::get_singleton()->execute(apksigner, args, nullptr, &retval);
if (retval) {
@@ -2302,24 +2347,41 @@ public:
args.push_back("verify");
args.push_back("--verbose");
args.push_back(export_path);
+ if (p_debug) {
+ print_verbose("Verifying signed build using: " + String("\n") + apksigner + " " + join_list(args, String(" ")));
+ }
OS::get_singleton()->execute(apksigner, args, nullptr, &retval);
if (retval) {
EditorNode::add_io_error("'apksigner' verification of " + export_label + " failed.");
return ERR_CANT_CREATE;
}
+
+ print_verbose("Successfully completed signing build.");
return OK;
}
void _clear_assets_directory() {
DirAccessRef da_res = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da_res->dir_exists("res://android/build/assets")) {
+ print_verbose("Clearing assets directory..");
DirAccessRef da_assets = DirAccess::open("res://android/build/assets");
da_assets->erase_contents_recursive();
da_res->remove("res://android/build/assets");
}
}
+ String join_list(List<String> parts, const String &separator) const {
+ String ret;
+ for (int i = 0; i < parts.size(); ++i) {
+ if (i > 0) {
+ ret += separator;
+ }
+ ret += parts[i];
+ }
+ return ret;
+ }
+
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override {
int export_format = int(p_preset->get("custom_template/export_format"));
bool should_sign = p_preset->get("package/signed");
@@ -2339,9 +2401,21 @@ public:
bool apk_expansion = p_preset->get("apk_expansion/enable");
Vector<String> enabled_abis = get_enabled_abis(p_preset);
+ print_verbose("Exporting for Android...");
+ print_verbose("- debug build: " + bool_to_string(p_debug));
+ print_verbose("- export path: " + p_path);
+ print_verbose("- export format: " + itos(export_format));
+ print_verbose("- sign build: " + bool_to_string(should_sign));
+ print_verbose("- custom build enabled: " + bool_to_string(use_custom_build));
+ print_verbose("- apk expansion enabled: " + bool_to_string(apk_expansion));
+ print_verbose("- enabled abis: " + String(",").join(enabled_abis));
+ print_verbose("- export filter: " + itos(p_preset->get_export_filter()));
+ print_verbose("- include filter: " + p_preset->get_include_filter());
+ print_verbose("- exclude filter: " + p_preset->get_exclude_filter());
+
Ref<Image> splash_image;
Ref<Image> splash_bg_color_image;
- load_splash_refs(splash_image, splash_bg_color_image);
+ String processed_splash_config_xml = load_splash_refs(splash_image, splash_bg_color_image);
Ref<Image> main_image;
Ref<Image> foreground;
@@ -2374,14 +2448,17 @@ public:
}
if (use_custom_build) {
+ print_verbose("Starting custom build..");
//test that installed build version is alright
{
+ print_verbose("Checking build version..");
FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::READ);
if (!f) {
EditorNode::get_singleton()->show_warning(TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu."));
return ERR_UNCONFIGURED;
}
String version = f->get_line().strip_edges();
+ print_verbose("- build version: " + version);
f->close();
if (version != VERSION_FULL_CONFIG) {
EditorNode::get_singleton()->show_warning(vformat(TTR("Android build version mismatch:\n Template installed: %s\n Godot Version: %s\nPlease reinstall Android build template from 'Project' menu."), version, VERSION_FULL_CONFIG));
@@ -2389,7 +2466,8 @@ public:
}
}
String sdk_path = EDITOR_GET("export/android/android_sdk_path");
- ERR_FAIL_COND_V_MSG(sdk_path == "", ERR_UNCONFIGURED, "Android SDK path must be configured in Editor Settings at 'export/android/android_sdk_path'.");
+ ERR_FAIL_COND_V_MSG(sdk_path.is_empty(), ERR_UNCONFIGURED, "Android SDK path must be configured in Editor Settings at 'export/android/android_sdk_path'.");
+ print_verbose("Android sdk path: " + sdk_path);
// TODO: should we use "package/name" or "application/config/name"?
String project_name = get_project_name(p_preset->get("package/name"));
@@ -2398,27 +2476,31 @@ public:
EditorNode::add_io_error("Unable to overwrite res://android/build/res/*.xml files with project name");
}
// Copies the project icon files into the appropriate Gradle project directory.
- _copy_icons_to_gradle_project(p_preset, splash_image, splash_bg_color_image, main_image, foreground, background);
+ _copy_icons_to_gradle_project(p_preset, processed_splash_config_xml, splash_image, splash_bg_color_image, main_image, foreground, background);
// Write an AndroidManifest.xml file into the Gradle project directory.
_write_tmp_manifest(p_preset, p_give_internet, p_debug);
//stores all the project files inside the Gradle project directory. Also includes all ABIs
_clear_assets_directory();
if (!apk_expansion) {
+ print_verbose("Exporting project files..");
err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, NULL, ignore_so_file);
if (err != OK) {
EditorNode::add_io_error("Could not export project files to gradle project\n");
return err;
}
} else {
+ print_verbose("Saving apk expansion file..");
err = save_apk_expansion_file(p_preset, p_path);
if (err != OK) {
EditorNode::add_io_error("Could not write expansion package file!");
return err;
}
}
+ print_verbose("Storing command line flags..");
store_file_at_path("res://android/build/assets/_cl_", command_line_flags);
+ print_verbose("Updating ANDROID_HOME environment to " + sdk_path);
OS::get_singleton()->set_environment("ANDROID_HOME", sdk_path); //set and overwrite if required
String build_command;
@@ -2458,6 +2540,8 @@ public:
cmdline.push_back(apk_build_command);
}
+ cmdline.push_back("-p"); // argument to specify the start directory.
+ cmdline.push_back(build_path); // start directory.
cmdline.push_back("-Pexport_package_name=" + package_name); // argument to specify the package name.
cmdline.push_back("-Pexport_version_code=" + version_code); // argument to specify the version code.
cmdline.push_back("-Pexport_version_name=" + version_name); // argument to specify the version name.
@@ -2467,6 +2551,14 @@ public:
cmdline.push_back("-Pplugins_maven_repos=" + custom_maven_repos); // argument to specify the list of custom maven repos for the plugins dependencies.
cmdline.push_back("-Pperform_zipalign=" + zipalign_flag); // argument to specify whether the build should be zipaligned.
cmdline.push_back("-Pperform_signing=" + sign_flag); // argument to specify whether the build should be signed.
+ cmdline.push_back("-Pgodot_editor_version=" + String(VERSION_FULL_CONFIG));
+
+ // NOTE: The release keystore is not included in the verbose logging
+ // to avoid accidentally leaking sensitive information when sharing verbose logs for troubleshooting.
+ // Any non-sensitive additions to the command line arguments must be done above this section.
+ // Sensitive additions must be done below the logging statement.
+ print_verbose("Build Android project using gradle command: " + String("\n") + build_command + " " + join_list(cmdline, String(" ")));
+
if (should_sign && !p_debug) {
// Pass the release keystore info as well
String release_keystore = p_preset->get("keystore/release");
@@ -2481,8 +2573,6 @@ public:
cmdline.push_back("-Prelease_keystore_alias=" + release_username); // argument to specify the release keystore alias.
cmdline.push_back("-Prelease_keystore_password=" + release_password); // argument to specity the release keystore password.
}
- cmdline.push_back("-p"); // argument to specify the start directory.
- cmdline.push_back(build_path); // start directory.
int result = EditorNode::get_singleton()->execute_and_show_output(TTR("Building Android Project (gradle)"), build_command, cmdline);
if (result != 0) {
@@ -2513,15 +2603,18 @@ public:
copy_args.push_back("-Pexport_path=file:" + export_path);
copy_args.push_back("-Pexport_filename=" + export_filename);
+ print_verbose("Copying Android binary using gradle command: " + String("\n") + build_command + " " + join_list(copy_args, String(" ")));
int copy_result = EditorNode::get_singleton()->execute_and_show_output(TTR("Moving output"), build_command, copy_args);
if (copy_result != 0) {
EditorNode::get_singleton()->show_warning(TTR("Unable to copy and rename export file, check gradle project directory for outputs."));
return ERR_CANT_CREATE;
}
+ print_verbose("Successfully completed Android custom build.");
return OK;
}
// This is the start of the Legacy build system
+ print_verbose("Starting legacy build system..");
if (p_debug)
src_apk = p_preset->get("custom_template/debug");
else
@@ -2845,14 +2938,13 @@ public:
run_icon.instance();
run_icon->create_from_image(img);
- devices_changed = true;
- plugins_changed = true;
- quit_request = false;
+ devices_changed.set();
+ plugins_changed.set();
check_for_changes_thread.start(_check_for_changes_poll_thread, this);
}
~EditorExportPlatformAndroid() {
- quit_request = true;
+ quit_request.set();
check_for_changes_thread.wait_to_finish();
}
};
diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h
index fc54b65d26..097a2391ee 100644
--- a/platform/android/export/gradle_export_util.h
+++ b/platform/android/export/gradle_export_util.h
@@ -146,6 +146,9 @@ Error store_string_at_path(const String &p_path, const String &p_data) {
String dir = p_path.get_base_dir();
Error err = create_directory(dir);
if (err != OK) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ print_error("Unable to write data into " + p_path);
+ }
return err;
}
FileAccess *fa = FileAccess::open(p_path, FileAccess::WRITE);
@@ -162,12 +165,14 @@ Error store_string_at_path(const String &p_path, const String &p_data) {
// This method will be called ONLY when custom build is enabled.
Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) {
String dst_path = p_path.replace_first("res://", "res://android/build/assets/");
+ print_verbose("Saving project files from " + p_path + " into " + dst_path);
Error err = store_file_at_path(dst_path, p_data);
return err;
}
// Creates strings.xml files inside the gradle project for different locales.
Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset, const String &project_name) {
+ print_verbose("Creating strings resources for supported locales for project " + project_name);
// Stores the string into the default values directory.
String processed_default_xml_string = vformat(godot_project_name_xml_string, project_name.xml_escape(true));
store_string_at_path("res://android/build/res/values/godot_project_name_string.xml", processed_default_xml_string);
@@ -175,6 +180,9 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset
// Searches the Gradle project res/ directory to find all supported locales
DirAccessRef da = DirAccess::open("res://android/build/res");
if (!da) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ print_error("Unable to open Android resources directory.");
+ }
return ERR_CANT_OPEN;
}
da->list_dir_begin();
@@ -193,6 +201,7 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset
if (ProjectSettings::get_singleton()->has_setting(property_name)) {
String locale_project_name = ProjectSettings::get_singleton()->get(property_name);
String processed_xml_string = vformat(godot_project_name_xml_string, locale_project_name.xml_escape(true));
+ print_verbose("Storing project name for locale " + locale + " under " + locale_directory);
store_string_at_path(locale_directory, processed_xml_string);
} else {
// TODO: Once the legacy build system is deprecated we don't need to have xml files for this else branch
@@ -208,8 +217,8 @@ String bool_to_string(bool v) {
}
String _get_gles_tag() {
- bool min_gles3 = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name") == "GLES3" &&
- !ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2");
+ bool min_gles3 = ProjectSettings::get_singleton()->get("rendering/driver/driver_name") == "GLES3" &&
+ !ProjectSettings::get_singleton()->get("rendering/driver/fallback_to_gles2");
return min_gles3 ? " <uses-feature android:glEsVersion=\"0x00030000\" android:required=\"true\" />\n" : "";
}
@@ -260,14 +269,6 @@ String _get_instrumentation_tag(const Ref<EditorExportPreset> &p_preset) {
return manifest_instrumentation_text;
}
-String _get_plugins_tag(const String &plugins_names) {
- if (!plugins_names.is_empty()) {
- return vformat(" <meta-data tools:node=\"replace\" android:name=\"plugins\" android:value=\"%s\" />\n", plugins_names);
- } else {
- return " <meta-data tools:node=\"remove\" android:name=\"plugins\" />\n";
- }
-}
-
String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
bool uses_xr = (int)(p_preset->get("xr_features/xr_mode")) == 1;
String orientation = _get_android_orientation_label(_get_screen_orientation());
@@ -286,7 +287,7 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
return manifest_activity_text;
}
-String _get_application_tag(const Ref<EditorExportPreset> &p_preset, const String &plugins_names) {
+String _get_application_tag(const Ref<EditorExportPreset> &p_preset) {
bool uses_xr = (int)(p_preset->get("xr_features/xr_mode")) == 1;
String manifest_application_text =
" <application android:label=\"@string/godot_project_name_string\"\n"
@@ -294,7 +295,6 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, const Strin
" android:icon=\"@mipmap/icon\">\n\n"
" <meta-data tools:node=\"remove\" android:name=\"xr_mode_metadata_name\" />\n";
- manifest_application_text += _get_plugins_tag(plugins_names);
if (uses_xr) {
manifest_application_text += " <meta-data tools:node=\"replace\" android:name=\"com.samsung.android.vr.application.mode\" android:value=\"vr_only\" />\n";
}
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index 165d5da3ae..e288c16777 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -114,6 +114,9 @@ uint8_t FileAccessAndroid::get_8() const {
}
int FileAccessAndroid::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
+
off_t r = AAsset_read(a, p_dst, p_length);
if (pos + p_length > len) {
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index e94681659c..948fa8c00b 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -22,6 +22,11 @@
tools:ignore="GoogleAppIndexingWarning"
android:icon="@mipmap/icon" >
+ <!-- Records the version of the Godot editor used for building -->
+ <meta-data
+ android:name="org.godotengine.editor.version"
+ android:value="${godotEditorVersion}" />
+
<!-- The following metadata values are replaced when Godot exports, modifying them here has no effect. -->
<!-- Do these changes in the export preset. Adding new ones is fine. -->
@@ -30,11 +35,6 @@
android:name="xr_mode_metadata_name"
android:value="xr_mode_metadata_value" />
- <!-- Metadata populated at export time and used by Godot to figure out which plugins must be enabled. -->
- <meta-data
- android:name="plugins"
- android:value="plugins_value"/>
-
<activity
android:name=".GodotApp"
android:label="@string/godot_project_name_string"
diff --git a/platform/android/java/app/assets/.gitignore b/platform/android/java/app/assets/.gitignore
new file mode 100644
index 0000000000..d6b7ef32c8
--- /dev/null
+++ b/platform/android/java/app/assets/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle
index 53d11fda5b..f103f22db2 100644
--- a/platform/android/java/app/build.gradle
+++ b/platform/android/java/app/build.gradle
@@ -77,7 +77,7 @@ android {
defaultConfig {
// The default ignore pattern for the 'assets' directory includes hidden files and directories which are used by Godot projects.
aaptOptions {
- ignoreAssetsPattern "!.svn:!.git:!.ds_store:!*.scc:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"
+ ignoreAssetsPattern "!.svn:!.git:!.gitignore:!.ds_store:!*.scc:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
ndk {
@@ -85,6 +85,8 @@ android {
abiFilters export_abi_list
}
+ manifestPlaceholders = [godotEditorVersion: getGodotEditorVersion()]
+
// Feel free to modify the application id to your own.
applicationId getExportPackageName()
versionCode getExportVersionCode()
@@ -98,12 +100,16 @@ android {
disable 'MissingTranslation', 'UnusedResources'
}
+ ndkVersion versions.ndkVersion
+
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
- // Should be uncommented for development purpose within Android Studio
- // doNotStrip '**/*.so'
+ // 'doNotStrip' is enabled for development within Android Studio
+ if (shouldNotStrip()) {
+ doNotStrip '**/*.so'
+ }
}
signingConfigs {
diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle
index 80cf6f7ede..c0ae4007d2 100644
--- a/platform/android/java/app/config.gradle
+++ b/platform/android/java/app/config.gradle
@@ -1,5 +1,5 @@
ext.versions = [
- androidGradlePlugin: '4.1.0',
+ androidGradlePlugin: '4.0.1',
compileSdk : 29,
minSdk : 18,
targetSdk : 29,
@@ -7,7 +7,8 @@ ext.versions = [
supportCoreUtils : '1.0.0',
kotlinVersion : '1.4.10',
v4Support : '1.0.0',
- javaVersion : 1.8
+ javaVersion : 1.8,
+ ndkVersion : '21.4.7075529' // Also update 'platform/android/detect.py#get_project_ndk_version()' when this is updated.
]
@@ -49,7 +50,56 @@ ext.getExportVersionName = { ->
return versionName
}
-final String PLUGIN_VALUE_SEPARATOR_REGEX = "\\|"
+ext.getGodotEditorVersion = { ->
+ String editorVersion = project.hasProperty("godot_editor_version") ? project.property("godot_editor_version") : ""
+ if (editorVersion == null || editorVersion.isEmpty()) {
+ // Try the library version first
+ editorVersion = getGodotLibraryVersion()
+
+ if (editorVersion.isEmpty()) {
+ // Fallback value.
+ editorVersion = "custom_build"
+ }
+ }
+ return editorVersion
+}
+
+ext.getGodotLibraryVersion = { ->
+ // Attempt to read the version from the `version.py` file.
+ String libraryVersion = ""
+
+ File versionFile = new File("../../../version.py")
+ if (versionFile.isFile()) {
+ List<String> requiredKeys = ["major", "minor", "patch", "status", "module_config"]
+ def map = [:]
+
+ List<String> lines = versionFile.readLines()
+ for (String line in lines) {
+ String[] keyValue = line.split("=")
+ String key = keyValue[0].trim()
+ String value = keyValue[1].trim().replaceAll("\"", "")
+
+ if (requiredKeys.contains(key)) {
+ if (!value.isEmpty()) {
+ map[key] = value
+ }
+ requiredKeys.remove(key)
+ }
+ }
+
+ if (requiredKeys.empty) {
+ libraryVersion = map.values().join(".")
+ }
+ }
+
+ if (libraryVersion.isEmpty()) {
+ // Fallback value in case we're unable to read the file.
+ libraryVersion = "custom_build"
+ }
+ return libraryVersion
+}
+
+final String VALUE_SEPARATOR_REGEX = "\\|"
// get the list of ABIs the project should be exported to
ext.getExportEnabledABIs = { ->
@@ -58,7 +108,7 @@ ext.getExportEnabledABIs = { ->
enabledABIs = "armeabi-v7a|arm64-v8a|x86|x86_64|"
}
Set<String> exportAbiFilter = [];
- for (String abi_name : enabledABIs.split(PLUGIN_VALUE_SEPARATOR_REGEX)) {
+ for (String abi_name : enabledABIs.split(VALUE_SEPARATOR_REGEX)) {
if (!abi_name.trim().isEmpty()){
exportAbiFilter.add(abi_name);
}
@@ -93,7 +143,7 @@ ext.getGodotPluginsMavenRepos = { ->
if (project.hasProperty("plugins_maven_repos")) {
String mavenReposProperty = project.property("plugins_maven_repos")
if (mavenReposProperty != null && !mavenReposProperty.trim().isEmpty()) {
- for (String mavenRepoUrl : mavenReposProperty.split(PLUGIN_VALUE_SEPARATOR_REGEX)) {
+ for (String mavenRepoUrl : mavenReposProperty.split(VALUE_SEPARATOR_REGEX)) {
mavenRepos += mavenRepoUrl.trim()
}
}
@@ -113,7 +163,7 @@ ext.getGodotPluginsRemoteBinaries = { ->
if (project.hasProperty("plugins_remote_binaries")) {
String remoteDepsList = project.property("plugins_remote_binaries")
if (remoteDepsList != null && !remoteDepsList.trim().isEmpty()) {
- for (String dep: remoteDepsList.split(PLUGIN_VALUE_SEPARATOR_REGEX)) {
+ for (String dep: remoteDepsList.split(VALUE_SEPARATOR_REGEX)) {
remoteDeps += dep.trim()
}
}
@@ -132,7 +182,7 @@ ext.getGodotPluginsLocalBinaries = { ->
if (project.hasProperty("plugins_local_binaries")) {
String pluginsList = project.property("plugins_local_binaries")
if (pluginsList != null && !pluginsList.trim().isEmpty()) {
- for (String plugin : pluginsList.split(PLUGIN_VALUE_SEPARATOR_REGEX)) {
+ for (String plugin : pluginsList.split(VALUE_SEPARATOR_REGEX)) {
binDeps += plugin.trim()
}
}
@@ -159,10 +209,19 @@ ext.getReleaseKeyAlias = { ->
return keyAlias
}
+ext.isAndroidStudio = { ->
+ def sysProps = System.getProperties()
+ return sysProps != null && sysProps['idea.platform.prefix'] != null
+}
+
ext.shouldZipAlign = { ->
String zipAlignFlag = project.hasProperty("perform_zipalign") ? project.property("perform_zipalign") : ""
if (zipAlignFlag == null || zipAlignFlag.isEmpty()) {
- zipAlignFlag = "false"
+ if (isAndroidStudio()) {
+ zipAlignFlag = "true"
+ } else {
+ zipAlignFlag = "false"
+ }
}
return Boolean.parseBoolean(zipAlignFlag)
}
@@ -170,7 +229,15 @@ ext.shouldZipAlign = { ->
ext.shouldSign = { ->
String signFlag = project.hasProperty("perform_signing") ? project.property("perform_signing") : ""
if (signFlag == null || signFlag.isEmpty()) {
- signFlag = "false"
+ if (isAndroidStudio()) {
+ signFlag = "true"
+ } else {
+ signFlag = "false"
+ }
}
return Boolean.parseBoolean(signFlag)
}
+
+ext.shouldNotStrip = { ->
+ return isAndroidStudio()
+}
diff --git a/platform/android/java/app/res/drawable/splash_drawable.xml b/platform/android/java/app/res/drawable/splash_drawable.xml
index 2794a40817..30627b998c 100644
--- a/platform/android/java/app/res/drawable/splash_drawable.xml
+++ b/platform/android/java/app/res/drawable/splash_drawable.xml
@@ -6,7 +6,7 @@
<item>
<bitmap
android:gravity="center"
+ android:filter="false"
android:src="@drawable/splash" />
</item>
-
</layer-list>
diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle
index 73c136ed0e..ec02b0fc7a 100644
--- a/platform/android/java/build.gradle
+++ b/platform/android/java/build.gradle
@@ -165,12 +165,6 @@ task cleanGodotTemplates(type: Delete) {
// Delete the library generated AAR files
delete("lib/build/outputs/aar")
- // Delete the godotpayment libs directory contents
- delete("plugins/godotpayment/libs")
-
- // Delete the generated godotpayment aar
- delete("plugins/godotpayment/build/outputs/aar")
-
// Delete the app libs directory contents
delete("app/libs")
diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml
index fa39bc0f1d..3034794d69 100644
--- a/platform/android/java/lib/AndroidManifest.xml
+++ b/platform/android/java/lib/AndroidManifest.xml
@@ -6,6 +6,11 @@
<application>
+ <!-- Records the version of the Godot library -->
+ <meta-data
+ android:name="org.godotengine.library.version"
+ android:value="${godotLibraryVersion}" />
+
<service android:name=".GodotDownloaderService" />
</application>
diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle
index 6260cadffb..663ba73d40 100644
--- a/platform/android/java/lib/build.gradle
+++ b/platform/android/java/lib/build.gradle
@@ -13,9 +13,13 @@ android {
compileSdkVersion versions.compileSdk
buildToolsVersion versions.buildTools
+ ndkVersion versions.ndkVersion
+
defaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
+
+ manifestPlaceholders = [godotLibraryVersion: getGodotLibraryVersion()]
}
compileOptions {
@@ -32,8 +36,10 @@ android {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
- // Should be uncommented for development purpose within Android Studio
- // doNotStrip '**/*.so'
+ // 'doNotStrip' is enabled for development within Android Studio
+ if (shouldNotStrip()) {
+ doNotStrip '**/*.so'
+ }
}
sourceSets {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
index 4e67402c63..ec2ace4821 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
@@ -34,6 +34,7 @@ import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
+import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
@@ -44,7 +45,7 @@ import androidx.fragment.app.FragmentActivity;
* It's also a reference implementation for how to setup and use the {@link Godot} fragment
* within an Android app.
*/
-public abstract class FullScreenGodotApp extends FragmentActivity {
+public abstract class FullScreenGodotApp extends FragmentActivity implements GodotHost {
@Nullable
private Godot godotFragment;
@@ -64,6 +65,28 @@ public abstract class FullScreenGodotApp extends FragmentActivity {
public void onNewIntent(Intent intent) {
if (godotFragment != null) {
godotFragment.onNewIntent(intent);
+ } else {
+ super.onNewIntent(intent);
+ }
+ }
+
+ @CallSuper
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (godotFragment != null) {
+ godotFragment.onActivityResult(requestCode, resultCode, data);
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+ @CallSuper
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ if (godotFragment != null) {
+ godotFragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ } else {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
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 7d396b402e..0c16214c8a 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -103,6 +103,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.MessageDigest;
+import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
@@ -131,6 +132,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
private boolean activityResumed;
private int mState;
+ private GodotHost godotHost;
private GodotPluginRegistry pluginRegistry;
static private Intent mCurrentIntent;
@@ -178,7 +180,25 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
public ResultCallback result_callback;
@Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if (getParentFragment() instanceof GodotHost) {
+ godotHost = (GodotHost)getParentFragment();
+ } else if (getActivity() instanceof GodotHost) {
+ godotHost = (GodotHost)getActivity();
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ godotHost = null;
+ }
+
+ @CallSuper
+ @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
if (result_callback != null) {
result_callback.callback(requestCode, resultCode, data);
result_callback = null;
@@ -189,8 +209,10 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
}
}
+ @CallSuper
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
plugin.onMainRequestPermissionsResult(requestCode, permissions, grantResults);
}
@@ -201,6 +223,20 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
};
/**
+ * Invoked on the render thread when the Godot setup is complete.
+ */
+ @CallSuper
+ protected void onGodotSetupCompleted() {
+ for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
+ plugin.onGodotSetupCompleted();
+ }
+
+ if (godotHost != null) {
+ godotHost.onGodotSetupCompleted();
+ }
+ }
+
+ /**
* Invoked on the render thread when the Godot main loop has started.
*/
@CallSuper
@@ -208,6 +244,10 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
plugin.onGodotMainLoopStarted();
}
+
+ if (godotHost != null) {
+ godotHost.onGodotMainLoopStarted();
+ }
}
/**
@@ -228,7 +268,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
GodotLib.setup(command_line);
- final String videoDriver = GodotLib.getGlobal("rendering/quality/driver/driver_name");
+ final String videoDriver = GodotLib.getGlobal("rendering/driver/driver_name");
if (videoDriver.equals("Vulkan")) {
mRenderView = new GodotVulkanRenderView(activity, this);
} else {
@@ -301,7 +341,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(durationMs, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
- //deprecated in API 26
+ // deprecated in API 26
v.vibrate(durationMs);
}
}
@@ -356,6 +396,21 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
@CallSuper
protected String[] getCommandLine() {
+ String[] original = parseCommandLine();
+ String[] updated;
+ List<String> hostCommandLine = godotHost != null ? godotHost.getCommandLine() : null;
+ if (hostCommandLine == null || hostCommandLine.isEmpty()) {
+ updated = original;
+ } else {
+ updated = Arrays.copyOf(original, original.length + hostCommandLine.size());
+ for (int i = 0; i < hostCommandLine.size(); i++) {
+ updated[original.length + i] = hostCommandLine.get(i);
+ }
+ }
+ return updated;
+ }
+
+ private String[] parseCommandLine() {
InputStream is;
try {
is = getActivity().getAssets().open("_cl_");
@@ -464,14 +519,16 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle) {
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
final Activity activity = getActivity();
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
mClipboard = (ClipboardManager)activity.getSystemService(Context.CLIPBOARD_SERVICE);
pluginRegistry = GodotPluginRegistry.initializePluginRegistry(this);
- //check for apk expansion API
+ // check for apk expansion API
boolean md5mismatch = false;
command_line = getCommandLine();
String main_pack_md5 = null;
@@ -527,9 +584,9 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
command_line = new_args.toArray(new String[new_args.size()]);
}
if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) {
- //check that environment is ok!
+ // check that environment is ok!
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- //show popup and die
+ // show popup and die
}
// Build the full path to the app's expansion files
@@ -572,24 +629,11 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
// This is where you do set up to display the download
- // progress (next step)
+ // progress (next step in onCreateView)
mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
GodotDownloaderService.class);
- View downloadingExpansionView =
- inflater.inflate(R.layout.downloading_expansion, container, false);
- mPB = (ProgressBar)downloadingExpansionView.findViewById(R.id.progressBar);
- mStatusText = (TextView)downloadingExpansionView.findViewById(R.id.statusText);
- mProgressFraction = (TextView)downloadingExpansionView.findViewById(R.id.progressAsFraction);
- mProgressPercent = (TextView)downloadingExpansionView.findViewById(R.id.progressAsPercentage);
- mAverageSpeed = (TextView)downloadingExpansionView.findViewById(R.id.progressAverageSpeed);
- mTimeRemaining = (TextView)downloadingExpansionView.findViewById(R.id.progressTimeRemaining);
- mDashboard = downloadingExpansionView.findViewById(R.id.downloaderDashboard);
- mCellMessage = downloadingExpansionView.findViewById(R.id.approveCellular);
- mPauseButton = (Button)downloadingExpansionView.findViewById(R.id.pauseButton);
- mWiFiSettingsButton = (Button)downloadingExpansionView.findViewById(R.id.wifiSettingsButton);
-
- return downloadingExpansionView;
+ return;
}
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
@@ -600,6 +644,27 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
mCurrentIntent = activity.getIntent();
initializeGodot();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle) {
+ if (mDownloaderClientStub != null) {
+ View downloadingExpansionView =
+ inflater.inflate(R.layout.downloading_expansion, container, false);
+ mPB = (ProgressBar)downloadingExpansionView.findViewById(R.id.progressBar);
+ mStatusText = (TextView)downloadingExpansionView.findViewById(R.id.statusText);
+ mProgressFraction = (TextView)downloadingExpansionView.findViewById(R.id.progressAsFraction);
+ mProgressPercent = (TextView)downloadingExpansionView.findViewById(R.id.progressAsPercentage);
+ mAverageSpeed = (TextView)downloadingExpansionView.findViewById(R.id.progressAverageSpeed);
+ mTimeRemaining = (TextView)downloadingExpansionView.findViewById(R.id.progressTimeRemaining);
+ mDashboard = downloadingExpansionView.findViewById(R.id.downloaderDashboard);
+ mCellMessage = downloadingExpansionView.findViewById(R.id.approveCellular);
+ mPauseButton = (Button)downloadingExpansionView.findViewById(R.id.pauseButton);
+ mWiFiSettingsButton = (Button)downloadingExpansionView.findViewById(R.id.wifiSettingsButton);
+
+ return downloadingExpansionView;
+ }
+
return containerLayout;
}
diff --git a/scene/3d/navigation_3d.h b/platform/android/java/lib/src/org/godotengine/godot/GodotHost.java
index 3e8adaf5ff..317fd13535 100644
--- a/scene/3d/navigation_3d.h
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotHost.java
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* navigation_3d.h */
+/* GodotHost.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,51 +28,29 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NAVIGATION_3D_H
-#define NAVIGATION_3D_H
+package org.godotengine.godot;
-#include "scene/3d/navigation_region_3d.h"
-#include "scene/3d/node_3d.h"
+import java.util.Collections;
+import java.util.List;
-class Navigation3D : public Node3D {
- GDCLASS(Navigation3D, Node3D);
-
- RID map;
-
- Vector3 up;
- real_t cell_size;
- real_t edge_connection_margin;
-
-protected:
- static void _bind_methods();
- void _notification(int p_what);
-
-public:
- RID get_rid() const {
- return map;
- }
-
- void set_up_vector(const Vector3 &p_up);
- Vector3 get_up_vector() const;
-
- void set_cell_size(float p_cell_size);
- float get_cell_size() const {
- return cell_size;
+/**
+ * Denotate a component (e.g: Activity, Fragment) that hosts the {@link Godot} fragment.
+ */
+public interface GodotHost {
+ /**
+ * Provides a set of command line parameters to setup the engine.
+ */
+ default List<String> getCommandLine() {
+ return Collections.emptyList();
}
- void set_edge_connection_margin(float p_edge_connection_margin);
- float get_edge_connection_margin() const {
- return edge_connection_margin;
- }
-
- Vector<Vector3> get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize = true) const;
- Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision = false) const;
- Vector3 get_closest_point(const Vector3 &p_point) const;
- Vector3 get_closest_point_normal(const Vector3 &p_point) const;
- RID get_closest_point_owner(const Vector3 &p_point) const;
-
- Navigation3D();
- ~Navigation3D();
-};
+ /**
+ * Invoked on the render thread when the Godot setup is complete.
+ */
+ default void onGodotSetupCompleted() {}
-#endif // NAVIGATION_H
+ /**
+ * Invoked on the render thread when the Godot main loop has started.
+ */
+ default void onGodotMainLoopStarted() {}
+}
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 3368363ce7..435b8b325f 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
@@ -38,6 +38,8 @@ import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener;
import android.os.Build;
import android.util.Log;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.InputDevice;
import android.view.InputDevice.MotionRange;
import android.view.KeyEvent;
@@ -46,17 +48,24 @@ import android.view.MotionEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* Handles input related events for the {@link GodotRenderView} view.
*/
public class GodotInputHandler implements InputDeviceListener {
- private final ArrayList<Joystick> mJoysticksDevices = new ArrayList<Joystick>();
-
private final GodotRenderView mRenderView;
private final InputManagerCompat mInputManager;
+ private final String tag = this.getClass().getSimpleName();
+
+ private final SparseIntArray mJoystickIds = new SparseIntArray(4);
+ private final SparseArray<Joystick> mJoysticksDevices = new SparseArray<Joystick>(4);
+
public GodotInputHandler(GodotRenderView godotView) {
mRenderView = godotView;
mInputManager = InputManagerCompat.Factory.getInputManager(mRenderView.getView().getContext());
@@ -82,19 +91,20 @@ public class GodotInputHandler implements InputDeviceListener {
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
return false;
- };
+ }
int source = event.getSource();
if (isKeyEvent_GameDevice(source)) {
- final int button = getGodotButton(keyCode);
- final int device_id = findJoystickDevice(event.getDeviceId());
-
// Check if the device exists
- if (device_id > -1) {
+ final int deviceId = event.getDeviceId();
+ if (mJoystickIds.indexOfKey(deviceId) >= 0) {
+ final int button = getGodotButton(keyCode);
+ final int godotJoyId = mJoystickIds.get(deviceId);
+
queueEvent(new Runnable() {
@Override
public void run() {
- GodotLib.joybutton(device_id, button, false);
+ GodotLib.joybutton(godotJoyId, button, false);
}
});
}
@@ -107,7 +117,7 @@ public class GodotInputHandler implements InputDeviceListener {
GodotLib.key(keyCode, scanCode, chr, false);
}
});
- };
+ }
return true;
}
@@ -122,24 +132,25 @@ public class GodotInputHandler implements InputDeviceListener {
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
return false;
- };
+ }
int source = event.getSource();
//Log.e(TAG, String.format("Key down! source %d, device %d, joystick %d, %d, %d", event.getDeviceId(), source, (source & InputDevice.SOURCE_JOYSTICK), (source & InputDevice.SOURCE_DPAD), (source & InputDevice.SOURCE_GAMEPAD)));
+ final int deviceId = event.getDeviceId();
+ // Check if source is a game device and that the device is a registered gamepad
if (isKeyEvent_GameDevice(source)) {
if (event.getRepeatCount() > 0) // ignore key echo
return true;
- final int button = getGodotButton(keyCode);
- final int device_id = findJoystickDevice(event.getDeviceId());
+ if (mJoystickIds.indexOfKey(deviceId) >= 0) {
+ final int button = getGodotButton(keyCode);
+ final int godotJoyId = mJoystickIds.get(deviceId);
- // Check if the device exists
- if (device_id > -1) {
queueEvent(new Runnable() {
@Override
public void run() {
- GodotLib.joybutton(device_id, button, true);
+ GodotLib.joybutton(godotJoyId, button, true);
}
});
}
@@ -152,7 +163,7 @@ public class GodotInputHandler implements InputDeviceListener {
GodotLib.key(keyCode, scanCode, chr, true);
}
});
- };
+ }
return true;
}
@@ -203,38 +214,52 @@ public class GodotInputHandler implements InputDeviceListener {
}
public boolean onGenericMotionEvent(MotionEvent event) {
- if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) {
- final int device_id = findJoystickDevice(event.getDeviceId());
-
+ if (event.isFromSource(InputDevice.SOURCE_JOYSTICK) && event.getAction() == MotionEvent.ACTION_MOVE) {
// Check if the device exists
- if (device_id > -1) {
- Joystick joy = mJoysticksDevices.get(device_id);
-
- for (int i = 0; i < joy.axes.size(); i++) {
- InputDevice.MotionRange range = joy.axes.get(i);
- final float value = (event.getAxisValue(range.getAxis()) - range.getMin()) / range.getRange() * 2.0f - 1.0f;
- final int idx = i;
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.joyaxis(device_id, idx, value);
- }
- });
+ final int deviceId = event.getDeviceId();
+ if (mJoystickIds.indexOfKey(deviceId) >= 0) {
+ final int godotJoyId = mJoystickIds.get(deviceId);
+ Joystick joystick = mJoysticksDevices.get(deviceId);
+
+ for (int i = 0; i < joystick.axes.size(); i++) {
+ final int axis = joystick.axes.get(i);
+ final float value = event.getAxisValue(axis);
+ /**
+ * As all axes are polled for each event, only fire an axis event if the value has actually changed.
+ * Prevents flooding Godot with repeated events.
+ */
+ if (joystick.axesValues.indexOfKey(axis) < 0 || (float)joystick.axesValues.get(axis) != value) {
+ // save value to prevent repeats
+ joystick.axesValues.put(axis, value);
+ final int godotAxisIdx = i;
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.joyaxis(godotJoyId, godotAxisIdx, value);
+ //Log.i(tag, "GodotLib.joyaxis("+godotJoyId+", "+godotAxisIdx+", "+value+");");
+ }
+ });
+ }
}
- for (int i = 0; i < joy.hats.size(); i += 2) {
- final int hatX = Math.round(event.getAxisValue(joy.hats.get(i).getAxis()));
- final int hatY = Math.round(event.getAxisValue(joy.hats.get(i + 1).getAxis()));
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.joyhat(device_id, hatX, hatY);
- }
- });
+ if (joystick.hasAxisHat) {
+ final int hatX = Math.round(event.getAxisValue(MotionEvent.AXIS_HAT_X));
+ final int hatY = Math.round(event.getAxisValue(MotionEvent.AXIS_HAT_Y));
+ if (joystick.hatX != hatX || joystick.hatY != hatY) {
+ joystick.hatX = hatX;
+ joystick.hatY = hatY;
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.joyhat(godotJoyId, hatX, hatY);
+ //Log.i(tag, "GodotLib.joyhat("+godotJoyId+", "+hatX+", "+hatY+");");
+ }
+ });
+ }
}
return true;
}
- } else if ((event.getSource() & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS) {
+ } else if (event.isFromSource(InputDevice.SOURCE_STYLUS)) {
final float x = event.getX();
final float y = event.getY();
final int type = event.getAction();
@@ -245,6 +270,7 @@ public class GodotInputHandler implements InputDeviceListener {
}
});
return true;
+
} else if (event.isFromSource(InputDevice.SOURCE_MOUSE) || event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return handleMouseEvent(event);
@@ -266,67 +292,98 @@ public class GodotInputHandler implements InputDeviceListener {
}
}
+ private int assignJoystickIdNumber(int deviceId) {
+ int godotJoyId = 0;
+ while (mJoystickIds.indexOfValue(godotJoyId) >= 0) {
+ godotJoyId++;
+ }
+ mJoystickIds.put(deviceId, godotJoyId);
+ return godotJoyId;
+ }
+
@Override
public void onInputDeviceAdded(int deviceId) {
- int id = findJoystickDevice(deviceId);
-
// Check if the device has not been already added
- if (id < 0) {
- InputDevice device = mInputManager.getInputDevice(deviceId);
- //device can be null if deviceId is not found
- if (device != null) {
- int sources = device.getSources();
- if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) ||
- ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)) {
- id = mJoysticksDevices.size();
-
- Joystick joy = new Joystick();
- joy.device_id = deviceId;
- joy.name = device.getName();
- joy.axes = new ArrayList<InputDevice.MotionRange>();
- joy.hats = new ArrayList<InputDevice.MotionRange>();
-
- List<InputDevice.MotionRange> ranges = device.getMotionRanges();
- Collections.sort(ranges, new RangeComparator());
-
- for (InputDevice.MotionRange range : ranges) {
- if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
- joy.hats.add(range);
- } else {
- joy.axes.add(range);
- }
- }
- mJoysticksDevices.add(joy);
+ if (mJoystickIds.indexOfKey(deviceId) >= 0) {
+ return;
+ }
+
+ InputDevice device = mInputManager.getInputDevice(deviceId);
+ //device can be null if deviceId is not found
+ if (device == null) {
+ return;
+ }
+
+ int sources = device.getSources();
+
+ // Device may not be a joystick or gamepad
+ if ((sources & InputDevice.SOURCE_GAMEPAD) != InputDevice.SOURCE_GAMEPAD &&
+ (sources & InputDevice.SOURCE_JOYSTICK) != InputDevice.SOURCE_JOYSTICK) {
+ return;
+ }
+
+ // Assign first available number. Re-use numbers where possible.
+ final int id = assignJoystickIdNumber(deviceId);
+
+ final Joystick joystick = new Joystick();
+ joystick.device_id = deviceId;
+ joystick.name = device.getName();
+
+ //Helps with creating new joypad mappings.
+ Log.i(tag, "=== New Input Device: " + joystick.name);
- final int device_id = id;
- final String name = joy.name;
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.joyconnectionchanged(device_id, true, name);
- }
- });
+ Set<Integer> already = new HashSet<Integer>();
+ for (InputDevice.MotionRange range : device.getMotionRanges()) {
+ boolean isJoystick = range.isFromSource(InputDevice.SOURCE_JOYSTICK);
+ boolean isGamepad = range.isFromSource(InputDevice.SOURCE_GAMEPAD);
+ //Log.i(tag, "axis: "+range.getAxis()+ ", isJoystick: "+isJoystick+", isGamepad: "+isGamepad);
+ if (!isJoystick && !isGamepad) {
+ continue;
+ }
+ final int axis = range.getAxis();
+ if (axis == MotionEvent.AXIS_HAT_X || axis == MotionEvent.AXIS_HAT_Y) {
+ joystick.hasAxisHat = true;
+ } else {
+ if (!already.contains(axis)) {
+ already.add(axis);
+ joystick.axes.add(axis);
+ } else {
+ Log.w(tag, " - DUPLICATE AXIS VALUE IN LIST: " + axis);
}
}
}
+ Collections.sort(joystick.axes);
+ for (int idx = 0; idx < joystick.axes.size(); idx++) {
+ //Helps with creating new joypad mappings.
+ Log.i(tag, " - Mapping Android axis " + joystick.axes.get(idx) + " to Godot axis " + idx);
+ }
+ mJoysticksDevices.put(deviceId, joystick);
+
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.joyconnectionchanged(id, true, joystick.name);
+ }
+ });
}
@Override
public void onInputDeviceRemoved(int deviceId) {
- final int device_id = findJoystickDevice(deviceId);
-
- // Check if the evice has not been already removed
- if (device_id > -1) {
- mJoysticksDevices.remove(device_id);
-
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.joyconnectionchanged(device_id, false, "");
- }
- });
+ // Check if the device has not been already removed
+ if (mJoystickIds.indexOfKey(deviceId) < 0) {
+ return;
}
+ final int godotJoyId = mJoystickIds.get(deviceId);
+ mJoystickIds.delete(deviceId);
+ mJoysticksDevices.delete(deviceId);
+
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.joyconnectionchanged(godotJoyId, false, "");
+ }
+ });
}
@Override
@@ -407,16 +464,6 @@ public class GodotInputHandler implements InputDeviceListener {
return button;
}
- private int findJoystickDevice(int device_id) {
- for (int i = 0; i < mJoysticksDevices.size(); i++) {
- if (mJoysticksDevices.get(i).device_id == device_id) {
- return i;
- }
- }
-
- return -1;
- }
-
private boolean handleMouseEvent(final MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_HOVER_ENTER:
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java b/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java
index 82bd45ee3f..4b7318c718 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java
@@ -30,9 +30,10 @@
package org.godotengine.godot.input;
-import android.view.InputDevice.MotionRange;
+import android.util.SparseArray;
import java.util.ArrayList;
+import java.util.List;
/**
* POJO class to represent a Joystick input device.
@@ -40,6 +41,12 @@ import java.util.ArrayList;
class Joystick {
int device_id;
String name;
- ArrayList<MotionRange> axes;
- ArrayList<MotionRange> hats;
+ List<Integer> axes = new ArrayList<Integer>();
+ protected boolean hasAxisHat = false;
+ /*
+ * Keep track of values so we can prevent flooding the engine with useless events.
+ */
+ protected final SparseArray axesValues = new SparseArray<Float>(4);
+ protected int hatX;
+ protected int hatY;
}
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 a22b80761d..6c8a3d4219 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
@@ -46,7 +46,10 @@ import androidx.annotation.Nullable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -107,23 +110,52 @@ public abstract class GodotPlugin {
* This method is invoked on the render thread.
*/
public final void onRegisterPluginWithGodotNative() {
- nativeRegisterSingleton(getPluginName());
+ registeredSignals.putAll(
+ registerPluginWithGodotNative(this, getPluginName(), getPluginMethods(), getPluginSignals(),
+ getPluginGDNativeLibrariesPaths()));
+ }
+
+ /**
+ * Register the plugin with Godot native code.
+ *
+ * This method must be invoked on the render thread.
+ */
+ public static void registerPluginWithGodotNative(Object pluginObject,
+ GodotPluginInfoProvider pluginInfoProvider) {
+ registerPluginWithGodotNative(pluginObject, pluginInfoProvider.getPluginName(),
+ Collections.emptyList(), pluginInfoProvider.getPluginSignals(),
+ pluginInfoProvider.getPluginGDNativeLibrariesPaths());
+
+ // Notify that registration is complete.
+ pluginInfoProvider.onPluginRegistered();
+ }
+
+ private static Map<String, SignalInfo> registerPluginWithGodotNative(Object pluginObject,
+ String pluginName, List<String> pluginMethods, Set<SignalInfo> pluginSignals,
+ Set<String> pluginGDNativeLibrariesPaths) {
+ nativeRegisterSingleton(pluginName, pluginObject);
+
+ Set<Method> filteredMethods = new HashSet<>();
+ Class clazz = pluginObject.getClass();
- Class clazz = getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
- boolean found = false;
-
- for (String s : getPluginMethods()) {
- if (s.equals(method.getName())) {
- found = true;
- break;
+ // Check if the method is annotated with {@link UsedByGodot}.
+ if (method.getAnnotation(UsedByGodot.class) != null) {
+ filteredMethods.add(method);
+ } else {
+ // For backward compatibility, process the methods from the given <pluginMethods> argument.
+ for (String methodName : pluginMethods) {
+ if (methodName.equals(method.getName())) {
+ filteredMethods.add(method);
+ break;
+ }
}
}
- if (!found)
- continue;
+ }
- List<String> ptr = new ArrayList<String>();
+ for (Method method : filteredMethods) {
+ List<String> ptr = new ArrayList<>();
Class[] paramTypes = method.getParameterTypes();
for (Class c : paramTypes) {
@@ -133,26 +165,28 @@ public abstract class GodotPlugin {
String[] pt = new String[ptr.size()];
ptr.toArray(pt);
- nativeRegisterMethod(getPluginName(), method.getName(), method.getReturnType().getName(), pt);
+ nativeRegisterMethod(pluginName, method.getName(), method.getReturnType().getName(), pt);
}
// Register the signals for this plugin.
- for (SignalInfo signalInfo : getPluginSignals()) {
+ Map<String, SignalInfo> registeredSignals = new HashMap<>();
+ for (SignalInfo signalInfo : pluginSignals) {
String signalName = signalInfo.getName();
- nativeRegisterSignal(getPluginName(), signalName, signalInfo.getParamTypesNames());
+ nativeRegisterSignal(pluginName, signalName, signalInfo.getParamTypesNames());
registeredSignals.put(signalName, signalInfo);
}
// Get the list of gdnative libraries to register.
- Set<String> gdnativeLibrariesPaths = getPluginGDNativeLibrariesPaths();
- if (!gdnativeLibrariesPaths.isEmpty()) {
- nativeRegisterGDNativeLibraries(gdnativeLibrariesPaths.toArray(new String[0]));
+ if (!pluginGDNativeLibrariesPaths.isEmpty()) {
+ nativeRegisterGDNativeLibraries(pluginGDNativeLibrariesPaths.toArray(new String[0]));
}
+
+ return registeredSignals;
}
/**
* Invoked once during the Godot Android initialization process after creation of the
- * {@link org.godotengine.godot.GodotView} view.
+ * {@link org.godotengine.godot.GodotRenderView} view.
* <p>
* The plugin can return a non-null {@link View} layout in order to add it to the Godot view
* hierarchy.
@@ -198,6 +232,11 @@ public abstract class GodotPlugin {
public boolean onMainBackPressed() { return false; }
/**
+ * Invoked on the render thread when the Godot setup is complete.
+ */
+ public void onGodotSetupCompleted() {}
+
+ /**
* Invoked on the render thread when the Godot main loop has started.
*/
public void onGodotMainLoopStarted() {}
@@ -244,8 +283,11 @@ public abstract class GodotPlugin {
/**
* Returns the list of methods to be exposed to Godot.
+ *
+ * @deprecated Used the {@link UsedByGodot} annotation instead.
*/
@NonNull
+ @Deprecated
public List<String> getPluginMethods() {
return Collections.emptyList();
}
@@ -290,8 +332,8 @@ public abstract class GodotPlugin {
/**
* Emit a registered Godot signal.
- * @param signalName
- * @param signalArgs
+ * @param signalName Name of the signal to emit. It will be validated against the set of registered signals.
+ * @param signalArgs Arguments used to populate the emitted signal. The arguments will be validated against the {@link SignalInfo} matching the registered signalName parameter.
*/
protected void emitSignal(final String signalName, final Object... signalArgs) {
try {
@@ -301,6 +343,27 @@ public abstract class GodotPlugin {
throw new IllegalArgumentException(
"Signal " + signalName + " is not registered for this plugin.");
}
+ emitSignal(getGodot(), getPluginName(), signalInfo, signalArgs);
+ } catch (IllegalArgumentException exception) {
+ Log.w(TAG, exception.getMessage());
+ if (BuildConfig.DEBUG) {
+ throw exception;
+ }
+ }
+ }
+
+ /**
+ * Emit a Godot signal.
+ * @param godot
+ * @param pluginName Name of the Godot plugin the signal will be emitted from. The plugin must already be registered with the Godot engine.
+ * @param signalInfo Information about the signal to emit.
+ * @param signalArgs Arguments used to populate the emitted signal. The arguments will be validated against the given {@link SignalInfo} parameter.
+ */
+ public static void emitSignal(Godot godot, String pluginName, SignalInfo signalInfo, final Object... signalArgs) {
+ try {
+ if (signalInfo == null) {
+ throw new IllegalArgumentException("Signal must be non null.");
+ }
// Validate the arguments count.
Class<?>[] signalParamTypes = signalInfo.getParamTypes();
@@ -317,12 +380,8 @@ public abstract class GodotPlugin {
}
}
- runOnRenderThread(new Runnable() {
- @Override
- public void run() {
- nativeEmitSignal(getPluginName(), signalName, signalArgs);
- }
- });
+ godot.runOnRenderThread(() -> nativeEmitSignal(pluginName, signalInfo.getName(), signalArgs));
+
} catch (IllegalArgumentException exception) {
Log.w(TAG, exception.getMessage());
if (BuildConfig.DEBUG) {
@@ -335,7 +394,7 @@ public abstract class GodotPlugin {
* Used to setup a {@link GodotPlugin} instance.
* @param p_name Name of the instance.
*/
- private native void nativeRegisterSingleton(String p_name);
+ private static native void nativeRegisterSingleton(String p_name, Object object);
/**
* Used to complete registration of the {@link GodotPlugin} instance's methods.
@@ -344,13 +403,13 @@ public abstract class GodotPlugin {
* @param p_ret Return type of the registered method
* @param p_params Method parameters types
*/
- private native void nativeRegisterMethod(String p_sname, String p_name, String p_ret, String[] p_params);
+ 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.
*/
- private native void nativeRegisterGDNativeLibraries(String[] gdnlibPaths);
+ private static native void nativeRegisterGDNativeLibraries(String[] gdnlibPaths);
/**
* Used to complete registration of the {@link GodotPlugin} instance's methods.
@@ -358,7 +417,7 @@ public abstract class GodotPlugin {
* @param signalName Name of the signal to register
* @param signalParamTypes Signal parameters types
*/
- private native void nativeRegisterSignal(String pluginName, String signalName, String[] signalParamTypes);
+ private static native void nativeRegisterSignal(String pluginName, String signalName, String[] signalParamTypes);
/**
* Used to emit signal by {@link GodotPlugin} instance.
@@ -366,5 +425,5 @@ public abstract class GodotPlugin {
* @param signalName Name of the signal to emit
* @param signalParams Signal parameters
*/
- private native void nativeEmitSignal(String pluginName, String signalName, Object[] signalParams);
+ private static native void nativeEmitSignal(String pluginName, String signalName, Object[] signalParams);
}
diff --git a/scene/2d/navigation_2d.h b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java
index 12847e52ac..09366384c2 100644
--- a/scene/2d/navigation_2d.h
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* navigation_2d.h */
+/* GodotPluginInfoProvider.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,44 +28,45 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NAVIGATION_2D_H
-#define NAVIGATION_2D_H
+package org.godotengine.godot.plugin;
-#include "scene/2d/navigation_region_2d.h"
-#include "scene/2d/node_2d.h"
+import androidx.annotation.NonNull;
-class Navigation2D : public Node2D {
- GDCLASS(Navigation2D, Node2D);
+import java.util.Collections;
+import java.util.Set;
- RID map;
- real_t cell_size;
- real_t edge_connection_margin;
+/**
+ * Provides the set of information expected from a Godot plugin.
+ */
+public interface GodotPluginInfoProvider {
+ /**
+ * Returns the name of the plugin.
+ */
+ @NonNull
+ String getPluginName();
-protected:
- static void _bind_methods();
- void _notification(int p_what);
-
-public:
- RID get_rid() const {
- return map;
+ /**
+ * Returns the list of signals to be exposed to Godot.
+ */
+ @NonNull
+ default Set<SignalInfo> getPluginSignals() {
+ return Collections.emptySet();
}
- void set_cell_size(float p_cell_size);
- float get_cell_size() const {
- return cell_size;
+ /**
+ * Returns the paths for the plugin's gdnative libraries (if any).
+ *
+ * The paths must be relative to the 'assets' directory and point to a '*.gdnlib' file.
+ */
+ @NonNull
+ default Set<String> getPluginGDNativeLibrariesPaths() {
+ return Collections.emptySet();
}
- void set_edge_connection_margin(float p_edge_connection_margin);
- float get_edge_connection_margin() const {
- return edge_connection_margin;
+ /**
+ * This is invoked on the render thread when the plugin described by this instance has been
+ * registered.
+ */
+ default void onPluginRegistered() {
}
-
- Vector<Vector2> get_simple_path(const Vector2 &p_start, const Vector2 &p_end, bool p_optimize = true) const;
- Vector2 get_closest_point(const Vector2 &p_point) const;
- RID get_closest_point_owner(const Vector2 &p_point) const;
-
- Navigation2D();
- ~Navigation2D();
-};
-
-#endif // NAVIGATION_2D_H
+}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
index 99811f72ed..5b41205253 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
@@ -44,8 +44,6 @@ import androidx.annotation.Nullable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -56,13 +54,6 @@ public final class GodotPluginRegistry {
private static final String GODOT_PLUGIN_V1_NAME_PREFIX = "org.godotengine.plugin.v1.";
- /**
- * Name for the metadata containing the list of Godot plugins to enable.
- */
- private static final String GODOT_ENABLED_PLUGINS_LABEL = "plugins";
-
- private static final String PLUGIN_VALUE_SEPARATOR_REGEX = "\\|";
-
private static GodotPluginRegistry instance;
private final ConcurrentHashMap<String, GodotPlugin> registry;
@@ -132,37 +123,11 @@ public final class GodotPluginRegistry {
return;
}
- // When using the Godot editor for building and exporting the apk, this is used to check
- // which plugins to enable.
- // When using a custom process to generate the apk, the metadata is not needed since
- // it's assumed that the developer is aware of the dependencies included in the apk.
- final Set<String> enabledPluginsSet;
- if (metaData.containsKey(GODOT_ENABLED_PLUGINS_LABEL)) {
- String enabledPlugins = metaData.getString(GODOT_ENABLED_PLUGINS_LABEL, "");
- String[] enabledPluginsList = enabledPlugins.split(PLUGIN_VALUE_SEPARATOR_REGEX);
- if (enabledPluginsList.length == 0) {
- // No plugins to enable. Aborting early.
- return;
- }
-
- enabledPluginsSet = new HashSet<>();
- for (String enabledPlugin : enabledPluginsList) {
- enabledPluginsSet.add(enabledPlugin.trim());
- }
- } else {
- enabledPluginsSet = null;
- }
-
int godotPluginV1NamePrefixLength = GODOT_PLUGIN_V1_NAME_PREFIX.length();
for (String metaDataName : metaData.keySet()) {
// Parse the meta-data looking for entry with the Godot plugin name prefix.
if (metaDataName.startsWith(GODOT_PLUGIN_V1_NAME_PREFIX)) {
String pluginName = metaDataName.substring(godotPluginV1NamePrefixLength).trim();
- if (enabledPluginsSet != null && !enabledPluginsSet.contains(pluginName)) {
- Log.w(TAG, "Plugin " + pluginName + " is listed in the dependencies but is not enabled.");
- continue;
- }
-
Log.i(TAG, "Initializing Godot plugin " + pluginName);
// Retrieve the plugin class full name.
@@ -177,8 +142,7 @@ public final class GodotPluginRegistry {
.getConstructor(Godot.class);
GodotPlugin pluginHandle = pluginConstructor.newInstance(godot);
- // Load the plugin initializer into the registry using the plugin name
- // as key.
+ // Load the plugin initializer into the registry using the plugin name as key.
if (!pluginName.equals(pluginHandle.getPluginName())) {
Log.w(TAG,
"Meta-data plugin name does not match the value returned by the plugin handle: " + pluginName + " =/= " + pluginHandle.getPluginName());
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/UsedByGodot.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/UsedByGodot.java
new file mode 100644
index 0000000000..04c091d944
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/UsedByGodot.java
@@ -0,0 +1,45 @@
+/*************************************************************************/
+/* UsedByGodot.java */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+package org.godotengine.godot.plugin;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to indicate a method is being invoked from the Godot game logic.
+ *
+ * At runtime, annotated plugin methods are detected and automatically registered.
+ */
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface UsedByGodot {}
diff --git a/platform/android/java/nativeSrcsConfigs/README.md b/platform/android/java/nativeSrcsConfigs/README.md
index e48505ccda..9d884415cc 100644
--- a/platform/android/java/nativeSrcsConfigs/README.md
+++ b/platform/android/java/nativeSrcsConfigs/README.md
@@ -1,4 +1,4 @@
## Native sources configs
-This is a non functional Android library used to provide Android Studio editor support to the Godot project native files.
+This is a non-functional Android library used to provide Android Studio editor support to the Godot project native files.
Nothing else should be added to this library.
diff --git a/platform/android/java/nativeSrcsConfigs/build.gradle b/platform/android/java/nativeSrcsConfigs/build.gradle
index 65b7bb9dc9..158bb2b98e 100644
--- a/platform/android/java/nativeSrcsConfigs/build.gradle
+++ b/platform/android/java/nativeSrcsConfigs/build.gradle
@@ -20,9 +20,6 @@ android {
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
-
- // Should be uncommented for development purpose within Android Studio
- // doNotStrip '**/*.so'
}
sourceSets {
@@ -31,6 +28,8 @@ android {
}
}
+ ndkVersion versions.ndkVersion
+
externalNativeBuild {
cmake {
path "CMakeLists.txt"
diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp
index ab03599dc3..f49b0e843a 100644
--- a/platform/android/java_class_wrapper.cpp
+++ b/platform/android/java_class_wrapper.cpp
@@ -38,6 +38,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
return false;
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, false);
MethodInfo *method = nullptr;
for (List<MethodInfo>::Element *E = M->get().front(); E; E = E->next()) {
@@ -965,6 +966,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
return class_cache[p_class];
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, Ref<JavaClass>());
jclass bclass = env->FindClass(p_class.utf8().get_data());
ERR_FAIL_COND_V(!bclass, Ref<JavaClass>());
@@ -1149,6 +1151,7 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) {
singleton = this;
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
jclass activityClass = env->FindClass("android/app/Activity");
jmethodID getClassLoader = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp
index 4ee4427aa0..ec3b6f8ac0 100644
--- a/platform/android/java_godot_io_wrapper.cpp
+++ b/platform/android/java_godot_io_wrapper.cpp
@@ -73,6 +73,7 @@ jobject GodotIOJavaWrapper::get_instance() {
Error GodotIOJavaWrapper::open_uri(const String &p_uri) {
if (_open_URI) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, ERR_UNAVAILABLE);
jstring jStr = env->NewStringUTF(p_uri.utf8().get_data());
return env->CallIntMethod(godot_io_instance, _open_URI, jStr) ? ERR_CANT_OPEN : OK;
} else {
@@ -83,6 +84,7 @@ Error GodotIOJavaWrapper::open_uri(const String &p_uri) {
String GodotIOJavaWrapper::get_user_data_dir() {
if (_get_data_dir) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, String());
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_data_dir);
return jstring_to_string(s, env);
} else {
@@ -93,6 +95,7 @@ String GodotIOJavaWrapper::get_user_data_dir() {
String GodotIOJavaWrapper::get_locale() {
if (_get_locale) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, String());
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_locale);
return jstring_to_string(s, env);
} else {
@@ -103,6 +106,7 @@ String GodotIOJavaWrapper::get_locale() {
String GodotIOJavaWrapper::get_model() {
if (_get_model) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, String());
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_model);
return jstring_to_string(s, env);
} else {
@@ -113,6 +117,7 @@ String GodotIOJavaWrapper::get_model() {
int GodotIOJavaWrapper::get_screen_dpi() {
if (_get_screen_DPI) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, 160);
return env->CallIntMethod(godot_io_instance, _get_screen_DPI);
} else {
return 160;
@@ -122,6 +127,7 @@ int GodotIOJavaWrapper::get_screen_dpi() {
void GodotIOJavaWrapper::screen_get_usable_rect(int (&p_rect_xywh)[4]) {
if (_screen_get_usable_rect) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
jintArray returnArray = (jintArray)env->CallObjectMethod(godot_io_instance, _screen_get_usable_rect);
ERR_FAIL_COND(env->GetArrayLength(returnArray) != 4);
jint *arrayBody = env->GetIntArrayElements(returnArray, JNI_FALSE);
@@ -135,6 +141,7 @@ void GodotIOJavaWrapper::screen_get_usable_rect(int (&p_rect_xywh)[4]) {
String GodotIOJavaWrapper::get_unique_id() {
if (_get_unique_id) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, String());
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_unique_id);
return jstring_to_string(s, env);
} else {
@@ -149,6 +156,7 @@ bool GodotIOJavaWrapper::has_vk() {
void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
if (_show_keyboard) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
jstring jStr = env->NewStringUTF(p_existing.utf8().get_data());
env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end);
}
@@ -157,6 +165,7 @@ void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int
void GodotIOJavaWrapper::hide_vk() {
if (_hide_keyboard) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
env->CallVoidMethod(godot_io_instance, _hide_keyboard);
}
}
@@ -164,6 +173,7 @@ void GodotIOJavaWrapper::hide_vk() {
void GodotIOJavaWrapper::set_screen_orientation(int p_orient) {
if (_set_screen_orientation) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
env->CallVoidMethod(godot_io_instance, _set_screen_orientation, p_orient);
}
}
@@ -171,6 +181,7 @@ void GodotIOJavaWrapper::set_screen_orientation(int p_orient) {
int GodotIOJavaWrapper::get_screen_orientation() {
if (_get_screen_orientation) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, 0);
return env->CallIntMethod(godot_io_instance, _get_screen_orientation);
} else {
return 0;
@@ -180,6 +191,7 @@ int GodotIOJavaWrapper::get_screen_orientation() {
String GodotIOJavaWrapper::get_system_dir(int p_dir) {
if (_get_system_dir) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, String("."));
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_system_dir, p_dir);
return jstring_to_string(s, env);
} else {
@@ -187,14 +199,14 @@ String GodotIOJavaWrapper::get_system_dir(int p_dir) {
}
}
-// volatile because it can be changed from non-main thread and we need to
+// SafeNumeric because it can be changed from non-main thread and we need to
// ensure the change is immediately visible to other threads.
-static volatile int virtual_keyboard_height;
+static SafeNumeric<int> virtual_keyboard_height;
int GodotIOJavaWrapper::get_vk_height() {
- return virtual_keyboard_height;
+ return virtual_keyboard_height.get();
}
void GodotIOJavaWrapper::set_vk_height(int p_height) {
- virtual_keyboard_height = p_height;
+ virtual_keyboard_height.set(p_height);
}
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index bb22162879..0c342dc280 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -127,9 +127,11 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc
if (p_cmdline) {
cmdlen = env->GetArrayLength(p_cmdline);
if (cmdlen) {
- cmdline = (const char **)malloc((cmdlen + 1) * sizeof(const char *));
+ cmdline = (const char **)memalloc((cmdlen + 1) * sizeof(const char *));
+ ERR_FAIL_NULL_MSG(cmdline, "Out of memory.");
cmdline[cmdlen] = nullptr;
- j_cmdline = (jstring *)malloc(cmdlen * sizeof(jstring));
+ j_cmdline = (jstring *)memalloc(cmdlen * sizeof(jstring));
+ ERR_FAIL_NULL_MSG(j_cmdline, "Out of memory.");
for (int i = 0; i < cmdlen; i++) {
jstring string = (jstring)env->GetObjectArrayElement(p_cmdline, i);
@@ -147,13 +149,13 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc
for (int i = 0; i < cmdlen; ++i) {
env->ReleaseStringUTFChars(j_cmdline[i], cmdline[i]);
}
- free(j_cmdline);
+ memfree(j_cmdline);
}
- free(cmdline);
+ memfree(cmdline);
}
if (err != OK) {
- return; //should exit instead and print the error
+ return; // should exit instead and print the error
}
java_class_wrapper = memnew(JavaClassWrapper(godot_java->get_activity()));
@@ -215,9 +217,10 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jcl
if (step == 1) {
if (!Main::start()) {
- return; //should exit instead and print the error
+ return; // should exit instead and print the error
}
+ godot_java->on_godot_setup_completed(env);
os_android->main_loop_begin();
godot_java->on_godot_main_loop_started(env);
++step;
diff --git a/platform/android/java_godot_view_wrapper.cpp b/platform/android/java_godot_view_wrapper.cpp
index 5b638300ef..6b5e44f371 100644
--- a/platform/android/java_godot_view_wrapper.cpp
+++ b/platform/android/java_godot_view_wrapper.cpp
@@ -34,6 +34,7 @@
GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
_godot_view = env->NewGlobalRef(godot_view);
@@ -48,6 +49,8 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) {
void GodotJavaViewWrapper::request_pointer_capture() {
if (_request_pointer_capture != 0) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+
env->CallVoidMethod(_godot_view, _request_pointer_capture);
}
}
@@ -55,12 +58,16 @@ void GodotJavaViewWrapper::request_pointer_capture() {
void GodotJavaViewWrapper::release_pointer_capture() {
if (_request_pointer_capture != 0) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+
env->CallVoidMethod(_godot_view, _release_pointer_capture);
}
}
GodotJavaViewWrapper::~GodotJavaViewWrapper() {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+
env->DeleteGlobalRef(_godot_view);
env->DeleteGlobalRef(_cls);
}
diff --git a/platform/android/java_godot_view_wrapper.h b/platform/android/java_godot_view_wrapper.h
index 548c278292..bfb4369fb8 100644
--- a/platform/android/java_godot_view_wrapper.h
+++ b/platform/android/java_godot_view_wrapper.h
@@ -34,6 +34,8 @@
#include <android/log.h>
#include <jni.h>
+#include "string_android.h"
+
// Class that makes functions in java/src/org/godotengine/godot/GodotView.java callable from C++
class GodotJavaViewWrapper {
private:
diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp
index 759980373a..bfd93345f3 100644
--- a/platform/android/java_godot_wrapper.cpp
+++ b/platform/android/java_godot_wrapper.cpp
@@ -74,6 +74,7 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_
_is_activity_resumed = p_env->GetMethodID(godot_class, "isActivityResumed", "()Z");
_vibrate = p_env->GetMethodID(godot_class, "vibrate", "(I)V");
_get_input_fallback_mapping = p_env->GetMethodID(godot_class, "getInputFallbackMapping", "()Ljava/lang/String;");
+ _on_godot_setup_completed = p_env->GetMethodID(godot_class, "onGodotSetupCompleted", "()V");
_on_godot_main_loop_started = p_env->GetMethodID(godot_class, "onGodotMainLoopStarted", "()V");
// get some Activity method pointers...
@@ -93,6 +94,8 @@ jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_cl
if (p_env == nullptr)
p_env = get_jni_env();
+ ERR_FAIL_COND_V(p_env == nullptr, nullptr);
+
jfieldID fid = p_env->GetStaticFieldID(godot_class, p_name, p_class);
return p_env->GetStaticObjectField(godot_class, fid);
} else {
@@ -103,6 +106,8 @@ jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_cl
jobject GodotJavaWrapper::get_class_loader() {
if (_get_class_loader) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, nullptr);
+
return env->CallObjectMethod(activity, _get_class_loader);
} else {
return nullptr;
@@ -114,17 +119,30 @@ GodotJavaViewWrapper *GodotJavaWrapper::get_godot_view() {
return _godot_view;
}
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, nullptr);
+
jmethodID godot_view_getter = env->GetMethodID(godot_class, "getRenderView", "()Lorg/godotengine/godot/GodotRenderView;");
_godot_view = new GodotJavaViewWrapper(env->CallObjectMethod(godot_instance, godot_view_getter));
return _godot_view;
}
void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
- if (_on_video_init)
+ if (_on_video_init) {
if (p_env == nullptr)
p_env = get_jni_env();
+ ERR_FAIL_COND(p_env == nullptr);
- p_env->CallVoidMethod(godot_instance, _on_video_init);
+ p_env->CallVoidMethod(godot_instance, _on_video_init);
+ }
+}
+
+void GodotJavaWrapper::on_godot_setup_completed(JNIEnv *p_env) {
+ if (_on_godot_setup_completed) {
+ if (p_env == nullptr) {
+ p_env = get_jni_env();
+ }
+ p_env->CallVoidMethod(godot_instance, _on_godot_setup_completed);
+ }
}
void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) {
@@ -132,29 +150,36 @@ void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) {
if (p_env == nullptr) {
p_env = get_jni_env();
}
+ ERR_FAIL_COND(p_env == nullptr);
+ p_env->CallVoidMethod(godot_instance, _on_godot_main_loop_started);
}
- p_env->CallVoidMethod(godot_instance, _on_godot_main_loop_started);
}
void GodotJavaWrapper::restart(JNIEnv *p_env) {
- if (_restart)
+ if (_restart) {
if (p_env == nullptr)
p_env = get_jni_env();
+ ERR_FAIL_COND(p_env == nullptr);
- p_env->CallVoidMethod(godot_instance, _restart);
+ p_env->CallVoidMethod(godot_instance, _restart);
+ }
}
void GodotJavaWrapper::force_quit(JNIEnv *p_env) {
- if (_finish)
+ if (_finish) {
if (p_env == nullptr)
p_env = get_jni_env();
+ ERR_FAIL_COND(p_env == nullptr);
- p_env->CallVoidMethod(godot_instance, _finish);
+ p_env->CallVoidMethod(godot_instance, _finish);
+ }
}
void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) {
if (_set_keep_screen_on) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+
env->CallVoidMethod(godot_instance, _set_keep_screen_on, p_enabled);
}
}
@@ -162,6 +187,8 @@ void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) {
void GodotJavaWrapper::alert(const String &p_message, const String &p_title) {
if (_alert) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+
jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data());
jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data());
env->CallVoidMethod(godot_instance, _alert, jStrMessage, jStrTitle);
@@ -170,6 +197,8 @@ void GodotJavaWrapper::alert(const String &p_message, const String &p_title) {
int GodotJavaWrapper::get_gles_version_code() {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, 0);
+
if (_get_GLES_version_code) {
return env->CallIntMethod(godot_instance, _get_GLES_version_code);
}
@@ -184,6 +213,8 @@ bool GodotJavaWrapper::has_get_clipboard() {
String GodotJavaWrapper::get_clipboard() {
if (_get_clipboard) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, String());
+
jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_clipboard);
return jstring_to_string(s, env);
} else {
@@ -194,6 +225,8 @@ String GodotJavaWrapper::get_clipboard() {
String GodotJavaWrapper::get_input_fallback_mapping() {
if (_get_input_fallback_mapping) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, String());
+
jstring fallback_mapping = (jstring)env->CallObjectMethod(godot_instance, _get_input_fallback_mapping);
return jstring_to_string(fallback_mapping, env);
} else {
@@ -208,6 +241,8 @@ bool GodotJavaWrapper::has_set_clipboard() {
void GodotJavaWrapper::set_clipboard(const String &p_text) {
if (_set_clipboard) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+
jstring jStr = env->NewStringUTF(p_text.utf8().get_data());
env->CallVoidMethod(godot_instance, _set_clipboard, jStr);
}
@@ -216,6 +251,8 @@ void GodotJavaWrapper::set_clipboard(const String &p_text) {
bool GodotJavaWrapper::request_permission(const String &p_name) {
if (_request_permission) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, false);
+
jstring jStrName = env->NewStringUTF(p_name.utf8().get_data());
return env->CallBooleanMethod(godot_instance, _request_permission, jStrName);
} else {
@@ -226,6 +263,8 @@ bool GodotJavaWrapper::request_permission(const String &p_name) {
bool GodotJavaWrapper::request_permissions() {
if (_request_permissions) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, false);
+
return env->CallBooleanMethod(godot_instance, _request_permissions);
} else {
return false;
@@ -236,6 +275,8 @@ Vector<String> GodotJavaWrapper::get_granted_permissions() const {
Vector<String> permissions_list;
if (_get_granted_permissions) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, permissions_list);
+
jobject permissions_object = env->CallObjectMethod(godot_instance, _get_granted_permissions);
jobjectArray *arr = reinterpret_cast<jobjectArray *>(&permissions_object);
@@ -254,6 +295,8 @@ Vector<String> GodotJavaWrapper::get_granted_permissions() const {
void GodotJavaWrapper::init_input_devices() {
if (_init_input_devices) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+
env->CallVoidMethod(godot_instance, _init_input_devices);
}
}
@@ -261,6 +304,8 @@ void GodotJavaWrapper::init_input_devices() {
jobject GodotJavaWrapper::get_surface() {
if (_get_surface) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, nullptr);
+
return env->CallObjectMethod(godot_instance, _get_surface);
} else {
return nullptr;
@@ -270,6 +315,8 @@ jobject GodotJavaWrapper::get_surface() {
bool GodotJavaWrapper::is_activity_resumed() {
if (_is_activity_resumed) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, false);
+
return env->CallBooleanMethod(godot_instance, _is_activity_resumed);
} else {
return false;
@@ -279,6 +326,8 @@ bool GodotJavaWrapper::is_activity_resumed() {
void GodotJavaWrapper::vibrate(int p_duration_ms) {
if (_vibrate) {
JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+
env->CallVoidMethod(godot_instance, _vibrate, p_duration_ms);
}
}
diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h
index 99a60dffa1..0e20747a16 100644
--- a/platform/android/java_godot_wrapper.h
+++ b/platform/android/java_godot_wrapper.h
@@ -66,6 +66,7 @@ private:
jmethodID _is_activity_resumed = 0;
jmethodID _vibrate = 0;
jmethodID _get_input_fallback_mapping = 0;
+ jmethodID _on_godot_setup_completed = 0;
jmethodID _on_godot_main_loop_started = 0;
jmethodID _get_class_loader = 0;
@@ -80,6 +81,7 @@ public:
GodotJavaViewWrapper *get_godot_view();
void on_video_init(JNIEnv *p_env = nullptr);
+ void on_godot_setup_completed(JNIEnv *p_env = nullptr);
void on_godot_main_loop_started(JNIEnv *p_env = nullptr);
void restart(JNIEnv *p_env = nullptr);
void force_quit(JNIEnv *p_env = nullptr);
diff --git a/platform/android/plugin/godot_plugin_jni.cpp b/platform/android/plugin/godot_plugin_jni.cpp
index f602e99e61..ba3e9fa20f 100644
--- a/platform/android/plugin/godot_plugin_jni.cpp
+++ b/platform/android/plugin/godot_plugin_jni.cpp
@@ -41,7 +41,7 @@ static HashMap<String, JNISingleton *> jni_singletons;
extern "C" {
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jobject obj, jstring name) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jclass clazz, jstring name, jobject obj) {
String singname = jstring_to_string(name, env);
JNISingleton *s = (JNISingleton *)ClassDB::instance("JNISingleton");
s->set_instance(env->NewGlobalRef(obj));
@@ -51,7 +51,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis
ProjectSettings::get_singleton()->set(singname, s);
}
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jclass clazz, jstring sname, jstring name, jstring ret, jobjectArray args) {
String singname = jstring_to_string(sname, env);
ERR_FAIL_COND(!jni_singletons.has(singname));
@@ -83,7 +83,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis
s->add_method(mname, mid, types, get_jni_type(retval));
}
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jobject obj, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types) {
+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) {
String singleton_name = jstring_to_string(j_plugin_name, env);
ERR_FAIL_COND(!jni_singletons.has(singleton_name));
@@ -104,7 +104,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis
singleton->add_signal(signal_name, types);
}
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jobject obj, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params) {
+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) {
String singleton_name = jstring_to_string(j_plugin_name, env);
ERR_FAIL_COND(!jni_singletons.has(singleton_name));
@@ -129,7 +129,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS
singleton->emit_signal(signal_name, args, count);
}
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jobject obj, jobjectArray gdnlib_paths) {
+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) {
return;
diff --git a/platform/android/plugin/godot_plugin_jni.h b/platform/android/plugin/godot_plugin_jni.h
index 8a08ec3709..b87f922e03 100644
--- a/platform/android/plugin/godot_plugin_jni.h
+++ b/platform/android/plugin/godot_plugin_jni.h
@@ -35,11 +35,11 @@
#include <jni.h>
extern "C" {
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jobject obj, jstring name);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jobject obj, 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, jobject obj, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jobject obj, jobjectArray gdnlib_paths);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jclass clazz, jstring name, jobject obj);
+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);
}
#endif // GODOT_PLUGIN_JNI_H
diff --git a/platform/android/thread_jandroid.cpp b/platform/android/thread_jandroid.cpp
index afcc7294f2..ba379c8d43 100644
--- a/platform/android/thread_jandroid.cpp
+++ b/platform/android/thread_jandroid.cpp
@@ -30,17 +30,34 @@
#include "thread_jandroid.h"
+#include <android/log.h>
+
#include "core/os/thread.h"
static JavaVM *java_vm = nullptr;
static thread_local JNIEnv *env = nullptr;
+// The logic here need to improve, init_thread/term_tread are designed to work with Thread::callback
+// Calling init_thread from setup_android_thread and get_jni_env to setup an env we're keeping and not detaching
+// could cause issues on app termination.
+//
+// We should be making sure that any thread started calls a nice cleanup function when it's done,
+// especially now that we use many more threads.
+
static void init_thread() {
+ if (env) {
+ // thread never detached! just keep using...
+ return;
+ }
+
java_vm->AttachCurrentThread(&env, nullptr);
}
static void term_thread() {
java_vm->DetachCurrentThread();
+
+ // this is no longer valid, must called init_thread to re-establish
+ env = nullptr;
}
void init_thread_jandroid(JavaVM *p_jvm, JNIEnv *p_env) {
@@ -50,9 +67,17 @@ void init_thread_jandroid(JavaVM *p_jvm, JNIEnv *p_env) {
}
void setup_android_thread() {
- init_thread();
+ if (!env) {
+ // !BAS! see remarks above
+ init_thread();
+ }
}
JNIEnv *get_jni_env() {
+ if (!env) {
+ // !BAS! see remarks above
+ init_thread();
+ }
+
return env;
}
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 17796beb6f..cf358e0878 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -54,7 +54,7 @@ def configure(env):
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["-O2", "-ftree-vectorize", "-fomit-frame-pointer"])
env.Append(LINKFLAGS=["-O2"])
- else: # optimize for size
+ elif env["optimize"] == "size": # optimize for size
env.Append(CCFLAGS=["-Os", "-ftree-vectorize"])
env.Append(LINKFLAGS=["-Os"])
diff --git a/platform/iphone/display_layer.mm b/platform/iphone/display_layer.mm
index fb57db4518..b8df81b89a 100644
--- a/platform/iphone/display_layer.mm
+++ b/platform/iphone/display_layer.mm
@@ -89,7 +89,7 @@
// FIXME: Add Vulkan support via MoltenVK. Add fallback code back?
// Create GL ES 2 context
- if (GLOBAL_GET("rendering/quality/driver/driver_name") == "GLES2") {
+ if (GLOBAL_GET("rendering/driver/driver_name") == "GLES2") {
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
NSLog(@"Setting up an OpenGL ES 2.0 context.");
if (!context) {
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 91cecdd704..c585c2afbe 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -37,6 +37,7 @@
#include "core/io/zip_io.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
+#include "core/templates/safe_refcount.h"
#include "core/version.h"
#include "editor/editor_export.h"
#include "editor/editor_node.h"
@@ -56,9 +57,9 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
Ref<ImageTexture> logo;
// Plugins
- volatile bool plugins_changed;
+ SafeFlag plugins_changed;
Thread check_for_changes_thread;
- volatile bool quit_request;
+ SafeFlag quit_request;
Mutex plugins_lock;
Vector<PluginConfigIOS> plugins;
@@ -141,19 +142,19 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
static void _check_for_changes_poll_thread(void *ud) {
EditorExportPlatformIOS *ea = (EditorExportPlatformIOS *)ud;
- while (!ea->quit_request) {
+ while (!ea->quit_request.is_set()) {
// Nothing to do if we already know the plugins have changed.
- if (!ea->plugins_changed) {
+ if (!ea->plugins_changed.is_set()) {
MutexLock lock(ea->plugins_lock);
Vector<PluginConfigIOS> loaded_plugins = get_plugins();
if (ea->plugins.size() != loaded_plugins.size()) {
- ea->plugins_changed = true;
+ ea->plugins_changed.set();
} else {
for (int i = 0; i < ea->plugins.size(); i++) {
if (ea->plugins[i].name != loaded_plugins[i].name || ea->plugins[i].last_updated != loaded_plugins[i].last_updated) {
- ea->plugins_changed = true;
+ ea->plugins_changed.set();
break;
}
}
@@ -165,7 +166,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
while (OS::get_singleton()->get_ticks_usec() - time < wait) {
OS::get_singleton()->delay_usec(300000);
- if (ea->quit_request) {
+ if (ea->quit_request.is_set()) {
break;
}
}
@@ -182,10 +183,10 @@ public:
virtual Ref<Texture2D> get_logo() const override { return logo; }
virtual bool should_update_export_options() override {
- bool export_options_changed = plugins_changed;
+ bool export_options_changed = plugins_changed.is_set();
if (export_options_changed) {
// don't clear unless we're reporting true, to avoid race
- plugins_changed = false;
+ plugins_changed.clear();
}
return export_options_changed;
}
@@ -291,7 +292,7 @@ public:
};
void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
- String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name");
+ String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
r_features->push_back("pvrtc");
if (driver == "Vulkan") {
// FIXME: Review if this is correct.
@@ -364,7 +365,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
for (int i = 0; i < found_plugins.size(); i++) {
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + found_plugins[i].name), false));
}
- plugins_changed = false;
+ plugins_changed.clear();
plugins = found_plugins;
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/access_wifi"), false));
@@ -1967,14 +1968,13 @@ EditorExportPlatformIOS::EditorExportPlatformIOS() {
logo.instance();
logo->create_from_image(img);
- plugins_changed = true;
- quit_request = false;
+ plugins_changed.set();
check_for_changes_thread.start(_check_for_changes_poll_thread, this);
}
EditorExportPlatformIOS::~EditorExportPlatformIOS() {
- quit_request = true;
+ quit_request.set();
check_for_changes_thread.wait_to_finish();
}
diff --git a/platform/iphone/godot_view.mm b/platform/iphone/godot_view.mm
index 887297848e..468fa2928a 100644
--- a/platform/iphone/godot_view.mm
+++ b/platform/iphone/godot_view.mm
@@ -39,6 +39,7 @@
#import <CoreMotion/CoreMotion.h>
static const int max_touches = 8;
+static const float earth_gravity = 9.80665;
@interface GodotView () {
UITouch *godot_touches[max_touches];
@@ -402,10 +403,19 @@ static const int max_touches = 8;
// https://developer.apple.com/reference/coremotion/cmmotionmanager?language=objc
// Apple splits our accelerometer date into a gravity and user movement
- // component. We add them back together
+ // component. We add them back together.
CMAcceleration gravity = self.motionManager.deviceMotion.gravity;
CMAcceleration acceleration = self.motionManager.deviceMotion.userAcceleration;
+ // To be consistent with Android we convert the unit of measurement from g (Earth's gravity)
+ // to m/s^2.
+ gravity.x *= earth_gravity;
+ gravity.y *= earth_gravity;
+ gravity.z *= earth_gravity;
+ acceleration.x *= earth_gravity;
+ acceleration.y *= earth_gravity;
+ acceleration.z *= earth_gravity;
+
///@TODO We don't seem to be getting data here, is my device broken or
/// is this code incorrect?
CMMagneticField magnetic = self.motionManager.deviceMotion.magneticField.field;
diff --git a/platform/iphone/joypad_iphone.mm b/platform/iphone/joypad_iphone.mm
index a0f0eee5d3..45842b38aa 100644
--- a/platform/iphone/joypad_iphone.mm
+++ b/platform/iphone/joypad_iphone.mm
@@ -287,7 +287,7 @@ void JoypadIPhone::start_processing() {
gamepad.dpad.right.isPressed);
};
- Input::JoyAxis jx;
+ Input::JoyAxisValue jx;
jx.min = -1;
if (element == gamepad.leftThumbstick) {
jx.value = gamepad.leftThumbstick.xAxis.value;
diff --git a/platform/javascript/.eslintrc.engine.js b/platform/javascript/.eslintrc.engine.js
index 00f0f147a9..78df6d41d9 100644
--- a/platform/javascript/.eslintrc.engine.js
+++ b/platform/javascript/.eslintrc.engine.js
@@ -3,8 +3,8 @@ module.exports = {
"./.eslintrc.js",
],
"globals": {
+ "InternalConfig": true,
"Godot": true,
"Preloader": true,
- "Utils": true,
},
};
diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub
index 11a45d2811..a760e36982 100644
--- a/platform/javascript/SCsub
+++ b/platform/javascript/SCsub
@@ -17,7 +17,7 @@ sys_env.AddJSLibraries(
[
"js/libs/library_godot_audio.js",
"js/libs/library_godot_display.js",
- "js/libs/library_godot_http_request.js",
+ "js/libs/library_godot_fetch.js",
"js/libs/library_godot_os.js",
"js/libs/library_godot_runtime.js",
]
@@ -73,7 +73,7 @@ sys_env.Depends(build[0], sys_env["JS_EXTERNS"])
engine = [
"js/engine/preloader.js",
- "js/engine/utils.js",
+ "js/engine/config.js",
"js/engine/engine.js",
]
externs = [env.File("#platform/javascript/js/engine/engine.externs.js")]
@@ -86,40 +86,6 @@ wrap_list = [
]
js_wrapped = env.Textfile("#bin/godot", [env.File(f) for f in wrap_list], TEXTFILESUFFIX="${PROGSUFFIX}.wrapped.js")
-zip_dir = env.Dir("#bin/.javascript_zip")
-binary_name = "godot.tools" if env["tools"] else "godot"
-out_files = [
- zip_dir.File(binary_name + ".js"),
- zip_dir.File(binary_name + ".wasm"),
- zip_dir.File(binary_name + ".html"),
- zip_dir.File(binary_name + ".audio.worklet.js"),
-]
-html_file = "#misc/dist/html/full-size.html"
-if env["tools"]:
- subst_dict = {"\$GODOT_VERSION": env.GetBuildVersion()}
- html_file = env.Substfile(
- target="#bin/godot${PROGSUFFIX}.html", source="#misc/dist/html/editor.html", SUBST_DICT=subst_dict
- )
-
-in_files = [js_wrapped, build[1], html_file, "#platform/javascript/js/libs/audio.worklet.js"]
-if env["gdnative_enabled"]:
- in_files.append(build[2]) # Runtime
- out_files.append(zip_dir.File(binary_name + ".side.wasm"))
-elif env["threads_enabled"]:
- in_files.append(build[2]) # Worker
- out_files.append(zip_dir.File(binary_name + ".worker.js"))
-
-if env["tools"]:
- in_files.append("#misc/dist/html/logo.svg")
- out_files.append(zip_dir.File("logo.svg"))
- in_files.append("#icon.png")
- out_files.append(zip_dir.File("favicon.png"))
-
-zip_files = env.InstallAs(out_files, in_files)
-env.Zip(
- "#bin/godot",
- zip_files,
- ZIPROOT=zip_dir,
- ZIPSUFFIX="${PROGSUFFIX}${ZIPSUFFIX}",
- ZIPCOMSTR="Archiving $SOURCES as $TARGET",
-)
+# Extra will be the thread worker, or the GDNative side, or None
+extra = build[2] if len(build) > 2 else None
+env.CreateTemplateZip(js_wrapped, build[1], extra)
diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp
index f7cc9e6540..478e848675 100644
--- a/platform/javascript/audio_driver_javascript.cpp
+++ b/platform/javascript/audio_driver_javascript.cpp
@@ -105,8 +105,8 @@ void AudioDriverJavaScript::_audio_driver_capture(int p_from, int p_samples) {
}
Error AudioDriverJavaScript::init() {
- mix_rate = GLOBAL_GET("audio/mix_rate");
- int latency = GLOBAL_GET("audio/output_latency");
+ mix_rate = GLOBAL_GET("audio/driver/mix_rate");
+ int latency = GLOBAL_GET("audio/driver/output_latency");
channel_count = godot_audio_init(mix_rate, latency, &_state_change_callback, &_latency_update_callback);
buffer_length = closest_power_of_2((latency * mix_rate / 1000));
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index 653d18f791..ac8d8de7e0 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -7,7 +7,7 @@ from emscripten_helpers import (
add_js_libraries,
add_js_pre,
add_js_externs,
- get_build_version,
+ create_template_zip,
)
from methods import get_compiler_version
from SCons.Util import WhereIs
@@ -64,21 +64,21 @@ def configure(env):
sys.exit(255)
## Build type
- if env["target"] == "release":
+ if env["target"].startswith("release"):
# Use -Os to prioritize optimizing for reduced file size. This is
# particularly valuable for the web platform because it directly
# decreases download time.
# -Os reduces file size by around 5 MiB over -O3. -Oz only saves about
# 100 KiB over -Os, which does not justify the negative impact on
# run-time performance.
- env.Append(CCFLAGS=["-Os"])
- env.Append(LINKFLAGS=["-Os"])
- elif env["target"] == "release_debug":
- env.Append(CCFLAGS=["-Os"])
- env.Append(LINKFLAGS=["-Os"])
- env.Append(CPPDEFINES=["DEBUG_ENABLED"])
- # Retain function names for backtraces at the cost of file size.
- env.Append(LINKFLAGS=["--profiling-funcs"])
+ if env["optimize"] != "none":
+ env.Append(CCFLAGS=["-Os"])
+ env.Append(LINKFLAGS=["-Os"])
+
+ if env["target"] == "release_debug":
+ env.Append(CPPDEFINES=["DEBUG_ENABLED"])
+ # Retain function names for backtraces at the cost of file size.
+ env.Append(LINKFLAGS=["--profiling-funcs"])
else: # "debug"
env.Append(CPPDEFINES=["DEBUG_ENABLED"])
env.Append(CCFLAGS=["-O1", "-g"])
@@ -92,9 +92,9 @@ def configure(env):
if not env["threads_enabled"]:
print("Threads must be enabled to build the editor. Please add the 'threads_enabled=yes' option")
sys.exit(255)
- if env["initial_memory"] < 32:
- print("Editor build requires at least 32MiB of initial memory. Forcing it.")
- env["initial_memory"] = 32
+ if env["initial_memory"] < 64:
+ print("Editor build requires at least 64MiB of initial memory. Forcing it.")
+ env["initial_memory"] = 64
elif env["builtin_icu"]:
env.Append(CCFLAGS=["-frtti"])
else:
@@ -147,12 +147,12 @@ def configure(env):
env.AddMethod(add_js_pre, "AddJSPre")
env.AddMethod(add_js_externs, "AddJSExterns")
- # Add method for getting build version string.
- env.AddMethod(get_build_version, "GetBuildVersion")
-
# Add method that joins/compiles our Engine files.
env.AddMethod(create_engine_file, "CreateEngineFile")
+ # Add method for creating the final zip file
+ env.AddMethod(create_template_zip, "CreateTemplateZip")
+
# Closure compiler extern and support for ecmascript specs (const, let, etc).
env["ENV"]["EMCC_CLOSURE_ARGS"] = "--language_in ECMASCRIPT6"
@@ -229,7 +229,15 @@ def configure(env):
env.Append(LINKFLAGS=["-s", "OFFSCREEN_FRAMEBUFFER=1"])
# callMain for manual start.
- env.Append(LINKFLAGS=["-s", "EXTRA_EXPORTED_RUNTIME_METHODS=['callMain']"])
+ env.Append(LINKFLAGS=["-s", "EXTRA_EXPORTED_RUNTIME_METHODS=['callMain','cwrap']"])
# Add code that allow exiting runtime.
env.Append(LINKFLAGS=["-s", "EXIT_RUNTIME=1"])
+
+ # TODO remove once we have GLES support back (temporary fix undefined symbols due to dead code elimination).
+ env.Append(
+ LINKFLAGS=[
+ "-s",
+ "EXPORTED_FUNCTIONS=['_main', '_emscripten_webgl_get_current_context', '_emscripten_webgl_commit_frame', '_emscripten_webgl_create_context']",
+ ]
+ )
diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp
index cfe093693f..c10fb40ecb 100644
--- a/platform/javascript/display_server_javascript.cpp
+++ b/platform/javascript/display_server_javascript.cpp
@@ -59,34 +59,13 @@ bool DisplayServerJavaScript::is_canvas_focused() {
}
bool DisplayServerJavaScript::check_size_force_redraw() {
- int canvas_width;
- int canvas_height;
- emscripten_get_canvas_element_size(DisplayServerJavaScript::canvas_id, &canvas_width, &canvas_height);
- if (last_width != canvas_width || last_height != canvas_height) {
- last_width = canvas_width;
- last_height = canvas_height;
- // Update the framebuffer size for redraw.
- emscripten_set_canvas_element_size(DisplayServerJavaScript::canvas_id, canvas_width, canvas_height);
- return true;
- }
- return false;
+ return godot_js_display_size_update() != 0;
}
Point2 DisplayServerJavaScript::compute_position_in_canvas(int p_x, int p_y) {
- DisplayServerJavaScript *display = get_singleton();
- int canvas_x;
- int canvas_y;
- godot_js_display_canvas_bounding_rect_position_get(&canvas_x, &canvas_y);
- int canvas_width;
- int canvas_height;
- emscripten_get_canvas_element_size(display->canvas_id, &canvas_width, &canvas_height);
-
- double element_width;
- double element_height;
- emscripten_get_element_css_size(display->canvas_id, &element_width, &element_height);
-
- return Point2((int)(canvas_width / element_width * (p_x - canvas_x)),
- (int)(canvas_height / element_height * (p_y - canvas_y)));
+ int point[2];
+ godot_js_display_compute_position(p_x, p_y, point, point + 1);
+ return Point2(point[0], point[1]);
}
EM_BOOL DisplayServerJavaScript::fullscreen_change_callback(int p_event_type, const EmscriptenFullscreenChangeEvent *p_event, void *p_user_data) {
@@ -210,19 +189,19 @@ EM_BOOL DisplayServerJavaScript::mouse_button_callback(int p_event_type, const E
switch (p_event->button) {
case DOM_BUTTON_LEFT:
- ev->set_button_index(BUTTON_LEFT);
+ ev->set_button_index(MOUSE_BUTTON_LEFT);
break;
case DOM_BUTTON_MIDDLE:
- ev->set_button_index(BUTTON_MIDDLE);
+ ev->set_button_index(MOUSE_BUTTON_MIDDLE);
break;
case DOM_BUTTON_RIGHT:
- ev->set_button_index(BUTTON_RIGHT);
+ ev->set_button_index(MOUSE_BUTTON_RIGHT);
break;
case DOM_BUTTON_XBUTTON1:
- ev->set_button_index(BUTTON_XBUTTON1);
+ ev->set_button_index(MOUSE_BUTTON_XBUTTON1);
break;
case DOM_BUTTON_XBUTTON2:
- ev->set_button_index(BUTTON_XBUTTON2);
+ ev->set_button_index(MOUSE_BUTTON_XBUTTON2);
break;
default:
return false;
@@ -482,13 +461,13 @@ EM_BOOL DisplayServerJavaScript::wheel_callback(int p_event_type, const Emscript
ev->set_metakey(input->is_key_pressed(KEY_META));
if (p_event->deltaY < 0)
- ev->set_button_index(BUTTON_WHEEL_UP);
+ ev->set_button_index(MOUSE_BUTTON_WHEEL_UP);
else if (p_event->deltaY > 0)
- ev->set_button_index(BUTTON_WHEEL_DOWN);
+ ev->set_button_index(MOUSE_BUTTON_WHEEL_DOWN);
else if (p_event->deltaX > 0)
- ev->set_button_index(BUTTON_WHEEL_LEFT);
+ ev->set_button_index(MOUSE_BUTTON_WHEEL_LEFT);
else if (p_event->deltaX < 0)
- ev->set_button_index(BUTTON_WHEEL_RIGHT);
+ ev->set_button_index(MOUSE_BUTTON_WHEEL_RIGHT);
else
return false;
@@ -557,6 +536,43 @@ bool DisplayServerJavaScript::screen_is_touchscreen(int p_screen) const {
return godot_js_display_touchscreen_is_available();
}
+// Virtual Keybaord
+void DisplayServerJavaScript::vk_input_text_callback(const char *p_text, int p_cursor) {
+ DisplayServerJavaScript *ds = DisplayServerJavaScript::get_singleton();
+ if (!ds || ds->input_text_callback.is_null()) {
+ return;
+ }
+ // Call input_text
+ Variant event = String(p_text);
+ Variant *eventp = &event;
+ Variant ret;
+ Callable::CallError ce;
+ ds->input_text_callback.call((const Variant **)&eventp, 1, ret, ce);
+ // Insert key right to reach position.
+ Input *input = Input::get_singleton();
+ Ref<InputEventKey> k;
+ for (int i = 0; i < p_cursor; i++) {
+ k.instance();
+ k->set_pressed(true);
+ k->set_echo(false);
+ k->set_keycode(KEY_RIGHT);
+ input->parse_input_event(k);
+ k.instance();
+ k->set_pressed(false);
+ k->set_echo(false);
+ k->set_keycode(KEY_RIGHT);
+ input->parse_input_event(k);
+ }
+}
+
+void DisplayServerJavaScript::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
+ godot_js_display_vk_show(p_existing_text.utf8().get_data(), p_multiline, p_cursor_start, p_cursor_end);
+}
+
+void DisplayServerJavaScript::virtual_keyboard_hide() {
+ godot_js_display_vk_hide();
+}
+
// Gamepad
void DisplayServerJavaScript::gamepad_callback(int p_index, int p_connected, const char *p_id, const char *p_guid) {
Input *input = Input::get_singleton();
@@ -585,7 +601,7 @@ void DisplayServerJavaScript::process_joypads() {
// Buttons 6 and 7 in the standard mapping need to be
// axis to be handled as JOY_AXIS_TRIGGER by Godot.
if (s_standard && (b == 6 || b == 7)) {
- Input::JoyAxis joy_axis;
+ Input::JoyAxisValue joy_axis;
joy_axis.min = 0;
joy_axis.value = value;
int a = b == 6 ? JOY_AXIS_TRIGGER_LEFT : JOY_AXIS_TRIGGER_RIGHT;
@@ -595,7 +611,7 @@ void DisplayServerJavaScript::process_joypads() {
}
}
for (int a = 0; a < s_axes_num; a++) {
- Input::JoyAxis joy_axis;
+ Input::JoyAxisValue joy_axis;
joy_axis.min = -1;
joy_axis.value = s_axes[a];
input->joy_axis(idx, a, joy_axis);
@@ -703,6 +719,9 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
// Ensure the canvas ID.
godot_js_config_canvas_id_get(canvas_id, 256);
+ // Handle contextmenu, webglcontextlost
+ godot_js_display_setup_canvas(p_resolution.x, p_resolution.y, p_mode == WINDOW_MODE_FULLSCREEN, OS::get_singleton()->is_hidpi_allowed() ? 1 : 0);
+
// Check if it's windows.
swap_cancel_ok = godot_js_display_is_swap_ok_cancel() == 1;
@@ -745,11 +764,6 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
video_driver_index = p_video_driver;
#endif
- window_set_mode(p_mode);
- if (godot_js_config_is_resize_on_start()) {
- window_set_size(p_resolution);
- }
-
EMSCRIPTEN_RESULT result;
#define EM_CHECK(ev) \
if (result != EMSCRIPTEN_RESULT_SUCCESS) \
@@ -787,6 +801,7 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
godot_js_display_paste_cb(update_clipboard_callback);
godot_js_display_drop_files_cb(drop_files_js_callback);
godot_js_display_gamepad_cb(&DisplayServerJavaScript::gamepad_callback);
+ godot_js_display_vk_cb(&vk_input_text_callback);
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_event);
}
@@ -816,7 +831,8 @@ bool DisplayServerJavaScript::has_feature(Feature p_feature) const {
//case FEATURE_WINDOW_TRANSPARENCY:
//case FEATURE_KEEP_SCREEN_ON:
//case FEATURE_ORIENTATION:
- //case FEATURE_VIRTUAL_KEYBOARD:
+ case FEATURE_VIRTUAL_KEYBOARD:
+ return godot_js_display_vk_available() != 0;
default:
return false;
}
@@ -839,20 +855,23 @@ Point2i DisplayServerJavaScript::screen_get_position(int p_screen) const {
}
Size2i DisplayServerJavaScript::screen_get_size(int p_screen) const {
- EmscriptenFullscreenChangeEvent ev;
- EMSCRIPTEN_RESULT result = emscripten_get_fullscreen_status(&ev);
- ERR_FAIL_COND_V(result != EMSCRIPTEN_RESULT_SUCCESS, Size2i());
- return Size2i(ev.screenWidth, ev.screenHeight);
+ int size[2];
+ godot_js_display_screen_size_get(size, size + 1);
+ return Size2(size[0], size[1]);
}
Rect2i DisplayServerJavaScript::screen_get_usable_rect(int p_screen) const {
- int canvas[2];
- emscripten_get_canvas_element_size(canvas_id, canvas, canvas + 1);
- return Rect2i(0, 0, canvas[0], canvas[1]);
+ int size[2];
+ godot_js_display_window_size_get(size, size + 1);
+ return Rect2i(0, 0, size[0], size[1]);
}
int DisplayServerJavaScript::screen_get_dpi(int p_screen) const {
- return 96; // TODO maybe check pixel ratio via window.devicePixelRatio * 96? Inexact.
+ return godot_js_display_screen_dpi_get();
+}
+
+float DisplayServerJavaScript::screen_get_scale(int p_screen) const {
+ return godot_js_display_pixel_ratio_get();
}
Vector<DisplayServer::WindowID> DisplayServerJavaScript::get_window_list() const {
@@ -886,7 +905,7 @@ void DisplayServerJavaScript::window_set_input_event_callback(const Callable &p_
}
void DisplayServerJavaScript::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) {
- input_text_callback = p_callable; // TODO unused... do I need this?
+ input_text_callback = p_callable;
}
void DisplayServerJavaScript::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) {
@@ -934,17 +953,13 @@ Size2i DisplayServerJavaScript::window_get_min_size(WindowID p_window) const {
}
void DisplayServerJavaScript::window_set_size(const Size2i p_size, WindowID p_window) {
- last_width = p_size.x;
- last_height = p_size.y;
- double scale = godot_js_display_pixel_ratio_get();
- emscripten_set_canvas_element_size(canvas_id, p_size.x, p_size.y);
- emscripten_set_element_css_size(canvas_id, p_size.x / scale, p_size.y / scale);
+ godot_js_display_desired_size_set(p_size.x, p_size.y);
}
Size2i DisplayServerJavaScript::window_get_size(WindowID p_window) const {
- int canvas[2];
- emscripten_get_canvas_element_size(canvas_id, canvas, canvas + 1);
- return Size2(canvas[0], canvas[1]);
+ int size[2];
+ godot_js_display_window_size_get(size, size + 1);
+ return Size2i(size[0], size[1]);
}
Size2i DisplayServerJavaScript::window_get_real_size(WindowID p_window) const {
@@ -958,20 +973,13 @@ void DisplayServerJavaScript::window_set_mode(WindowMode p_mode, WindowID p_wind
switch (p_mode) {
case WINDOW_MODE_WINDOWED: {
if (window_mode == WINDOW_MODE_FULLSCREEN) {
- emscripten_exit_fullscreen();
+ godot_js_display_fullscreen_exit();
}
window_mode = WINDOW_MODE_WINDOWED;
- window_set_size(Size2i(last_width, last_height));
} break;
case WINDOW_MODE_FULLSCREEN: {
- EmscriptenFullscreenStrategy strategy;
- strategy.scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH;
- strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
- strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
- strategy.canvasResizedCallback = nullptr;
- EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(canvas_id, false, &strategy);
- ERR_FAIL_COND_MSG(result == EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED, "Enabling fullscreen is only possible from an input callback for the HTML5 platform.");
- ERR_FAIL_COND_MSG(result != EMSCRIPTEN_RESULT_SUCCESS, "Enabling fullscreen is only possible from an input callback for the HTML5 platform.");
+ int result = godot_js_display_fullscreen_request();
+ ERR_FAIL_COND_MSG(result, "The request was denied. Remember that enabling fullscreen is only possible from an input callback for the HTML5 platform.");
} break;
case WINDOW_MODE_MAXIMIZED:
case WINDOW_MODE_MINIMIZED:
diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h
index e28fbc56f3..ece38f1a95 100644
--- a/platform/javascript/display_server_javascript.h
+++ b/platform/javascript/display_server_javascript.h
@@ -57,9 +57,6 @@ private:
double last_click_ms = 0;
int last_click_button_index = -1;
- int last_width = 0;
- int last_height = 0;
-
bool swap_cancel_ok = false;
// utilities
@@ -78,6 +75,8 @@ private:
static EM_BOOL keypress_callback(int p_event_type, const EmscriptenKeyboardEvent *p_event, void *p_user_data);
static EM_BOOL keyup_callback(int p_event_type, const EmscriptenKeyboardEvent *p_event, void *p_user_data);
+ static void vk_input_text_callback(const char *p_text, int p_cursor);
+
static EM_BOOL mousemove_callback(int p_event_type, const EmscriptenMouseEvent *p_event, void *p_user_data);
static EM_BOOL mouse_button_callback(int p_event_type, const EmscriptenMouseEvent *p_event, void *p_user_data);
@@ -136,6 +135,10 @@ public:
Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+
+ void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
+ void virtual_keyboard_hide() override;
// windows
Vector<DisplayServer::WindowID> get_window_list() const override;
diff --git a/platform/javascript/emscripten_helpers.py b/platform/javascript/emscripten_helpers.py
index d08555916b..b3b15a1574 100644
--- a/platform/javascript/emscripten_helpers.py
+++ b/platform/javascript/emscripten_helpers.py
@@ -15,13 +15,17 @@ def run_closure_compiler(target, source, env, for_signature):
return " ".join(cmd)
-def get_build_version(env):
+def get_build_version():
import version
name = "custom_build"
if os.getenv("BUILD_NAME") != None:
name = os.getenv("BUILD_NAME")
- return "%d.%d.%d.%s.%s" % (version.major, version.minor, version.patch, version.status, name)
+ v = "%d.%d" % (version.major, version.minor)
+ if version.patch > 0:
+ v += ".%d" % version.patch
+ v += ".%s.%s" % (version.status, name)
+ return v
def create_engine_file(env, target, source, externs):
@@ -30,6 +34,65 @@ def create_engine_file(env, target, source, externs):
return env.Textfile(target, [env.File(s) for s in source])
+def create_template_zip(env, js, wasm, extra):
+ binary_name = "godot.tools" if env["tools"] else "godot"
+ zip_dir = env.Dir("#bin/.javascript_zip")
+ in_files = [
+ js,
+ wasm,
+ "#platform/javascript/js/libs/audio.worklet.js",
+ ]
+ out_files = [
+ zip_dir.File(binary_name + ".js"),
+ zip_dir.File(binary_name + ".wasm"),
+ zip_dir.File(binary_name + ".audio.worklet.js"),
+ ]
+ # GDNative/Threads specific
+ if env["gdnative_enabled"]:
+ in_files.append(extra) # Runtime
+ out_files.append(zip_dir.File(binary_name + ".side.wasm"))
+ elif env["threads_enabled"]:
+ in_files.append(extra) # Worker
+ out_files.append(zip_dir.File(binary_name + ".worker.js"))
+
+ service_worker = "#misc/dist/html/service-worker.js"
+ if env["tools"]:
+ # HTML
+ html = "#misc/dist/html/editor.html"
+ subst_dict = {"@GODOT_VERSION@": get_build_version(), "@GODOT_NAME@": "GodotEngine"}
+ html = env.Substfile(target="#bin/godot${PROGSUFFIX}.html", source=html, SUBST_DICT=subst_dict)
+ in_files.append(html)
+ out_files.append(zip_dir.File(binary_name + ".html"))
+ # And logo/favicon
+ in_files.append("#misc/dist/html/logo.svg")
+ out_files.append(zip_dir.File("logo.svg"))
+ in_files.append("#icon.png")
+ out_files.append(zip_dir.File("favicon.png"))
+ # PWA
+ service_worker = env.Substfile(
+ target="#bin/godot${PROGSUFFIX}.service.worker.js", source=service_worker, SUBST_DICT=subst_dict
+ )
+ in_files.append(service_worker)
+ out_files.append(zip_dir.File("service.worker.js"))
+ in_files.append("#misc/dist/html/manifest.json")
+ out_files.append(zip_dir.File("manifest.json"))
+ in_files.append("#misc/dist/html/offline.html")
+ out_files.append(zip_dir.File("offline.html"))
+ else:
+ # HTML
+ in_files.append("#misc/dist/html/full-size.html")
+ out_files.append(zip_dir.File(binary_name + ".html"))
+
+ zip_files = env.InstallAs(out_files, in_files)
+ env.Zip(
+ "#bin/godot",
+ zip_files,
+ ZIPROOT=zip_dir,
+ ZIPSUFFIX="${PROGSUFFIX}${ZIPSUFFIX}",
+ ZIPCOMSTR="Archiving $SOURCES as $TARGET",
+ )
+
+
def add_js_libraries(env, libraries):
env.Append(JS_LIBS=env.File(libraries))
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index f5d8a68994..1e89e144cc 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -242,7 +242,7 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform {
return name;
}
- void _fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, int p_flags, const Vector<SharedObject> p_shared_objects);
+ void _fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, int p_flags, const Vector<SharedObject> p_shared_objects, const Dictionary &p_file_sizes);
static void _server_thread_poll(void *data);
@@ -281,28 +281,35 @@ public:
~EditorExportPlatformJavaScript();
};
-void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, int p_flags, const Vector<SharedObject> p_shared_objects) {
+void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, int p_flags, const Vector<SharedObject> p_shared_objects, const Dictionary &p_file_sizes) {
String str_template = String::utf8(reinterpret_cast<const char *>(p_html.ptr()), p_html.size());
String str_export;
Vector<String> lines = str_template.split("\n");
- Vector<String> flags;
- String flags_json;
- gen_export_flags(flags, p_flags);
- flags_json = JSON::print(flags);
- String libs;
+ Array libs;
for (int i = 0; i < p_shared_objects.size(); i++) {
- libs += "\"" + p_shared_objects[i].path.get_file() + "\",";
+ libs.push_back(p_shared_objects[i].path.get_file());
}
+ Vector<String> flags;
+ gen_export_flags(flags, p_flags & (~DEBUG_FLAG_DUMB_CLIENT));
+ Array args;
+ for (int i = 0; i < flags.size(); i++) {
+ args.push_back(flags[i]);
+ }
+ Dictionary config;
+ config["canvasResizePolicy"] = p_preset->get("html/canvas_resize_policy");
+ config["experimentalVK"] = p_preset->get("html/experimental_virtual_keyboard");
+ config["gdnativeLibs"] = libs;
+ config["executable"] = p_name;
+ config["args"] = args;
+ config["fileSizes"] = p_file_sizes;
+ const String str_config = JSON::print(config);
for (int i = 0; i < lines.size(); i++) {
String current_line = lines[i];
- current_line = current_line.replace("$GODOT_BASENAME", p_name);
+ current_line = current_line.replace("$GODOT_URL", p_name + ".js");
current_line = current_line.replace("$GODOT_PROJECT_NAME", ProjectSettings::get_singleton()->get_setting("application/config/name"));
current_line = current_line.replace("$GODOT_HEAD_INCLUDE", p_preset->get("html/head_include"));
- current_line = current_line.replace("$GODOT_FULL_WINDOW", p_preset->get("html/full_window_size") ? "true" : "false");
- current_line = current_line.replace("$GODOT_GDNATIVE_LIBS", libs);
- current_line = current_line.replace("$GODOT_DEBUG_ENABLED", p_debug ? "true" : "false");
- current_line = current_line.replace("$GODOT_ARGS", flags_json);
+ current_line = current_line.replace("$GODOT_CONFIG", str_config);
str_export += current_line + "\n";
}
@@ -319,7 +326,7 @@ void EditorExportPlatformJavaScript::get_preset_features(const Ref<EditorExportP
}
if (p_preset->get("vram_texture_compression/for_mobile")) {
- String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name");
+ String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
if (driver == "GLES2") {
r_features->push_back("etc");
} else if (driver == "Vulkan") {
@@ -345,7 +352,8 @@ void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_op
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/custom_html_shell", PROPERTY_HINT_FILE, "*.html"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/head_include", PROPERTY_HINT_MULTILINE_TEXT), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/full_window_size"), true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "html/canvas_resize_policy", PROPERTY_HINT_ENUM, "None,Project,Adaptive"), 2));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/experimental_virtual_keyboard"), false));
}
String EditorExportPlatformJavaScript::get_name() const {
@@ -467,6 +475,8 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
return ERR_FILE_CORRUPT;
}
+ Vector<uint8_t> html;
+ Dictionary file_sizes;
do {
//get filename
unz_file_info info;
@@ -475,6 +485,16 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
String file = fname;
+ // HTML is handled later
+ if (file == "godot.html") {
+ if (custom_html.is_empty()) {
+ html.resize(info.uncompressed_size);
+ unzOpenCurrentFile(pkg);
+ unzReadCurrentFile(pkg, html.ptrw(), html.size());
+ unzCloseCurrentFile(pkg);
+ }
+ continue;
+ }
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
@@ -485,14 +505,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
//write
- if (file == "godot.html") {
- if (!custom_html.is_empty()) {
- continue;
- }
- _fix_html(data, p_preset, p_path.get_file().get_basename(), p_debug, p_flags, shared_objects);
- file = p_path.get_file();
-
- } else if (file == "godot.js") {
+ if (file == "godot.js") {
file = p_path.get_file().get_basename() + ".js";
} else if (file == "godot.worker.js") {
@@ -506,6 +519,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
} else if (file == "godot.wasm") {
file = p_path.get_file().get_basename() + ".wasm";
+ file_sizes[file.get_file()] = (uint64_t)info.uncompressed_size;
}
String dst = p_path.get_base_dir().plus_file(file);
@@ -527,19 +541,26 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
EditorNode::get_singleton()->show_warning(TTR("Could not read custom HTML shell:") + "\n" + custom_html);
return ERR_FILE_CANT_READ;
}
- Vector<uint8_t> buf;
- buf.resize(f->get_len());
- f->get_buffer(buf.ptrw(), buf.size());
+ html.resize(f->get_len());
+ f->get_buffer(html.ptrw(), html.size());
memdelete(f);
- _fix_html(buf, p_preset, p_path.get_file().get_basename(), p_debug, p_flags, shared_objects);
-
+ }
+ {
+ FileAccess *f = FileAccess::open(pck_path, FileAccess::READ);
+ if (f) {
+ file_sizes[pck_path.get_file()] = (uint64_t)f->get_len();
+ memdelete(f);
+ f = NULL;
+ }
+ _fix_html(html, p_preset, p_path.get_file().get_basename(), p_debug, p_flags, shared_objects, file_sizes);
f = FileAccess::open(p_path, FileAccess::WRITE);
if (!f) {
EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + p_path);
return ERR_FILE_CANT_WRITE;
}
- f->store_buffer(buf.ptr(), buf.size());
+ f->store_buffer(html.ptr(), html.size());
memdelete(f);
+ html.resize(0);
}
Ref<Image> splash;
diff --git a/platform/javascript/godot_js.h b/platform/javascript/godot_js.h
index 0006848756..4448a35670 100644
--- a/platform/javascript/godot_js.h
+++ b/platform/javascript/godot_js.h
@@ -40,7 +40,6 @@ extern "C" {
// Config
extern void godot_js_config_locale_get(char *p_ptr, int p_ptr_max);
extern void godot_js_config_canvas_id_get(char *p_ptr, int p_ptr_max);
-extern int godot_js_config_is_resize_on_start();
// OS
extern void godot_js_os_finish_async(void (*p_callback)());
@@ -49,8 +48,10 @@ extern int godot_js_os_fs_is_persistent();
extern void godot_js_os_fs_sync(void (*p_callback)());
extern int godot_js_os_execute(const char *p_json);
extern void godot_js_os_shell_open(const char *p_uri);
+extern int godot_js_os_hw_concurrency_get();
// Display
+extern int godot_js_display_screen_dpi_get();
extern double godot_js_display_pixel_ratio_get();
extern void godot_js_display_alert(const char *p_text);
extern int godot_js_display_touchscreen_is_available();
@@ -59,10 +60,15 @@ extern int godot_js_display_is_swap_ok_cancel();
// Display canvas
extern void godot_js_display_canvas_focus();
extern int godot_js_display_canvas_is_focused();
-extern void godot_js_display_canvas_bounding_rect_position_get(int32_t *p_x, int32_t *p_y);
// Display window
-extern void godot_js_display_window_request_fullscreen();
+extern void godot_js_display_desired_size_set(int p_width, int p_height);
+extern int godot_js_display_size_update();
+extern void godot_js_display_window_size_get(int32_t *p_x, int32_t *p_y);
+extern void godot_js_display_screen_size_get(int32_t *p_x, int32_t *p_y);
+extern int godot_js_display_fullscreen_request();
+extern int godot_js_display_fullscreen_exit();
+extern void godot_js_display_compute_position(int p_x, int p_y, int32_t *r_x, int32_t *r_y);
extern void godot_js_display_window_title_set(const char *p_text);
extern void godot_js_display_window_icon_set(const uint8_t *p_ptr, int p_len);
@@ -86,6 +92,14 @@ extern int godot_js_display_gamepad_sample_get(int p_idx, float r_btns[16], int3
extern void godot_js_display_notification_cb(void (*p_callback)(int p_notification), int p_enter, int p_exit, int p_in, int p_out);
extern void godot_js_display_paste_cb(void (*p_callback)(const char *p_text));
extern void godot_js_display_drop_files_cb(void (*p_callback)(char **p_filev, int p_filec));
+extern void godot_js_display_setup_canvas(int p_width, int p_height, int p_fullscreen, int p_hidpi);
+
+// Display Virtual Keyboard
+extern int godot_js_display_vk_available();
+extern void godot_js_display_vk_cb(void (*p_input)(const char *p_text, int p_cursor));
+extern void godot_js_display_vk_show(const char *p_text, int p_multiline, int p_start, int p_end);
+extern void godot_js_display_vk_hide();
+
#ifdef __cplusplus
}
#endif
diff --git a/platform/javascript/http_client.h.inc b/platform/javascript/http_client.h.inc
index 2ef1ad5b83..842a93fcba 100644
--- a/platform/javascript/http_client.h.inc
+++ b/platform/javascript/http_client.h.inc
@@ -30,24 +30,21 @@
// HTTPClient's additional private members in the javascript platform
-Error prepare_request(Method p_method, const String &p_url, const Vector<String> &p_headers);
+Error make_request(Method p_method, const String &p_url, const Vector<String> &p_headers, const uint8_t *p_body, int p_body_len);
+static void _parse_headers(int p_len, const char **p_headers, void *p_ref);
-int xhr_id;
+int js_id = 0;
int read_limit = 4096;
-int response_read_offset = 0;
Status status = STATUS_DISCONNECTED;
String host;
int port = -1;
bool use_tls = false;
-String username;
-String password;
int polled_response_code = 0;
-String polled_response_header;
-PackedByteArray polled_response;
+Vector<String> response_headers;
+Vector<uint8_t> response_buffer;
#ifdef DEBUG_ENABLED
-bool has_polled = false;
uint64_t last_polling_frame = 0;
#endif
diff --git a/platform/javascript/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp
index c8c48dd582..b79c965854 100644
--- a/platform/javascript/http_client_javascript.cpp
+++ b/platform/javascript/http_client_javascript.cpp
@@ -30,7 +30,38 @@
#include "core/io/http_client.h"
-#include "http_request.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "stddef.h"
+
+typedef enum {
+ GODOT_JS_FETCH_STATE_REQUESTING = 0,
+ GODOT_JS_FETCH_STATE_BODY = 1,
+ GODOT_JS_FETCH_STATE_DONE = 2,
+ GODOT_JS_FETCH_STATE_ERROR = -1,
+} godot_js_fetch_state_t;
+
+extern int godot_js_fetch_create(const char *p_method, const char *p_url, const char **p_headers, int p_headers_len, const uint8_t *p_body, int p_body_len);
+extern int godot_js_fetch_read_headers(int p_id, void (*parse_callback)(int p_size, const char **p_headers, void *p_ref), void *p_ref);
+extern int godot_js_fetch_read_chunk(int p_id, uint8_t *p_buf, int p_buf_size);
+extern void godot_js_fetch_free(int p_id);
+extern godot_js_fetch_state_t godot_js_fetch_state_get(int p_id);
+extern int godot_js_fetch_body_length_get(int p_id);
+extern int godot_js_fetch_http_status_get(int p_id);
+extern int godot_js_fetch_is_chunked(int p_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+void HTTPClient::_parse_headers(int p_len, const char **p_headers, void *p_ref) {
+ HTTPClient *client = static_cast<HTTPClient *>(p_ref);
+ for (int i = 0; i < p_len; i++) {
+ client->response_headers.push_back(String::utf8(p_headers[i]));
+ }
+}
Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, bool p_verify_host) {
close();
@@ -74,7 +105,7 @@ Ref<StreamPeer> HTTPClient::get_connection() const {
ERR_FAIL_V_MSG(REF(), "Accessing an HTTPClient's StreamPeer is not supported for the HTML5 platform.");
}
-Error HTTPClient::prepare_request(Method p_method, const String &p_url, const Vector<String> &p_headers) {
+Error HTTPClient::make_request(Method p_method, const String &p_url, const Vector<String> &p_headers, const uint8_t *p_body, int p_body_len) {
ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(p_method == METHOD_TRACE || p_method == METHOD_CONNECT, ERR_UNAVAILABLE, "HTTP methods TRACE and CONNECT are not supported for the HTML5 platform.");
ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
@@ -83,37 +114,33 @@ Error HTTPClient::prepare_request(Method p_method, const String &p_url, const Ve
ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER);
String url = (use_tls ? "https://" : "http://") + host + ":" + itos(port) + p_url;
- godot_xhr_reset(xhr_id);
- godot_xhr_open(xhr_id, _methods[p_method], url.utf8().get_data(),
- username.is_empty() ? nullptr : username.utf8().get_data(),
- password.is_empty() ? nullptr : password.utf8().get_data());
-
+ Vector<CharString> keeper;
+ Vector<const char *> c_strings;
for (int i = 0; i < p_headers.size(); i++) {
- int header_separator = p_headers[i].find(": ");
- ERR_FAIL_COND_V(header_separator < 0, ERR_INVALID_PARAMETER);
- godot_xhr_set_request_header(xhr_id,
- p_headers[i].left(header_separator).utf8().get_data(),
- p_headers[i].right(header_separator + 2).utf8().get_data());
+ keeper.push_back(p_headers[i].utf8());
+ c_strings.push_back(keeper[i].get_data());
+ }
+ if (js_id) {
+ godot_js_fetch_free(js_id);
}
- response_read_offset = 0;
+ js_id = godot_js_fetch_create(_methods[p_method], url.utf8().get_data(), c_strings.ptrw(), c_strings.size(), p_body, p_body_len);
status = STATUS_REQUESTING;
return OK;
}
Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const Vector<uint8_t> &p_body) {
- Error err = prepare_request(p_method, p_url, p_headers);
- if (err != OK)
- return err;
- godot_xhr_send_data(xhr_id, p_body.ptr(), p_body.size());
- return OK;
+ if (p_body.is_empty()) {
+ return make_request(p_method, p_url, p_headers, nullptr, 0);
+ }
+ return make_request(p_method, p_url, p_headers, p_body.ptr(), p_body.size());
}
Error HTTPClient::request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body) {
- Error err = prepare_request(p_method, p_url, p_headers);
- if (err != OK)
- return err;
- godot_xhr_send_string(xhr_id, p_body.utf8().get_data());
- return OK;
+ if (p_body.is_empty()) {
+ return make_request(p_method, p_url, p_headers, nullptr, 0);
+ }
+ const CharString cs = p_body.utf8();
+ return make_request(p_method, p_url, p_headers, (const uint8_t *)cs.get_data(), cs.size() - 1);
}
void HTTPClient::close() {
@@ -121,10 +148,13 @@ void HTTPClient::close() {
port = -1;
use_tls = false;
status = STATUS_DISCONNECTED;
- polled_response.resize(0);
polled_response_code = 0;
- polled_response_header = String();
- godot_xhr_reset(xhr_id);
+ response_headers.resize(0);
+ response_buffer.resize(0);
+ if (js_id) {
+ godot_js_fetch_free(js_id);
+ js_id = 0;
+ }
}
HTTPClient::Status HTTPClient::get_status() const {
@@ -132,12 +162,11 @@ HTTPClient::Status HTTPClient::get_status() const {
}
bool HTTPClient::has_response() const {
- return !polled_response_header.is_empty();
+ return response_headers.size() > 0;
}
bool HTTPClient::is_response_chunked() const {
- // TODO evaluate using moz-chunked-arraybuffer, fetch & ReadableStream
- return false;
+ return godot_js_fetch_is_chunked(js_id);
}
int HTTPClient::get_response_code() const {
@@ -145,36 +174,42 @@ int HTTPClient::get_response_code() const {
}
Error HTTPClient::get_response_headers(List<String> *r_response) {
- if (polled_response_header.is_empty())
+ if (!response_headers.size()) {
return ERR_INVALID_PARAMETER;
-
- Vector<String> header_lines = polled_response_header.split("\r\n", false);
- for (int i = 0; i < header_lines.size(); ++i) {
- r_response->push_back(header_lines[i]);
}
- polled_response_header = String();
+ for (int i = 0; i < response_headers.size(); i++) {
+ r_response->push_back(response_headers[i]);
+ }
+ response_headers.clear();
return OK;
}
int HTTPClient::get_response_body_length() const {
- return polled_response.size();
+ return godot_js_fetch_body_length_get(js_id);
}
PackedByteArray HTTPClient::read_response_body_chunk() {
ERR_FAIL_COND_V(status != STATUS_BODY, PackedByteArray());
- int to_read = MIN(read_limit, polled_response.size() - response_read_offset);
- PackedByteArray chunk;
- chunk.resize(to_read);
- memcpy(chunk.ptrw(), polled_response.ptr() + response_read_offset, to_read);
- response_read_offset += to_read;
-
- if (response_read_offset == polled_response.size()) {
- status = STATUS_CONNECTED;
- polled_response.resize(0);
- godot_xhr_reset(xhr_id);
+ if (response_buffer.size() != read_limit) {
+ response_buffer.resize(read_limit);
+ }
+ int read = godot_js_fetch_read_chunk(js_id, response_buffer.ptrw(), read_limit);
+
+ // Check if the stream is over.
+ godot_js_fetch_state_t state = godot_js_fetch_state_get(js_id);
+ if (state == GODOT_JS_FETCH_STATE_DONE) {
+ status = STATUS_DISCONNECTED;
+ } else if (state != GODOT_JS_FETCH_STATE_BODY) {
+ status = STATUS_CONNECTION_ERROR;
}
+ PackedByteArray chunk;
+ if (!read) {
+ return chunk;
+ }
+ chunk.resize(read);
+ copymem(chunk.ptrw(), response_buffer.ptr(), read);
return chunk;
}
@@ -208,48 +243,48 @@ Error HTTPClient::poll() {
return OK;
case STATUS_CONNECTED:
- case STATUS_BODY:
return OK;
+ case STATUS_BODY: {
+ godot_js_fetch_state_t state = godot_js_fetch_state_get(js_id);
+ if (state == GODOT_JS_FETCH_STATE_DONE) {
+ status = STATUS_DISCONNECTED;
+ } else if (state != GODOT_JS_FETCH_STATE_BODY) {
+ status = STATUS_CONNECTION_ERROR;
+ return ERR_CONNECTION_ERROR;
+ }
+ return OK;
+ }
+
case STATUS_CONNECTION_ERROR:
return ERR_CONNECTION_ERROR;
case STATUS_REQUESTING: {
#ifdef DEBUG_ENABLED
- if (!has_polled) {
- has_polled = true;
- } else {
- // forcing synchronous requests is not possible on the web
- if (last_polling_frame == Engine::get_singleton()->get_process_frames()) {
- WARN_PRINT("HTTPClient polled multiple times in one frame, "
- "but request cannot progress more than once per "
- "frame on the HTML5 platform.");
- }
+ // forcing synchronous requests is not possible on the web
+ if (last_polling_frame == Engine::get_singleton()->get_process_frames()) {
+ WARN_PRINT("HTTPClient polled multiple times in one frame, "
+ "but request cannot progress more than once per "
+ "frame on the HTML5 platform.");
}
last_polling_frame = Engine::get_singleton()->get_process_frames();
#endif
- polled_response_code = godot_xhr_get_status(xhr_id);
- if (godot_xhr_get_ready_state(xhr_id) != XHR_READY_STATE_DONE) {
+ polled_response_code = godot_js_fetch_http_status_get(js_id);
+ godot_js_fetch_state_t js_state = godot_js_fetch_state_get(js_id);
+ if (js_state == GODOT_JS_FETCH_STATE_REQUESTING) {
return OK;
- } else if (!polled_response_code) {
+ } else if (js_state == GODOT_JS_FETCH_STATE_ERROR) {
+ // Fetch is in error state.
+ status = STATUS_CONNECTION_ERROR;
+ return ERR_CONNECTION_ERROR;
+ }
+ if (godot_js_fetch_read_headers(js_id, &_parse_headers, this)) {
+ // Failed to parse headers.
status = STATUS_CONNECTION_ERROR;
return ERR_CONNECTION_ERROR;
}
-
status = STATUS_BODY;
-
- PackedByteArray bytes;
- int len = godot_xhr_get_response_headers_length(xhr_id);
- bytes.resize(len + 1);
-
- godot_xhr_get_response_headers(xhr_id, reinterpret_cast<char *>(bytes.ptrw()), len);
- bytes.ptrw()[len] = 0;
-
- polled_response_header = String::utf8(reinterpret_cast<const char *>(bytes.ptr()));
-
- polled_response.resize(godot_xhr_get_response_length(xhr_id));
- godot_xhr_get_response(xhr_id, polled_response.ptrw(), polled_response.size());
break;
}
@@ -260,9 +295,8 @@ Error HTTPClient::poll() {
}
HTTPClient::HTTPClient() {
- xhr_id = godot_xhr_new();
}
HTTPClient::~HTTPClient() {
- godot_xhr_free(xhr_id);
+ close();
}
diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp
index 0b8af70b13..0fe95b0a8f 100644
--- a/platform/javascript/javascript_main.cpp
+++ b/platform/javascript/javascript_main.cpp
@@ -88,6 +88,13 @@ extern EMSCRIPTEN_KEEPALIVE int godot_js_main(int argc, char *argv[]) {
Main::start();
os->get_main_loop()->initialize();
+#ifdef TOOLS_ENABLED
+ if (Main::is_project_manager() && FileAccess::exists("/tmp/preload.zip")) {
+ PackedStringArray ps;
+ ps.push_back("/tmp/preload.zip");
+ os->get_main_loop()->emit_signal("files_dropped", ps, -1);
+ }
+#endif
emscripten_set_main_loop(main_loop_callback, -1, false);
// Immediately run the first iteration.
// We are inside an animation frame, we want to immediately draw on the newly setup canvas.
diff --git a/platform/javascript/js/engine/config.js b/platform/javascript/js/engine/config.js
new file mode 100644
index 0000000000..6072782875
--- /dev/null
+++ b/platform/javascript/js/engine/config.js
@@ -0,0 +1,337 @@
+/**
+ * An object used to configure the Engine instance based on godot export options, and to override those in custom HTML
+ * templates if needed.
+ *
+ * @header Engine configuration
+ * @summary The Engine configuration object. This is just a typedef, create it like a regular object, e.g.:
+ *
+ * ``const MyConfig = { executable: 'godot', unloadAfterInit: false }``
+ *
+ * @typedef {Object} EngineConfig
+ */
+const EngineConfig = {}; // eslint-disable-line no-unused-vars
+
+/**
+ * @struct
+ * @constructor
+ * @ignore
+ */
+const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-vars
+ const cfg = /** @lends {InternalConfig.prototype} */ {
+ /**
+ * Whether the unload the engine automatically after the instance is initialized.
+ *
+ * @memberof EngineConfig
+ * @default
+ * @type {boolean}
+ */
+ unloadAfterInit: true,
+ /**
+ * The HTML DOM Canvas object to use.
+ *
+ * By default, the first canvas element in the document will be used is none is specified.
+ *
+ * @memberof EngineConfig
+ * @default
+ * @type {?HTMLCanvasElement}
+ */
+ canvas: null,
+ /**
+ * The name of the WASM file without the extension. (Set by Godot Editor export process).
+ *
+ * @memberof EngineConfig
+ * @default
+ * @type {string}
+ */
+ executable: '',
+ /**
+ * An alternative name for the game pck to load. The executable name is used otherwise.
+ *
+ * @memberof EngineConfig
+ * @default
+ * @type {?string}
+ */
+ mainPack: null,
+ /**
+ * Specify a language code to select the proper localization for the game.
+ *
+ * The browser locale will be used if none is specified. See complete list of
+ * :ref:`supported locales <doc_locales>`.
+ *
+ * @memberof EngineConfig
+ * @type {?string}
+ * @default
+ */
+ locale: null,
+ /**
+ * The canvas resize policy determines how the canvas should be resized by Godot.
+ *
+ * ``0`` means Godot won't do any resizing. This is useful if you want to control the canvas size from
+ * javascript code in your template.
+ *
+ * ``1`` means Godot will resize the canvas on start, and when changing window size via engine functions.
+ *
+ * ``2`` means Godot will adapt the canvas size to match the whole browser window.
+ *
+ * @memberof EngineConfig
+ * @type {number}
+ * @default
+ */
+ canvasResizePolicy: 2,
+ /**
+ * The arguments to be passed as command line arguments on startup.
+ *
+ * See :ref:`command line tutorial <doc_command_line_tutorial>`.
+ *
+ * **Note**: :js:meth:`startGame <Engine.prototype.startGame>` will always add the ``--main-pack`` argument.
+ *
+ * @memberof EngineConfig
+ * @type {Array<string>}
+ * @default
+ */
+ args: [],
+ /**
+ * When enabled, this will turn on experimental virtual keyboard support on mobile.
+ *
+ * @memberof EngineConfig
+ * @type {boolean}
+ * @default
+ */
+ experimentalVK: false,
+ /**
+ * @ignore
+ * @type {Array.<string>}
+ */
+ persistentPaths: ['/userfs'],
+ /**
+ * @ignore
+ * @type {boolean}
+ */
+ persistentDrops: false,
+ /**
+ * @ignore
+ * @type {Array.<string>}
+ */
+ gdnativeLibs: [],
+ /**
+ * @ignore
+ * @type {Array.<string>}
+ */
+ fileSizes: [],
+ /**
+ * A callback function for handling Godot's ``OS.execute`` calls.
+ *
+ * This is for example used in the Web Editor template to switch between project manager and editor, and for running the game.
+ *
+ * @callback EngineConfig.onExecute
+ * @param {string} path The path that Godot's wants executed.
+ * @param {Array.<string>} args The arguments of the "command" to execute.
+ */
+ /**
+ * @ignore
+ * @type {?function(string, Array.<string>)}
+ */
+ onExecute: null,
+ /**
+ * A callback function for being notified when the Godot instance quits.
+ *
+ * **Note**: This function will not be called if the engine crashes or become unresponsive.
+ *
+ * @callback EngineConfig.onExit
+ * @param {number} status_code The status code returned by Godot on exit.
+ */
+ /**
+ * @ignore
+ * @type {?function(number)}
+ */
+ onExit: null,
+ /**
+ * A callback function for displaying download progress.
+ *
+ * The function is called once per frame while downloading files, so the usage of ``requestAnimationFrame()``
+ * is not necessary.
+ *
+ * If the callback function receives a total amount of bytes as 0, this means that it is impossible to calculate.
+ * Possible reasons include:
+ *
+ * - Files are delivered with server-side chunked compression
+ * - Files are delivered with server-side compression on Chromium
+ * - Not all file downloads have started yet (usually on servers without multi-threading)
+ *
+ * @callback EngineConfig.onProgress
+ * @param {number} current The current amount of downloaded bytes so far.
+ * @param {number} total The total amount of bytes to be downloaded.
+ */
+ /**
+ * @ignore
+ * @type {?function(number, number)}
+ */
+ onProgress: null,
+ /**
+ * A callback function for handling the standard output stream. This method should usually only be used in debug pages.
+ *
+ * By default, ``console.log()`` is used.
+ *
+ * @callback EngineConfig.onPrint
+ * @param {...*} [var_args] A variadic number of arguments to be printed.
+ */
+ /**
+ * @ignore
+ * @type {?function(...*)}
+ */
+ onPrint: function () {
+ console.log.apply(console, Array.from(arguments)); // eslint-disable-line no-console
+ },
+ /**
+ * A callback function for handling the standard error stream. This method should usually only be used in debug pages.
+ *
+ * By default, ``console.error()`` is used.
+ *
+ * @callback EngineConfig.onPrintError
+ * @param {...*} [var_args] A variadic number of arguments to be printed as errors.
+ */
+ /**
+ * @ignore
+ * @type {?function(...*)}
+ */
+ onPrintError: function (var_args) {
+ console.error.apply(console, Array.from(arguments)); // eslint-disable-line no-console
+ },
+ };
+
+ /**
+ * @ignore
+ * @struct
+ * @constructor
+ * @param {EngineConfig} opts
+ */
+ function Config(opts) {
+ this.update(opts);
+ }
+
+ Config.prototype = cfg;
+
+ /**
+ * @ignore
+ * @param {EngineConfig} opts
+ */
+ Config.prototype.update = function (opts) {
+ const config = opts || {};
+ function parse(key, def) {
+ if (typeof (config[key]) === 'undefined') {
+ return def;
+ }
+ return config[key];
+ }
+ // Module config
+ this.unloadAfterInit = parse('unloadAfterInit', this.unloadAfterInit);
+ this.onPrintError = parse('onPrintError', this.onPrintError);
+ this.onPrint = parse('onPrint', this.onPrint);
+ this.onProgress = parse('onProgress', this.onProgress);
+
+ // Godot config
+ this.canvas = parse('canvas', this.canvas);
+ this.executable = parse('executable', this.executable);
+ this.mainPack = parse('mainPack', this.mainPack);
+ this.locale = parse('locale', this.locale);
+ this.canvasResizePolicy = parse('canvasResizePolicy', this.canvasResizePolicy);
+ this.persistentPaths = parse('persistentPaths', this.persistentPaths);
+ this.persistentDrops = parse('persistentDrops', this.persistentDrops);
+ this.experimentalVK = parse('experimentalVK', this.experimentalVK);
+ this.gdnativeLibs = parse('gdnativeLibs', this.gdnativeLibs);
+ this.fileSizes = parse('fileSizes', this.fileSizes);
+ this.args = parse('args', this.args);
+ this.onExecute = parse('onExecute', this.onExecute);
+ this.onExit = parse('onExit', this.onExit);
+ };
+
+ /**
+ * @ignore
+ * @param {string} loadPath
+ * @param {Response} response
+ */
+ Config.prototype.getModuleConfig = function (loadPath, response) {
+ let r = response;
+ return {
+ 'print': this.onPrint,
+ 'printErr': this.onPrintError,
+ 'thisProgram': this.executable,
+ 'noExitRuntime': true,
+ 'dynamicLibraries': [`${loadPath}.side.wasm`],
+ 'instantiateWasm': function (imports, onSuccess) {
+ function done(result) {
+ onSuccess(result['instance'], result['module']);
+ }
+ if (typeof (WebAssembly.instantiateStreaming) !== 'undefined') {
+ WebAssembly.instantiateStreaming(Promise.resolve(r), imports).then(done);
+ } else {
+ r.arrayBuffer().then(function (buffer) {
+ WebAssembly.instantiate(buffer, imports).then(done);
+ });
+ }
+ r = null;
+ return {};
+ },
+ 'locateFile': function (path) {
+ if (path.endsWith('.worker.js')) {
+ return `${loadPath}.worker.js`;
+ } else if (path.endsWith('.audio.worklet.js')) {
+ return `${loadPath}.audio.worklet.js`;
+ } else if (path.endsWith('.js')) {
+ return `${loadPath}.js`;
+ } else if (path.endsWith('.side.wasm')) {
+ return `${loadPath}.side.wasm`;
+ } else if (path.endsWith('.wasm')) {
+ return `${loadPath}.wasm`;
+ }
+ return path;
+ },
+ };
+ };
+
+ /**
+ * @ignore
+ * @param {function()} cleanup
+ */
+ Config.prototype.getGodotConfig = function (cleanup) {
+ // Try to find a canvas
+ if (!(this.canvas instanceof HTMLCanvasElement)) {
+ const nodes = document.getElementsByTagName('canvas');
+ if (nodes.length && nodes[0] instanceof HTMLCanvasElement) {
+ this.canvas = nodes[0];
+ }
+ if (!this.canvas) {
+ throw new Error('No canvas found in page');
+ }
+ }
+ // Canvas can grab focus on click, or key events won't work.
+ if (this.canvas.tabIndex < 0) {
+ this.canvas.tabIndex = 0;
+ }
+
+ // Browser locale, or custom one if defined.
+ let locale = this.locale;
+ if (!locale) {
+ locale = navigator.languages ? navigator.languages[0] : navigator.language;
+ locale = locale.split('.')[0];
+ }
+ const onExit = this.onExit;
+
+ // Godot configuration.
+ return {
+ 'canvas': this.canvas,
+ 'canvasResizePolicy': this.canvasResizePolicy,
+ 'locale': locale,
+ 'persistentDrops': this.persistentDrops,
+ 'virtualKeyboard': this.experimentalVK,
+ 'onExecute': this.onExecute,
+ 'onExit': function (p_code) {
+ cleanup(); // We always need to call the cleanup callback to free memory.
+ if (typeof (onExit) === 'function') {
+ onExit(p_code);
+ }
+ },
+ };
+ };
+ return new Config(initConfig);
+};
diff --git a/platform/javascript/js/engine/engine.externs.js b/platform/javascript/js/engine/engine.externs.js
index 1a94dd15ec..35a66a93ae 100644
--- a/platform/javascript/js/engine/engine.externs.js
+++ b/platform/javascript/js/engine/engine.externs.js
@@ -1,3 +1,4 @@
var Godot;
var WebAssembly = {};
WebAssembly.instantiate = function(buffer, imports) {};
+WebAssembly.instantiateStreaming = function(response, imports) {};
diff --git a/platform/javascript/js/engine/engine.js b/platform/javascript/js/engine/engine.js
index 01232cbece..7211ebbfd8 100644
--- a/platform/javascript/js/engine/engine.js
+++ b/platform/javascript/js/engine/engine.js
@@ -1,291 +1,273 @@
+/**
+ * Projects exported for the Web expose the :js:class:`Engine` class to the JavaScript environment, that allows
+ * fine control over the engine's start-up process.
+ *
+ * This API is built in an asynchronous manner and requires basic understanding
+ * of `Promises <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises>`__.
+ *
+ * @module Engine
+ * @header HTML5 shell class reference
+ */
const Engine = (function () {
const preloader = new Preloader();
- let wasmExt = '.wasm';
- let unloadAfterInit = true;
- let loadPath = '';
let loadPromise = null;
+ let loadPath = '';
let initPromise = null;
- let stderr = null;
- let stdout = null;
- let progressFunc = null;
- function load(basePath) {
+ /**
+ * @classdesc The ``Engine`` class provides methods for loading and starting exported projects on the Web. For default export
+ * settings, this is already part of the exported HTML page. To understand practical use of the ``Engine`` class,
+ * see :ref:`Custom HTML page for Web export <doc_customizing_html5_shell>`.
+ *
+ * @description Create a new Engine instance with the given configuration.
+ *
+ * @global
+ * @constructor
+ * @param {EngineConfig} initConfig The initial config for this instance.
+ */
+ function Engine(initConfig) { // eslint-disable-line no-shadow
+ this.config = new InternalConfig(initConfig);
+ this.rtenv = null;
+ }
+
+ /**
+ * Load the engine from the specified base path.
+ *
+ * @param {string} basePath Base path of the engine to load.
+ * @param {number=} [size=0] The file size if known.
+ * @returns {Promise} A Promise that resolves once the engine is loaded.
+ *
+ * @function Engine.load
+ */
+ Engine.load = function (basePath, size) {
if (loadPromise == null) {
loadPath = basePath;
- loadPromise = preloader.loadPromise(basePath + wasmExt);
- preloader.setProgressFunc(progressFunc);
+ loadPromise = preloader.loadPromise(`${loadPath}.wasm`, size, true);
requestAnimationFrame(preloader.animateProgress);
}
return loadPromise;
- }
+ };
- function unload() {
+ /**
+ * Unload the engine to free memory.
+ *
+ * This method will be called automatically depending on the configuration. See :js:attr:`unloadAfterInit`.
+ *
+ * @function Engine.unload
+ */
+ Engine.unload = function () {
loadPromise = null;
- }
-
- /** @constructor */
- function Engine() { // eslint-disable-line no-shadow
- this.canvas = null;
- this.executableName = '';
- this.rtenv = null;
- this.customLocale = null;
- this.resizeCanvasOnStart = false;
- this.onExecute = null;
- this.onExit = null;
- this.persistentPaths = ['/userfs'];
- this.gdnativeLibs = [];
- }
-
- Engine.prototype.init = /** @param {string=} basePath */ function (basePath) {
- if (initPromise) {
- return initPromise;
- }
- if (loadPromise == null) {
- if (!basePath) {
- initPromise = Promise.reject(new Error('A base path must be provided when calling `init` and the engine is not loaded.'));
- return initPromise;
- }
- load(basePath);
- }
- let config = {};
- if (typeof stdout === 'function') {
- config.print = stdout;
- }
- if (typeof stderr === 'function') {
- config.printErr = stderr;
- }
- const me = this;
- initPromise = new Promise(function (resolve, reject) {
- config['locateFile'] = Utils.createLocateRewrite(loadPath);
- config['instantiateWasm'] = Utils.createInstantiatePromise(loadPromise);
- // Emscripten configuration.
- config['thisProgram'] = me.executableName;
- config['noExitRuntime'] = true;
- config['dynamicLibraries'] = [`${me.executableName}.side.wasm`].concat(me.gdnativeLibs);
- Godot(config).then(function (module) {
- module['initFS'](me.persistentPaths).then(function (fs_err) {
- me.rtenv = module;
- if (unloadAfterInit) {
- unload();
- }
- resolve();
- config = null;
- });
- });
- });
- return initPromise;
};
- /** @type {function(string, string):Object} */
- Engine.prototype.preloadFile = function (file, path) {
- return preloader.preload(file, path);
+ /**
+ * Check whether WebGL is available. Optionally, specify a particular version of WebGL to check for.
+ *
+ * @param {number=} [majorVersion=1] The major WebGL version to check for.
+ * @returns {boolean} If the given major version of WebGL is available.
+ * @function Engine.isWebGLAvailable
+ */
+ Engine.isWebGLAvailable = function (majorVersion = 1) {
+ try {
+ return !!document.createElement('canvas').getContext(['webgl', 'webgl2'][majorVersion - 1]);
+ } catch (e) { /* Not available */ }
+ return false;
};
- /** @type {function(...string):Object} */
- Engine.prototype.start = function () {
- // Start from arguments.
- const args = [];
- for (let i = 0; i < arguments.length; i++) {
- args.push(arguments[i]);
- }
- const me = this;
- return me.init().then(function () {
- if (!me.rtenv) {
- return Promise.reject(new Error('The engine must be initialized before it can be started'));
- }
-
- if (!(me.canvas instanceof HTMLCanvasElement)) {
- me.canvas = Utils.findCanvas();
- if (!me.canvas) {
- return Promise.reject(new Error('No canvas found in page'));
+ /**
+ * Safe Engine constructor, creates a new prototype for every new instance to avoid prototype pollution.
+ * @ignore
+ * @constructor
+ */
+ function SafeEngine(initConfig) {
+ const proto = /** @lends Engine.prototype */ {
+ /**
+ * Initialize the engine instance. Optionally, pass the base path to the engine to load it,
+ * if it hasn't been loaded yet. See :js:meth:`Engine.load`.
+ *
+ * @param {string=} basePath Base path of the engine to load.
+ * @return {Promise} A ``Promise`` that resolves once the engine is loaded and initialized.
+ */
+ init: function (basePath) {
+ if (initPromise) {
+ return initPromise;
}
- }
-
- // Canvas can grab focus on click, or key events won't work.
- if (me.canvas.tabIndex < 0) {
- me.canvas.tabIndex = 0;
- }
-
- // Disable right-click context menu.
- me.canvas.addEventListener('contextmenu', function (ev) {
- ev.preventDefault();
- }, false);
+ if (loadPromise == null) {
+ if (!basePath) {
+ initPromise = Promise.reject(new Error('A base path must be provided when calling `init` and the engine is not loaded.'));
+ return initPromise;
+ }
+ Engine.load(basePath, this.config.fileSizes[`${basePath}.wasm`]);
+ }
+ const me = this;
+ function doInit(promise) {
+ return promise.then(function (response) {
+ return Godot(me.config.getModuleConfig(loadPath, new Response(response.clone().body, { 'headers': [['content-type', 'application/wasm']] })));
+ }).then(function (module) {
+ const paths = me.config.persistentPaths;
+ return module['initFS'](paths).then(function (err) {
+ return Promise.resolve(module);
+ });
+ }).then(function (module) {
+ me.rtenv = module;
+ if (me.config.unloadAfterInit) {
+ Engine.unload();
+ }
+ return Promise.resolve();
+ });
+ }
+ preloader.setProgressFunc(this.config.onProgress);
+ initPromise = doInit(loadPromise);
+ return initPromise;
+ },
- // Until context restoration is implemented warn the user of context loss.
- me.canvas.addEventListener('webglcontextlost', function (ev) {
- alert('WebGL context lost, please reload the page'); // eslint-disable-line no-alert
- ev.preventDefault();
- }, false);
+ /**
+ * Load a file so it is available in the instance's file system once it runs. Must be called **before** starting the
+ * instance.
+ *
+ * If not provided, the ``path`` is derived from the URL of the loaded file.
+ *
+ * @param {string|ArrayBuffer} file The file to preload.
+ *
+ * If a ``string`` the file will be loaded from that path.
+ *
+ * If an ``ArrayBuffer`` or a view on one, the buffer will used as the content of the file.
+ *
+ * @param {string=} path Path by which the file will be accessible. Required, if ``file`` is not a string.
+ *
+ * @returns {Promise} A Promise that resolves once the file is loaded.
+ */
+ preloadFile: function (file, path) {
+ return preloader.preload(file, path, this.config.fileSizes[file]);
+ },
- // Browser locale, or custom one if defined.
- let locale = me.customLocale;
- if (!locale) {
- locale = navigator.languages ? navigator.languages[0] : navigator.language;
- locale = locale.split('.')[0];
- }
- // Godot configuration.
- me.rtenv['initConfig']({
- 'resizeCanvasOnStart': me.resizeCanvasOnStart,
- 'canvas': me.canvas,
- 'locale': locale,
- 'onExecute': function (p_args) {
- if (me.onExecute) {
- me.onExecute(p_args);
- return 0;
+ /**
+ * Start the engine instance using the given override configuration (if any).
+ * :js:meth:`startGame <Engine.prototype.startGame>` can be used in typical cases instead.
+ *
+ * This will initialize the instance if it is not initialized. For manual initialization, see :js:meth:`init <Engine.prototype.init>`.
+ * The engine must be loaded beforehand.
+ *
+ * Fails if a canvas cannot be found on the page, or not specified in the configuration.
+ *
+ * @param {EngineConfig} override An optional configuration override.
+ * @return {Promise} Promise that resolves once the engine started.
+ */
+ start: function (override) {
+ this.config.update(override);
+ const me = this;
+ return me.init().then(function () {
+ if (!me.rtenv) {
+ return Promise.reject(new Error('The engine must be initialized before it can be started'));
}
- return 1;
- },
- 'onExit': function (p_code) {
- me.rtenv['deinitFS']();
- if (me.onExit) {
- me.onExit(p_code);
+
+ let config = {};
+ try {
+ config = me.config.getGodotConfig(function () {
+ me.rtenv = null;
+ });
+ } catch (e) {
+ return Promise.reject(e);
}
- me.rtenv = null;
- },
- });
+ // Godot configuration.
+ me.rtenv['initConfig'](config);
- return new Promise(function (resolve, reject) {
- preloader.preloadedFiles.forEach(function (file) {
- me.rtenv['copyToFS'](file.path, file.buffer);
+ // Preload GDNative libraries.
+ const libs = [];
+ me.config.gdnativeLibs.forEach(function (lib) {
+ libs.push(me.rtenv['loadDynamicLibrary'](lib, { 'loadAsync': true }));
+ });
+ return Promise.all(libs).then(function () {
+ return new Promise(function (resolve, reject) {
+ preloader.preloadedFiles.forEach(function (file) {
+ me.rtenv['copyToFS'](file.path, file.buffer);
+ });
+ preloader.preloadedFiles.length = 0; // Clear memory
+ me.rtenv['callMain'](me.config.args);
+ initPromise = null;
+ resolve();
+ });
+ });
});
- preloader.preloadedFiles.length = 0; // Clear memory
- me.rtenv['callMain'](args);
- initPromise = null;
- resolve();
- });
- });
- };
+ },
- Engine.prototype.startGame = function (execName, mainPack, extraArgs) {
- // Start and init with execName as loadPath if not inited.
- this.executableName = execName;
- const me = this;
- return Promise.all([
- this.init(execName),
- this.preloadFile(mainPack, mainPack),
- ]).then(function () {
- let args = ['--main-pack', mainPack];
- if (extraArgs) {
- args = args.concat(extraArgs);
- }
- return me.start.apply(me, args);
- });
- };
-
- Engine.prototype.setWebAssemblyFilenameExtension = function (override) {
- if (String(override).length === 0) {
- throw new Error('Invalid WebAssembly filename extension override');
- }
- wasmExt = String(override);
- };
-
- Engine.prototype.setUnloadAfterInit = function (enabled) {
- unloadAfterInit = enabled;
- };
-
- Engine.prototype.setCanvas = function (canvasElem) {
- this.canvas = canvasElem;
- };
-
- Engine.prototype.setCanvasResizedOnStart = function (enabled) {
- this.resizeCanvasOnStart = enabled;
- };
-
- Engine.prototype.setLocale = function (locale) {
- this.customLocale = locale;
- };
-
- Engine.prototype.setExecutableName = function (newName) {
- this.executableName = newName;
- };
-
- Engine.prototype.setProgressFunc = function (func) {
- progressFunc = func;
- };
+ /**
+ * Start the game instance using the given configuration override (if any).
+ *
+ * This will initialize the instance if it is not initialized. For manual initialization, see :js:meth:`init <Engine.prototype.init>`.
+ *
+ * This will load the engine if it is not loaded, and preload the main pck.
+ *
+ * This method expects the initial config (or the override) to have both the :js:attr:`executable` and :js:attr:`mainPack`
+ * properties set (normally done by the editor during export).
+ *
+ * @param {EngineConfig} override An optional configuration override.
+ * @return {Promise} Promise that resolves once the game started.
+ */
+ startGame: function (override) {
+ this.config.update(override);
+ // Add main-pack argument.
+ const exe = this.config.executable;
+ const pack = this.config.mainPack || `${exe}.pck`;
+ this.config.args = ['--main-pack', pack].concat(this.config.args);
+ // Start and init with execName as loadPath if not inited.
+ const me = this;
+ return Promise.all([
+ this.init(exe),
+ this.preloadFile(pack, pack),
+ ]).then(function () {
+ return me.start.apply(me);
+ });
+ },
- Engine.prototype.setStdoutFunc = function (func) {
- const print = function (text) {
- let msg = text;
- if (arguments.length > 1) {
- msg = Array.prototype.slice.call(arguments).join(' ');
- }
- func(msg);
- };
- if (this.rtenv) {
- this.rtenv.print = print;
- }
- stdout = print;
- };
+ /**
+ * Create a file at the specified ``path`` with the passed as ``buffer`` in the instance's file system.
+ *
+ * @param {string} path The location where the file will be created.
+ * @param {ArrayBuffer} buffer The content of the file.
+ */
+ copyToFS: function (path, buffer) {
+ if (this.rtenv == null) {
+ throw new Error('Engine must be inited before copying files');
+ }
+ this.rtenv['copyToFS'](path, buffer);
+ },
- Engine.prototype.setStderrFunc = function (func) {
- const printErr = function (text) {
- let msg = text;
- if (arguments.length > 1) {
- msg = Array.prototype.slice.call(arguments).join(' ');
- }
- func(msg);
+ /**
+ * Request that the current instance quit.
+ *
+ * This is akin the user pressing the close button in the window manager, and will
+ * have no effect if the engine has crashed, or is stuck in a loop.
+ *
+ */
+ requestQuit: function () {
+ if (this.rtenv) {
+ this.rtenv['request_quit']();
+ }
+ },
};
- if (this.rtenv) {
- this.rtenv.printErr = printErr;
- }
- stderr = printErr;
- };
-
- Engine.prototype.setOnExecute = function (onExecute) {
- this.onExecute = onExecute;
- };
-
- Engine.prototype.setOnExit = function (onExit) {
- this.onExit = onExit;
- };
-
- Engine.prototype.copyToFS = function (path, buffer) {
- if (this.rtenv == null) {
- throw new Error('Engine must be inited before copying files');
- }
- this.rtenv['copyToFS'](path, buffer);
- };
-
- Engine.prototype.setPersistentPaths = function (persistentPaths) {
- this.persistentPaths = persistentPaths;
- };
- Engine.prototype.setGDNativeLibraries = function (gdnativeLibs) {
- this.gdnativeLibs = gdnativeLibs;
- };
+ Engine.prototype = proto;
+ // Closure compiler exported instance methods.
+ Engine.prototype['init'] = Engine.prototype.init;
+ Engine.prototype['preloadFile'] = Engine.prototype.preloadFile;
+ Engine.prototype['start'] = Engine.prototype.start;
+ Engine.prototype['startGame'] = Engine.prototype.startGame;
+ Engine.prototype['copyToFS'] = Engine.prototype.copyToFS;
+ Engine.prototype['requestQuit'] = Engine.prototype.requestQuit;
+ // Also expose static methods as instance methods
+ Engine.prototype['load'] = Engine.load;
+ Engine.prototype['unload'] = Engine.unload;
+ Engine.prototype['isWebGLAvailable'] = Engine.isWebGLAvailable;
+ return new Engine(initConfig);
+ }
- Engine.prototype.requestQuit = function () {
- if (this.rtenv) {
- this.rtenv['request_quit']();
- }
- };
+ // Closure compiler exported static methods.
+ SafeEngine['load'] = Engine.load;
+ SafeEngine['unload'] = Engine.unload;
+ SafeEngine['isWebGLAvailable'] = Engine.isWebGLAvailable;
- // Closure compiler exported engine methods.
- /** @export */
- Engine['isWebGLAvailable'] = Utils.isWebGLAvailable;
- Engine['load'] = load;
- Engine['unload'] = unload;
- Engine.prototype['init'] = Engine.prototype.init;
- Engine.prototype['preloadFile'] = Engine.prototype.preloadFile;
- Engine.prototype['start'] = Engine.prototype.start;
- Engine.prototype['startGame'] = Engine.prototype.startGame;
- Engine.prototype['setWebAssemblyFilenameExtension'] = Engine.prototype.setWebAssemblyFilenameExtension;
- Engine.prototype['setUnloadAfterInit'] = Engine.prototype.setUnloadAfterInit;
- Engine.prototype['setCanvas'] = Engine.prototype.setCanvas;
- Engine.prototype['setCanvasResizedOnStart'] = Engine.prototype.setCanvasResizedOnStart;
- Engine.prototype['setLocale'] = Engine.prototype.setLocale;
- Engine.prototype['setExecutableName'] = Engine.prototype.setExecutableName;
- Engine.prototype['setProgressFunc'] = Engine.prototype.setProgressFunc;
- Engine.prototype['setStdoutFunc'] = Engine.prototype.setStdoutFunc;
- Engine.prototype['setStderrFunc'] = Engine.prototype.setStderrFunc;
- Engine.prototype['setOnExecute'] = Engine.prototype.setOnExecute;
- Engine.prototype['setOnExit'] = Engine.prototype.setOnExit;
- Engine.prototype['copyToFS'] = Engine.prototype.copyToFS;
- Engine.prototype['setPersistentPaths'] = Engine.prototype.setPersistentPaths;
- Engine.prototype['setGDNativeLibraries'] = Engine.prototype.setGDNativeLibraries;
- Engine.prototype['requestQuit'] = Engine.prototype.requestQuit;
- return Engine;
+ return SafeEngine;
}());
if (typeof window !== 'undefined') {
window['Engine'] = Engine;
diff --git a/platform/javascript/js/engine/preloader.js b/platform/javascript/js/engine/preloader.js
index ec34fb93f2..3535fdb361 100644
--- a/platform/javascript/js/engine/preloader.js
+++ b/platform/javascript/js/engine/preloader.js
@@ -1,54 +1,79 @@
const Preloader = /** @constructor */ function () { // eslint-disable-line no-unused-vars
- const loadXHR = function (resolve, reject, file, tracker, attempts) {
- const xhr = new XMLHttpRequest();
+ function getTrackedResponse(response, load_status) {
+ let clen = 0;
+ let compressed = false;
+ response.headers.forEach(function (value, header) {
+ const h = header.toLowerCase().trim();
+ // We can't accurately compute compressed stream length.
+ if (h === 'content-encoding') {
+ compressed = true;
+ } else if (h === 'content-length') {
+ const length = parseInt(value, 10);
+ if (!Number.isNaN(length) && length > 0) {
+ clen = length;
+ }
+ }
+ });
+ if (!compressed && clen) {
+ load_status.total = clen;
+ }
+ function onloadprogress(reader, controller) {
+ return reader.read().then(function (result) {
+ if (load_status.done) {
+ return Promise.resolve();
+ }
+ if (result.value) {
+ controller.enqueue(result.value);
+ load_status.loaded += result.value.length;
+ }
+ if (!result.done) {
+ return onloadprogress(reader, controller);
+ }
+ load_status.done = true;
+ return Promise.resolve();
+ });
+ }
+ const reader = response.body.getReader();
+ return new Response(new ReadableStream({
+ start: function (controller) {
+ onloadprogress(reader, controller).then(function () {
+ controller.close();
+ });
+ },
+ }), { headers: response.headers });
+ }
+
+ function loadFetch(file, tracker, fileSize, raw) {
tracker[file] = {
- total: 0,
+ total: fileSize || 0,
loaded: 0,
- final: false,
+ done: false,
};
- xhr.onerror = function () {
+ return fetch(file).then(function (response) {
+ if (!response.ok) {
+ return Promise.reject(new Error(`Failed loading file '${file}'`));
+ }
+ const tr = getTrackedResponse(response, tracker[file]);
+ if (raw) {
+ return Promise.resolve(tr);
+ }
+ return tr.arrayBuffer();
+ });
+ }
+
+ function retry(func, attempts = 1) {
+ function onerror(err) {
if (attempts <= 1) {
- reject(new Error(`Failed loading file '${file}'`));
- } else {
+ return Promise.reject(err);
+ }
+ return new Promise(function (resolve, reject) {
setTimeout(function () {
- loadXHR(resolve, reject, file, tracker, attempts - 1);
+ retry(func, attempts - 1).then(resolve).catch(reject);
}, 1000);
- }
- };
- xhr.onabort = function () {
- tracker[file].final = true;
- reject(new Error(`Loading file '${file}' was aborted.`));
- };
- xhr.onloadstart = function (ev) {
- tracker[file].total = ev.total;
- tracker[file].loaded = ev.loaded;
- };
- xhr.onprogress = function (ev) {
- tracker[file].loaded = ev.loaded;
- tracker[file].total = ev.total;
- };
- xhr.onload = function () {
- if (xhr.status >= 400) {
- if (xhr.status < 500 || attempts <= 1) {
- reject(new Error(`Failed loading file '${file}': ${xhr.statusText}`));
- xhr.abort();
- } else {
- setTimeout(function () {
- loadXHR(resolve, reject, file, tracker, attempts - 1);
- }, 1000);
- }
- } else {
- tracker[file].final = true;
- resolve(xhr);
- }
- };
- // Make request.
- xhr.open('GET', file);
- if (!file.endsWith('.js')) {
- xhr.responseType = 'arraybuffer';
+ });
}
- xhr.send();
- };
+ return func().catch(onerror);
+ }
const DOWNLOAD_ATTEMPTS_MAX = 4;
const loadingFiles = {};
@@ -63,7 +88,7 @@ const Preloader = /** @constructor */ function () { // eslint-disable-line no-un
Object.keys(loadingFiles).forEach(function (file) {
const stat = loadingFiles[file];
- if (!stat.final) {
+ if (!stat.done) {
progressIsFinal = false;
}
if (!totalIsValid || stat.total === 0) {
@@ -92,21 +117,19 @@ const Preloader = /** @constructor */ function () { // eslint-disable-line no-un
progressFunc = callback;
};
- this.loadPromise = function (file) {
- return new Promise(function (resolve, reject) {
- loadXHR(resolve, reject, file, loadingFiles, DOWNLOAD_ATTEMPTS_MAX);
- });
+ this.loadPromise = function (file, fileSize, raw = false) {
+ return retry(loadFetch.bind(null, file, loadingFiles, fileSize, raw), DOWNLOAD_ATTEMPTS_MAX);
};
this.preloadedFiles = [];
- this.preload = function (pathOrBuffer, destPath) {
+ this.preload = function (pathOrBuffer, destPath, fileSize) {
let buffer = null;
if (typeof pathOrBuffer === 'string') {
const me = this;
- return this.loadPromise(pathOrBuffer).then(function (xhr) {
+ return this.loadPromise(pathOrBuffer, fileSize).then(function (buf) {
me.preloadedFiles.push({
path: destPath || pathOrBuffer,
- buffer: xhr.response,
+ buffer: buf,
});
return Promise.resolve();
});
diff --git a/platform/javascript/js/engine/utils.js b/platform/javascript/js/engine/utils.js
deleted file mode 100644
index 9273bbad42..0000000000
--- a/platform/javascript/js/engine/utils.js
+++ /dev/null
@@ -1,58 +0,0 @@
-const Utils = { // eslint-disable-line no-unused-vars
-
- createLocateRewrite: function (execName) {
- function rw(path) {
- if (path.endsWith('.worker.js')) {
- return `${execName}.worker.js`;
- } else if (path.endsWith('.audio.worklet.js')) {
- return `${execName}.audio.worklet.js`;
- } else if (path.endsWith('.js')) {
- return `${execName}.js`;
- } else if (path.endsWith('.side.wasm')) {
- return `${execName}.side.wasm`;
- } else if (path.endsWith('.wasm')) {
- return `${execName}.wasm`;
- }
- return path;
- }
- return rw;
- },
-
- createInstantiatePromise: function (wasmLoader) {
- let loader = wasmLoader;
- function instantiateWasm(imports, onSuccess) {
- loader.then(function (xhr) {
- WebAssembly.instantiate(xhr.response, imports).then(function (result) {
- onSuccess(result['instance'], result['module']);
- });
- });
- loader = null;
- return {};
- }
-
- return instantiateWasm;
- },
-
- findCanvas: function () {
- const nodes = document.getElementsByTagName('canvas');
- if (nodes.length && nodes[0] instanceof HTMLCanvasElement) {
- return nodes[0];
- }
- return null;
- },
-
- isWebGLAvailable: function (majorVersion = 1) {
- let testContext = false;
- try {
- const testCanvas = document.createElement('canvas');
- if (majorVersion === 1) {
- testContext = testCanvas.getContext('webgl') || testCanvas.getContext('experimental-webgl');
- } else if (majorVersion === 2) {
- testContext = testCanvas.getContext('webgl2') || testCanvas.getContext('experimental-webgl2');
- }
- } catch (e) {
- // Not available
- }
- return !!testContext;
- },
-};
diff --git a/platform/javascript/js/jsdoc2rst/publish.js b/platform/javascript/js/jsdoc2rst/publish.js
new file mode 100644
index 0000000000..ad9c0fbaaa
--- /dev/null
+++ b/platform/javascript/js/jsdoc2rst/publish.js
@@ -0,0 +1,354 @@
+/* eslint-disable strict */
+
+'use strict';
+
+const fs = require('fs');
+
+class JSDoclet {
+ constructor(doc) {
+ this.doc = doc;
+ this.description = doc['description'] || '';
+ this.name = doc['name'] || 'unknown';
+ this.longname = doc['longname'] || '';
+ this.types = [];
+ if (doc['type'] && doc['type']['names']) {
+ this.types = doc['type']['names'].slice();
+ }
+ this.type = this.types.length > 0 ? this.types.join('\\|') : '*';
+ this.variable = doc['variable'] || false;
+ this.kind = doc['kind'] || '';
+ this.memberof = doc['memberof'] || null;
+ this.scope = doc['scope'] || '';
+ this.members = [];
+ this.optional = doc['optional'] || false;
+ this.defaultvalue = doc['defaultvalue'];
+ this.summary = doc['summary'] || null;
+ this.classdesc = doc['classdesc'] || null;
+
+ // Parameters (functions)
+ this.params = [];
+ this.returns = doc['returns'] ? doc['returns'][0]['type']['names'][0] : 'void';
+ this.returns_desc = doc['returns'] ? doc['returns'][0]['description'] : null;
+
+ this.params = (doc['params'] || []).slice().map((p) => new JSDoclet(p));
+
+ // Custom tags
+ this.tags = doc['tags'] || [];
+ this.header = this.tags.filter((t) => t['title'] === 'header').map((t) => t['text']).pop() || null;
+ }
+
+ add_member(obj) {
+ this.members.push(obj);
+ }
+
+ is_static() {
+ return this.scope === 'static';
+ }
+
+ is_instance() {
+ return this.scope === 'instance';
+ }
+
+ is_object() {
+ return this.kind === 'Object' || (this.kind === 'typedef' && this.type === 'Object');
+ }
+
+ is_class() {
+ return this.kind === 'class';
+ }
+
+ is_function() {
+ return this.kind === 'function' || (this.kind === 'typedef' && this.type === 'function');
+ }
+
+ is_module() {
+ return this.kind === 'module';
+ }
+}
+
+function format_table(f, data, depth = 0) {
+ if (!data.length) {
+ return;
+ }
+
+ const column_sizes = new Array(data[0].length).fill(0);
+
+ data.forEach((row) => {
+ row.forEach((e, idx) => {
+ column_sizes[idx] = Math.max(e.length, column_sizes[idx]);
+ });
+ });
+
+ const indent = ' '.repeat(depth);
+ let sep = indent;
+ column_sizes.forEach((size) => {
+ sep += '+';
+ sep += '-'.repeat(size + 2);
+ });
+ sep += '+\n';
+ f.write(sep);
+
+ data.forEach((row) => {
+ let row_text = `${indent}|`;
+ row.forEach((entry, idx) => {
+ row_text += ` ${entry.padEnd(column_sizes[idx])} |`;
+ });
+ row_text += '\n';
+ f.write(row_text);
+ f.write(sep);
+ });
+
+ f.write('\n');
+}
+
+function make_header(header, sep) {
+ return `${header}\n${sep.repeat(header.length)}\n\n`;
+}
+
+function indent_multiline(text, depth) {
+ const indent = ' '.repeat(depth);
+ return text.split('\n').map((l) => (l === '' ? l : indent + l)).join('\n');
+}
+
+function make_rst_signature(obj, types = false, style = false) {
+ let out = '';
+ const fmt = style ? '*' : '';
+ obj.params.forEach((arg, idx) => {
+ if (idx > 0) {
+ if (arg.optional) {
+ out += ` ${fmt}[`;
+ }
+ out += ', ';
+ } else {
+ out += ' ';
+ if (arg.optional) {
+ out += `${fmt}[ `;
+ }
+ }
+ if (types) {
+ out += `${arg.type} `;
+ }
+ const variable = arg.variable ? '...' : '';
+ const defval = arg.defaultvalue !== undefined ? `=${arg.defaultvalue}` : '';
+ out += `${variable}${arg.name}${defval}`;
+ if (arg.optional) {
+ out += ` ]${fmt}`;
+ }
+ });
+ out += ' ';
+ return out;
+}
+
+function make_rst_param(f, obj, depth = 0) {
+ const indent = ' '.repeat(depth * 3);
+ f.write(indent);
+ f.write(`:param ${obj.type} ${obj.name}:\n`);
+ f.write(indent_multiline(obj.description, (depth + 1) * 3));
+ f.write('\n\n');
+}
+
+function make_rst_attribute(f, obj, depth = 0, brief = false) {
+ const indent = ' '.repeat(depth * 3);
+ f.write(indent);
+ f.write(`.. js:attribute:: ${obj.name}\n\n`);
+
+ if (brief) {
+ if (obj.summary) {
+ f.write(indent_multiline(obj.summary, (depth + 1) * 3));
+ }
+ f.write('\n\n');
+ return;
+ }
+
+ f.write(indent_multiline(obj.description, (depth + 1) * 3));
+ f.write('\n\n');
+
+ f.write(indent);
+ f.write(` :type: ${obj.type}\n\n`);
+
+ if (obj.defaultvalue !== undefined) {
+ let defval = obj.defaultvalue;
+ if (defval === '') {
+ defval = '""';
+ }
+ f.write(indent);
+ f.write(` :value: \`\`${defval}\`\`\n\n`);
+ }
+}
+
+function make_rst_function(f, obj, depth = 0) {
+ let prefix = '';
+ if (obj.is_instance()) {
+ prefix = 'prototype.';
+ }
+
+ const indent = ' '.repeat(depth * 3);
+ const sig = make_rst_signature(obj);
+ f.write(indent);
+ f.write(`.. js:function:: ${prefix}${obj.name}(${sig})\n`);
+ f.write('\n');
+
+ f.write(indent_multiline(obj.description, (depth + 1) * 3));
+ f.write('\n\n');
+
+ obj.params.forEach((param) => {
+ make_rst_param(f, param, depth + 1);
+ });
+
+ if (obj.returns !== 'void') {
+ f.write(indent);
+ f.write(' :return:\n');
+ f.write(indent_multiline(obj.returns_desc, (depth + 2) * 3));
+ f.write('\n\n');
+ f.write(indent);
+ f.write(` :rtype: ${obj.returns}\n\n`);
+ }
+}
+
+function make_rst_object(f, obj) {
+ let brief = false;
+ // Our custom header flag.
+ if (obj.header !== null) {
+ f.write(make_header(obj.header, '-'));
+ f.write(`${obj.description}\n\n`);
+ brief = true;
+ }
+
+ // Format members table and descriptions
+ const data = [['type', 'name']].concat(obj.members.map((m) => [m.type, `:js:attr:\`${m.name}\``]));
+
+ f.write(make_header('Properties', '^'));
+ format_table(f, data, 0);
+
+ make_rst_attribute(f, obj, 0, brief);
+
+ if (!obj.members.length) {
+ return;
+ }
+
+ f.write(' **Property Descriptions**\n\n');
+
+ // Properties first
+ obj.members.filter((m) => !m.is_function()).forEach((m) => {
+ make_rst_attribute(f, m, 1);
+ });
+
+ // Callbacks last
+ obj.members.filter((m) => m.is_function()).forEach((m) => {
+ make_rst_function(f, m, 1);
+ });
+}
+
+function make_rst_class(f, obj) {
+ const header = obj.header ? obj.header : obj.name;
+ f.write(make_header(header, '-'));
+
+ if (obj.classdesc) {
+ f.write(`${obj.classdesc}\n\n`);
+ }
+
+ const funcs = obj.members.filter((m) => m.is_function());
+ function make_data(m) {
+ const base = m.is_static() ? obj.name : `${obj.name}.prototype`;
+ const params = make_rst_signature(m, true, true);
+ const sig = `:js:attr:\`${m.name} <${base}.${m.name}>\` **(**${params}**)**`;
+ return [m.returns, sig];
+ }
+ const sfuncs = funcs.filter((m) => m.is_static());
+ const ifuncs = funcs.filter((m) => !m.is_static());
+
+ f.write(make_header('Static Methods', '^'));
+ format_table(f, sfuncs.map((m) => make_data(m)));
+
+ f.write(make_header('Instance Methods', '^'));
+ format_table(f, ifuncs.map((m) => make_data(m)));
+
+ const sig = make_rst_signature(obj);
+ f.write(`.. js:class:: ${obj.name}(${sig})\n\n`);
+ f.write(indent_multiline(obj.description, 3));
+ f.write('\n\n');
+
+ obj.params.forEach((p) => {
+ make_rst_param(f, p, 1);
+ });
+
+ f.write(' **Static Methods**\n\n');
+ sfuncs.forEach((m) => {
+ make_rst_function(f, m, 1);
+ });
+
+ f.write(' **Instance Methods**\n\n');
+ ifuncs.forEach((m) => {
+ make_rst_function(f, m, 1);
+ });
+}
+
+function make_rst_module(f, obj) {
+ const header = obj.header !== null ? obj.header : obj.name;
+ f.write(make_header(header, '='));
+ f.write(obj.description);
+ f.write('\n\n');
+}
+
+function write_base_object(f, obj) {
+ if (obj.is_object()) {
+ make_rst_object(f, obj);
+ } else if (obj.is_function()) {
+ make_rst_function(f, obj);
+ } else if (obj.is_class()) {
+ make_rst_class(f, obj);
+ } else if (obj.is_module()) {
+ make_rst_module(f, obj);
+ }
+}
+
+function generate(f, docs) {
+ const globs = [];
+ const SYMBOLS = {};
+ docs.filter((d) => !d.ignore && d.kind !== 'package').forEach((d) => {
+ SYMBOLS[d.name] = d;
+ if (d.memberof) {
+ const up = SYMBOLS[d.memberof];
+ if (up === undefined) {
+ console.log(d); // eslint-disable-line no-console
+ console.log(`Undefined symbol! ${d.memberof}`); // eslint-disable-line no-console
+ throw new Error('Undefined symbol!');
+ }
+ SYMBOLS[d.memberof].add_member(d);
+ } else {
+ globs.push(d);
+ }
+ });
+
+ f.write('.. _doc_html5_shell_classref:\n\n');
+ globs.forEach((obj) => write_base_object(f, obj));
+}
+
+/**
+ * Generate documentation output.
+ *
+ * @param {TAFFY} data - A TaffyDB collection representing
+ * all the symbols documented in your code.
+ * @param {object} opts - An object with options information.
+ */
+exports.publish = function (data, opts) {
+ const docs = data().get().filter((doc) => !doc.undocumented && !doc.ignore).map((doc) => new JSDoclet(doc));
+ const dest = opts.destination;
+ if (dest === 'dry-run') {
+ process.stdout.write('Dry run... ');
+ generate({
+ write: function () { /* noop */ },
+ }, docs);
+ process.stdout.write('Okay!\n');
+ return;
+ }
+ if (dest !== '' && !dest.endsWith('.rst')) {
+ throw new Error('Destination file must be either a ".rst" file, or an empty string (for printing to stdout)');
+ }
+ if (dest !== '') {
+ const f = fs.createWriteStream(dest);
+ generate(f, docs);
+ } else {
+ generate(process.stdout, docs);
+ }
+};
diff --git a/platform/javascript/js/libs/library_godot_audio.js b/platform/javascript/js/libs/library_godot_audio.js
index 8e385e9176..ac4055516c 100644
--- a/platform/javascript/js/libs/library_godot_audio.js
+++ b/platform/javascript/js/libs/library_godot_audio.js
@@ -238,6 +238,9 @@ const GodotAudioWorklet = {
close: function () {
return new Promise(function (resolve, reject) {
+ if (GodotAudioWorklet.promise === null) {
+ return;
+ }
GodotAudioWorklet.promise.then(function () {
GodotAudioWorklet.worklet.port.postMessage({
'cmd': 'stop',
@@ -247,7 +250,7 @@ const GodotAudioWorklet = {
GodotAudioWorklet.worklet = null;
GodotAudioWorklet.promise = null;
resolve();
- });
+ }).catch(function (err) { /* aborted? */ });
});
},
},
diff --git a/platform/javascript/js/libs/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js
index 2977b7c122..99aa4793d9 100644
--- a/platform/javascript/js/libs/library_godot_display.js
+++ b/platform/javascript/js/libs/library_godot_display.js
@@ -192,33 +192,45 @@ const GodotDisplayDragDrop = {
GodotDisplayDragDrop.promises = [];
GodotDisplayDragDrop.pending_files = [];
callback(drops);
- const dirs = [DROP.substr(0, DROP.length - 1)];
- // Remove temporary files
- files.forEach(function (file) {
- FS.unlink(file);
- let dir = file.replace(DROP, '');
- let idx = dir.lastIndexOf('/');
- while (idx > 0) {
- dir = dir.substr(0, idx);
- if (dirs.indexOf(DROP + dir) === -1) {
- dirs.push(DROP + dir);
- }
- idx = dir.lastIndexOf('/');
- }
- });
- // Remove dirs.
- dirs.sort(function (a, b) {
- const al = (a.match(/\//g) || []).length;
- const bl = (b.match(/\//g) || []).length;
- if (al > bl) {
- return -1;
- } else if (al < bl) {
- return 1;
+ if (GodotConfig.persistent_drops) {
+ // Delay removal at exit.
+ GodotOS.atexit(function (resolve, reject) {
+ GodotDisplayDragDrop.remove_drop(files, DROP);
+ resolve();
+ });
+ } else {
+ GodotDisplayDragDrop.remove_drop(files, DROP);
+ }
+ });
+ },
+
+ remove_drop: function (files, drop_path) {
+ const dirs = [drop_path.substr(0, drop_path.length - 1)];
+ // Remove temporary files
+ files.forEach(function (file) {
+ FS.unlink(file);
+ let dir = file.replace(drop_path, '');
+ let idx = dir.lastIndexOf('/');
+ while (idx > 0) {
+ dir = dir.substr(0, idx);
+ if (dirs.indexOf(drop_path + dir) === -1) {
+ dirs.push(drop_path + dir);
}
- return 0;
- }).forEach(function (dir) {
- FS.rmdir(dir);
- });
+ idx = dir.lastIndexOf('/');
+ }
+ });
+ // Remove dirs.
+ dirs.sort(function (a, b) {
+ const al = (a.match(/\//g) || []).length;
+ const bl = (b.match(/\//g) || []).length;
+ if (al > bl) {
+ return -1;
+ } else if (al < bl) {
+ return 1;
+ }
+ return 0;
+ }).forEach(function (dir) {
+ FS.rmdir(dir);
});
},
@@ -231,6 +243,105 @@ const GodotDisplayDragDrop = {
};
mergeInto(LibraryManager.library, GodotDisplayDragDrop);
+const GodotDisplayVK = {
+
+ $GodotDisplayVK__deps: ['$GodotRuntime', '$GodotConfig', '$GodotDisplayListeners'],
+ $GodotDisplayVK__postset: 'GodotOS.atexit(function(resolve, reject) { GodotDisplayVK.clear(); resolve(); });',
+ $GodotDisplayVK: {
+ textinput: null,
+ textarea: null,
+
+ available: function () {
+ return GodotConfig.virtual_keyboard && 'ontouchstart' in window;
+ },
+
+ init: function (input_cb) {
+ function create(what) {
+ const elem = document.createElement(what);
+ elem.style.display = 'none';
+ elem.style.position = 'absolute';
+ elem.style.zIndex = '-1';
+ elem.style.background = 'transparent';
+ elem.style.padding = '0px';
+ elem.style.margin = '0px';
+ elem.style.overflow = 'hidden';
+ elem.style.width = '0px';
+ elem.style.height = '0px';
+ elem.style.border = '0px';
+ elem.style.outline = 'none';
+ elem.readonly = true;
+ elem.disabled = true;
+ GodotDisplayListeners.add(elem, 'input', function (evt) {
+ const c_str = GodotRuntime.allocString(elem.value);
+ input_cb(c_str, elem.selectionEnd);
+ GodotRuntime.free(c_str);
+ }, false);
+ GodotDisplayListeners.add(elem, 'blur', function (evt) {
+ elem.style.display = 'none';
+ elem.readonly = true;
+ elem.disabled = true;
+ }, false);
+ GodotConfig.canvas.insertAdjacentElement('beforebegin', elem);
+ return elem;
+ }
+ GodotDisplayVK.textinput = create('input');
+ GodotDisplayVK.textarea = create('textarea');
+ GodotDisplayVK.updateSize();
+ },
+ show: function (text, multiline, start, end) {
+ if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) {
+ return;
+ }
+ if (GodotDisplayVK.textinput.style.display !== '' || GodotDisplayVK.textarea.style.display !== '') {
+ GodotDisplayVK.hide();
+ }
+ GodotDisplayVK.updateSize();
+ const elem = multiline ? GodotDisplayVK.textarea : GodotDisplayVK.textinput;
+ elem.readonly = false;
+ elem.disabled = false;
+ elem.value = text;
+ elem.style.display = 'block';
+ elem.focus();
+ elem.setSelectionRange(start, end);
+ },
+ hide: function () {
+ if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) {
+ return;
+ }
+ [GodotDisplayVK.textinput, GodotDisplayVK.textarea].forEach(function (elem) {
+ elem.blur();
+ elem.style.display = 'none';
+ elem.value = '';
+ });
+ },
+ updateSize: function () {
+ if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) {
+ return;
+ }
+ const rect = GodotConfig.canvas.getBoundingClientRect();
+ function update(elem) {
+ elem.style.left = `${rect.left}px`;
+ elem.style.top = `${rect.top}px`;
+ elem.style.width = `${rect.width}px`;
+ elem.style.height = `${rect.height}px`;
+ }
+ update(GodotDisplayVK.textinput);
+ update(GodotDisplayVK.textarea);
+ },
+ clear: function () {
+ if (GodotDisplayVK.textinput) {
+ GodotDisplayVK.textinput.remove();
+ GodotDisplayVK.textinput = null;
+ }
+ if (GodotDisplayVK.textarea) {
+ GodotDisplayVK.textarea.remove();
+ GodotDisplayVK.textarea = null;
+ }
+ },
+ },
+};
+mergeInto(LibraryManager.library, GodotDisplayVK);
+
/*
* Display server cursor helper.
* Keeps track of cursor status and custom shapes.
@@ -396,15 +507,145 @@ const GodotDisplayGamepads = {
};
mergeInto(LibraryManager.library, GodotDisplayGamepads);
+const GodotDisplayScreen = {
+ $GodotDisplayScreen__deps: ['$GodotConfig', '$GodotOS', '$GL', 'emscripten_webgl_get_current_context'],
+ $GodotDisplayScreen: {
+ desired_size: [0, 0],
+ hidpi: true,
+ getPixelRatio: function () {
+ return GodotDisplayScreen.hidpi ? window.devicePixelRatio || 1 : 1;
+ },
+ isFullscreen: function () {
+ const elem = document.fullscreenElement || document.mozFullscreenElement
+ || document.webkitFullscreenElement || document.msFullscreenElement;
+ if (elem) {
+ return elem === GodotConfig.canvas;
+ }
+ // But maybe knowing the element is not supported.
+ return document.fullscreen || document.mozFullScreen
+ || document.webkitIsFullscreen;
+ },
+ hasFullscreen: function () {
+ return document.fullscreenEnabled || document.mozFullScreenEnabled
+ || document.webkitFullscreenEnabled;
+ },
+ requestFullscreen: function () {
+ if (!GodotDisplayScreen.hasFullscreen()) {
+ return 1;
+ }
+ const canvas = GodotConfig.canvas;
+ try {
+ const promise = (canvas.requestFullscreen || canvas.msRequestFullscreen
+ || canvas.mozRequestFullScreen || canvas.mozRequestFullscreen
+ || canvas.webkitRequestFullscreen
+ ).call(canvas);
+ // Some browsers (Safari) return undefined.
+ // For the standard ones, we need to catch it.
+ if (promise) {
+ promise.catch(function () {
+ // nothing to do.
+ });
+ }
+ } catch (e) {
+ return 1;
+ }
+ return 0;
+ },
+ exitFullscreen: function () {
+ if (!GodotDisplayScreen.isFullscreen()) {
+ return 0;
+ }
+ try {
+ const promise = document.exitFullscreen();
+ if (promise) {
+ promise.catch(function () {
+ // nothing to do.
+ });
+ }
+ } catch (e) {
+ return 1;
+ }
+ return 0;
+ },
+ _updateGL: function () {
+ const gl_context_handle = _emscripten_webgl_get_current_context(); // eslint-disable-line no-undef
+ const gl = GL.getContext(gl_context_handle);
+ if (gl) {
+ GL.resizeOffscreenFramebuffer(gl);
+ }
+ },
+ updateSize: function () {
+ const isFullscreen = GodotDisplayScreen.isFullscreen();
+ const wantsFullWindow = GodotConfig.canvas_resize_policy === 2;
+ const noResize = GodotConfig.canvas_resize_policy === 0;
+ const wwidth = GodotDisplayScreen.desired_size[0];
+ const wheight = GodotDisplayScreen.desired_size[1];
+ const canvas = GodotConfig.canvas;
+ let width = wwidth;
+ let height = wheight;
+ if (noResize) {
+ // Don't resize canvas, just update GL if needed.
+ if (canvas.width !== width || canvas.height !== height) {
+ GodotDisplayScreen.desired_size = [canvas.width, canvas.height];
+ GodotDisplayScreen._updateGL();
+ return 1;
+ }
+ return 0;
+ }
+ const scale = GodotDisplayScreen.getPixelRatio();
+ if (isFullscreen || wantsFullWindow) {
+ // We need to match screen size.
+ width = window.innerWidth * scale;
+ height = window.innerHeight * scale;
+ }
+ const csw = `${width / scale}px`;
+ const csh = `${height / scale}px`;
+ if (canvas.style.width !== csw || canvas.style.height !== csh || canvas.width !== width || canvas.height !== height) {
+ // Size doesn't match.
+ // Resize canvas, set correct CSS pixel size, update GL.
+ canvas.width = width;
+ canvas.height = height;
+ canvas.style.width = csw;
+ canvas.style.height = csh;
+ GodotDisplayScreen._updateGL();
+ return 1;
+ }
+ return 0;
+ },
+ },
+};
+mergeInto(LibraryManager.library, GodotDisplayScreen);
+
/**
* Display server interface.
*
* Exposes all the functions needed by DisplayServer implementation.
*/
const GodotDisplay = {
- $GodotDisplay__deps: ['$GodotConfig', '$GodotRuntime', '$GodotDisplayCursor', '$GodotDisplayListeners', '$GodotDisplayDragDrop', '$GodotDisplayGamepads'],
+ $GodotDisplay__deps: ['$GodotConfig', '$GodotRuntime', '$GodotDisplayCursor', '$GodotDisplayListeners', '$GodotDisplayDragDrop', '$GodotDisplayGamepads', '$GodotDisplayScreen', '$GodotDisplayVK'],
$GodotDisplay: {
window_icon: '',
+ findDPI: function () {
+ function testDPI(dpi) {
+ return window.matchMedia(`(max-resolution: ${dpi}dpi)`).matches;
+ }
+ function bisect(low, high, func) {
+ const mid = parseInt(((high - low) / 2) + low, 10);
+ if (high - low <= 1) {
+ return func(high) ? high : low;
+ }
+ if (func(mid)) {
+ return bisect(low, mid, func);
+ }
+ return bisect(mid, high, func);
+ }
+ try {
+ const dpi = bisect(0, 800, testDPI);
+ return dpi >= 96 ? dpi : 96;
+ } catch (e) {
+ return 96;
+ }
+ },
},
godot_js_display_is_swap_ok_cancel__sig: 'i',
@@ -422,9 +663,60 @@ const GodotDisplay = {
window.alert(GodotRuntime.parseString(p_text)); // eslint-disable-line no-alert
},
+ godot_js_display_screen_dpi_get__sig: 'i',
+ godot_js_display_screen_dpi_get: function () {
+ return GodotDisplay.findDPI();
+ },
+
godot_js_display_pixel_ratio_get__sig: 'f',
godot_js_display_pixel_ratio_get: function () {
- return window.devicePixelRatio || 1;
+ return GodotDisplayScreen.getPixelRatio();
+ },
+
+ godot_js_display_fullscreen_request__sig: 'i',
+ godot_js_display_fullscreen_request: function () {
+ return GodotDisplayScreen.requestFullscreen();
+ },
+
+ godot_js_display_fullscreen_exit__sig: 'i',
+ godot_js_display_fullscreen_exit: function () {
+ return GodotDisplayScreen.exitFullscreen();
+ },
+
+ godot_js_display_desired_size_set__sig: 'v',
+ godot_js_display_desired_size_set: function (width, height) {
+ GodotDisplayScreen.desired_size = [width, height];
+ GodotDisplayScreen.updateSize();
+ },
+
+ godot_js_display_size_update__sig: 'i',
+ godot_js_display_size_update: function () {
+ const updated = GodotDisplayScreen.updateSize();
+ if (updated) {
+ GodotDisplayVK.updateSize();
+ }
+ return updated;
+ },
+
+ godot_js_display_screen_size_get__sig: 'vii',
+ godot_js_display_screen_size_get: function (width, height) {
+ const scale = GodotDisplayScreen.getPixelRatio();
+ GodotRuntime.setHeapValue(width, window.screen.width * scale, 'i32');
+ GodotRuntime.setHeapValue(height, window.screen.height * scale, 'i32');
+ },
+
+ godot_js_display_window_size_get: function (p_width, p_height) {
+ GodotRuntime.setHeapValue(p_width, GodotConfig.canvas.width, 'i32');
+ GodotRuntime.setHeapValue(p_height, GodotConfig.canvas.height, 'i32');
+ },
+
+ godot_js_display_compute_position: function (x, y, r_x, r_y) {
+ const canvas = GodotConfig.canvas;
+ const rect = canvas.getBoundingClientRect();
+ const rw = canvas.width / rect.width;
+ const rh = canvas.height / rect.height;
+ GodotRuntime.setHeapValue(r_x, (x - rect.x) * rw, 'i32');
+ GodotRuntime.setHeapValue(r_y, (y - rect.y) * rh, 'i32');
},
/*
@@ -440,13 +732,6 @@ const GodotDisplay = {
return document.activeElement === GodotConfig.canvas;
},
- godot_js_display_canvas_bounding_rect_position_get__sig: 'vii',
- godot_js_display_canvas_bounding_rect_position_get: function (r_x, r_y) {
- const brect = GodotConfig.canvas.getBoundingClientRect();
- GodotRuntime.setHeapValue(r_x, brect.x, 'i32');
- GodotRuntime.setHeapValue(r_y, brect.y, 'i32');
- },
-
/*
* Touchscreen
*/
@@ -490,15 +775,6 @@ const GodotDisplay = {
/*
* Window
*/
- godot_js_display_window_request_fullscreen__sig: 'v',
- godot_js_display_window_request_fullscreen: function () {
- const canvas = GodotConfig.canvas;
- (canvas.requestFullscreen || canvas.msRequestFullscreen
- || canvas.mozRequestFullScreen || canvas.mozRequestFullscreen
- || canvas.webkitRequestFullscreen
- ).call(canvas);
- },
-
godot_js_display_window_title_set__sig: 'vi',
godot_js_display_window_title_set: function (p_data) {
document.title = GodotRuntime.parseString(p_data);
@@ -514,7 +790,7 @@ const GodotDisplay = {
document.head.appendChild(link);
}
const old_icon = GodotDisplay.window_icon;
- const png = new Blob([GodotRuntime.heapCopy(HEAPU8, p_ptr, p_len)], { type: 'image/png' });
+ const png = new Blob([GodotRuntime.heapSlice(HEAPU8, p_ptr, p_len)], { type: 'image/png' });
GodotDisplay.window_icon = URL.createObjectURL(png);
link.href = GodotDisplay.window_icon;
if (old_icon) {
@@ -554,7 +830,7 @@ const GodotDisplay = {
const shape = GodotRuntime.parseString(p_shape);
const old_shape = GodotDisplayCursor.cursors[shape];
if (p_len > 0) {
- const png = new Blob([GodotRuntime.heapCopy(HEAPU8, p_ptr, p_len)], { type: 'image/png' });
+ const png = new Blob([GodotRuntime.heapSlice(HEAPU8, p_ptr, p_len)], { type: 'image/png' });
const url = URL.createObjectURL(png);
GodotDisplayCursor.cursors[shape] = {
url: url,
@@ -619,6 +895,66 @@ const GodotDisplay = {
GodotDisplayListeners.add(canvas, 'drop', GodotDisplayDragDrop.handler(dropFiles));
},
+ godot_js_display_setup_canvas__sig: 'viiii',
+ godot_js_display_setup_canvas: function (p_width, p_height, p_fullscreen, p_hidpi) {
+ const canvas = GodotConfig.canvas;
+ GodotDisplayListeners.add(canvas, 'contextmenu', function (ev) {
+ ev.preventDefault();
+ }, false);
+ GodotDisplayListeners.add(canvas, 'webglcontextlost', function (ev) {
+ alert('WebGL context lost, please reload the page'); // eslint-disable-line no-alert
+ ev.preventDefault();
+ }, false);
+ GodotDisplayScreen.hidpi = !!p_hidpi;
+ switch (GodotConfig.canvas_resize_policy) {
+ case 0: // None
+ GodotDisplayScreen.desired_size = [canvas.width, canvas.height];
+ break;
+ case 1: // Project
+ GodotDisplayScreen.desired_size = [p_width, p_height];
+ break;
+ default: // Full window
+ // Ensure we display in the right place, the size will be handled by updateSize
+ canvas.style.position = 'absolute';
+ canvas.style.top = 0;
+ canvas.style.left = 0;
+ break;
+ }
+ GodotDisplayScreen.updateSize();
+ if (p_fullscreen) {
+ GodotDisplayScreen.requestFullscreen();
+ }
+ },
+
+ /*
+ * Virtual Keyboard
+ */
+ godot_js_display_vk_show__sig: 'viiii',
+ godot_js_display_vk_show: function (p_text, p_multiline, p_start, p_end) {
+ const text = GodotRuntime.parseString(p_text);
+ const start = p_start > 0 ? p_start : 0;
+ const end = p_end > 0 ? p_end : start;
+ GodotDisplayVK.show(text, p_multiline, start, end);
+ },
+
+ godot_js_display_vk_hide__sig: 'v',
+ godot_js_display_vk_hide: function () {
+ GodotDisplayVK.hide();
+ },
+
+ godot_js_display_vk_available__sig: 'i',
+ godot_js_display_vk_available: function () {
+ return GodotDisplayVK.available();
+ },
+
+ godot_js_display_vk_cb__sig: 'vi',
+ godot_js_display_vk_cb: function (p_input_cb) {
+ const input_cb = GodotRuntime.get_func(p_input_cb);
+ if (GodotDisplayVK.available()) {
+ GodotDisplayVK.init(input_cb);
+ }
+ },
+
/*
* Gamepads
*/
diff --git a/platform/javascript/js/libs/library_godot_fetch.js b/platform/javascript/js/libs/library_godot_fetch.js
new file mode 100644
index 0000000000..4ae6a23593
--- /dev/null
+++ b/platform/javascript/js/libs/library_godot_fetch.js
@@ -0,0 +1,258 @@
+/*************************************************************************/
+/* library_godot_fetch.js */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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. */
+/*************************************************************************/
+
+const GodotFetch = {
+ $GodotFetch__deps: ['$GodotRuntime'],
+ $GodotFetch: {
+
+ onread: function (id, result) {
+ const obj = IDHandler.get(id);
+ if (!obj) {
+ return;
+ }
+ if (result.value) {
+ obj.chunks.push(result.value);
+ }
+ obj.reading = false;
+ obj.done = result.done;
+ },
+
+ onresponse: function (id, response) {
+ const obj = IDHandler.get(id);
+ if (!obj) {
+ return;
+ }
+ let size = -1;
+ let compressed = false;
+ let chunked = false;
+ response.headers.forEach(function (value, header) {
+ const v = value.toLowerCase().trim();
+ const h = header.toLowerCase().trim();
+ if (h === 'content-encoding') {
+ compressed = true;
+ size = -1;
+ } else if (h === 'content-length') {
+ const len = Number.parseInt(value, 10);
+ if (!Number.isNaN(len) && !compressed) {
+ size = len;
+ }
+ } else if (h === 'transfer-encoding' && v === 'chunked') {
+ chunked = true;
+ }
+ });
+ obj.bodySize = size;
+ obj.status = response.status;
+ obj.response = response;
+ obj.reader = response.body.getReader();
+ obj.chunked = chunked;
+ },
+
+ onerror: function (id, err) {
+ GodotRuntime.error(err);
+ const obj = IDHandler.get(id);
+ if (!obj) {
+ return;
+ }
+ obj.error = err;
+ },
+
+ create: function (method, url, headers, body) {
+ const obj = {
+ request: null,
+ response: null,
+ reader: null,
+ error: null,
+ done: false,
+ reading: false,
+ status: 0,
+ chunks: [],
+ bodySize: -1,
+ };
+ const id = IDHandler.add(obj);
+ const init = {
+ method: method,
+ headers: headers,
+ body: body,
+ };
+ obj.request = fetch(url, init);
+ obj.request.then(GodotFetch.onresponse.bind(null, id)).catch(GodotFetch.onerror.bind(null, id));
+ return id;
+ },
+
+ free: function (id) {
+ const obj = IDHandler.get(id);
+ if (!obj) {
+ return;
+ }
+ IDHandler.remove(id);
+ if (!obj.request) {
+ return;
+ }
+ // Try to abort
+ obj.request.then(function (response) {
+ response.abort();
+ }).catch(function (e) { /* nothing to do */ });
+ },
+
+ read: function (id) {
+ const obj = IDHandler.get(id);
+ if (!obj) {
+ return;
+ }
+ if (obj.reader && !obj.reading) {
+ if (obj.done) {
+ obj.reader = null;
+ return;
+ }
+ obj.reading = true;
+ obj.reader.read().then(GodotFetch.onread.bind(null, id)).catch(GodotFetch.onerror.bind(null, id));
+ }
+ },
+ },
+
+ godot_js_fetch_create__sig: 'iii',
+ godot_js_fetch_create: function (p_method, p_url, p_headers, p_headers_size, p_body, p_body_size) {
+ const method = GodotRuntime.parseString(p_method);
+ const url = GodotRuntime.parseString(p_url);
+ const headers = GodotRuntime.parseStringArray(p_headers, p_headers_size);
+ const body = p_body_size ? GodotRuntime.heapSlice(HEAP8, p_body, p_body_size) : null;
+ return GodotFetch.create(method, url, headers.map(function (hv) {
+ const idx = hv.indexOf(':');
+ if (idx <= 0) {
+ return [];
+ }
+ return [
+ hv.slice(0, idx).trim(),
+ hv.slice(idx + 1).trim(),
+ ];
+ }).filter(function (v) {
+ return v.length === 2;
+ }), body);
+ },
+
+ godot_js_fetch_state_get__sig: 'ii',
+ godot_js_fetch_state_get: function (p_id) {
+ const obj = IDHandler.get(p_id);
+ if (!obj) {
+ return -1;
+ }
+ if (obj.error) {
+ return -1;
+ }
+ if (!obj.response) {
+ return 0;
+ }
+ if (obj.reader) {
+ return 1;
+ }
+ if (obj.done) {
+ return 2;
+ }
+ return -1;
+ },
+
+ godot_js_fetch_http_status_get__sig: 'ii',
+ godot_js_fetch_http_status_get: function (p_id) {
+ const obj = IDHandler.get(p_id);
+ if (!obj || !obj.response) {
+ return 0;
+ }
+ return obj.status;
+ },
+
+ godot_js_fetch_read_headers__sig: 'iii',
+ godot_js_fetch_read_headers: function (p_id, p_parse_cb, p_ref) {
+ const obj = IDHandler.get(p_id);
+ if (!obj || !obj.response) {
+ return 1;
+ }
+ const cb = GodotRuntime.get_func(p_parse_cb);
+ const arr = [];
+ obj.response.headers.forEach(function (v, h) {
+ arr.push(`${h}:${v}`);
+ });
+ const c_ptr = GodotRuntime.allocStringArray(arr);
+ cb(arr.length, c_ptr, p_ref);
+ GodotRuntime.freeStringArray(c_ptr, arr.length);
+ return 0;
+ },
+
+ godot_js_fetch_read_chunk__sig: 'ii',
+ godot_js_fetch_read_chunk: function (p_id, p_buf, p_buf_size) {
+ const obj = IDHandler.get(p_id);
+ if (!obj || !obj.response) {
+ return 0;
+ }
+ let to_read = p_buf_size;
+ const chunks = obj.chunks;
+ while (to_read && chunks.length) {
+ const chunk = obj.chunks[0];
+ if (chunk.length > to_read) {
+ GodotRuntime.heapCopy(HEAP8, chunk.slice(0, to_read), p_buf);
+ chunks[0] = chunk.slice(to_read);
+ to_read = 0;
+ } else {
+ GodotRuntime.heapCopy(HEAP8, chunk, p_buf);
+ to_read -= chunk.length;
+ chunks.pop();
+ }
+ }
+ if (!chunks.length) {
+ GodotFetch.read(p_id);
+ }
+ return p_buf_size - to_read;
+ },
+
+ godot_js_fetch_body_length_get__sig: 'ii',
+ godot_js_fetch_body_length_get: function (p_id) {
+ const obj = IDHandler.get(p_id);
+ if (!obj || !obj.response) {
+ return -1;
+ }
+ return obj.bodySize;
+ },
+
+ godot_js_fetch_is_chunked__sig: 'ii',
+ godot_js_fetch_is_chunked: function (p_id) {
+ const obj = IDHandler.get(p_id);
+ if (!obj || !obj.response) {
+ return -1;
+ }
+ return obj.chunked ? 1 : 0;
+ },
+
+ godot_js_fetch_free__sig: 'vi',
+ godot_js_fetch_free: function (id) {
+ GodotFetch.free(id);
+ },
+};
+
+autoAddDeps(GodotFetch, '$GodotFetch');
+mergeInto(LibraryManager.library, GodotFetch);
diff --git a/platform/javascript/js/libs/library_godot_http_request.js b/platform/javascript/js/libs/library_godot_http_request.js
deleted file mode 100644
index 930d3209f8..0000000000
--- a/platform/javascript/js/libs/library_godot_http_request.js
+++ /dev/null
@@ -1,160 +0,0 @@
-/*************************************************************************/
-/* http_request.js */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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. */
-/*************************************************************************/
-
-const GodotHTTPRequest = {
- $GodotHTTPRequest__deps: ['$GodotRuntime'],
- $GodotHTTPRequest: {
- requests: [],
-
- getUnusedRequestId: function () {
- const idMax = GodotHTTPRequest.requests.length;
- for (let potentialId = 0; potentialId < idMax; ++potentialId) {
- if (GodotHTTPRequest.requests[potentialId] instanceof XMLHttpRequest) {
- continue;
- }
- return potentialId;
- }
- GodotHTTPRequest.requests.push(null);
- return idMax;
- },
-
- setupRequest: function (xhr) {
- xhr.responseType = 'arraybuffer';
- },
- },
-
- godot_xhr_new__sig: 'i',
- godot_xhr_new: function () {
- const newId = GodotHTTPRequest.getUnusedRequestId();
- GodotHTTPRequest.requests[newId] = new XMLHttpRequest();
- GodotHTTPRequest.setupRequest(GodotHTTPRequest.requests[newId]);
- return newId;
- },
-
- godot_xhr_reset__sig: 'vi',
- godot_xhr_reset: function (xhrId) {
- GodotHTTPRequest.requests[xhrId] = new XMLHttpRequest();
- GodotHTTPRequest.setupRequest(GodotHTTPRequest.requests[xhrId]);
- },
-
- godot_xhr_free__sig: 'vi',
- godot_xhr_free: function (xhrId) {
- GodotHTTPRequest.requests[xhrId].abort();
- GodotHTTPRequest.requests[xhrId] = null;
- },
-
- godot_xhr_open__sig: 'viiiii',
- godot_xhr_open: function (xhrId, method, url, p_user, p_password) {
- const user = p_user > 0 ? GodotRuntime.parseString(p_user) : null;
- const password = p_password > 0 ? GodotRuntime.parseString(p_password) : null;
- GodotHTTPRequest.requests[xhrId].open(GodotRuntime.parseString(method), GodotRuntime.parseString(url), true, user, password);
- },
-
- godot_xhr_set_request_header__sig: 'viii',
- godot_xhr_set_request_header: function (xhrId, header, value) {
- GodotHTTPRequest.requests[xhrId].setRequestHeader(GodotRuntime.parseString(header), GodotRuntime.parseString(value));
- },
-
- godot_xhr_send_null__sig: 'vi',
- godot_xhr_send_null: function (xhrId) {
- GodotHTTPRequest.requests[xhrId].send();
- },
-
- godot_xhr_send_string__sig: 'vii',
- godot_xhr_send_string: function (xhrId, strPtr) {
- if (!strPtr) {
- GodotRuntime.error('Failed to send string per XHR: null pointer');
- return;
- }
- GodotHTTPRequest.requests[xhrId].send(GodotRuntime.parseString(strPtr));
- },
-
- godot_xhr_send_data__sig: 'viii',
- godot_xhr_send_data: function (xhrId, ptr, len) {
- if (!ptr) {
- GodotRuntime.error('Failed to send data per XHR: null pointer');
- return;
- }
- if (len < 0) {
- GodotRuntime.error('Failed to send data per XHR: buffer length less than 0');
- return;
- }
- GodotHTTPRequest.requests[xhrId].send(HEAPU8.subarray(ptr, ptr + len));
- },
-
- godot_xhr_abort__sig: 'vi',
- godot_xhr_abort: function (xhrId) {
- GodotHTTPRequest.requests[xhrId].abort();
- },
-
- godot_xhr_get_status__sig: 'ii',
- godot_xhr_get_status: function (xhrId) {
- return GodotHTTPRequest.requests[xhrId].status;
- },
-
- godot_xhr_get_ready_state__sig: 'ii',
- godot_xhr_get_ready_state: function (xhrId) {
- return GodotHTTPRequest.requests[xhrId].readyState;
- },
-
- godot_xhr_get_response_headers_length__sig: 'ii',
- godot_xhr_get_response_headers_length: function (xhrId) {
- const headers = GodotHTTPRequest.requests[xhrId].getAllResponseHeaders();
- return headers === null ? 0 : GodotRuntime.strlen(headers);
- },
-
- godot_xhr_get_response_headers__sig: 'viii',
- godot_xhr_get_response_headers: function (xhrId, dst, len) {
- const str = GodotHTTPRequest.requests[xhrId].getAllResponseHeaders();
- if (str === null) {
- return;
- }
- GodotRuntime.stringToHeap(str, dst, len);
- },
-
- godot_xhr_get_response_length__sig: 'ii',
- godot_xhr_get_response_length: function (xhrId) {
- const body = GodotHTTPRequest.requests[xhrId].response;
- return body === null ? 0 : body.byteLength;
- },
-
- godot_xhr_get_response__sig: 'viii',
- godot_xhr_get_response: function (xhrId, dst, len) {
- let buf = GodotHTTPRequest.requests[xhrId].response;
- if (buf === null) {
- return;
- }
- buf = new Uint8Array(buf).subarray(0, len);
- HEAPU8.set(buf, dst);
- },
-};
-
-autoAddDeps(GodotHTTPRequest, '$GodotHTTPRequest');
-mergeInto(LibraryManager.library, GodotHTTPRequest);
diff --git a/platform/javascript/js/libs/library_godot_os.js b/platform/javascript/js/libs/library_godot_os.js
index 9fde4a84e1..1d9f889bce 100644
--- a/platform/javascript/js/libs/library_godot_os.js
+++ b/platform/javascript/js/libs/library_godot_os.js
@@ -58,21 +58,34 @@ const GodotConfig = {
$GodotConfig: {
canvas: null,
locale: 'en',
- resize_on_start: false,
+ canvas_resize_policy: 2, // Adaptive
+ virtual_keyboard: false,
+ persistent_drops: false,
on_execute: null,
+ on_exit: null,
init_config: function (p_opts) {
- GodotConfig.resize_on_start = !!p_opts['resizeCanvasOnStart'];
+ GodotConfig.canvas_resize_policy = p_opts['canvasResizePolicy'];
GodotConfig.canvas = p_opts['canvas'];
GodotConfig.locale = p_opts['locale'] || GodotConfig.locale;
+ GodotConfig.virtual_keyboard = p_opts['virtualKeyboard'];
+ GodotConfig.persistent_drops = !!p_opts['persistentDrops'];
GodotConfig.on_execute = p_opts['onExecute'];
- // This is called by emscripten, even if undocumented.
- Module['onExit'] = p_opts['onExit']; // eslint-disable-line no-undef
+ GodotConfig.on_exit = p_opts['onExit'];
},
locate_file: function (file) {
return Module['locateFile'](file); // eslint-disable-line no-undef
},
+ clear: function () {
+ GodotConfig.canvas = null;
+ GodotConfig.locale = 'en';
+ GodotConfig.canvas_resize_policy = 2;
+ GodotConfig.virtual_keyboard = false;
+ GodotConfig.persistent_drops = false;
+ GodotConfig.on_execute = null;
+ GodotConfig.on_exit = null;
+ },
},
godot_js_config_canvas_id_get__sig: 'vii',
@@ -84,11 +97,6 @@ const GodotConfig = {
godot_js_config_locale_get: function (p_ptr, p_ptr_max) {
GodotRuntime.stringToHeap(GodotConfig.locale, p_ptr, p_ptr_max);
},
-
- godot_js_config_is_resize_on_start__sig: 'i',
- godot_js_config_is_resize_on_start: function () {
- return GodotConfig.resize_on_start ? 1 : 0;
- },
};
autoAddDeps(GodotConfig, '$GodotConfig');
@@ -98,7 +106,6 @@ const GodotFS = {
$GodotFS__deps: ['$FS', '$IDBFS', '$GodotRuntime'],
$GodotFS__postset: [
'Module["initFS"] = GodotFS.init;',
- 'Module["deinitFS"] = GodotFS.deinit;',
'Module["copyToFS"] = GodotFS.copy_to_fs;',
].join(''),
$GodotFS: {
@@ -210,9 +217,10 @@ const GodotFS = {
mergeInto(LibraryManager.library, GodotFS);
const GodotOS = {
- $GodotOS__deps: ['$GodotFS', '$GodotRuntime'],
+ $GodotOS__deps: ['$GodotRuntime', '$GodotConfig', '$GodotFS'],
$GodotOS__postset: [
'Module["request_quit"] = function() { GodotOS.request_quit() };',
+ 'Module["onExit"] = GodotOS.cleanup;',
'GodotOS._fs_sync_promise = Promise.resolve();',
].join(''),
$GodotOS: {
@@ -224,6 +232,15 @@ const GodotOS = {
GodotOS._async_cbs.push(p_promise_cb);
},
+ cleanup: function (exit_code) {
+ const cb = GodotConfig.on_exit;
+ GodotFS.deinit();
+ GodotConfig.clear();
+ if (cb) {
+ cb(exit_code);
+ }
+ },
+
finish_async: function (callback) {
GodotOS._fs_sync_promise.then(function (err) {
const promises = [];
@@ -282,6 +299,11 @@ const GodotOS = {
godot_js_os_shell_open: function (p_uri) {
window.open(GodotRuntime.parseString(p_uri), '_blank');
},
+
+ godot_js_os_hw_concurrency_get__sig: 'i',
+ godot_js_os_hw_concurrency_get: function () {
+ return navigator.hardwareConcurrency || 1;
+ },
};
autoAddDeps(GodotOS, '$GodotOS');
diff --git a/platform/javascript/js/libs/library_godot_runtime.js b/platform/javascript/js/libs/library_godot_runtime.js
index 7e36ff8ab5..3da1ed8f06 100644
--- a/platform/javascript/js/libs/library_godot_runtime.js
+++ b/platform/javascript/js/libs/library_godot_runtime.js
@@ -72,11 +72,16 @@ const GodotRuntime = {
return p_heap.subarray(p_ptr / bytes, p_ptr / bytes + p_len);
},
- heapCopy: function (p_heap, p_ptr, p_len) {
+ heapSlice: function (p_heap, p_ptr, p_len) {
const bytes = p_heap.BYTES_PER_ELEMENT;
return p_heap.slice(p_ptr / bytes, p_ptr / bytes + p_len);
},
+ heapCopy: function (p_dst, p_src, p_ptr) {
+ const bytes = p_src.BYTES_PER_ELEMENT;
+ return p_dst.set(p_src, p_ptr / bytes);
+ },
+
/*
* Strings
*/
@@ -84,6 +89,15 @@ const GodotRuntime = {
return UTF8ToString(p_ptr); // eslint-disable-line no-undef
},
+ parseStringArray: function (p_ptr, p_size) {
+ const strings = [];
+ const ptrs = GodotRuntime.heapSub(HEAP32, p_ptr, p_size); // TODO wasm64
+ ptrs.forEach(function (ptr) {
+ strings.push(GodotRuntime.parseString(ptr));
+ });
+ return strings;
+ },
+
strlen: function (p_str) {
return lengthBytesUTF8(p_str); // eslint-disable-line no-undef
},
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index b922b2ba91..0b1650076c 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -129,6 +129,10 @@ int OS_JavaScript::get_process_id() const {
ERR_FAIL_V_MSG(0, "OS::get_process_id() is not available on the HTML5 platform.");
}
+int OS_JavaScript::get_processor_count() const {
+ return godot_js_os_hw_concurrency_get();
+}
+
bool OS_JavaScript::_check_internal_feature_support(const String &p_feature) {
if (p_feature == "HTML5" || p_feature == "web") {
return true;
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index 8db62d9d1c..81bb9c5f3d 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -74,6 +74,7 @@ public:
Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
Error kill(const ProcessID &p_pid) override;
int get_process_id() const override;
+ int get_processor_count() const override;
String get_executable_path() const override;
Error shell_open(String p_uri) override;
diff --git a/platform/javascript/package-lock.json b/platform/javascript/package-lock.json
index 8e298a495e..b8c434b3dd 100644
--- a/platform/javascript/package-lock.json
+++ b/platform/javascript/package-lock.json
@@ -43,6 +43,12 @@
}
}
},
+ "@babel/parser": {
+ "version": "7.13.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.4.tgz",
+ "integrity": "sha512-uvoOulWHhI+0+1f9L4BoozY7U5cIkZ9PgJqvb041d6vypgUmtVPG4vmGm4pSggjl8BELzvHyUeJSUyEMY6b+qA==",
+ "dev": true
+ },
"@eslint/eslintrc": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
@@ -202,6 +208,12 @@
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+ "dev": true
+ },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -218,6 +230,15 @@
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true
},
+ "catharsis": {
+ "version": "0.8.11",
+ "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz",
+ "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
@@ -362,6 +383,12 @@
"ansi-colors": "^4.1.1"
}
},
+ "entities": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
+ "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==",
+ "dev": true
+ },
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -925,6 +952,51 @@
"esprima": "^4.0.0"
}
},
+ "js2xmlparser": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz",
+ "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==",
+ "dev": true,
+ "requires": {
+ "xmlcreate": "^2.0.3"
+ }
+ },
+ "jsdoc": {
+ "version": "3.6.6",
+ "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.6.tgz",
+ "integrity": "sha512-znR99e1BHeyEkSvgDDpX0sTiTu+8aQyDl9DawrkOGZTTW8hv0deIFXx87114zJ7gRaDZKVQD/4tr1ifmJp9xhQ==",
+ "dev": true,
+ "requires": {
+ "@babel/parser": "^7.9.4",
+ "bluebird": "^3.7.2",
+ "catharsis": "^0.8.11",
+ "escape-string-regexp": "^2.0.0",
+ "js2xmlparser": "^4.0.1",
+ "klaw": "^3.0.0",
+ "markdown-it": "^10.0.0",
+ "markdown-it-anchor": "^5.2.7",
+ "marked": "^0.8.2",
+ "mkdirp": "^1.0.4",
+ "requizzle": "^0.2.3",
+ "strip-json-comments": "^3.1.0",
+ "taffydb": "2.6.2",
+ "underscore": "~1.10.2"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ }
+ }
+ },
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -946,6 +1018,15 @@
"minimist": "^1.2.0"
}
},
+ "klaw": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz",
+ "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.9"
+ }
+ },
"levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@@ -956,6 +1037,15 @@
"type-check": "~0.4.0"
}
},
+ "linkify-it": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
+ "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
+ "dev": true,
+ "requires": {
+ "uc.micro": "^1.0.1"
+ }
+ },
"load-json-file": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
@@ -984,6 +1074,37 @@
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
"dev": true
},
+ "markdown-it": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
+ "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "entities": "~2.0.0",
+ "linkify-it": "^2.0.0",
+ "mdurl": "^1.0.1",
+ "uc.micro": "^1.0.5"
+ }
+ },
+ "markdown-it-anchor": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz",
+ "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==",
+ "dev": true
+ },
+ "marked": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz",
+ "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==",
+ "dev": true
+ },
+ "mdurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
+ "dev": true
+ },
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -1287,6 +1408,15 @@
"integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
"dev": true
},
+ "requizzle": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz",
+ "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
"resolve": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
@@ -1513,6 +1643,12 @@
"string-width": "^3.0.0"
}
},
+ "taffydb": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
+ "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=",
+ "dev": true
+ },
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -1546,6 +1682,18 @@
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"dev": true
},
+ "uc.micro": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
+ "dev": true
+ },
+ "underscore": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz",
+ "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==",
+ "dev": true
+ },
"uri-js": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
@@ -1600,6 +1748,12 @@
"requires": {
"mkdirp": "^0.5.1"
}
+ },
+ "xmlcreate": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz",
+ "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==",
+ "dev": true
}
}
}
diff --git a/platform/javascript/package.json b/platform/javascript/package.json
index 630b584f5b..d9d272923e 100644
--- a/platform/javascript/package.json
+++ b/platform/javascript/package.json
@@ -5,20 +5,24 @@
"description": "Linting setup for Godot's HTML5 platform code",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
- "lint": "npm run lint:engine && npm run lint:libs && npm run lint:modules",
+ "docs": "jsdoc --template js/jsdoc2rst/ js/engine/engine.js js/engine/config.js --destination ''",
+ "lint": "npm run lint:engine && npm run lint:libs && npm run lint:modules && npm run lint:tools",
"lint:engine": "eslint \"js/engine/*.js\" --no-eslintrc -c .eslintrc.engine.js",
"lint:libs": "eslint \"js/libs/*.js\" --no-eslintrc -c .eslintrc.libs.js",
"lint:modules": "eslint \"../../modules/**/*.js\" --no-eslintrc -c .eslintrc.libs.js",
- "format": "npm run format:engine && npm run format:libs && npm run format:modules",
+ "lint:tools": "eslint \"js/jsdoc2rst/**/*.js\" --no-eslintrc -c .eslintrc.engine.js",
+ "format": "npm run format:engine && npm run format:libs && npm run format:modules && npm run format:tools",
"format:engine": "npm run lint:engine -- --fix",
"format:libs": "npm run lint:libs -- --fix",
- "format:modules": "npm run lint:modules -- --fix"
+ "format:modules": "npm run lint:modules -- --fix",
+ "format:tools": "npm run lint:tools -- --fix"
},
"author": "Godot Engine contributors",
"license": "MIT",
"devDependencies": {
"eslint": "^7.9.0",
"eslint-config-airbnb-base": "^14.2.0",
- "eslint-plugin-import": "^2.22.0"
+ "eslint-plugin-import": "^2.22.0",
+ "jsdoc": "^3.6.6"
}
}
diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub
index 6e43ffcedb..46714e9502 100644
--- a/platform/linuxbsd/SCsub
+++ b/platform/linuxbsd/SCsub
@@ -16,7 +16,10 @@ common_x11 = [
"key_mapping_x11.cpp",
]
+if "udev" in env and env["udev"]:
+ common_x11.append("libudev-so_wrap.c")
+
prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_x11)
-if env["debug_symbols"] == "yes" and env["separate_debug_symbols"]:
+if env["debug_symbols"] and env["separate_debug_symbols"]:
env.AddPostAction(prog, run_in_subprocess(platform_linuxbsd_builders.make_debug_linuxbsd))
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index 2141f68725..6b527c6fb5 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -70,6 +70,7 @@ def get_opts():
BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN))", False),
BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN))", False),
BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN))", False),
+ BoolVariable("use_msan", "Use LLVM/GCC compiler memory sanitizer (MSAN))", False),
BoolVariable("pulseaudio", "Detect and use PulseAudio", True),
BoolVariable("udev", "Use udev for gamepad connection callbacks", True),
BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
@@ -89,20 +90,20 @@ def configure(env):
if env["target"] == "release":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O3"])
- else: # optimize for size
+ elif env["optimize"] == "size": # optimize for size
env.Prepend(CCFLAGS=["-Os"])
- if env["debug_symbols"] == "yes":
+ if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
elif env["target"] == "release_debug":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O2"])
- else: # optimize for size
+ elif env["optimize"] == "size": # optimize for size
env.Prepend(CCFLAGS=["-Os"])
env.Prepend(CPPDEFINES=["DEBUG_ENABLED"])
- if env["debug_symbols"] == "yes":
+ if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
elif env["target"] == "debug":
@@ -142,7 +143,7 @@ def configure(env):
env.Append(CCFLAGS=["-ftest-coverage", "-fprofile-arcs"])
env.Append(LINKFLAGS=["-ftest-coverage", "-fprofile-arcs"])
- if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"]:
+ if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"] or env["use_msan"]:
env.extra_suffix += "s"
if env["use_ubsan"]:
@@ -161,6 +162,10 @@ def configure(env):
env.Append(CCFLAGS=["-fsanitize=thread"])
env.Append(LINKFLAGS=["-fsanitize=thread"])
+ if env["use_msan"]:
+ env.Append(CCFLAGS=["-fsanitize=memory"])
+ env.Append(LINKFLAGS=["-fsanitize=memory"])
+
if env["use_lto"]:
if not env["use_llvm"] and env.GetOption("num_jobs") > 1:
env.Append(CCFLAGS=["-flto"])
@@ -310,9 +315,8 @@ def configure(env):
if os.system("pkg-config --exists alsa") == 0: # 0 means found
print("Enabling ALSA")
+ env["alsa"] = True
env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
- # Don't parse --cflags, we don't need to add /usr/include/alsa to include path
- env.ParseConfig("pkg-config alsa --libs")
else:
print("ALSA libraries not found, disabling driver")
@@ -320,20 +324,20 @@ def configure(env):
if os.system("pkg-config --exists libpulse") == 0: # 0 means found
print("Enabling PulseAudio")
env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED"])
- env.ParseConfig("pkg-config --cflags --libs libpulse")
+ env.ParseConfig("pkg-config --cflags libpulse")
else:
print("PulseAudio development libraries not found, disabling driver")
if platform.system() == "Linux":
env.Append(CPPDEFINES=["JOYDEV_ENABLED"])
-
if env["udev"]:
if os.system("pkg-config --exists libudev") == 0: # 0 means found
print("Enabling udev support")
env.Append(CPPDEFINES=["UDEV_ENABLED"])
- env.ParseConfig("pkg-config libudev --cflags --libs")
else:
print("libudev development libraries not found, disabling udev support")
+ else:
+ env["udev"] = False # Linux specific
# Linkflags below this line should typically stay the last ones
if not env["builtin_zlib"]:
@@ -394,3 +398,9 @@ def configure(env):
# That doesn't make any sense but it's likely a Ubuntu bug?
if is64 or env["bits"] == "64":
env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"])
+ if env["use_llvm"]:
+ env["LINKCOM"] = env["LINKCOM"] + " -l:libatomic.a"
+
+ else:
+ if env["use_llvm"]:
+ env.Append(LIBS=["atomic"])
diff --git a/platform/linuxbsd/detect_prime_x11.cpp b/platform/linuxbsd/detect_prime_x11.cpp
index 0f8d108dff..da1c95a593 100644
--- a/platform/linuxbsd/detect_prime_x11.cpp
+++ b/platform/linuxbsd/detect_prime_x11.cpp
@@ -61,6 +61,7 @@ struct vendor {
vendor vendormap[] = {
{ "Advanced Micro Devices, Inc.", 30 },
+ { "AMD", 30 },
{ "NVIDIA Corporation", 30 },
{ "X.Org", 30 },
{ "Intel Open Source Technology Center", 20 },
@@ -128,7 +129,7 @@ void create_context() {
int detect_prime() {
pid_t p;
- int priorities[2];
+ int priorities[2] = {};
String vendors[2];
String renderers[2];
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 53baf17858..27b9d9485a 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -727,9 +727,9 @@ Point2i DisplayServerX11::screen_get_position(int p_screen) const {
int count;
XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
- if (p_screen >= count) {
- return Point2i(0, 0);
- }
+
+ // Check if screen is valid
+ ERR_FAIL_INDEX_V(p_screen, count, Point2i(0, 0));
Point2i position = Point2i(xsi[p_screen].x_org, xsi[p_screen].y_org);
@@ -758,9 +758,9 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
int count;
XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
- if (p_screen >= count) {
- return Rect2i(0, 0, 0, 0);
- }
+
+ // Check if screen is valid
+ ERR_FAIL_INDEX_V(p_screen, count, Rect2i(0, 0, 0, 0));
Rect2i rect = Rect2i(xsi[p_screen].x_org, xsi[p_screen].y_org, xsi[p_screen].width, xsi[p_screen].height);
XFree(xsi);
@@ -1041,11 +1041,13 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- int count = get_screen_count();
- if (p_screen >= count) {
- return;
+ if (p_screen == SCREEN_OF_MAIN_WINDOW) {
+ p_screen = window_get_current_screen();
}
+ // Check if screen is valid
+ ERR_FAIL_INDEX(p_screen, get_screen_count());
+
if (window_get_mode(p_window) == WINDOW_MODE_FULLSCREEN) {
Point2i position = screen_get_position(p_screen);
Size2i size = screen_get_size(p_screen);
@@ -2697,7 +2699,7 @@ bool DisplayServerX11::_wait_for_events() const {
}
void DisplayServerX11::_poll_events() {
- while (!events_thread_done) {
+ while (!events_thread_done.is_set()) {
_wait_for_events();
// Process events from the queue.
@@ -3296,7 +3298,7 @@ void DisplayServerX11::process_events() {
if (xi.pressure_supported) {
mm->set_pressure(xi.pressure);
} else {
- mm->set_pressure((mouse_get_button_state() & (1 << (BUTTON_LEFT - 1))) ? 1.0f : 0.0f);
+ mm->set_pressure((mouse_get_button_state() & (1 << (MOUSE_BUTTON_LEFT - 1))) ? 1.0f : 0.0f);
}
mm->set_tilt(xi.tilt);
@@ -4028,7 +4030,10 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
use_prime = 0;
}
- if (getenv("LD_LIBRARY_PATH")) {
+ // Some tools use fake libGL libraries and have them override the real one using
+ // LD_LIBRARY_PATH, so we skip them. *But* Steam also sets LD_LIBRARY_PATH for its
+ // runtime and includes system `/lib` and `/lib64`... so ignore Steam.
+ if (use_prime == -1 && getenv("LD_LIBRARY_PATH") && !getenv("STEAM_RUNTIME_LIBRARY_PATH")) {
String ld_library_path(getenv("LD_LIBRARY_PATH"));
Vector<String> libraries = ld_library_path.split(":");
@@ -4279,7 +4284,7 @@ DisplayServerX11::~DisplayServerX11() {
_clipboard_transfer_ownership(XA_PRIMARY, x11_main_window);
_clipboard_transfer_ownership(XInternAtom(x11_display, "CLIPBOARD", 0), x11_main_window);
- events_thread_done = true;
+ events_thread_done.set();
events_thread.wait_to_finish();
//destroy all windows
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index 906710f933..10686d8424 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -253,7 +253,7 @@ class DisplayServerX11 : public DisplayServer {
mutable Mutex events_mutex;
Thread events_thread;
- bool events_thread_done = false;
+ SafeFlag events_thread_done;
LocalVector<XEvent> polled_events;
static void _poll_events_thread(void *ud);
bool _wait_for_events() const;
diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp
index 4e96e6d687..8ea0f6c246 100644
--- a/platform/linuxbsd/joypad_linux.cpp
+++ b/platform/linuxbsd/joypad_linux.cpp
@@ -39,7 +39,7 @@
#include <unistd.h>
#ifdef UDEV_ENABLED
-#include <libudev.h>
+#include "libudev-so_wrap.h"
#endif
#define LONG_BITS (sizeof(long) * 8)
@@ -62,7 +62,7 @@ void JoypadLinux::Joypad::reset() {
dpad = 0;
fd = -1;
- Input::JoyAxis jx;
+ Input::JoyAxisValue jx;
jx.min = -1;
jx.value = 0.0f;
for (int i = 0; i < MAX_ABS; i++) {
@@ -72,13 +72,27 @@ void JoypadLinux::Joypad::reset() {
}
JoypadLinux::JoypadLinux(Input *in) {
- exit_udev = false;
+#ifdef UDEV_ENABLED
+#ifdef DEBUG_ENABLED
+ int dylibloader_verbose = 1;
+#else
+ int dylibloader_verbose = 0;
+#endif
+ use_udev = initialize_libudev(dylibloader_verbose) == 0;
+ if (use_udev) {
+ print_verbose("JoypadLinux: udev enabled and loaded successfully.");
+ } else {
+ print_verbose("JoypadLinux: udev enabled, but couldn't be loaded. Falling back to /dev/input to detect joypads.");
+ }
+#else
+ print_verbose("JoypadLinux: udev disabled, parsing /dev/input to detect joypads.");
+#endif
input = in;
joy_thread.start(joy_thread_func, this);
}
JoypadLinux::~JoypadLinux() {
- exit_udev = true;
+ exit_monitor.set();
joy_thread.wait_to_finish();
close_joypad();
}
@@ -92,11 +106,20 @@ void JoypadLinux::joy_thread_func(void *p_user) {
void JoypadLinux::run_joypad_thread() {
#ifdef UDEV_ENABLED
- udev *_udev = udev_new();
- ERR_FAIL_COND(!_udev);
- enumerate_joypads(_udev);
- monitor_joypads(_udev);
- udev_unref(_udev);
+ if (use_udev) {
+ udev *_udev = udev_new();
+ if (!_udev) {
+ use_udev = false;
+ ERR_PRINT("Failed getting an udev context, falling back to parsing /dev/input.");
+ monitor_joypads();
+ } else {
+ enumerate_joypads(_udev);
+ monitor_joypads(_udev);
+ udev_unref(_udev);
+ }
+ } else {
+ monitor_joypads();
+ }
#else
monitor_joypads();
#endif
@@ -137,7 +160,7 @@ void JoypadLinux::monitor_joypads(udev *p_udev) {
udev_monitor_enable_receiving(mon);
int fd = udev_monitor_get_fd(mon);
- while (!exit_udev) {
+ while (!exit_monitor.is_set()) {
fd_set fds;
struct timeval tv;
int ret;
@@ -179,7 +202,7 @@ void JoypadLinux::monitor_joypads(udev *p_udev) {
#endif
void JoypadLinux::monitor_joypads() {
- while (!exit_udev) {
+ while (!exit_monitor.is_set()) {
{
MutexLock lock(joy_mutex);
@@ -405,10 +428,10 @@ void JoypadLinux::joypad_vibration_stop(int p_id, uint64_t p_timestamp) {
joy.ff_effect_timestamp = p_timestamp;
}
-Input::JoyAxis JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const {
+Input::JoyAxisValue JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const {
int min = p_abs->minimum;
int max = p_abs->maximum;
- Input::JoyAxis jx;
+ Input::JoyAxisValue jx;
if (min < 0) {
jx.min = -1;
@@ -490,7 +513,7 @@ void JoypadLinux::process_joypads() {
return;
}
if (joy->abs_map[ev.code] != -1 && joy->abs_info[ev.code]) {
- Input::JoyAxis value = axis_correct(joy->abs_info[ev.code], ev.value);
+ Input::JoyAxisValue value = axis_correct(joy->abs_info[ev.code], ev.value);
joy->curr_axis[joy->abs_map[ev.code]] = value;
}
break;
diff --git a/platform/linuxbsd/joypad_linux.h b/platform/linuxbsd/joypad_linux.h
index bf343b7ceb..177d7a51ce 100644
--- a/platform/linuxbsd/joypad_linux.h
+++ b/platform/linuxbsd/joypad_linux.h
@@ -53,7 +53,7 @@ private:
};
struct Joypad {
- Input::JoyAxis curr_axis[MAX_ABS];
+ Input::JoyAxisValue curr_axis[MAX_ABS];
int key_map[MAX_KEY];
int abs_map[MAX_ABS];
int dpad = 0;
@@ -70,10 +70,13 @@ private:
void reset();
};
- bool exit_udev;
+#ifdef UDEV_ENABLED
+ bool use_udev = false;
+#endif
+ SafeFlag exit_monitor;
Mutex joy_mutex;
Thread joy_thread;
- Input *input;
+ Input *input = nullptr;
Joypad joypads[JOYPADS_MAX];
Vector<String> attached_devices;
@@ -94,7 +97,7 @@ private:
void joypad_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp);
void joypad_vibration_stop(int p_id, uint64_t p_timestamp);
- Input::JoyAxis axis_correct(const input_absinfo *p_abs, int p_value) const;
+ Input::JoyAxisValue axis_correct(const input_absinfo *p_abs, int p_value) const;
};
#endif
diff --git a/platform/linuxbsd/libudev-so_wrap.c b/platform/linuxbsd/libudev-so_wrap.c
new file mode 100644
index 0000000000..a9fa4a494a
--- /dev/null
+++ b/platform/linuxbsd/libudev-so_wrap.c
@@ -0,0 +1,1013 @@
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-20 00:08:59
+// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/libudev.h --sys-include <libudev.h> --soname libudev.so.1 --init-name libudev --omit-prefix gnu_ --output-header libudev-so_wrap.h --output-implementation libudev-so_wrap.c
+//
+#include <stdint.h>
+
+#define udev_ref udev_ref_dylibloader_orig_libudev
+#define udev_unref udev_unref_dylibloader_orig_libudev
+#define udev_new udev_new_dylibloader_orig_libudev
+#define udev_set_log_fn udev_set_log_fn_dylibloader_orig_libudev
+#define udev_get_log_priority udev_get_log_priority_dylibloader_orig_libudev
+#define udev_set_log_priority udev_set_log_priority_dylibloader_orig_libudev
+#define udev_get_userdata udev_get_userdata_dylibloader_orig_libudev
+#define udev_set_userdata udev_set_userdata_dylibloader_orig_libudev
+#define udev_list_entry_get_next udev_list_entry_get_next_dylibloader_orig_libudev
+#define udev_list_entry_get_by_name udev_list_entry_get_by_name_dylibloader_orig_libudev
+#define udev_list_entry_get_name udev_list_entry_get_name_dylibloader_orig_libudev
+#define udev_list_entry_get_value udev_list_entry_get_value_dylibloader_orig_libudev
+#define udev_device_ref udev_device_ref_dylibloader_orig_libudev
+#define udev_device_unref udev_device_unref_dylibloader_orig_libudev
+#define udev_device_get_udev udev_device_get_udev_dylibloader_orig_libudev
+#define udev_device_new_from_syspath udev_device_new_from_syspath_dylibloader_orig_libudev
+#define udev_device_new_from_devnum udev_device_new_from_devnum_dylibloader_orig_libudev
+#define udev_device_new_from_subsystem_sysname udev_device_new_from_subsystem_sysname_dylibloader_orig_libudev
+#define udev_device_new_from_device_id udev_device_new_from_device_id_dylibloader_orig_libudev
+#define udev_device_new_from_environment udev_device_new_from_environment_dylibloader_orig_libudev
+#define udev_device_get_parent udev_device_get_parent_dylibloader_orig_libudev
+#define udev_device_get_parent_with_subsystem_devtype udev_device_get_parent_with_subsystem_devtype_dylibloader_orig_libudev
+#define udev_device_get_devpath udev_device_get_devpath_dylibloader_orig_libudev
+#define udev_device_get_subsystem udev_device_get_subsystem_dylibloader_orig_libudev
+#define udev_device_get_devtype udev_device_get_devtype_dylibloader_orig_libudev
+#define udev_device_get_syspath udev_device_get_syspath_dylibloader_orig_libudev
+#define udev_device_get_sysname udev_device_get_sysname_dylibloader_orig_libudev
+#define udev_device_get_sysnum udev_device_get_sysnum_dylibloader_orig_libudev
+#define udev_device_get_devnode udev_device_get_devnode_dylibloader_orig_libudev
+#define udev_device_get_is_initialized udev_device_get_is_initialized_dylibloader_orig_libudev
+#define udev_device_get_devlinks_list_entry udev_device_get_devlinks_list_entry_dylibloader_orig_libudev
+#define udev_device_get_properties_list_entry udev_device_get_properties_list_entry_dylibloader_orig_libudev
+#define udev_device_get_tags_list_entry udev_device_get_tags_list_entry_dylibloader_orig_libudev
+#define udev_device_get_sysattr_list_entry udev_device_get_sysattr_list_entry_dylibloader_orig_libudev
+#define udev_device_get_property_value udev_device_get_property_value_dylibloader_orig_libudev
+#define udev_device_get_driver udev_device_get_driver_dylibloader_orig_libudev
+#define udev_device_get_devnum udev_device_get_devnum_dylibloader_orig_libudev
+#define udev_device_get_action udev_device_get_action_dylibloader_orig_libudev
+#define udev_device_get_seqnum udev_device_get_seqnum_dylibloader_orig_libudev
+#define udev_device_get_usec_since_initialized udev_device_get_usec_since_initialized_dylibloader_orig_libudev
+#define udev_device_get_sysattr_value udev_device_get_sysattr_value_dylibloader_orig_libudev
+#define udev_device_set_sysattr_value udev_device_set_sysattr_value_dylibloader_orig_libudev
+#define udev_device_has_tag udev_device_has_tag_dylibloader_orig_libudev
+#define udev_monitor_ref udev_monitor_ref_dylibloader_orig_libudev
+#define udev_monitor_unref udev_monitor_unref_dylibloader_orig_libudev
+#define udev_monitor_get_udev udev_monitor_get_udev_dylibloader_orig_libudev
+#define udev_monitor_new_from_netlink udev_monitor_new_from_netlink_dylibloader_orig_libudev
+#define udev_monitor_enable_receiving udev_monitor_enable_receiving_dylibloader_orig_libudev
+#define udev_monitor_set_receive_buffer_size udev_monitor_set_receive_buffer_size_dylibloader_orig_libudev
+#define udev_monitor_get_fd udev_monitor_get_fd_dylibloader_orig_libudev
+#define udev_monitor_receive_device udev_monitor_receive_device_dylibloader_orig_libudev
+#define udev_monitor_filter_add_match_subsystem_devtype udev_monitor_filter_add_match_subsystem_devtype_dylibloader_orig_libudev
+#define udev_monitor_filter_add_match_tag udev_monitor_filter_add_match_tag_dylibloader_orig_libudev
+#define udev_monitor_filter_update udev_monitor_filter_update_dylibloader_orig_libudev
+#define udev_monitor_filter_remove udev_monitor_filter_remove_dylibloader_orig_libudev
+#define udev_enumerate_ref udev_enumerate_ref_dylibloader_orig_libudev
+#define udev_enumerate_unref udev_enumerate_unref_dylibloader_orig_libudev
+#define udev_enumerate_get_udev udev_enumerate_get_udev_dylibloader_orig_libudev
+#define udev_enumerate_new udev_enumerate_new_dylibloader_orig_libudev
+#define udev_enumerate_add_match_subsystem udev_enumerate_add_match_subsystem_dylibloader_orig_libudev
+#define udev_enumerate_add_nomatch_subsystem udev_enumerate_add_nomatch_subsystem_dylibloader_orig_libudev
+#define udev_enumerate_add_match_sysattr udev_enumerate_add_match_sysattr_dylibloader_orig_libudev
+#define udev_enumerate_add_nomatch_sysattr udev_enumerate_add_nomatch_sysattr_dylibloader_orig_libudev
+#define udev_enumerate_add_match_property udev_enumerate_add_match_property_dylibloader_orig_libudev
+#define udev_enumerate_add_match_sysname udev_enumerate_add_match_sysname_dylibloader_orig_libudev
+#define udev_enumerate_add_match_tag udev_enumerate_add_match_tag_dylibloader_orig_libudev
+#define udev_enumerate_add_match_parent udev_enumerate_add_match_parent_dylibloader_orig_libudev
+#define udev_enumerate_add_match_is_initialized udev_enumerate_add_match_is_initialized_dylibloader_orig_libudev
+#define udev_enumerate_add_syspath udev_enumerate_add_syspath_dylibloader_orig_libudev
+#define udev_enumerate_scan_devices udev_enumerate_scan_devices_dylibloader_orig_libudev
+#define udev_enumerate_scan_subsystems udev_enumerate_scan_subsystems_dylibloader_orig_libudev
+#define udev_enumerate_get_list_entry udev_enumerate_get_list_entry_dylibloader_orig_libudev
+#define udev_queue_ref udev_queue_ref_dylibloader_orig_libudev
+#define udev_queue_unref udev_queue_unref_dylibloader_orig_libudev
+#define udev_queue_get_udev udev_queue_get_udev_dylibloader_orig_libudev
+#define udev_queue_new udev_queue_new_dylibloader_orig_libudev
+#define udev_queue_get_kernel_seqnum udev_queue_get_kernel_seqnum_dylibloader_orig_libudev
+#define udev_queue_get_udev_seqnum udev_queue_get_udev_seqnum_dylibloader_orig_libudev
+#define udev_queue_get_udev_is_active udev_queue_get_udev_is_active_dylibloader_orig_libudev
+#define udev_queue_get_queue_is_empty udev_queue_get_queue_is_empty_dylibloader_orig_libudev
+#define udev_queue_get_seqnum_is_finished udev_queue_get_seqnum_is_finished_dylibloader_orig_libudev
+#define udev_queue_get_seqnum_sequence_is_finished udev_queue_get_seqnum_sequence_is_finished_dylibloader_orig_libudev
+#define udev_queue_get_fd udev_queue_get_fd_dylibloader_orig_libudev
+#define udev_queue_flush udev_queue_flush_dylibloader_orig_libudev
+#define udev_queue_get_queued_list_entry udev_queue_get_queued_list_entry_dylibloader_orig_libudev
+#define udev_hwdb_new udev_hwdb_new_dylibloader_orig_libudev
+#define udev_hwdb_ref udev_hwdb_ref_dylibloader_orig_libudev
+#define udev_hwdb_unref udev_hwdb_unref_dylibloader_orig_libudev
+#define udev_hwdb_get_properties_list_entry udev_hwdb_get_properties_list_entry_dylibloader_orig_libudev
+#define udev_util_encode_string udev_util_encode_string_dylibloader_orig_libudev
+#include <libudev.h>
+#undef udev_ref
+#undef udev_unref
+#undef udev_new
+#undef udev_set_log_fn
+#undef udev_get_log_priority
+#undef udev_set_log_priority
+#undef udev_get_userdata
+#undef udev_set_userdata
+#undef udev_list_entry_get_next
+#undef udev_list_entry_get_by_name
+#undef udev_list_entry_get_name
+#undef udev_list_entry_get_value
+#undef udev_device_ref
+#undef udev_device_unref
+#undef udev_device_get_udev
+#undef udev_device_new_from_syspath
+#undef udev_device_new_from_devnum
+#undef udev_device_new_from_subsystem_sysname
+#undef udev_device_new_from_device_id
+#undef udev_device_new_from_environment
+#undef udev_device_get_parent
+#undef udev_device_get_parent_with_subsystem_devtype
+#undef udev_device_get_devpath
+#undef udev_device_get_subsystem
+#undef udev_device_get_devtype
+#undef udev_device_get_syspath
+#undef udev_device_get_sysname
+#undef udev_device_get_sysnum
+#undef udev_device_get_devnode
+#undef udev_device_get_is_initialized
+#undef udev_device_get_devlinks_list_entry
+#undef udev_device_get_properties_list_entry
+#undef udev_device_get_tags_list_entry
+#undef udev_device_get_sysattr_list_entry
+#undef udev_device_get_property_value
+#undef udev_device_get_driver
+#undef udev_device_get_devnum
+#undef udev_device_get_action
+#undef udev_device_get_seqnum
+#undef udev_device_get_usec_since_initialized
+#undef udev_device_get_sysattr_value
+#undef udev_device_set_sysattr_value
+#undef udev_device_has_tag
+#undef udev_monitor_ref
+#undef udev_monitor_unref
+#undef udev_monitor_get_udev
+#undef udev_monitor_new_from_netlink
+#undef udev_monitor_enable_receiving
+#undef udev_monitor_set_receive_buffer_size
+#undef udev_monitor_get_fd
+#undef udev_monitor_receive_device
+#undef udev_monitor_filter_add_match_subsystem_devtype
+#undef udev_monitor_filter_add_match_tag
+#undef udev_monitor_filter_update
+#undef udev_monitor_filter_remove
+#undef udev_enumerate_ref
+#undef udev_enumerate_unref
+#undef udev_enumerate_get_udev
+#undef udev_enumerate_new
+#undef udev_enumerate_add_match_subsystem
+#undef udev_enumerate_add_nomatch_subsystem
+#undef udev_enumerate_add_match_sysattr
+#undef udev_enumerate_add_nomatch_sysattr
+#undef udev_enumerate_add_match_property
+#undef udev_enumerate_add_match_sysname
+#undef udev_enumerate_add_match_tag
+#undef udev_enumerate_add_match_parent
+#undef udev_enumerate_add_match_is_initialized
+#undef udev_enumerate_add_syspath
+#undef udev_enumerate_scan_devices
+#undef udev_enumerate_scan_subsystems
+#undef udev_enumerate_get_list_entry
+#undef udev_queue_ref
+#undef udev_queue_unref
+#undef udev_queue_get_udev
+#undef udev_queue_new
+#undef udev_queue_get_kernel_seqnum
+#undef udev_queue_get_udev_seqnum
+#undef udev_queue_get_udev_is_active
+#undef udev_queue_get_queue_is_empty
+#undef udev_queue_get_seqnum_is_finished
+#undef udev_queue_get_seqnum_sequence_is_finished
+#undef udev_queue_get_fd
+#undef udev_queue_flush
+#undef udev_queue_get_queued_list_entry
+#undef udev_hwdb_new
+#undef udev_hwdb_ref
+#undef udev_hwdb_unref
+#undef udev_hwdb_get_properties_list_entry
+#undef udev_util_encode_string
+#include <dlfcn.h>
+#include <stdio.h>
+struct udev* (*udev_ref_dylibloader_wrapper_libudev)(struct udev*);
+struct udev* (*udev_unref_dylibloader_wrapper_libudev)(struct udev*);
+struct udev* (*udev_new_dylibloader_wrapper_libudev)( void);
+void (*udev_set_log_fn_dylibloader_wrapper_libudev)(struct udev*, void*);
+int (*udev_get_log_priority_dylibloader_wrapper_libudev)(struct udev*);
+void (*udev_set_log_priority_dylibloader_wrapper_libudev)(struct udev*, int);
+void* (*udev_get_userdata_dylibloader_wrapper_libudev)(struct udev*);
+void (*udev_set_userdata_dylibloader_wrapper_libudev)(struct udev*, void*);
+struct udev_list_entry* (*udev_list_entry_get_next_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+struct udev_list_entry* (*udev_list_entry_get_by_name_dylibloader_wrapper_libudev)(struct udev_list_entry*,const char*);
+const char* (*udev_list_entry_get_name_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+const char* (*udev_list_entry_get_value_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+struct udev_device* (*udev_device_ref_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_device* (*udev_device_unref_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev* (*udev_device_get_udev_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_device* (*udev_device_new_from_syspath_dylibloader_wrapper_libudev)(struct udev*,const char*);
+struct udev_device* (*udev_device_new_from_devnum_dylibloader_wrapper_libudev)(struct udev*, char, dev_t);
+struct udev_device* (*udev_device_new_from_subsystem_sysname_dylibloader_wrapper_libudev)(struct udev*,const char*,const char*);
+struct udev_device* (*udev_device_new_from_device_id_dylibloader_wrapper_libudev)(struct udev*,const char*);
+struct udev_device* (*udev_device_new_from_environment_dylibloader_wrapper_libudev)(struct udev*);
+struct udev_device* (*udev_device_get_parent_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_device* (*udev_device_get_parent_with_subsystem_devtype_dylibloader_wrapper_libudev)(struct udev_device*,const char*,const char*);
+const char* (*udev_device_get_devpath_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_subsystem_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_devtype_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_syspath_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_sysname_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_sysnum_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_devnode_dylibloader_wrapper_libudev)(struct udev_device*);
+int (*udev_device_get_is_initialized_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_list_entry* (*udev_device_get_devlinks_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_list_entry* (*udev_device_get_properties_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_list_entry* (*udev_device_get_tags_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_list_entry* (*udev_device_get_sysattr_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_property_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+const char* (*udev_device_get_driver_dylibloader_wrapper_libudev)(struct udev_device*);
+dev_t (*udev_device_get_devnum_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_action_dylibloader_wrapper_libudev)(struct udev_device*);
+unsigned long long int (*udev_device_get_seqnum_dylibloader_wrapper_libudev)(struct udev_device*);
+unsigned long long int (*udev_device_get_usec_since_initialized_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_sysattr_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+int (*udev_device_set_sysattr_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*,const char*);
+int (*udev_device_has_tag_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+struct udev_monitor* (*udev_monitor_ref_dylibloader_wrapper_libudev)(struct udev_monitor*);
+struct udev_monitor* (*udev_monitor_unref_dylibloader_wrapper_libudev)(struct udev_monitor*);
+struct udev* (*udev_monitor_get_udev_dylibloader_wrapper_libudev)(struct udev_monitor*);
+struct udev_monitor* (*udev_monitor_new_from_netlink_dylibloader_wrapper_libudev)(struct udev*,const char*);
+int (*udev_monitor_enable_receiving_dylibloader_wrapper_libudev)(struct udev_monitor*);
+int (*udev_monitor_set_receive_buffer_size_dylibloader_wrapper_libudev)(struct udev_monitor*, int);
+int (*udev_monitor_get_fd_dylibloader_wrapper_libudev)(struct udev_monitor*);
+struct udev_device* (*udev_monitor_receive_device_dylibloader_wrapper_libudev)(struct udev_monitor*);
+int (*udev_monitor_filter_add_match_subsystem_devtype_dylibloader_wrapper_libudev)(struct udev_monitor*,const char*,const char*);
+int (*udev_monitor_filter_add_match_tag_dylibloader_wrapper_libudev)(struct udev_monitor*,const char*);
+int (*udev_monitor_filter_update_dylibloader_wrapper_libudev)(struct udev_monitor*);
+int (*udev_monitor_filter_remove_dylibloader_wrapper_libudev)(struct udev_monitor*);
+struct udev_enumerate* (*udev_enumerate_ref_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+struct udev_enumerate* (*udev_enumerate_unref_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+struct udev* (*udev_enumerate_get_udev_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+struct udev_enumerate* (*udev_enumerate_new_dylibloader_wrapper_libudev)(struct udev*);
+int (*udev_enumerate_add_match_subsystem_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+int (*udev_enumerate_add_nomatch_subsystem_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+int (*udev_enumerate_add_match_sysattr_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+int (*udev_enumerate_add_nomatch_sysattr_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+int (*udev_enumerate_add_match_property_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+int (*udev_enumerate_add_match_sysname_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+int (*udev_enumerate_add_match_tag_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+int (*udev_enumerate_add_match_parent_dylibloader_wrapper_libudev)(struct udev_enumerate*,struct udev_device*);
+int (*udev_enumerate_add_match_is_initialized_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+int (*udev_enumerate_add_syspath_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+int (*udev_enumerate_scan_devices_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+int (*udev_enumerate_scan_subsystems_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+struct udev_list_entry* (*udev_enumerate_get_list_entry_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+struct udev_queue* (*udev_queue_ref_dylibloader_wrapper_libudev)(struct udev_queue*);
+struct udev_queue* (*udev_queue_unref_dylibloader_wrapper_libudev)(struct udev_queue*);
+struct udev* (*udev_queue_get_udev_dylibloader_wrapper_libudev)(struct udev_queue*);
+struct udev_queue* (*udev_queue_new_dylibloader_wrapper_libudev)(struct udev*);
+unsigned long long int (*udev_queue_get_kernel_seqnum_dylibloader_wrapper_libudev)(struct udev_queue*);
+unsigned long long int (*udev_queue_get_udev_seqnum_dylibloader_wrapper_libudev)(struct udev_queue*);
+int (*udev_queue_get_udev_is_active_dylibloader_wrapper_libudev)(struct udev_queue*);
+int (*udev_queue_get_queue_is_empty_dylibloader_wrapper_libudev)(struct udev_queue*);
+int (*udev_queue_get_seqnum_is_finished_dylibloader_wrapper_libudev)(struct udev_queue*, unsigned long long int);
+int (*udev_queue_get_seqnum_sequence_is_finished_dylibloader_wrapper_libudev)(struct udev_queue*, unsigned long long int, unsigned long long int);
+int (*udev_queue_get_fd_dylibloader_wrapper_libudev)(struct udev_queue*);
+int (*udev_queue_flush_dylibloader_wrapper_libudev)(struct udev_queue*);
+struct udev_list_entry* (*udev_queue_get_queued_list_entry_dylibloader_wrapper_libudev)(struct udev_queue*);
+struct udev_hwdb* (*udev_hwdb_new_dylibloader_wrapper_libudev)(struct udev*);
+struct udev_hwdb* (*udev_hwdb_ref_dylibloader_wrapper_libudev)(struct udev_hwdb*);
+struct udev_hwdb* (*udev_hwdb_unref_dylibloader_wrapper_libudev)(struct udev_hwdb*);
+struct udev_list_entry* (*udev_hwdb_get_properties_list_entry_dylibloader_wrapper_libudev)(struct udev_hwdb*,const char*, unsigned);
+int (*udev_util_encode_string_dylibloader_wrapper_libudev)(const char*, char*, size_t);
+int initialize_libudev(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libudev.so.1", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// udev_ref
+ *(void **) (&udev_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_unref
+ *(void **) (&udev_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_new
+ *(void **) (&udev_new_dylibloader_wrapper_libudev) = dlsym(handle, "udev_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_set_log_fn
+ *(void **) (&udev_set_log_fn_dylibloader_wrapper_libudev) = dlsym(handle, "udev_set_log_fn");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_get_log_priority
+ *(void **) (&udev_get_log_priority_dylibloader_wrapper_libudev) = dlsym(handle, "udev_get_log_priority");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_set_log_priority
+ *(void **) (&udev_set_log_priority_dylibloader_wrapper_libudev) = dlsym(handle, "udev_set_log_priority");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_get_userdata
+ *(void **) (&udev_get_userdata_dylibloader_wrapper_libudev) = dlsym(handle, "udev_get_userdata");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_set_userdata
+ *(void **) (&udev_set_userdata_dylibloader_wrapper_libudev) = dlsym(handle, "udev_set_userdata");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_list_entry_get_next
+ *(void **) (&udev_list_entry_get_next_dylibloader_wrapper_libudev) = dlsym(handle, "udev_list_entry_get_next");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_list_entry_get_by_name
+ *(void **) (&udev_list_entry_get_by_name_dylibloader_wrapper_libudev) = dlsym(handle, "udev_list_entry_get_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_list_entry_get_name
+ *(void **) (&udev_list_entry_get_name_dylibloader_wrapper_libudev) = dlsym(handle, "udev_list_entry_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_list_entry_get_value
+ *(void **) (&udev_list_entry_get_value_dylibloader_wrapper_libudev) = dlsym(handle, "udev_list_entry_get_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_ref
+ *(void **) (&udev_device_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_unref
+ *(void **) (&udev_device_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_udev
+ *(void **) (&udev_device_get_udev_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_udev");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_new_from_syspath
+ *(void **) (&udev_device_new_from_syspath_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_new_from_syspath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_new_from_devnum
+ *(void **) (&udev_device_new_from_devnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_new_from_devnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_new_from_subsystem_sysname
+ *(void **) (&udev_device_new_from_subsystem_sysname_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_new_from_subsystem_sysname");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_new_from_device_id
+ *(void **) (&udev_device_new_from_device_id_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_new_from_device_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_new_from_environment
+ *(void **) (&udev_device_new_from_environment_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_new_from_environment");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_parent
+ *(void **) (&udev_device_get_parent_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_parent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_parent_with_subsystem_devtype
+ *(void **) (&udev_device_get_parent_with_subsystem_devtype_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_parent_with_subsystem_devtype");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_devpath
+ *(void **) (&udev_device_get_devpath_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_devpath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_subsystem
+ *(void **) (&udev_device_get_subsystem_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_subsystem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_devtype
+ *(void **) (&udev_device_get_devtype_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_devtype");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_syspath
+ *(void **) (&udev_device_get_syspath_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_syspath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_sysname
+ *(void **) (&udev_device_get_sysname_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_sysname");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_sysnum
+ *(void **) (&udev_device_get_sysnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_sysnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_devnode
+ *(void **) (&udev_device_get_devnode_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_devnode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_is_initialized
+ *(void **) (&udev_device_get_is_initialized_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_is_initialized");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_devlinks_list_entry
+ *(void **) (&udev_device_get_devlinks_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_devlinks_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_properties_list_entry
+ *(void **) (&udev_device_get_properties_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_properties_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_tags_list_entry
+ *(void **) (&udev_device_get_tags_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_tags_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_sysattr_list_entry
+ *(void **) (&udev_device_get_sysattr_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_sysattr_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_property_value
+ *(void **) (&udev_device_get_property_value_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_property_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_driver
+ *(void **) (&udev_device_get_driver_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_driver");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_devnum
+ *(void **) (&udev_device_get_devnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_devnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_action
+ *(void **) (&udev_device_get_action_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_action");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_seqnum
+ *(void **) (&udev_device_get_seqnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_seqnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_usec_since_initialized
+ *(void **) (&udev_device_get_usec_since_initialized_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_usec_since_initialized");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_sysattr_value
+ *(void **) (&udev_device_get_sysattr_value_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_sysattr_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_set_sysattr_value
+ *(void **) (&udev_device_set_sysattr_value_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_set_sysattr_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_has_tag
+ *(void **) (&udev_device_has_tag_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_has_tag");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_ref
+ *(void **) (&udev_monitor_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_unref
+ *(void **) (&udev_monitor_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_get_udev
+ *(void **) (&udev_monitor_get_udev_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_get_udev");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_new_from_netlink
+ *(void **) (&udev_monitor_new_from_netlink_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_new_from_netlink");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_enable_receiving
+ *(void **) (&udev_monitor_enable_receiving_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_enable_receiving");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_set_receive_buffer_size
+ *(void **) (&udev_monitor_set_receive_buffer_size_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_set_receive_buffer_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_get_fd
+ *(void **) (&udev_monitor_get_fd_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_get_fd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_receive_device
+ *(void **) (&udev_monitor_receive_device_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_receive_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_filter_add_match_subsystem_devtype
+ *(void **) (&udev_monitor_filter_add_match_subsystem_devtype_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_filter_add_match_subsystem_devtype");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_filter_add_match_tag
+ *(void **) (&udev_monitor_filter_add_match_tag_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_filter_add_match_tag");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_filter_update
+ *(void **) (&udev_monitor_filter_update_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_filter_update");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_filter_remove
+ *(void **) (&udev_monitor_filter_remove_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_filter_remove");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_ref
+ *(void **) (&udev_enumerate_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_unref
+ *(void **) (&udev_enumerate_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_get_udev
+ *(void **) (&udev_enumerate_get_udev_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_get_udev");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_new
+ *(void **) (&udev_enumerate_new_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_subsystem
+ *(void **) (&udev_enumerate_add_match_subsystem_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_subsystem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_nomatch_subsystem
+ *(void **) (&udev_enumerate_add_nomatch_subsystem_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_nomatch_subsystem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_sysattr
+ *(void **) (&udev_enumerate_add_match_sysattr_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_sysattr");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_nomatch_sysattr
+ *(void **) (&udev_enumerate_add_nomatch_sysattr_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_nomatch_sysattr");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_property
+ *(void **) (&udev_enumerate_add_match_property_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_property");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_sysname
+ *(void **) (&udev_enumerate_add_match_sysname_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_sysname");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_tag
+ *(void **) (&udev_enumerate_add_match_tag_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_tag");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_parent
+ *(void **) (&udev_enumerate_add_match_parent_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_parent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_is_initialized
+ *(void **) (&udev_enumerate_add_match_is_initialized_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_is_initialized");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_syspath
+ *(void **) (&udev_enumerate_add_syspath_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_syspath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_scan_devices
+ *(void **) (&udev_enumerate_scan_devices_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_scan_devices");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_scan_subsystems
+ *(void **) (&udev_enumerate_scan_subsystems_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_scan_subsystems");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_get_list_entry
+ *(void **) (&udev_enumerate_get_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_get_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_ref
+ *(void **) (&udev_queue_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_unref
+ *(void **) (&udev_queue_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_udev
+ *(void **) (&udev_queue_get_udev_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_udev");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_new
+ *(void **) (&udev_queue_new_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_kernel_seqnum
+ *(void **) (&udev_queue_get_kernel_seqnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_kernel_seqnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_udev_seqnum
+ *(void **) (&udev_queue_get_udev_seqnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_udev_seqnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_udev_is_active
+ *(void **) (&udev_queue_get_udev_is_active_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_udev_is_active");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_queue_is_empty
+ *(void **) (&udev_queue_get_queue_is_empty_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_queue_is_empty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_seqnum_is_finished
+ *(void **) (&udev_queue_get_seqnum_is_finished_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_seqnum_is_finished");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_seqnum_sequence_is_finished
+ *(void **) (&udev_queue_get_seqnum_sequence_is_finished_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_seqnum_sequence_is_finished");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_fd
+ *(void **) (&udev_queue_get_fd_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_fd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_flush
+ *(void **) (&udev_queue_flush_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_flush");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_queued_list_entry
+ *(void **) (&udev_queue_get_queued_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_queued_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_hwdb_new
+ *(void **) (&udev_hwdb_new_dylibloader_wrapper_libudev) = dlsym(handle, "udev_hwdb_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_hwdb_ref
+ *(void **) (&udev_hwdb_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_hwdb_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_hwdb_unref
+ *(void **) (&udev_hwdb_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_hwdb_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_hwdb_get_properties_list_entry
+ *(void **) (&udev_hwdb_get_properties_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_hwdb_get_properties_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_util_encode_string
+ *(void **) (&udev_util_encode_string_dylibloader_wrapper_libudev) = dlsym(handle, "udev_util_encode_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/platform/linuxbsd/libudev-so_wrap.h b/platform/linuxbsd/libudev-so_wrap.h
new file mode 100644
index 0000000000..dd43fd1191
--- /dev/null
+++ b/platform/linuxbsd/libudev-so_wrap.h
@@ -0,0 +1,378 @@
+#ifndef DYLIBLOAD_WRAPPER_LIBUDEV
+#define DYLIBLOAD_WRAPPER_LIBUDEV
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-20 00:08:59
+// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/libudev.h --sys-include <libudev.h> --soname libudev.so.1 --init-name libudev --omit-prefix gnu_ --output-header libudev-so_wrap.h --output-implementation libudev-so_wrap.c
+//
+#include <stdint.h>
+
+#define udev_ref udev_ref_dylibloader_orig_libudev
+#define udev_unref udev_unref_dylibloader_orig_libudev
+#define udev_new udev_new_dylibloader_orig_libudev
+#define udev_set_log_fn udev_set_log_fn_dylibloader_orig_libudev
+#define udev_get_log_priority udev_get_log_priority_dylibloader_orig_libudev
+#define udev_set_log_priority udev_set_log_priority_dylibloader_orig_libudev
+#define udev_get_userdata udev_get_userdata_dylibloader_orig_libudev
+#define udev_set_userdata udev_set_userdata_dylibloader_orig_libudev
+#define udev_list_entry_get_next udev_list_entry_get_next_dylibloader_orig_libudev
+#define udev_list_entry_get_by_name udev_list_entry_get_by_name_dylibloader_orig_libudev
+#define udev_list_entry_get_name udev_list_entry_get_name_dylibloader_orig_libudev
+#define udev_list_entry_get_value udev_list_entry_get_value_dylibloader_orig_libudev
+#define udev_device_ref udev_device_ref_dylibloader_orig_libudev
+#define udev_device_unref udev_device_unref_dylibloader_orig_libudev
+#define udev_device_get_udev udev_device_get_udev_dylibloader_orig_libudev
+#define udev_device_new_from_syspath udev_device_new_from_syspath_dylibloader_orig_libudev
+#define udev_device_new_from_devnum udev_device_new_from_devnum_dylibloader_orig_libudev
+#define udev_device_new_from_subsystem_sysname udev_device_new_from_subsystem_sysname_dylibloader_orig_libudev
+#define udev_device_new_from_device_id udev_device_new_from_device_id_dylibloader_orig_libudev
+#define udev_device_new_from_environment udev_device_new_from_environment_dylibloader_orig_libudev
+#define udev_device_get_parent udev_device_get_parent_dylibloader_orig_libudev
+#define udev_device_get_parent_with_subsystem_devtype udev_device_get_parent_with_subsystem_devtype_dylibloader_orig_libudev
+#define udev_device_get_devpath udev_device_get_devpath_dylibloader_orig_libudev
+#define udev_device_get_subsystem udev_device_get_subsystem_dylibloader_orig_libudev
+#define udev_device_get_devtype udev_device_get_devtype_dylibloader_orig_libudev
+#define udev_device_get_syspath udev_device_get_syspath_dylibloader_orig_libudev
+#define udev_device_get_sysname udev_device_get_sysname_dylibloader_orig_libudev
+#define udev_device_get_sysnum udev_device_get_sysnum_dylibloader_orig_libudev
+#define udev_device_get_devnode udev_device_get_devnode_dylibloader_orig_libudev
+#define udev_device_get_is_initialized udev_device_get_is_initialized_dylibloader_orig_libudev
+#define udev_device_get_devlinks_list_entry udev_device_get_devlinks_list_entry_dylibloader_orig_libudev
+#define udev_device_get_properties_list_entry udev_device_get_properties_list_entry_dylibloader_orig_libudev
+#define udev_device_get_tags_list_entry udev_device_get_tags_list_entry_dylibloader_orig_libudev
+#define udev_device_get_sysattr_list_entry udev_device_get_sysattr_list_entry_dylibloader_orig_libudev
+#define udev_device_get_property_value udev_device_get_property_value_dylibloader_orig_libudev
+#define udev_device_get_driver udev_device_get_driver_dylibloader_orig_libudev
+#define udev_device_get_devnum udev_device_get_devnum_dylibloader_orig_libudev
+#define udev_device_get_action udev_device_get_action_dylibloader_orig_libudev
+#define udev_device_get_seqnum udev_device_get_seqnum_dylibloader_orig_libudev
+#define udev_device_get_usec_since_initialized udev_device_get_usec_since_initialized_dylibloader_orig_libudev
+#define udev_device_get_sysattr_value udev_device_get_sysattr_value_dylibloader_orig_libudev
+#define udev_device_set_sysattr_value udev_device_set_sysattr_value_dylibloader_orig_libudev
+#define udev_device_has_tag udev_device_has_tag_dylibloader_orig_libudev
+#define udev_monitor_ref udev_monitor_ref_dylibloader_orig_libudev
+#define udev_monitor_unref udev_monitor_unref_dylibloader_orig_libudev
+#define udev_monitor_get_udev udev_monitor_get_udev_dylibloader_orig_libudev
+#define udev_monitor_new_from_netlink udev_monitor_new_from_netlink_dylibloader_orig_libudev
+#define udev_monitor_enable_receiving udev_monitor_enable_receiving_dylibloader_orig_libudev
+#define udev_monitor_set_receive_buffer_size udev_monitor_set_receive_buffer_size_dylibloader_orig_libudev
+#define udev_monitor_get_fd udev_monitor_get_fd_dylibloader_orig_libudev
+#define udev_monitor_receive_device udev_monitor_receive_device_dylibloader_orig_libudev
+#define udev_monitor_filter_add_match_subsystem_devtype udev_monitor_filter_add_match_subsystem_devtype_dylibloader_orig_libudev
+#define udev_monitor_filter_add_match_tag udev_monitor_filter_add_match_tag_dylibloader_orig_libudev
+#define udev_monitor_filter_update udev_monitor_filter_update_dylibloader_orig_libudev
+#define udev_monitor_filter_remove udev_monitor_filter_remove_dylibloader_orig_libudev
+#define udev_enumerate_ref udev_enumerate_ref_dylibloader_orig_libudev
+#define udev_enumerate_unref udev_enumerate_unref_dylibloader_orig_libudev
+#define udev_enumerate_get_udev udev_enumerate_get_udev_dylibloader_orig_libudev
+#define udev_enumerate_new udev_enumerate_new_dylibloader_orig_libudev
+#define udev_enumerate_add_match_subsystem udev_enumerate_add_match_subsystem_dylibloader_orig_libudev
+#define udev_enumerate_add_nomatch_subsystem udev_enumerate_add_nomatch_subsystem_dylibloader_orig_libudev
+#define udev_enumerate_add_match_sysattr udev_enumerate_add_match_sysattr_dylibloader_orig_libudev
+#define udev_enumerate_add_nomatch_sysattr udev_enumerate_add_nomatch_sysattr_dylibloader_orig_libudev
+#define udev_enumerate_add_match_property udev_enumerate_add_match_property_dylibloader_orig_libudev
+#define udev_enumerate_add_match_sysname udev_enumerate_add_match_sysname_dylibloader_orig_libudev
+#define udev_enumerate_add_match_tag udev_enumerate_add_match_tag_dylibloader_orig_libudev
+#define udev_enumerate_add_match_parent udev_enumerate_add_match_parent_dylibloader_orig_libudev
+#define udev_enumerate_add_match_is_initialized udev_enumerate_add_match_is_initialized_dylibloader_orig_libudev
+#define udev_enumerate_add_syspath udev_enumerate_add_syspath_dylibloader_orig_libudev
+#define udev_enumerate_scan_devices udev_enumerate_scan_devices_dylibloader_orig_libudev
+#define udev_enumerate_scan_subsystems udev_enumerate_scan_subsystems_dylibloader_orig_libudev
+#define udev_enumerate_get_list_entry udev_enumerate_get_list_entry_dylibloader_orig_libudev
+#define udev_queue_ref udev_queue_ref_dylibloader_orig_libudev
+#define udev_queue_unref udev_queue_unref_dylibloader_orig_libudev
+#define udev_queue_get_udev udev_queue_get_udev_dylibloader_orig_libudev
+#define udev_queue_new udev_queue_new_dylibloader_orig_libudev
+#define udev_queue_get_kernel_seqnum udev_queue_get_kernel_seqnum_dylibloader_orig_libudev
+#define udev_queue_get_udev_seqnum udev_queue_get_udev_seqnum_dylibloader_orig_libudev
+#define udev_queue_get_udev_is_active udev_queue_get_udev_is_active_dylibloader_orig_libudev
+#define udev_queue_get_queue_is_empty udev_queue_get_queue_is_empty_dylibloader_orig_libudev
+#define udev_queue_get_seqnum_is_finished udev_queue_get_seqnum_is_finished_dylibloader_orig_libudev
+#define udev_queue_get_seqnum_sequence_is_finished udev_queue_get_seqnum_sequence_is_finished_dylibloader_orig_libudev
+#define udev_queue_get_fd udev_queue_get_fd_dylibloader_orig_libudev
+#define udev_queue_flush udev_queue_flush_dylibloader_orig_libudev
+#define udev_queue_get_queued_list_entry udev_queue_get_queued_list_entry_dylibloader_orig_libudev
+#define udev_hwdb_new udev_hwdb_new_dylibloader_orig_libudev
+#define udev_hwdb_ref udev_hwdb_ref_dylibloader_orig_libudev
+#define udev_hwdb_unref udev_hwdb_unref_dylibloader_orig_libudev
+#define udev_hwdb_get_properties_list_entry udev_hwdb_get_properties_list_entry_dylibloader_orig_libudev
+#define udev_util_encode_string udev_util_encode_string_dylibloader_orig_libudev
+#include <libudev.h>
+#undef udev_ref
+#undef udev_unref
+#undef udev_new
+#undef udev_set_log_fn
+#undef udev_get_log_priority
+#undef udev_set_log_priority
+#undef udev_get_userdata
+#undef udev_set_userdata
+#undef udev_list_entry_get_next
+#undef udev_list_entry_get_by_name
+#undef udev_list_entry_get_name
+#undef udev_list_entry_get_value
+#undef udev_device_ref
+#undef udev_device_unref
+#undef udev_device_get_udev
+#undef udev_device_new_from_syspath
+#undef udev_device_new_from_devnum
+#undef udev_device_new_from_subsystem_sysname
+#undef udev_device_new_from_device_id
+#undef udev_device_new_from_environment
+#undef udev_device_get_parent
+#undef udev_device_get_parent_with_subsystem_devtype
+#undef udev_device_get_devpath
+#undef udev_device_get_subsystem
+#undef udev_device_get_devtype
+#undef udev_device_get_syspath
+#undef udev_device_get_sysname
+#undef udev_device_get_sysnum
+#undef udev_device_get_devnode
+#undef udev_device_get_is_initialized
+#undef udev_device_get_devlinks_list_entry
+#undef udev_device_get_properties_list_entry
+#undef udev_device_get_tags_list_entry
+#undef udev_device_get_sysattr_list_entry
+#undef udev_device_get_property_value
+#undef udev_device_get_driver
+#undef udev_device_get_devnum
+#undef udev_device_get_action
+#undef udev_device_get_seqnum
+#undef udev_device_get_usec_since_initialized
+#undef udev_device_get_sysattr_value
+#undef udev_device_set_sysattr_value
+#undef udev_device_has_tag
+#undef udev_monitor_ref
+#undef udev_monitor_unref
+#undef udev_monitor_get_udev
+#undef udev_monitor_new_from_netlink
+#undef udev_monitor_enable_receiving
+#undef udev_monitor_set_receive_buffer_size
+#undef udev_monitor_get_fd
+#undef udev_monitor_receive_device
+#undef udev_monitor_filter_add_match_subsystem_devtype
+#undef udev_monitor_filter_add_match_tag
+#undef udev_monitor_filter_update
+#undef udev_monitor_filter_remove
+#undef udev_enumerate_ref
+#undef udev_enumerate_unref
+#undef udev_enumerate_get_udev
+#undef udev_enumerate_new
+#undef udev_enumerate_add_match_subsystem
+#undef udev_enumerate_add_nomatch_subsystem
+#undef udev_enumerate_add_match_sysattr
+#undef udev_enumerate_add_nomatch_sysattr
+#undef udev_enumerate_add_match_property
+#undef udev_enumerate_add_match_sysname
+#undef udev_enumerate_add_match_tag
+#undef udev_enumerate_add_match_parent
+#undef udev_enumerate_add_match_is_initialized
+#undef udev_enumerate_add_syspath
+#undef udev_enumerate_scan_devices
+#undef udev_enumerate_scan_subsystems
+#undef udev_enumerate_get_list_entry
+#undef udev_queue_ref
+#undef udev_queue_unref
+#undef udev_queue_get_udev
+#undef udev_queue_new
+#undef udev_queue_get_kernel_seqnum
+#undef udev_queue_get_udev_seqnum
+#undef udev_queue_get_udev_is_active
+#undef udev_queue_get_queue_is_empty
+#undef udev_queue_get_seqnum_is_finished
+#undef udev_queue_get_seqnum_sequence_is_finished
+#undef udev_queue_get_fd
+#undef udev_queue_flush
+#undef udev_queue_get_queued_list_entry
+#undef udev_hwdb_new
+#undef udev_hwdb_ref
+#undef udev_hwdb_unref
+#undef udev_hwdb_get_properties_list_entry
+#undef udev_util_encode_string
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define udev_ref udev_ref_dylibloader_wrapper_libudev
+#define udev_unref udev_unref_dylibloader_wrapper_libudev
+#define udev_new udev_new_dylibloader_wrapper_libudev
+#define udev_set_log_fn udev_set_log_fn_dylibloader_wrapper_libudev
+#define udev_get_log_priority udev_get_log_priority_dylibloader_wrapper_libudev
+#define udev_set_log_priority udev_set_log_priority_dylibloader_wrapper_libudev
+#define udev_get_userdata udev_get_userdata_dylibloader_wrapper_libudev
+#define udev_set_userdata udev_set_userdata_dylibloader_wrapper_libudev
+#define udev_list_entry_get_next udev_list_entry_get_next_dylibloader_wrapper_libudev
+#define udev_list_entry_get_by_name udev_list_entry_get_by_name_dylibloader_wrapper_libudev
+#define udev_list_entry_get_name udev_list_entry_get_name_dylibloader_wrapper_libudev
+#define udev_list_entry_get_value udev_list_entry_get_value_dylibloader_wrapper_libudev
+#define udev_device_ref udev_device_ref_dylibloader_wrapper_libudev
+#define udev_device_unref udev_device_unref_dylibloader_wrapper_libudev
+#define udev_device_get_udev udev_device_get_udev_dylibloader_wrapper_libudev
+#define udev_device_new_from_syspath udev_device_new_from_syspath_dylibloader_wrapper_libudev
+#define udev_device_new_from_devnum udev_device_new_from_devnum_dylibloader_wrapper_libudev
+#define udev_device_new_from_subsystem_sysname udev_device_new_from_subsystem_sysname_dylibloader_wrapper_libudev
+#define udev_device_new_from_device_id udev_device_new_from_device_id_dylibloader_wrapper_libudev
+#define udev_device_new_from_environment udev_device_new_from_environment_dylibloader_wrapper_libudev
+#define udev_device_get_parent udev_device_get_parent_dylibloader_wrapper_libudev
+#define udev_device_get_parent_with_subsystem_devtype udev_device_get_parent_with_subsystem_devtype_dylibloader_wrapper_libudev
+#define udev_device_get_devpath udev_device_get_devpath_dylibloader_wrapper_libudev
+#define udev_device_get_subsystem udev_device_get_subsystem_dylibloader_wrapper_libudev
+#define udev_device_get_devtype udev_device_get_devtype_dylibloader_wrapper_libudev
+#define udev_device_get_syspath udev_device_get_syspath_dylibloader_wrapper_libudev
+#define udev_device_get_sysname udev_device_get_sysname_dylibloader_wrapper_libudev
+#define udev_device_get_sysnum udev_device_get_sysnum_dylibloader_wrapper_libudev
+#define udev_device_get_devnode udev_device_get_devnode_dylibloader_wrapper_libudev
+#define udev_device_get_is_initialized udev_device_get_is_initialized_dylibloader_wrapper_libudev
+#define udev_device_get_devlinks_list_entry udev_device_get_devlinks_list_entry_dylibloader_wrapper_libudev
+#define udev_device_get_properties_list_entry udev_device_get_properties_list_entry_dylibloader_wrapper_libudev
+#define udev_device_get_tags_list_entry udev_device_get_tags_list_entry_dylibloader_wrapper_libudev
+#define udev_device_get_sysattr_list_entry udev_device_get_sysattr_list_entry_dylibloader_wrapper_libudev
+#define udev_device_get_property_value udev_device_get_property_value_dylibloader_wrapper_libudev
+#define udev_device_get_driver udev_device_get_driver_dylibloader_wrapper_libudev
+#define udev_device_get_devnum udev_device_get_devnum_dylibloader_wrapper_libudev
+#define udev_device_get_action udev_device_get_action_dylibloader_wrapper_libudev
+#define udev_device_get_seqnum udev_device_get_seqnum_dylibloader_wrapper_libudev
+#define udev_device_get_usec_since_initialized udev_device_get_usec_since_initialized_dylibloader_wrapper_libudev
+#define udev_device_get_sysattr_value udev_device_get_sysattr_value_dylibloader_wrapper_libudev
+#define udev_device_set_sysattr_value udev_device_set_sysattr_value_dylibloader_wrapper_libudev
+#define udev_device_has_tag udev_device_has_tag_dylibloader_wrapper_libudev
+#define udev_monitor_ref udev_monitor_ref_dylibloader_wrapper_libudev
+#define udev_monitor_unref udev_monitor_unref_dylibloader_wrapper_libudev
+#define udev_monitor_get_udev udev_monitor_get_udev_dylibloader_wrapper_libudev
+#define udev_monitor_new_from_netlink udev_monitor_new_from_netlink_dylibloader_wrapper_libudev
+#define udev_monitor_enable_receiving udev_monitor_enable_receiving_dylibloader_wrapper_libudev
+#define udev_monitor_set_receive_buffer_size udev_monitor_set_receive_buffer_size_dylibloader_wrapper_libudev
+#define udev_monitor_get_fd udev_monitor_get_fd_dylibloader_wrapper_libudev
+#define udev_monitor_receive_device udev_monitor_receive_device_dylibloader_wrapper_libudev
+#define udev_monitor_filter_add_match_subsystem_devtype udev_monitor_filter_add_match_subsystem_devtype_dylibloader_wrapper_libudev
+#define udev_monitor_filter_add_match_tag udev_monitor_filter_add_match_tag_dylibloader_wrapper_libudev
+#define udev_monitor_filter_update udev_monitor_filter_update_dylibloader_wrapper_libudev
+#define udev_monitor_filter_remove udev_monitor_filter_remove_dylibloader_wrapper_libudev
+#define udev_enumerate_ref udev_enumerate_ref_dylibloader_wrapper_libudev
+#define udev_enumerate_unref udev_enumerate_unref_dylibloader_wrapper_libudev
+#define udev_enumerate_get_udev udev_enumerate_get_udev_dylibloader_wrapper_libudev
+#define udev_enumerate_new udev_enumerate_new_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_subsystem udev_enumerate_add_match_subsystem_dylibloader_wrapper_libudev
+#define udev_enumerate_add_nomatch_subsystem udev_enumerate_add_nomatch_subsystem_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_sysattr udev_enumerate_add_match_sysattr_dylibloader_wrapper_libudev
+#define udev_enumerate_add_nomatch_sysattr udev_enumerate_add_nomatch_sysattr_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_property udev_enumerate_add_match_property_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_sysname udev_enumerate_add_match_sysname_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_tag udev_enumerate_add_match_tag_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_parent udev_enumerate_add_match_parent_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_is_initialized udev_enumerate_add_match_is_initialized_dylibloader_wrapper_libudev
+#define udev_enumerate_add_syspath udev_enumerate_add_syspath_dylibloader_wrapper_libudev
+#define udev_enumerate_scan_devices udev_enumerate_scan_devices_dylibloader_wrapper_libudev
+#define udev_enumerate_scan_subsystems udev_enumerate_scan_subsystems_dylibloader_wrapper_libudev
+#define udev_enumerate_get_list_entry udev_enumerate_get_list_entry_dylibloader_wrapper_libudev
+#define udev_queue_ref udev_queue_ref_dylibloader_wrapper_libudev
+#define udev_queue_unref udev_queue_unref_dylibloader_wrapper_libudev
+#define udev_queue_get_udev udev_queue_get_udev_dylibloader_wrapper_libudev
+#define udev_queue_new udev_queue_new_dylibloader_wrapper_libudev
+#define udev_queue_get_kernel_seqnum udev_queue_get_kernel_seqnum_dylibloader_wrapper_libudev
+#define udev_queue_get_udev_seqnum udev_queue_get_udev_seqnum_dylibloader_wrapper_libudev
+#define udev_queue_get_udev_is_active udev_queue_get_udev_is_active_dylibloader_wrapper_libudev
+#define udev_queue_get_queue_is_empty udev_queue_get_queue_is_empty_dylibloader_wrapper_libudev
+#define udev_queue_get_seqnum_is_finished udev_queue_get_seqnum_is_finished_dylibloader_wrapper_libudev
+#define udev_queue_get_seqnum_sequence_is_finished udev_queue_get_seqnum_sequence_is_finished_dylibloader_wrapper_libudev
+#define udev_queue_get_fd udev_queue_get_fd_dylibloader_wrapper_libudev
+#define udev_queue_flush udev_queue_flush_dylibloader_wrapper_libudev
+#define udev_queue_get_queued_list_entry udev_queue_get_queued_list_entry_dylibloader_wrapper_libudev
+#define udev_hwdb_new udev_hwdb_new_dylibloader_wrapper_libudev
+#define udev_hwdb_ref udev_hwdb_ref_dylibloader_wrapper_libudev
+#define udev_hwdb_unref udev_hwdb_unref_dylibloader_wrapper_libudev
+#define udev_hwdb_get_properties_list_entry udev_hwdb_get_properties_list_entry_dylibloader_wrapper_libudev
+#define udev_util_encode_string udev_util_encode_string_dylibloader_wrapper_libudev
+extern struct udev* (*udev_ref_dylibloader_wrapper_libudev)(struct udev*);
+extern struct udev* (*udev_unref_dylibloader_wrapper_libudev)(struct udev*);
+extern struct udev* (*udev_new_dylibloader_wrapper_libudev)( void);
+extern void (*udev_set_log_fn_dylibloader_wrapper_libudev)(struct udev*, void*);
+extern int (*udev_get_log_priority_dylibloader_wrapper_libudev)(struct udev*);
+extern void (*udev_set_log_priority_dylibloader_wrapper_libudev)(struct udev*, int);
+extern void* (*udev_get_userdata_dylibloader_wrapper_libudev)(struct udev*);
+extern void (*udev_set_userdata_dylibloader_wrapper_libudev)(struct udev*, void*);
+extern struct udev_list_entry* (*udev_list_entry_get_next_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+extern struct udev_list_entry* (*udev_list_entry_get_by_name_dylibloader_wrapper_libudev)(struct udev_list_entry*,const char*);
+extern const char* (*udev_list_entry_get_name_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+extern const char* (*udev_list_entry_get_value_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+extern struct udev_device* (*udev_device_ref_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_device* (*udev_device_unref_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev* (*udev_device_get_udev_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_device* (*udev_device_new_from_syspath_dylibloader_wrapper_libudev)(struct udev*,const char*);
+extern struct udev_device* (*udev_device_new_from_devnum_dylibloader_wrapper_libudev)(struct udev*, char, dev_t);
+extern struct udev_device* (*udev_device_new_from_subsystem_sysname_dylibloader_wrapper_libudev)(struct udev*,const char*,const char*);
+extern struct udev_device* (*udev_device_new_from_device_id_dylibloader_wrapper_libudev)(struct udev*,const char*);
+extern struct udev_device* (*udev_device_new_from_environment_dylibloader_wrapper_libudev)(struct udev*);
+extern struct udev_device* (*udev_device_get_parent_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_device* (*udev_device_get_parent_with_subsystem_devtype_dylibloader_wrapper_libudev)(struct udev_device*,const char*,const char*);
+extern const char* (*udev_device_get_devpath_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_subsystem_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_devtype_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_syspath_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_sysname_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_sysnum_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_devnode_dylibloader_wrapper_libudev)(struct udev_device*);
+extern int (*udev_device_get_is_initialized_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_list_entry* (*udev_device_get_devlinks_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_list_entry* (*udev_device_get_properties_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_list_entry* (*udev_device_get_tags_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_list_entry* (*udev_device_get_sysattr_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_property_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+extern const char* (*udev_device_get_driver_dylibloader_wrapper_libudev)(struct udev_device*);
+extern dev_t (*udev_device_get_devnum_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_action_dylibloader_wrapper_libudev)(struct udev_device*);
+extern unsigned long long int (*udev_device_get_seqnum_dylibloader_wrapper_libudev)(struct udev_device*);
+extern unsigned long long int (*udev_device_get_usec_since_initialized_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_sysattr_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+extern int (*udev_device_set_sysattr_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*,const char*);
+extern int (*udev_device_has_tag_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+extern struct udev_monitor* (*udev_monitor_ref_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern struct udev_monitor* (*udev_monitor_unref_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern struct udev* (*udev_monitor_get_udev_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern struct udev_monitor* (*udev_monitor_new_from_netlink_dylibloader_wrapper_libudev)(struct udev*,const char*);
+extern int (*udev_monitor_enable_receiving_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern int (*udev_monitor_set_receive_buffer_size_dylibloader_wrapper_libudev)(struct udev_monitor*, int);
+extern int (*udev_monitor_get_fd_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern struct udev_device* (*udev_monitor_receive_device_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern int (*udev_monitor_filter_add_match_subsystem_devtype_dylibloader_wrapper_libudev)(struct udev_monitor*,const char*,const char*);
+extern int (*udev_monitor_filter_add_match_tag_dylibloader_wrapper_libudev)(struct udev_monitor*,const char*);
+extern int (*udev_monitor_filter_update_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern int (*udev_monitor_filter_remove_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern struct udev_enumerate* (*udev_enumerate_ref_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern struct udev_enumerate* (*udev_enumerate_unref_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern struct udev* (*udev_enumerate_get_udev_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern struct udev_enumerate* (*udev_enumerate_new_dylibloader_wrapper_libudev)(struct udev*);
+extern int (*udev_enumerate_add_match_subsystem_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+extern int (*udev_enumerate_add_nomatch_subsystem_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+extern int (*udev_enumerate_add_match_sysattr_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+extern int (*udev_enumerate_add_nomatch_sysattr_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+extern int (*udev_enumerate_add_match_property_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+extern int (*udev_enumerate_add_match_sysname_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+extern int (*udev_enumerate_add_match_tag_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+extern int (*udev_enumerate_add_match_parent_dylibloader_wrapper_libudev)(struct udev_enumerate*,struct udev_device*);
+extern int (*udev_enumerate_add_match_is_initialized_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern int (*udev_enumerate_add_syspath_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+extern int (*udev_enumerate_scan_devices_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern int (*udev_enumerate_scan_subsystems_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern struct udev_list_entry* (*udev_enumerate_get_list_entry_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern struct udev_queue* (*udev_queue_ref_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern struct udev_queue* (*udev_queue_unref_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern struct udev* (*udev_queue_get_udev_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern struct udev_queue* (*udev_queue_new_dylibloader_wrapper_libudev)(struct udev*);
+extern unsigned long long int (*udev_queue_get_kernel_seqnum_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern unsigned long long int (*udev_queue_get_udev_seqnum_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern int (*udev_queue_get_udev_is_active_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern int (*udev_queue_get_queue_is_empty_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern int (*udev_queue_get_seqnum_is_finished_dylibloader_wrapper_libudev)(struct udev_queue*, unsigned long long int);
+extern int (*udev_queue_get_seqnum_sequence_is_finished_dylibloader_wrapper_libudev)(struct udev_queue*, unsigned long long int, unsigned long long int);
+extern int (*udev_queue_get_fd_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern int (*udev_queue_flush_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern struct udev_list_entry* (*udev_queue_get_queued_list_entry_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern struct udev_hwdb* (*udev_hwdb_new_dylibloader_wrapper_libudev)(struct udev*);
+extern struct udev_hwdb* (*udev_hwdb_ref_dylibloader_wrapper_libudev)(struct udev_hwdb*);
+extern struct udev_hwdb* (*udev_hwdb_unref_dylibloader_wrapper_libudev)(struct udev_hwdb*);
+extern struct udev_list_entry* (*udev_hwdb_get_properties_list_entry_dylibloader_wrapper_libudev)(struct udev_hwdb*,const char*, unsigned);
+extern int (*udev_util_encode_string_dylibloader_wrapper_libudev)(const char*, char*, size_t);
+int initialize_libudev(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/osx/SCsub b/platform/osx/SCsub
index aa95a89444..46c13d8550 100644
--- a/platform/osx/SCsub
+++ b/platform/osx/SCsub
@@ -18,5 +18,5 @@ files = [
prog = env.add_program("#bin/godot", files)
-if env["debug_symbols"] == "yes" and env["separate_debug_symbols"]:
+if env["debug_symbols"] and env["separate_debug_symbols"]:
env.AddPostAction(prog, run_in_subprocess(platform_osx_builders.make_debug_osx))
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 47ac609917..5b320da82f 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -35,6 +35,7 @@ def get_opts():
BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False),
BoolVariable("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False),
BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN))", False),
+ BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN))", False),
BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN))", False),
]
@@ -49,21 +50,21 @@ def configure(env):
if env["target"] == "release":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O3", "-fomit-frame-pointer", "-ftree-vectorize"])
- else: # optimize for size
+ elif env["optimize"] == "size": # optimize for size
env.Prepend(CCFLAGS=["-Os", "-ftree-vectorize"])
if env["arch"] != "arm64":
env.Prepend(CCFLAGS=["-msse2"])
- if env["debug_symbols"] == "yes":
+ if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
elif env["target"] == "release_debug":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O2"])
- else: # optimize for size
+ elif env["optimize"] == "size": # optimize for size
env.Prepend(CCFLAGS=["-Os"])
env.Prepend(CPPDEFINES=["DEBUG_ENABLED"])
- if env["debug_symbols"] == "yes":
+ if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
elif env["target"] == "debug":
@@ -131,7 +132,7 @@ def configure(env):
env["AS"] = basecmd + "as"
env.Append(CPPDEFINES=["__MACPORTS__"]) # hack to fix libvpx MM256_BROADCASTSI128_SI256 define
- if env["use_ubsan"] or env["use_asan"] or env["use_tsan"]:
+ if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"]:
env.extra_suffix += "s"
if env["use_ubsan"]:
@@ -142,6 +143,10 @@ def configure(env):
env.Append(CCFLAGS=["-fsanitize=address"])
env.Append(LINKFLAGS=["-fsanitize=address"])
+ if env["use_lsan"]:
+ env.Append(CCFLAGS=["-fsanitize=leak"])
+ env.Append(LINKFLAGS=["-fsanitize=leak"])
+
if env["use_tsan"]:
env.Append(CCFLAGS=["-fsanitize=thread"])
env.Append(LINKFLAGS=["-fsanitize=thread"])
diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h
index 597ebce6ff..9fac99810b 100644
--- a/platform/osx/display_server_osx.h
+++ b/platform/osx/display_server_osx.h
@@ -93,6 +93,7 @@ public:
List<WarpEvent> warp_events;
NSTimeInterval last_warp = 0;
+ bool ignore_warp = false;
Vector<KeyEvent> key_event_buffer;
int key_event_pos;
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index 2d43454501..412dd59f56 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -829,7 +829,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
mb->set_position(pos);
mb->set_global_position(pos);
mb->set_button_mask(DS_OSX->last_button_state);
- if (index == BUTTON_LEFT && pressed) {
+ if (index == MOUSE_BUTTON_LEFT && pressed) {
mb->set_doubleclick([event clickCount] == 2);
}
@@ -842,10 +842,10 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
if (([event modifierFlags] & NSEventModifierFlagControl)) {
wd.mouse_down_control = true;
- _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, true);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, true);
} else {
wd.mouse_down_control = false;
- _mouseDownEvent(window_id, event, BUTTON_LEFT, BUTTON_MASK_LEFT, true);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MASK_LEFT, true);
}
}
@@ -858,9 +858,9 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
if (wd.mouse_down_control) {
- _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, false);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, false);
} else {
- _mouseDownEvent(window_id, event, BUTTON_LEFT, BUTTON_MASK_LEFT, false);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MASK_LEFT, false);
}
}
@@ -871,6 +871,15 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
NSPoint delta = NSMakePoint([event deltaX], [event deltaY]);
NSPoint mpos = [event locationInWindow];
+ if (DS_OSX->ignore_warp) {
+ // Discard late events, before warp
+ if (([event timestamp]) < DS_OSX->last_warp) {
+ return;
+ }
+ DS_OSX->ignore_warp = false;
+ return;
+ }
+
if (DS_OSX->mouse_mode == DisplayServer::MOUSE_MODE_CONFINED) {
// Discard late events
if (([event timestamp]) < DS_OSX->last_warp) {
@@ -937,7 +946,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
}
- (void)rightMouseDown:(NSEvent *)event {
- _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, true);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, true);
}
- (void)rightMouseDragged:(NSEvent *)event {
@@ -945,16 +954,16 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
}
- (void)rightMouseUp:(NSEvent *)event {
- _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, false);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, false);
}
- (void)otherMouseDown:(NSEvent *)event {
if ((int)[event buttonNumber] == 2) {
- _mouseDownEvent(window_id, event, BUTTON_MIDDLE, BUTTON_MASK_MIDDLE, true);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_MASK_MIDDLE, true);
} else if ((int)[event buttonNumber] == 3) {
- _mouseDownEvent(window_id, event, BUTTON_XBUTTON1, BUTTON_MASK_XBUTTON1, true);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON1, MOUSE_BUTTON_MASK_XBUTTON1, true);
} else if ((int)[event buttonNumber] == 4) {
- _mouseDownEvent(window_id, event, BUTTON_XBUTTON2, BUTTON_MASK_XBUTTON2, true);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON2, MOUSE_BUTTON_MASK_XBUTTON2, true);
} else {
return;
}
@@ -966,11 +975,11 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
- (void)otherMouseUp:(NSEvent *)event {
if ((int)[event buttonNumber] == 2) {
- _mouseDownEvent(window_id, event, BUTTON_MIDDLE, BUTTON_MASK_MIDDLE, false);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_MASK_MIDDLE, false);
} else if ((int)[event buttonNumber] == 3) {
- _mouseDownEvent(window_id, event, BUTTON_XBUTTON1, BUTTON_MASK_XBUTTON1, false);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON1, MOUSE_BUTTON_MASK_XBUTTON1, false);
} else if ((int)[event buttonNumber] == 4) {
- _mouseDownEvent(window_id, event, BUTTON_XBUTTON2, BUTTON_MASK_XBUTTON2, false);
+ _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON2, MOUSE_BUTTON_MASK_XBUTTON2, false);
} else {
return;
}
@@ -1549,10 +1558,10 @@ inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy
sendPanEvent(window_id, deltaX, deltaY, [event modifierFlags]);
} else {
if (fabs(deltaX)) {
- sendScrollEvent(window_id, 0 > deltaX ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]);
+ sendScrollEvent(window_id, 0 > deltaX ? MOUSE_BUTTON_WHEEL_RIGHT : MOUSE_BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]);
}
if (fabs(deltaY)) {
- sendScrollEvent(window_id, 0 < deltaY ? BUTTON_WHEEL_UP : BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]);
+ sendScrollEvent(window_id, 0 < deltaY ? MOUSE_BUTTON_WHEEL_UP : MOUSE_BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]);
}
}
}
@@ -2098,6 +2107,8 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) {
CGAssociateMouseAndMouseCursorPosition(true);
}
+ last_warp = [[NSProcessInfo processInfo] systemUptime];
+ ignore_warp = true;
warp_events.clear();
mouse_mode = p_mode;
}
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 337cfd6808..6ac98cae9c 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -56,7 +56,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform {
void _make_icon(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);
+ Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path);
Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name);
void _zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name);
@@ -114,7 +114,7 @@ public:
virtual void get_platform_features(List<String> *r_features) override {
r_features->push_back("pc");
r_features->push_back("s3tc");
- r_features->push_back("OSX");
+ r_features->push_back("macOS");
}
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override {
@@ -159,7 +159,31 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/hardened_runtime"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements", PROPERTY_HINT_GLOBAL_FILE, "*.plist"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/replace_existing_signature"), true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements/custom_file", PROPERTY_HINT_GLOBAL_FILE, "*.plist"), ""));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_jit_code_execution"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_unsigned_executable_memory"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_dyld_environment_variables"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/disable_library_validation"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/audio_input"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/camera"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/location"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/address_book"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/calendars"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/photos_library"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/apple_events"), false));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/enabled"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/network_server"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/network_client"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/device_usb"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/device_bluetooth"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_downloads", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_pictures", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_music", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_movies", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
+
r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "notarization/enable"), false));
@@ -437,7 +461,7 @@ Error EditorExportPlatformOSX::_notarize(const Ref<EditorExportPreset> &p_preset
return OK;
}
-Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
+Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path) {
#ifdef OSX_ENABLED
List<String> args;
@@ -449,9 +473,9 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
args.push_back("runtime");
}
- if ((p_preset->get("codesign/entitlements") != "") && (p_path.get_extension() != "dmg")) {
+ if (p_path.get_extension() != "dmg") {
args.push_back("--entitlements");
- args.push_back(p_preset->get("codesign/entitlements"));
+ args.push_back(p_ent_path);
}
PackedStringArray user_args = p_preset->get("codesign/custom_options");
@@ -467,6 +491,10 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
args.push_back("-v"); /* provide some more feedback */
+ if (p_preset->get("codesign/replace_existing_signature")) {
+ args.push_back("-f");
+ }
+
args.push_back(p_path);
String str;
@@ -607,6 +635,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
// Now process our template.
bool found_binary = false;
int total_size = 0;
+ Vector<String> dylibs_found;
while (ret == UNZ_OK && err == OK) {
bool is_execute = false;
@@ -678,14 +707,18 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
ret = unzGoToNextFile(src_pkg_zip);
continue; // skip
}
- file = file.replace("/data.mono.osx.64.release_debug/", "/data_" + pkg_name + "/");
+ file = file.replace("/data.mono.osx.64.release_debug/", "/GodotSharp/");
}
if (file.find("/data.mono.osx.64.release/") != -1) {
if (p_debug) {
ret = unzGoToNextFile(src_pkg_zip);
continue; // skip
}
- file = file.replace("/data.mono.osx.64.release/", "/data_" + pkg_name + "/");
+ file = file.replace("/data.mono.osx.64.release/", "/GodotSharp/");
+ }
+
+ if (file.ends_with(".dylib")) {
+ dylibs_found.push_back(file);
}
print_line("ADDING: " + file + " size: " + itos(data.size()));
@@ -735,22 +768,149 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
// See if we can code sign our new package.
bool sign_enabled = p_preset->get("codesign/enable");
+ String ent_path = p_preset->get("codesign/entitlements/custom_file");
+ if (sign_enabled && (ent_path == "")) {
+ ent_path = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".entitlements");
+
+ FileAccess *ent_f = FileAccess::open(ent_path, FileAccess::WRITE);
+ if (ent_f) {
+ ent_f->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ ent_f->store_line("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
+ ent_f->store_line("<plist version=\"1.0\">");
+ ent_f->store_line("<dict>");
+ if ((bool)p_preset->get("codesign/entitlements/allow_jit_code_execution")) {
+ ent_f->store_line("<key>com.apple.security.cs.allow-jit</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/allow_unsigned_executable_memory")) {
+ ent_f->store_line("<key>com.apple.security.cs.allow-unsigned-executable-memory</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/allow_dyld_environment_variables")) {
+ ent_f->store_line("<key>com.apple.security.cs.allow-dyld-environment-variables</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/disable_library_validation")) {
+ ent_f->store_line("<key>com.apple.security.cs.disable-library-validation</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/audio_input")) {
+ ent_f->store_line("<key>com.apple.security.device.audio-input</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/camera")) {
+ ent_f->store_line("<key>com.apple.security.device.camera</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/location")) {
+ ent_f->store_line("<key>com.apple.security.personal-information.location</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/address_book")) {
+ ent_f->store_line("<key>com.apple.security.personal-information.addressbook</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/calendars")) {
+ ent_f->store_line("<key>com.apple.security.personal-information.calendars</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/photos_library")) {
+ ent_f->store_line("<key>com.apple.security.personal-information.photos-library</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/apple_events")) {
+ ent_f->store_line("<key>com.apple.security.automation.apple-events</key>");
+ ent_f->store_line("<true/>");
+ }
+
+ if ((bool)p_preset->get("codesign/entitlements/app_sandbox/enabled")) {
+ ent_f->store_line("<key>com.apple.security.app-sandbox</key>");
+ ent_f->store_line("<true/>");
+
+ if ((bool)p_preset->get("codesign/entitlements/app_sandbox/network_server")) {
+ ent_f->store_line("<key>com.apple.security.network.server</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/app_sandbox/network_client")) {
+ ent_f->store_line("<key>com.apple.security.network.client</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/app_sandbox/device_usb")) {
+ ent_f->store_line("<key>com.apple.security.device.usb</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((bool)p_preset->get("codesign/entitlements/app_sandbox/device_bluetooth")) {
+ ent_f->store_line("<key>com.apple.security.device.bluetooth</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_downloads") == 1) {
+ ent_f->store_line("<key>com.apple.security.files.downloads.read-only</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_downloads") == 2) {
+ ent_f->store_line("<key>com.apple.security.files.downloads.read-write</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_pictures") == 1) {
+ ent_f->store_line("<key>com.apple.security.files.pictures.read-only</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_pictures") == 2) {
+ ent_f->store_line("<key>com.apple.security.files.pictures.read-write</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_music") == 1) {
+ ent_f->store_line("<key>com.apple.security.files.music.read-only</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_music") == 2) {
+ ent_f->store_line("<key>com.apple.security.files.music.read-write</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_movies") == 1) {
+ ent_f->store_line("<key>com.apple.security.files.movies.read-only</key>");
+ ent_f->store_line("<true/>");
+ }
+ if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_movies") == 2) {
+ ent_f->store_line("<key>com.apple.security.files.movies.read-write</key>");
+ ent_f->store_line("<true/>");
+ }
+ }
+
+ ent_f->store_line("</dict>");
+ ent_f->store_line("</plist>");
+
+ ent_f->close();
+ memdelete(ent_f);
+ } else {
+ err = ERR_CANT_CREATE;
+ }
+ }
+
if (err == OK) {
DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < shared_objects.size(); i++) {
err = da->copy(shared_objects[i].path, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
if (err == OK && sign_enabled) {
- err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file(), ent_path);
}
}
memdelete(da);
}
+ if (sign_enabled) {
+ for (int i = 0; i < dylibs_found.size(); i++) {
+ if (err == OK) {
+ err = _code_sign(p_preset, tmp_app_path_name + "/" + dylibs_found[i], ent_path);
+ }
+ }
+ }
+
if (err == OK && sign_enabled) {
if (ep.step("Code signing bundle", 2)) {
return ERR_SKIP;
}
- err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name);
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name, ent_path);
}
if (export_format == "dmg") {
@@ -766,7 +926,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (ep.step("Code signing DMG", 3)) {
return ERR_SKIP;
}
- err = _code_sign(p_preset, p_path);
+ err = _code_sign(p_preset, p_path, ent_path);
}
} else {
// Create ZIP.
diff --git a/platform/osx/joypad_osx.cpp b/platform/osx/joypad_osx.cpp
index 0b6a0e20a6..b12526915f 100644
--- a/platform/osx/joypad_osx.cpp
+++ b/platform/osx/joypad_osx.cpp
@@ -433,8 +433,8 @@ void JoypadOSX::poll_joypads() const {
}
}
-static const Input::JoyAxis axis_correct(int p_value, int p_min, int p_max) {
- Input::JoyAxis jx;
+static const Input::JoyAxisValue axis_correct(int p_value, int p_min, int p_max) {
+ Input::JoyAxisValue jx;
if (p_min < 0) {
jx.min = -1;
if (p_value < 0) {
diff --git a/platform/server/detect.py b/platform/server/detect.py
index 06042c8e17..16ddbe1768 100644
--- a/platform/server/detect.py
+++ b/platform/server/detect.py
@@ -39,6 +39,7 @@ def get_opts():
BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN))", False),
BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN))", False),
BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
+ BoolVariable("use_msan", "Use LLVM/GCC compiler memory sanitizer (MSAN))", False),
BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False),
BoolVariable("execinfo", "Use libexecinfo on systems where glibc is not available", False),
]
@@ -55,20 +56,20 @@ def configure(env):
if env["target"] == "release":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O3"])
- else: # optimize for size
+ elif env["optimize"] == "size": # optimize for size
env.Prepend(CCFLAGS=["-Os"])
- if env["debug_symbols"] == "yes":
+ if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
elif env["target"] == "release_debug":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O2"])
- else: # optimize for size
+ elif env["optimize"] == "size": # optimize for size
env.Prepend(CCFLAGS=["-Os"])
env.Prepend(CPPDEFINES=["DEBUG_ENABLED"])
- if env["debug_symbols"] == "yes":
+ if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
elif env["target"] == "debug":
@@ -93,12 +94,13 @@ def configure(env):
env["CC"] = "clang"
env["CXX"] = "clang++"
env.extra_suffix = ".llvm" + env.extra_suffix
+ env.Append(LIBS=["atomic"])
if env["use_coverage"]:
env.Append(CCFLAGS=["-ftest-coverage", "-fprofile-arcs"])
env.Append(LINKFLAGS=["-ftest-coverage", "-fprofile-arcs"])
- if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"]:
+ if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"] or env["use_msan"]:
env.extra_suffix += "s"
if env["use_ubsan"]:
@@ -117,6 +119,10 @@ def configure(env):
env.Append(CCFLAGS=["-fsanitize=thread"])
env.Append(LINKFLAGS=["-fsanitize=thread"])
+ if env["use_msan"]:
+ env.Append(CCFLAGS=["-fsanitize=memory"])
+ env.Append(LINKFLAGS=["-fsanitize=memory"])
+
if env["use_lto"]:
env.Append(CCFLAGS=["-flto"])
if not env["use_llvm"] and env.GetOption("num_jobs") > 1:
diff --git a/platform/uwp/app.cpp b/platform/uwp/app.cpp
index dc4238bdd4..b7e4361831 100644
--- a/platform/uwp/app.cpp
+++ b/platform/uwp/app.cpp
@@ -149,28 +149,28 @@ static int _get_button(Windows::UI::Input::PointerPoint ^ pt) {
using namespace Windows::UI::Input;
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
- return BUTTON_LEFT;
+ return MOUSE_BUTTON_LEFT;
#else
switch (pt->Properties->PointerUpdateKind) {
case PointerUpdateKind::LeftButtonPressed:
case PointerUpdateKind::LeftButtonReleased:
- return BUTTON_LEFT;
+ return MOUSE_BUTTON_LEFT;
case PointerUpdateKind::RightButtonPressed:
case PointerUpdateKind::RightButtonReleased:
- return BUTTON_RIGHT;
+ return MOUSE_BUTTON_RIGHT;
case PointerUpdateKind::MiddleButtonPressed:
case PointerUpdateKind::MiddleButtonReleased:
- return BUTTON_MIDDLE;
+ return MOUSE_BUTTON_MIDDLE;
case PointerUpdateKind::XButton1Pressed:
case PointerUpdateKind::XButton1Released:
- return BUTTON_WHEEL_UP;
+ return MOUSE_BUTTON_WHEEL_UP;
case PointerUpdateKind::XButton2Pressed:
case PointerUpdateKind::XButton2Released:
- return BUTTON_WHEEL_DOWN;
+ return MOUSE_BUTTON_WHEEL_DOWN;
default:
break;
@@ -265,9 +265,9 @@ void App::pointer_event(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Cor
if (p_is_wheel) {
if (point->Properties->MouseWheelDelta > 0) {
- mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_UP);
+ mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? MOUSE_BUTTON_WHEEL_RIGHT : MOUSE_BUTTON_WHEEL_UP);
} else if (point->Properties->MouseWheelDelta < 0) {
- mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_LEFT : BUTTON_WHEEL_DOWN);
+ mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? MOUSE_BUTTON_WHEEL_LEFT : MOUSE_BUTTON_WHEEL_DOWN);
}
}
diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py
index fda8fdec66..28922a4f59 100644
--- a/platform/uwp/detect.py
+++ b/platform/uwp/detect.py
@@ -54,16 +54,19 @@ def configure(env):
## Build type
if env["target"] == "release":
- env.Append(CCFLAGS=["/O2", "/GL"])
env.Append(CCFLAGS=["/MD"])
- env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS", "/LTCG"])
+ env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS"])
+ if env["optimize"] != "none":
+ env.Append(CCFLAGS=["/O2", "/GL"])
+ env.Append(LINKFLAGS=["/LTCG"])
elif env["target"] == "release_debug":
- env.Append(CCFLAGS=["/O2", "/Zi"])
env.Append(CCFLAGS=["/MD"])
- env.Append(CPPDEFINES=["DEBUG_ENABLED"])
env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"])
env.AppendUnique(CPPDEFINES=["WINDOWS_SUBSYSTEM_CONSOLE"])
+ env.Append(CPPDEFINES=["DEBUG_ENABLED"])
+ if env["optimize"] != "none":
+ env.Append(CCFLAGS=["/O2", "/Zi"])
elif env["target"] == "debug":
env.Append(CCFLAGS=["/Zi"])
diff --git a/platform/uwp/joypad_uwp.cpp b/platform/uwp/joypad_uwp.cpp
index 5da90db49d..b419fb4fae 100644
--- a/platform/uwp/joypad_uwp.cpp
+++ b/platform/uwp/joypad_uwp.cpp
@@ -134,8 +134,8 @@ void JoypadUWP::OnGamepadRemoved(Platform::Object ^ sender, Windows::Gaming::Inp
input->joy_connection_changed(idx, false, "Xbox Controller");
}
-InputDefault::JoyAxis JoypadUWP::axis_correct(double p_val, bool p_negate, bool p_trigger) const {
- InputDefault::JoyAxis jx;
+InputDefault::JoyAxisValue JoypadUWP::axis_correct(double p_val, bool p_negate, bool p_trigger) const {
+ InputDefault::JoyAxisValue jx;
jx.min = p_trigger ? 0 : -1;
jx.value = (float)(p_negate ? -p_val : p_val);
diff --git a/platform/uwp/joypad_uwp.h b/platform/uwp/joypad_uwp.h
index 5df4a211ac..d760d9e2fe 100644
--- a/platform/uwp/joypad_uwp.h
+++ b/platform/uwp/joypad_uwp.h
@@ -73,7 +73,7 @@ private:
void OnGamepadAdded(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value);
void OnGamepadRemoved(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value);
- InputDefault::JoyAxis axis_correct(double p_val, bool p_negate = false, bool p_trigger = false) const;
+ InputDefault::JoyAxisValue axis_correct(double p_val, bool p_negate = false, bool p_trigger = false) const;
void joypad_vibration_start(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp);
void joypad_vibration_stop(int p_device, uint64_t p_timestamp);
};
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index 8b60e55d2d..33992069f9 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -44,7 +44,6 @@
#include "platform/windows/windows_terminal_logger.h"
#include "servers/audio_server.h"
#include "servers/rendering/rendering_server_default.h"
-#include "servers/rendering/rendering_server_wrap_mt.h"
#include <ppltasks.h>
#include <wrl.h>
@@ -63,6 +62,8 @@ using namespace Windows::Devices::Sensors;
using namespace Windows::ApplicationModel::DataTransfer;
using namespace concurrency;
+static const float earth_gravity = 9.80665;
+
int OS_UWP::get_video_driver_count() const {
return 2;
}
@@ -373,9 +374,9 @@ void OS_UWP::ManagedType::on_accelerometer_reading_changed(Accelerometer ^ sende
AccelerometerReading ^ reading = args->Reading;
os->input->set_accelerometer(Vector3(
- reading->AccelerationX,
- reading->AccelerationY,
- reading->AccelerationZ));
+ reading->AccelerationX * earth_gravity,
+ reading->AccelerationY * earth_gravity,
+ reading->AccelerationZ * earth_gravity));
}
void OS_UWP::ManagedType::on_magnetometer_reading_changed(Magnetometer ^ sender, MagnetometerReadingChangedEventArgs ^ args) {
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index 0c9aa77803..47d8e14680 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -32,5 +32,5 @@ if env["vsproj"]:
env.vs_srcs += ["platform/windows/" + str(x)]
if not os.getenv("VCINSTALLDIR"):
- if env["debug_symbols"] == "yes" and env["separate_debug_symbols"]:
+ if env["debug_symbols"] and env["separate_debug_symbols"]:
env.AddPostAction(prog, run_in_subprocess(platform_windows_builders.make_debug_mingw))
diff --git a/platform/windows/crash_handler_windows.cpp b/platform/windows/crash_handler_windows.cpp
index e24e466f88..e2d507eddd 100644
--- a/platform/windows/crash_handler_windows.cpp
+++ b/platform/windows/crash_handler_windows.cpp
@@ -36,7 +36,7 @@
#ifdef CRASH_HANDLER_EXCEPTION
-// Backtrace code code based on: https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app
+// Backtrace code based on: https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app
#include <algorithm>
#include <iterator>
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index a675a2302f..7772ba2dbe 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -72,6 +72,7 @@ def get_opts():
BoolVariable("use_llvm", "Use the LLVM compiler", False),
BoolVariable("use_thinlto", "Use ThinLTO", False),
BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True),
+ BoolVariable("use_asan", "Use address sanitizer (ASAN)", False),
]
@@ -190,26 +191,28 @@ def configure_msvc(env, manual_msvc_config):
if env["target"] == "release":
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["/O2"])
- else: # optimize for size
+ env.Append(LINKFLAGS=["/OPT:REF"])
+ elif env["optimize"] == "size": # optimize for size
env.Append(CCFLAGS=["/O1"])
+ env.Append(LINKFLAGS=["/OPT:REF"])
env.Append(LINKFLAGS=["/ENTRY:mainCRTStartup"])
- env.Append(LINKFLAGS=["/OPT:REF"])
elif env["target"] == "release_debug":
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["/O2"])
- else: # optimize for size
+ env.Append(LINKFLAGS=["/OPT:REF"])
+ elif env["optimize"] == "size": # optimize for size
env.Append(CCFLAGS=["/O1"])
+ env.Append(LINKFLAGS=["/OPT:REF"])
env.AppendUnique(CPPDEFINES=["DEBUG_ENABLED"])
- env.Append(LINKFLAGS=["/OPT:REF"])
elif env["target"] == "debug":
- env.AppendUnique(CCFLAGS=["/Z7", "/Od", "/EHsc"])
+ env.AppendUnique(CCFLAGS=["/Zi", "/FS", "/Od", "/EHsc"])
env.AppendUnique(CPPDEFINES=["DEBUG_ENABLED"])
env.Append(LINKFLAGS=["/DEBUG"])
- if env["debug_symbols"] == "yes":
- env.AppendUnique(CCFLAGS=["/Z7"])
+ if env["debug_symbols"]:
+ env.AppendUnique(CCFLAGS=["/Zi", "/FS"])
env.AppendUnique(LINKFLAGS=["/DEBUG"])
if env["windows_subsystem"] == "gui":
@@ -224,6 +227,7 @@ def configure_msvc(env, manual_msvc_config):
env.AppendUnique(CCFLAGS=["/MT"])
else:
env.AppendUnique(CCFLAGS=["/MD"])
+
env.AppendUnique(CCFLAGS=["/Gd", "/GR", "/nologo"])
# Force to use Unicode encoding
env.AppendUnique(CCFLAGS=["/utf-8"])
@@ -305,6 +309,12 @@ def configure_msvc(env, manual_msvc_config):
env.Prepend(CPPPATH=[p for p in os.getenv("INCLUDE").split(";")])
env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")])
+ # Sanitizers
+ if env["use_asan"]:
+ env.extra_suffix += ".s"
+ env.Append(LINKFLAGS=["/INFERASANLIBS"])
+ env.Append(CCFLAGS=["/fsanitize=address"])
+
# Incremental linking fix
env["BUILDERS"]["ProgramOriginal"] = env["BUILDERS"]["Program"]
env["BUILDERS"]["Program"] = methods.precious_program
@@ -339,13 +349,13 @@ def configure_mingw(env):
else: # optimize for size
env.Prepend(CCFLAGS=["-Os"])
- if env["debug_symbols"] == "yes":
+ if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
elif env["target"] == "release_debug":
env.Append(CCFLAGS=["-O2"])
env.Append(CPPDEFINES=["DEBUG_ENABLED"])
- if env["debug_symbols"] == "yes":
+ if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["-O2"])
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 14e7d395d3..4d81afc5dd 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -535,7 +535,7 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
}
#endif
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[p_window].wtctx) {
+ if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[p_window].wtctx) {
wintab_WTClose(windows[p_window].wtctx);
windows[p_window].wtctx = 0;
}
@@ -1253,12 +1253,12 @@ void DisplayServerWindows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTra
HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap);
HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap);
- // Assign the monochrome AND mask bitmap pixels so that a pixels of the source bitmap
+ // Assign the monochrome AND mask bitmap pixels so that the pixels of the source bitmap
// with 'clrTransparent' will be white pixels of the monochrome bitmap
SetBkColor(hMainDC, clrTransparent);
BitBlt(hAndMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCCOPY);
- // Assign the color XOR mask bitmap pixels so that a pixels of the source bitmap
+ // Assign the color XOR mask bitmap pixels so that the pixels of the source bitmap
// with 'clrTransparent' will be black and rest the pixels same as corresponding
// pixels of the source bitmap
SetBkColor(hXorMaskDC, RGB(0, 0, 0));
@@ -1784,7 +1784,10 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
Ref<InputEventFromWindow> event_from_window = p_event;
if (event_from_window.is_valid() && event_from_window->get_window_id() != INVALID_WINDOW_ID) {
//send to a window
- ERR_FAIL_COND(!windows.has(event_from_window->get_window_id()));
+ if (!windows.has(event_from_window->get_window_id())) {
+ in_dispatch_input_event = false;
+ ERR_FAIL_MSG("DisplayServerWindows: Invalid window id in input event.");
+ }
Callable callable = windows[event_from_window->get_window_id()].input_event_callback;
if (callable.is_null()) {
in_dispatch_input_event = false;
@@ -2018,7 +2021,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
} break;
case WT_CSRCHANGE:
case WT_PROXIMITY: {
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
+ if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
AXIS pressure;
if (wintab_WTInfo(WTI_DEVICES + windows[window_id].wtlc.lcDevice, DVC_NPRESSURE, &pressure)) {
windows[window_id].min_pressure = int(pressure.axMin);
@@ -2032,7 +2035,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
} break;
case WT_PACKET: {
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
+ if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
PACKET packet;
if (wintab_WTPacket(windows[window_id].wtctx, wParam, &packet)) {
float pressure = float(packet.pkNormalPressure - windows[window_id].min_pressure) / float(windows[window_id].max_pressure - windows[window_id].min_pressure);
@@ -2111,7 +2114,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
break;
}
- if ((OS::get_singleton()->get_current_tablet_driver() != "winink") || !winink_available) {
+ if ((tablet_get_current_driver() != "winink") || !winink_available) {
break;
}
@@ -2137,7 +2140,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
break;
}
- if ((OS::get_singleton()->get_current_tablet_driver() != "winink") || !winink_available) {
+ if ((tablet_get_current_driver() != "winink") || !winink_available) {
break;
}
@@ -2301,8 +2304,8 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mm->set_shift((wParam & MK_SHIFT) != 0);
mm->set_alt(alt_mem);
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
- // Note: WinTab sends both WT_PACKET and WM_xBUTTONDOWN/UP/MOUSEMOVE events, use mouse 1/0 pressure only when last_pressure was not update recently.
+ if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
+ // Note: WinTab sends both WT_PACKET and WM_xBUTTONDOWN/UP/MOUSEMOVE events, use mouse 1/0 pressure only when last_pressure was not updated recently.
if (windows[window_id].last_pressure_update < 10) {
windows[window_id].last_pressure_update++;
} else {
@@ -2428,9 +2431,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
return 0;
if (motion > 0)
- mb->set_button_index(BUTTON_WHEEL_UP);
+ mb->set_button_index(MOUSE_BUTTON_WHEEL_UP);
else
- mb->set_button_index(BUTTON_WHEEL_DOWN);
+ mb->set_button_index(MOUSE_BUTTON_WHEEL_DOWN);
} break;
case WM_MOUSEHWHEEL: {
@@ -2440,33 +2443,33 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
return 0;
if (motion < 0) {
- mb->set_button_index(BUTTON_WHEEL_LEFT);
+ mb->set_button_index(MOUSE_BUTTON_WHEEL_LEFT);
mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA));
} else {
- mb->set_button_index(BUTTON_WHEEL_RIGHT);
+ mb->set_button_index(MOUSE_BUTTON_WHEEL_RIGHT);
mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA));
}
} break;
case WM_XBUTTONDOWN: {
mb->set_pressed(true);
if (HIWORD(wParam) == XBUTTON1)
- mb->set_button_index(BUTTON_XBUTTON1);
+ mb->set_button_index(MOUSE_BUTTON_XBUTTON1);
else
- mb->set_button_index(BUTTON_XBUTTON2);
+ mb->set_button_index(MOUSE_BUTTON_XBUTTON2);
} break;
case WM_XBUTTONUP: {
mb->set_pressed(false);
if (HIWORD(wParam) == XBUTTON1)
- mb->set_button_index(BUTTON_XBUTTON1);
+ mb->set_button_index(MOUSE_BUTTON_XBUTTON1);
else
- mb->set_button_index(BUTTON_XBUTTON2);
+ mb->set_button_index(MOUSE_BUTTON_XBUTTON2);
} break;
case WM_XBUTTONDBLCLK: {
mb->set_pressed(true);
if (HIWORD(wParam) == XBUTTON1)
- mb->set_button_index(BUTTON_XBUTTON1);
+ mb->set_button_index(MOUSE_BUTTON_XBUTTON1);
else
- mb->set_button_index(BUTTON_XBUTTON2);
+ mb->set_button_index(MOUSE_BUTTON_XBUTTON2);
mb->set_doubleclick(true);
} break;
default: {
@@ -2796,7 +2799,7 @@ void DisplayServerWindows::_process_activate_event(WindowID p_window_id, WPARAM
alt_mem = false;
}
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[p_window_id].wtctx) {
+ if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[p_window_id].wtctx) {
wintab_WTEnable(windows[p_window_id].wtctx, GET_WM_ACTIVATE_STATE(wParam, lParam));
}
}
@@ -3034,7 +3037,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
DragAcceptFiles(wd.hWnd, true);
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available) {
+ if ((tablet_get_current_driver() == "wintab") && wintab_available) {
wintab_WTInfo(WTI_DEFSYSCTX, 0, &wd.wtlc);
wd.wtlc.lcOptions |= CXO_MESSAGES;
wd.wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
@@ -3101,6 +3104,40 @@ typedef enum _SHC_PROCESS_DPI_AWARENESS {
SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2
} SHC_PROCESS_DPI_AWARENESS;
+int DisplayServerWindows::tablet_get_driver_count() const {
+ return tablet_drivers.size();
+}
+
+String DisplayServerWindows::tablet_get_driver_name(int p_driver) const {
+ if (p_driver < 0 || p_driver >= tablet_drivers.size()) {
+ return "";
+ } else {
+ return tablet_drivers[p_driver];
+ }
+}
+
+String DisplayServerWindows::tablet_get_current_driver() const {
+ return tablet_driver;
+}
+
+void DisplayServerWindows::tablet_set_current_driver(const String &p_driver) {
+ if (tablet_get_driver_count() == 0) {
+ return;
+ }
+ bool found = false;
+ for (int i = 0; i < tablet_get_driver_count(); i++) {
+ if (p_driver == tablet_get_driver_name(i)) {
+ found = true;
+ }
+ }
+ if (found) {
+ _update_tablet_ctx(tablet_driver, p_driver);
+ tablet_driver = p_driver;
+ } else {
+ ERR_PRINT("Unknown tablet driver " + p_driver + ".");
+ }
+}
+
DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
drop_events = false;
key_event_pos = 0;
@@ -3119,6 +3156,35 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
outside = true;
+ //Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
+ HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
+ if (wintab_lib) {
+ wintab_WTOpen = (WTOpenPtr)GetProcAddress(wintab_lib, "WTOpenW");
+ wintab_WTClose = (WTClosePtr)GetProcAddress(wintab_lib, "WTClose");
+ wintab_WTInfo = (WTInfoPtr)GetProcAddress(wintab_lib, "WTInfoW");
+ wintab_WTPacket = (WTPacketPtr)GetProcAddress(wintab_lib, "WTPacket");
+ wintab_WTEnable = (WTEnablePtr)GetProcAddress(wintab_lib, "WTEnable");
+
+ wintab_available = wintab_WTOpen && wintab_WTClose && wintab_WTInfo && wintab_WTPacket && wintab_WTEnable;
+ }
+
+ if (wintab_available) {
+ tablet_drivers.push_back("wintab");
+ }
+
+ //Note: Windows Ink API for pen input, available on Windows 8+ only.
+ HMODULE user32_lib = LoadLibraryW(L"user32.dll");
+ if (user32_lib) {
+ win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType");
+ win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo");
+
+ winink_available = win8p_GetPointerType && win8p_GetPointerPenInfo;
+ }
+
+ if (winink_available) {
+ tablet_drivers.push_back("winink");
+ }
+
if (OS::get_singleton()->is_hidpi_allowed()) {
HMODULE Shcore = LoadLibraryW(L"Shcore.dll");
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index c8c6a75bf5..a734077e59 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -264,7 +264,6 @@ class DisplayServerWindows : public DisplayServer {
_THREAD_SAFE_CLASS_
-public:
// WinTab API
static bool wintab_available;
static WTOpenPtr wintab_WTOpen;
@@ -279,8 +278,9 @@ public:
static GetPointerPenInfoPtr win8p_GetPointerPenInfo;
void _update_tablet_ctx(const String &p_old_driver, const String &p_new_driver);
+ String tablet_driver;
+ Vector<String> tablet_drivers;
-private:
void GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap);
enum {
@@ -542,6 +542,11 @@ public:
virtual String keyboard_get_layout_language(int p_index) const;
virtual String keyboard_get_layout_name(int p_index) const;
+ virtual int tablet_get_driver_count() const;
+ virtual String tablet_get_driver_name(int p_driver) const;
+ virtual String tablet_get_current_driver() const;
+ virtual void tablet_set_current_driver(const String &p_driver);
+
virtual void process_events();
virtual void force_process_and_drop_events();
diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis
index d85dfbc3d3..857c6a88f1 100644
--- a/platform/windows/godot.natvis
+++ b/platform/windows/godot.natvis
@@ -10,6 +10,16 @@
</Expand>
</Type>
+ <Type Name="LocalVector&lt;*&gt;">
+ <Expand>
+ <Item Name="[size]">count</Item>
+ <ArrayItems>
+ <Size>count</Size>
+ <ValuePointer>data</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
<Type Name="List&lt;*&gt;">
<Expand>
<Item Name="[size]">_data ? (_data->size_cache) : 0</Item>
diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp
index f46a0dbe2e..da36dc1f2b 100644
--- a/platform/windows/joypad_windows.cpp
+++ b/platform/windows/joypad_windows.cpp
@@ -110,12 +110,11 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
if (GetRawInputDeviceList(nullptr, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
return false;
}
- dev_list = (PRAWINPUTDEVICELIST)malloc(sizeof(RAWINPUTDEVICELIST) * dev_list_count);
- if (!dev_list)
- return false;
+ dev_list = (PRAWINPUTDEVICELIST)memalloc(sizeof(RAWINPUTDEVICELIST) * dev_list_count);
+ ERR_FAIL_NULL_V_MSG(dev_list, false, "Out of memory.");
if (GetRawInputDeviceList(dev_list, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
- free(dev_list);
+ memfree(dev_list);
return false;
}
for (unsigned int i = 0; i < dev_list_count; i++) {
@@ -130,11 +129,11 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
(MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == (LONG)p_guid->Data1) &&
(GetRawInputDeviceInfoA(dev_list[i].hDevice, RIDI_DEVICENAME, &dev_name, &nameSize) != (UINT)-1) &&
(strstr(dev_name, "IG_") != nullptr)) {
- free(dev_list);
+ memfree(dev_list);
return true;
}
}
- free(dev_list);
+ memfree(dev_list);
return false;
}
@@ -447,8 +446,8 @@ void JoypadWindows::post_hat(int p_device, DWORD p_dpad) {
input->joy_hat(p_device, dpad_val);
};
-Input::JoyAxis JoypadWindows::axis_correct(int p_val, bool p_xinput, bool p_trigger, bool p_negate) const {
- Input::JoyAxis jx;
+Input::JoyAxisValue JoypadWindows::axis_correct(int p_val, bool p_xinput, bool p_trigger, bool p_negate) const {
+ Input::JoyAxisValue jx;
if (Math::abs(p_val) < MIN_JOY_AXIS) {
jx.min = p_trigger ? 0 : -1;
jx.value = 0.0f;
diff --git a/platform/windows/joypad_windows.h b/platform/windows/joypad_windows.h
index 4727b4a14c..757fb54fb3 100644
--- a/platform/windows/joypad_windows.h
+++ b/platform/windows/joypad_windows.h
@@ -132,7 +132,7 @@ private:
void joypad_vibration_start_xinput(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp);
void joypad_vibration_stop_xinput(int p_device, uint64_t p_timestamp);
- Input::JoyAxis axis_correct(int p_val, bool p_xinput = false, bool p_trigger = false, bool p_negate = false) const;
+ Input::JoyAxisValue axis_correct(int p_val, bool p_xinput = false, bool p_trigger = false, bool p_negate = false) const;
XInputGetState_t xinput_get_state;
XInputSetState_t xinput_set_state;
};
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index fe007027da..1e9cdd241d 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -45,7 +45,6 @@
#include "platform/windows/display_server_windows.h"
#include "servers/audio_server.h"
#include "servers/rendering/rendering_server_default.h"
-#include "servers/rendering/rendering_server_wrap_mt.h"
#include "windows_terminal_logger.h"
#include <avrt.h>
@@ -335,7 +334,7 @@ OS::TimeZoneInfo OS_Windows::get_time_zone_info() const {
}
// Bias value returned by GetTimeZoneInformation is inverted of what we expect
- // For example on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180
+ // For example, on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180
ret.bias = -info.Bias;
return ret;
}
@@ -766,77 +765,12 @@ Error OS_Windows::move_to_trash(const String &p_path) {
return OK;
}
-int OS_Windows::get_tablet_driver_count() const {
- return tablet_drivers.size();
-}
-
-String OS_Windows::get_tablet_driver_name(int p_driver) const {
- if (p_driver < 0 || p_driver >= tablet_drivers.size()) {
- return "";
- } else {
- return tablet_drivers[p_driver];
- }
-}
-
-String OS_Windows::get_current_tablet_driver() const {
- return tablet_driver;
-}
-
-void OS_Windows::set_current_tablet_driver(const String &p_driver) {
- if (get_tablet_driver_count() == 0) {
- return;
- }
- bool found = false;
- for (int i = 0; i < get_tablet_driver_count(); i++) {
- if (p_driver == get_tablet_driver_name(i)) {
- found = true;
- }
- }
- if (found) {
- if (DisplayServerWindows::get_singleton()) {
- ((DisplayServerWindows *)DisplayServerWindows::get_singleton())->_update_tablet_ctx(tablet_driver, p_driver);
- }
- tablet_driver = p_driver;
- } else {
- ERR_PRINT("Unknown tablet driver " + p_driver + ".");
- }
-}
-
OS_Windows::OS_Windows(HINSTANCE _hInstance) {
ticks_per_second = 0;
ticks_start = 0;
main_loop = nullptr;
process_map = nullptr;
- //Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
- HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
- if (wintab_lib) {
- DisplayServerWindows::wintab_WTOpen = (WTOpenPtr)GetProcAddress(wintab_lib, "WTOpenW");
- DisplayServerWindows::wintab_WTClose = (WTClosePtr)GetProcAddress(wintab_lib, "WTClose");
- DisplayServerWindows::wintab_WTInfo = (WTInfoPtr)GetProcAddress(wintab_lib, "WTInfoW");
- DisplayServerWindows::wintab_WTPacket = (WTPacketPtr)GetProcAddress(wintab_lib, "WTPacket");
- DisplayServerWindows::wintab_WTEnable = (WTEnablePtr)GetProcAddress(wintab_lib, "WTEnable");
-
- DisplayServerWindows::wintab_available = DisplayServerWindows::wintab_WTOpen && DisplayServerWindows::wintab_WTClose && DisplayServerWindows::wintab_WTInfo && DisplayServerWindows::wintab_WTPacket && DisplayServerWindows::wintab_WTEnable;
- }
-
- if (DisplayServerWindows::wintab_available) {
- tablet_drivers.push_back("wintab");
- }
-
- //Note: Windows Ink API for pen input, available on Windows 8+ only.
- HMODULE user32_lib = LoadLibraryW(L"user32.dll");
- if (user32_lib) {
- DisplayServerWindows::win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType");
- DisplayServerWindows::win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo");
-
- DisplayServerWindows::winink_available = DisplayServerWindows::win8p_GetPointerType && DisplayServerWindows::win8p_GetPointerPenInfo;
- }
-
- if (DisplayServerWindows::winink_available) {
- tablet_drivers.push_back("winink");
- }
-
force_quit = false;
hInstance = _hInstance;
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 1a8791196b..8f9ef254f1 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -73,9 +73,6 @@ class OS_Windows : public OS {
HINSTANCE hInstance;
MainLoop *main_loop;
- String tablet_driver;
- Vector<String> tablet_drivers;
-
#ifdef WASAPI_ENABLED
AudioDriverWASAPI driver_wasapi;
#endif
@@ -119,11 +116,6 @@ public:
virtual String get_name() const override;
- virtual int get_tablet_driver_count() const override;
- virtual String get_tablet_driver_name(int p_driver) const override;
- virtual String get_current_tablet_driver() const override;
- virtual void set_current_tablet_driver(const String &p_driver) override;
-
virtual void initialize_joypads() override {}
virtual Date get_date(bool utc) const override;
diff --git a/platform/windows/windows_terminal_logger.cpp b/platform/windows/windows_terminal_logger.cpp
index 56b620a6d9..c1f3827d15 100644
--- a/platform/windows/windows_terminal_logger.cpp
+++ b/platform/windows/windows_terminal_logger.cpp
@@ -53,7 +53,8 @@ void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_er
if (wlen < 0)
return;
- wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
+ wchar_t *wbuf = (wchar_t *)memalloc((len + 1) * sizeof(wchar_t));
+ ERR_FAIL_NULL_MSG(wbuf, "Out of memory.");
MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
wbuf[wlen] = 0;
@@ -62,7 +63,7 @@ void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_er
else
wprintf(L"%ls", wbuf);
- free(wbuf);
+ memfree(wbuf);
#ifdef DEBUG_ENABLED
fflush(stdout);
diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp
index d9d551074d..dfc08583f2 100644
--- a/scene/2d/animated_sprite_2d.cpp
+++ b/scene/2d/animated_sprite_2d.cpp
@@ -105,214 +105,6 @@ Rect2 AnimatedSprite2D::_get_rect() const {
return Rect2(ofs, s);
}
-void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture2D> &p_frame, int p_at_pos) {
- Map<StringName, Anim>::Element *E = animations.find(p_anim);
- ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
-
- if (p_at_pos >= 0 && p_at_pos < E->get().frames.size()) {
- E->get().frames.insert(p_at_pos, p_frame);
- } else {
- E->get().frames.push_back(p_frame);
- }
-
- emit_changed();
-}
-
-int SpriteFrames::get_frame_count(const StringName &p_anim) const {
- const Map<StringName, Anim>::Element *E = animations.find(p_anim);
- ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist.");
-
- return E->get().frames.size();
-}
-
-void SpriteFrames::remove_frame(const StringName &p_anim, int p_idx) {
- Map<StringName, Anim>::Element *E = animations.find(p_anim);
- ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
-
- E->get().frames.remove(p_idx);
- emit_changed();
-}
-
-void SpriteFrames::clear(const StringName &p_anim) {
- Map<StringName, Anim>::Element *E = animations.find(p_anim);
- ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
-
- E->get().frames.clear();
- emit_changed();
-}
-
-void SpriteFrames::clear_all() {
- animations.clear();
- add_animation("default");
-}
-
-void SpriteFrames::add_animation(const StringName &p_anim) {
- ERR_FAIL_COND_MSG(animations.has(p_anim), "SpriteFrames already has animation '" + p_anim + "'.");
-
- animations[p_anim] = Anim();
-}
-
-bool SpriteFrames::has_animation(const StringName &p_anim) const {
- return animations.has(p_anim);
-}
-
-void SpriteFrames::remove_animation(const StringName &p_anim) {
- animations.erase(p_anim);
-}
-
-void SpriteFrames::rename_animation(const StringName &p_prev, const StringName &p_next) {
- ERR_FAIL_COND_MSG(!animations.has(p_prev), "SpriteFrames doesn't have animation '" + String(p_prev) + "'.");
- ERR_FAIL_COND_MSG(animations.has(p_next), "Animation '" + String(p_next) + "' already exists.");
-
- Anim anim = animations[p_prev];
- animations.erase(p_prev);
- animations[p_next] = anim;
-}
-
-Vector<String> SpriteFrames::_get_animation_list() const {
- Vector<String> ret;
- List<StringName> al;
- get_animation_list(&al);
- for (List<StringName>::Element *E = al.front(); E; E = E->next()) {
- ret.push_back(E->get());
- }
-
- return ret;
-}
-
-void SpriteFrames::get_animation_list(List<StringName> *r_animations) const {
- for (const Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) {
- r_animations->push_back(E->key());
- }
-}
-
-Vector<String> SpriteFrames::get_animation_names() const {
- Vector<String> names;
- for (const Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) {
- names.push_back(E->key());
- }
- names.sort();
- return names;
-}
-
-void SpriteFrames::set_animation_speed(const StringName &p_anim, float p_fps) {
- ERR_FAIL_COND_MSG(p_fps < 0, "Animation speed cannot be negative (" + itos(p_fps) + ").");
- Map<StringName, Anim>::Element *E = animations.find(p_anim);
- ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
- E->get().speed = p_fps;
-}
-
-float SpriteFrames::get_animation_speed(const StringName &p_anim) const {
- const Map<StringName, Anim>::Element *E = animations.find(p_anim);
- ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist.");
- return E->get().speed;
-}
-
-void SpriteFrames::set_animation_loop(const StringName &p_anim, bool p_loop) {
- Map<StringName, Anim>::Element *E = animations.find(p_anim);
- ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
- E->get().loop = p_loop;
-}
-
-bool SpriteFrames::get_animation_loop(const StringName &p_anim) const {
- const Map<StringName, Anim>::Element *E = animations.find(p_anim);
- ERR_FAIL_COND_V_MSG(!E, false, "Animation '" + String(p_anim) + "' doesn't exist.");
- return E->get().loop;
-}
-
-void SpriteFrames::_set_frames(const Array &p_frames) {
- clear_all();
- Map<StringName, Anim>::Element *E = animations.find(SceneStringNames::get_singleton()->_default);
- ERR_FAIL_COND(!E);
-
- E->get().frames.resize(p_frames.size());
- for (int i = 0; i < E->get().frames.size(); i++) {
- E->get().frames.write[i] = p_frames[i];
- }
-}
-
-Array SpriteFrames::_get_frames() const {
- return Array();
-}
-
-Array SpriteFrames::_get_animations() const {
- Array anims;
- for (Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) {
- Dictionary d;
- d["name"] = E->key();
- d["speed"] = E->get().speed;
- d["loop"] = E->get().loop;
- Array frames;
- for (int i = 0; i < E->get().frames.size(); i++) {
- frames.push_back(E->get().frames[i]);
- }
- d["frames"] = frames;
- anims.push_back(d);
- }
-
- return anims;
-}
-
-void SpriteFrames::_set_animations(const Array &p_animations) {
- animations.clear();
- for (int i = 0; i < p_animations.size(); i++) {
- Dictionary d = p_animations[i];
-
- ERR_CONTINUE(!d.has("name"));
- ERR_CONTINUE(!d.has("speed"));
- ERR_CONTINUE(!d.has("loop"));
- ERR_CONTINUE(!d.has("frames"));
-
- Anim anim;
- anim.speed = d["speed"];
- anim.loop = d["loop"];
- Array frames = d["frames"];
- for (int j = 0; j < frames.size(); j++) {
- RES res = frames[j];
- anim.frames.push_back(res);
- }
-
- animations[d["name"]] = anim;
- }
-}
-
-void SpriteFrames::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_animation", "anim"), &SpriteFrames::add_animation);
- ClassDB::bind_method(D_METHOD("has_animation", "anim"), &SpriteFrames::has_animation);
- ClassDB::bind_method(D_METHOD("remove_animation", "anim"), &SpriteFrames::remove_animation);
- ClassDB::bind_method(D_METHOD("rename_animation", "anim", "newname"), &SpriteFrames::rename_animation);
-
- ClassDB::bind_method(D_METHOD("get_animation_names"), &SpriteFrames::get_animation_names);
-
- ClassDB::bind_method(D_METHOD("set_animation_speed", "anim", "speed"), &SpriteFrames::set_animation_speed);
- ClassDB::bind_method(D_METHOD("get_animation_speed", "anim"), &SpriteFrames::get_animation_speed);
-
- ClassDB::bind_method(D_METHOD("set_animation_loop", "anim", "loop"), &SpriteFrames::set_animation_loop);
- ClassDB::bind_method(D_METHOD("get_animation_loop", "anim"), &SpriteFrames::get_animation_loop);
-
- ClassDB::bind_method(D_METHOD("add_frame", "anim", "frame", "at_position"), &SpriteFrames::add_frame, DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("get_frame_count", "anim"), &SpriteFrames::get_frame_count);
- ClassDB::bind_method(D_METHOD("get_frame", "anim", "idx"), &SpriteFrames::get_frame);
- ClassDB::bind_method(D_METHOD("set_frame", "anim", "idx", "txt"), &SpriteFrames::set_frame);
- ClassDB::bind_method(D_METHOD("remove_frame", "anim", "idx"), &SpriteFrames::remove_frame);
- ClassDB::bind_method(D_METHOD("clear", "anim"), &SpriteFrames::clear);
- ClassDB::bind_method(D_METHOD("clear_all"), &SpriteFrames::clear_all);
-
- ClassDB::bind_method(D_METHOD("_set_frames"), &SpriteFrames::_set_frames);
- ClassDB::bind_method(D_METHOD("_get_frames"), &SpriteFrames::_get_frames);
-
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "frames", PROPERTY_HINT_NONE, "", 0), "_set_frames", "_get_frames"); //compatibility
-
- ClassDB::bind_method(D_METHOD("_set_animations"), &SpriteFrames::_set_animations);
- ClassDB::bind_method(D_METHOD("_get_animations"), &SpriteFrames::_get_animations);
-
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations"); //compatibility
-}
-
-SpriteFrames::SpriteFrames() {
- add_animation(SceneStringNames::get_singleton()->_default);
-}
-
void AnimatedSprite2D::_validate_property(PropertyInfo &property) const {
if (!frames.is_valid()) {
return;
@@ -409,7 +201,7 @@ void AnimatedSprite2D::_notification(int p_what) {
}
update();
- _change_notify("frame");
+
emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
@@ -477,7 +269,7 @@ void AnimatedSprite2D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
set_frame(frame);
}
- _change_notify();
+ notify_property_list_changed();
_reset_timeout();
update();
update_configuration_warning();
@@ -510,7 +302,7 @@ void AnimatedSprite2D::set_frame(int p_frame) {
frame = p_frame;
_reset_timeout();
update();
- _change_notify("frame");
+
emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
@@ -546,7 +338,6 @@ void AnimatedSprite2D::set_offset(const Point2 &p_offset) {
offset = p_offset;
update();
item_rect_changed();
- _change_notify("offset");
}
Point2 AnimatedSprite2D::get_offset() const {
@@ -573,8 +364,7 @@ bool AnimatedSprite2D::is_flipped_v() const {
void AnimatedSprite2D::_res_changed() {
set_frame(frame);
- _change_notify("frame");
- _change_notify("animation");
+
update();
}
@@ -592,6 +382,7 @@ bool AnimatedSprite2D::_is_playing() const {
}
void AnimatedSprite2D::play(const StringName &p_animation, const bool p_backwards) {
+ ERR_FAIL_NULL_MSG(frames, "Can't play AnimatedSprite2D without a valid SpriteFrames resource.");
backwards = p_backwards;
if (p_animation) {
@@ -642,7 +433,7 @@ void AnimatedSprite2D::set_animation(const StringName &p_animation) {
animation = p_animation;
_reset_timeout();
set_frame(0);
- _change_notify();
+ notify_property_list_changed();
update();
}
@@ -712,15 +503,4 @@ void AnimatedSprite2D::_bind_methods() {
}
AnimatedSprite2D::AnimatedSprite2D() {
- centered = true;
- hflip = false;
- vflip = false;
-
- frame = 0;
- speed_scale = 1.0f;
- playing = false;
- backwards = false;
- animation = "default";
- timeout = 0;
- is_over = false;
}
diff --git a/scene/2d/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h
index a558a3e657..14ecb18866 100644
--- a/scene/2d/animated_sprite_2d.h
+++ b/scene/2d/animated_sprite_2d.h
@@ -32,97 +32,27 @@
#define ANIMATED_SPRITE_2D_H
#include "scene/2d/node_2d.h"
+#include "scene/resources/sprite_frames.h"
#include "scene/resources/texture.h"
-class SpriteFrames : public Resource {
- GDCLASS(SpriteFrames, Resource);
-
- struct Anim {
- float speed;
- bool loop;
- Vector<Ref<Texture2D>> frames;
-
- Anim() {
- loop = true;
- speed = 5;
- }
- };
-
- Map<StringName, Anim> animations;
-
- Array _get_frames() const;
- void _set_frames(const Array &p_frames);
-
- Array _get_animations() const;
- void _set_animations(const Array &p_animations);
-
- Vector<String> _get_animation_list() const;
-
-protected:
- static void _bind_methods();
-
-public:
- void add_animation(const StringName &p_anim);
- bool has_animation(const StringName &p_anim) const;
- void remove_animation(const StringName &p_anim);
- void rename_animation(const StringName &p_prev, const StringName &p_next);
-
- void get_animation_list(List<StringName> *r_animations) const;
- Vector<String> get_animation_names() const;
-
- void set_animation_speed(const StringName &p_anim, float p_fps);
- float get_animation_speed(const StringName &p_anim) const;
-
- void set_animation_loop(const StringName &p_anim, bool p_loop);
- bool get_animation_loop(const StringName &p_anim) const;
-
- void add_frame(const StringName &p_anim, const Ref<Texture2D> &p_frame, int p_at_pos = -1);
- int get_frame_count(const StringName &p_anim) const;
- _FORCE_INLINE_ Ref<Texture2D> get_frame(const StringName &p_anim, int p_idx) const {
- const Map<StringName, Anim>::Element *E = animations.find(p_anim);
- ERR_FAIL_COND_V_MSG(!E, Ref<Texture2D>(), "Animation '" + String(p_anim) + "' doesn't exist.");
- ERR_FAIL_COND_V(p_idx < 0, Ref<Texture2D>());
- if (p_idx >= E->get().frames.size()) {
- return Ref<Texture2D>();
- }
-
- return E->get().frames[p_idx];
- }
-
- void set_frame(const StringName &p_anim, int p_idx, const Ref<Texture2D> &p_frame) {
- Map<StringName, Anim>::Element *E = animations.find(p_anim);
- ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
- ERR_FAIL_COND(p_idx < 0);
- if (p_idx >= E->get().frames.size()) {
- return;
- }
- E->get().frames.write[p_idx] = p_frame;
- }
- void remove_frame(const StringName &p_anim, int p_idx);
- void clear(const StringName &p_anim);
- void clear_all();
-
- SpriteFrames();
-};
-
class AnimatedSprite2D : public Node2D {
GDCLASS(AnimatedSprite2D, Node2D);
Ref<SpriteFrames> frames;
- bool playing;
- bool backwards;
- StringName animation;
- int frame;
- float speed_scale;
+ bool playing = false;
+ bool backwards = false;
+ StringName animation = "default";
+ int frame = 0;
+ float speed_scale = 1.0f;
- bool centered;
+ bool centered = true;
Point2 offset;
- bool is_over;
- float timeout;
+ bool is_over = false;
+ float timeout = 0.0;
- bool hflip;
- bool vflip;
+ bool hflip = false;
+ bool vflip = false;
void _res_changed();
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index fae893a76c..49d1654e3f 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -590,10 +590,10 @@ void Area2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout);
ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout);
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D")));
+ ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D")));
ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
@@ -627,20 +627,8 @@ void Area2D::_bind_methods() {
Area2D::Area2D() :
CollisionObject2D(PhysicsServer2D::get_singleton()->area_create(), true) {
- space_override = SPACE_OVERRIDE_DISABLED;
set_gravity(98);
set_gravity_vector(Vector2(0, 1));
- gravity_is_point = false;
- gravity_distance_scale = 0;
- linear_damp = 0.1;
- angular_damp = 1;
- locked = false;
- priority = 0;
- monitoring = false;
- monitorable = false;
- collision_mask = 1;
- collision_layer = 1;
- audio_bus_override = false;
set_monitoring(true);
set_monitorable(true);
}
diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h
index 0b45675555..39b022fd2c 100644
--- a/scene/2d/area_2d.h
+++ b/scene/2d/area_2d.h
@@ -47,19 +47,19 @@ public:
};
private:
- SpaceOverride space_override;
+ SpaceOverride space_override = SPACE_OVERRIDE_DISABLED;
Vector2 gravity_vec;
real_t gravity;
- bool gravity_is_point;
- real_t gravity_distance_scale;
- real_t linear_damp;
- real_t angular_damp;
- uint32_t collision_mask;
- uint32_t collision_layer;
- int priority;
- bool monitoring;
- bool monitorable;
- bool locked;
+ bool gravity_is_point = false;
+ real_t gravity_distance_scale = 0.0;
+ real_t linear_damp = 0.1;
+ real_t angular_damp = 1.0;
+ uint32_t collision_mask = 1;
+ uint32_t collision_layer = 1;
+ int priority = 0;
+ bool monitoring = false;
+ bool monitorable = false;
+ bool locked = false;
void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape);
@@ -67,8 +67,8 @@ private:
void _body_exit_tree(ObjectID p_id);
struct ShapePair {
- int body_shape;
- int area_shape;
+ int body_shape = 0;
+ int area_shape = 0;
bool operator<(const ShapePair &p_sp) const {
if (body_shape == p_sp.body_shape) {
return area_shape < p_sp.area_shape;
@@ -85,8 +85,8 @@ private:
};
struct BodyState {
- int rc;
- bool in_tree;
+ int rc = 0;
+ bool in_tree = false;
VSet<ShapePair> shapes;
};
@@ -98,8 +98,8 @@ private:
void _area_exit_tree(ObjectID p_id);
struct AreaShapePair {
- int area_shape;
- int self_shape;
+ int area_shape = 0;
+ int self_shape = 0;
bool operator<(const AreaShapePair &p_sp) const {
if (area_shape == p_sp.area_shape) {
return self_shape < p_sp.self_shape;
@@ -116,15 +116,15 @@ private:
};
struct AreaState {
- int rc;
- bool in_tree;
+ int rc = 0;
+ bool in_tree = false;
VSet<AreaShapePair> shapes;
};
Map<ObjectID, AreaState> area_map;
void _clear_monitoring();
- bool audio_bus_override;
+ bool audio_bus_override = false;
StringName audio_bus;
protected:
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index f1eb7d017d..6d8d6058eb 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -35,14 +35,14 @@
#include "scene/main/window.h"
void AudioStreamPlayer2D::_mix_audio() {
- if (!stream_playback.is_valid() || !active ||
+ if (!stream_playback.is_valid() || !active.is_set() ||
(stream_paused && !stream_paused_fade_out)) {
return;
}
- if (setseek >= 0.0) {
- stream_playback->start(setseek);
- setseek = -1.0; //reset seek
+ if (setseek.get() >= 0.0) {
+ stream_playback->start(setseek.get());
+ setseek.set(-1.0); //reset seek
}
//get data
@@ -57,7 +57,8 @@ void AudioStreamPlayer2D::_mix_audio() {
stream_playback->mix(buffer, pitch_scale, buffer_size);
//write all outputs
- for (int i = 0; i < output_count; i++) {
+ int oc = output_count.get();
+ for (int i = 0; i < oc; i++) {
Output current = outputs[i];
//see if current output exists, to keep volume ramp
@@ -130,14 +131,14 @@ void AudioStreamPlayer2D::_mix_audio() {
prev_outputs[i] = current;
}
- prev_output_count = output_count;
+ prev_output_count = oc;
//stream is no longer active, disable this.
if (!stream_playback->is_playing()) {
- active = false;
+ active.clear();
}
- output_ready = false;
+ output_ready.clear();
stream_paused_fade_in = false;
stream_paused_fade_out = false;
}
@@ -168,7 +169,7 @@ void AudioStreamPlayer2D::_notification(int p_what) {
if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
//update anything related to position first, if possible of course
- if (!output_ready) {
+ if (!output_ready.is_set()) {
List<Viewport *> viewports;
Ref<World2D> world_2d = get_world_2d();
ERR_FAIL_COND(world_2d.is_null());
@@ -240,24 +241,20 @@ void AudioStreamPlayer2D::_notification(int p_what) {
}
}
- output_count = new_output_count;
- output_ready = true;
+ output_count.set(new_output_count);
+ output_ready.set();
}
//start playing if requested
- if (setplay >= 0.0) {
- setseek = setplay;
- active = true;
- setplay = -1;
- //do not update, this makes it easier to animate (will shut off otherwise)
- //_change_notify("playing"); //update property in editor
+ if (setplay.get() >= 0.0) {
+ setseek.set(setplay.get());
+ active.set();
+ setplay.set(-1);
}
//stop playing if no longer active
- if (!active) {
+ if (!active.is_set()) {
set_physics_process_internal(false);
- //do not update, this makes it easier to animate (will shut off otherwise)
- //_change_notify("playing"); //update property in editor
emit_signal("finished");
}
}
@@ -271,8 +268,8 @@ void AudioStreamPlayer2D::set_stream(Ref<AudioStream> p_stream) {
if (stream_playback.is_valid()) {
stream_playback.unref();
stream.unref();
- active = false;
- setseek = -1;
+ active.clear();
+ setseek.set(-1);
}
if (p_stream.is_valid()) {
@@ -315,30 +312,29 @@ void AudioStreamPlayer2D::play(float p_from_pos) {
}
if (stream_playback.is_valid()) {
- active = true;
- setplay = p_from_pos;
- output_ready = false;
+ setplay.set(p_from_pos);
+ output_ready.clear();
set_physics_process_internal(true);
}
}
void AudioStreamPlayer2D::seek(float p_seconds) {
if (stream_playback.is_valid()) {
- setseek = p_seconds;
+ setseek.set(p_seconds);
}
}
void AudioStreamPlayer2D::stop() {
if (stream_playback.is_valid()) {
- active = false;
+ active.clear();
set_physics_process_internal(false);
- setplay = -1;
+ setplay.set(-1);
}
}
bool AudioStreamPlayer2D::is_playing() const {
if (stream_playback.is_valid()) {
- return active; // && stream_playback->is_playing();
+ return active.is_set() || setplay.get() >= 0;
}
return false;
@@ -346,6 +342,10 @@ bool AudioStreamPlayer2D::is_playing() const {
float AudioStreamPlayer2D::get_playback_position() {
if (stream_playback.is_valid()) {
+ float ss = setseek.get();
+ if (ss >= 0.0) {
+ return ss;
+ }
return stream_playback->get_playback_position();
}
@@ -385,7 +385,7 @@ void AudioStreamPlayer2D::_set_playing(bool p_enable) {
}
bool AudioStreamPlayer2D::_is_active() const {
- return active;
+ return active.is_set();
}
void AudioStreamPlayer2D::_validate_property(PropertyInfo &property) const {
@@ -404,7 +404,7 @@ void AudioStreamPlayer2D::_validate_property(PropertyInfo &property) const {
}
void AudioStreamPlayer2D::_bus_layout_changed() {
- _change_notify();
+ notify_property_list_changed();
}
void AudioStreamPlayer2D::set_max_distance(float p_pixels) {
@@ -503,21 +503,6 @@ void AudioStreamPlayer2D::_bind_methods() {
}
AudioStreamPlayer2D::AudioStreamPlayer2D() {
- volume_db = 0;
- pitch_scale = 1.0;
- autoplay = false;
- setseek = -1;
- active = false;
- output_count = 0;
- prev_output_count = 0;
- max_distance = 2000;
- attenuation = 1;
- setplay = -1;
- output_ready = false;
- area_mask = 1;
- stream_paused = false;
- stream_paused_fade_in = false;
- stream_paused_fade_out = false;
AudioServer::get_singleton()->connect("bus_layout_changed", callable_mp(this, &AudioStreamPlayer2D::_bus_layout_changed));
}
diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h
index 4eb709facb..21f524c703 100644
--- a/scene/2d/audio_stream_player_2d.h
+++ b/scene/2d/audio_stream_player_2d.h
@@ -31,6 +31,7 @@
#ifndef AUDIO_STREAM_PLAYER_2D_H
#define AUDIO_STREAM_PLAYER_2D_H
+#include "core/templates/safe_refcount.h"
#include "scene/2d/node_2d.h"
#include "servers/audio/audio_stream.h"
#include "servers/audio_server.h"
@@ -47,32 +48,32 @@ private:
struct Output {
AudioFrame vol;
- int bus_index;
- Viewport *viewport; //pointer only used for reference to previous mix
+ int bus_index = 0;
+ Viewport *viewport = nullptr; //pointer only used for reference to previous mix
};
Output outputs[MAX_OUTPUTS];
- volatile int output_count;
- volatile bool output_ready;
+ SafeNumeric<int> output_count;
+ SafeFlag output_ready;
//these are used by audio thread to have a reference of previous volumes (for ramping volume and avoiding clicks)
Output prev_outputs[MAX_OUTPUTS];
- int prev_output_count;
+ int prev_output_count = 0;
Ref<AudioStreamPlayback> stream_playback;
Ref<AudioStream> stream;
Vector<AudioFrame> mix_buffer;
- volatile float setseek;
- volatile bool active;
- volatile float setplay;
+ SafeNumeric<float> setseek{ -1.0 };
+ SafeFlag active;
+ SafeNumeric<float> setplay{ -1.0 };
- float volume_db;
- float pitch_scale;
- bool autoplay;
- bool stream_paused;
- bool stream_paused_fade_in;
- bool stream_paused_fade_out;
+ float volume_db = 0.0;
+ float pitch_scale = 1.0;
+ bool autoplay = false;
+ bool stream_paused = false;
+ bool stream_paused_fade_in = false;
+ bool stream_paused_fade_out = false;
StringName bus;
void _mix_audio();
@@ -83,10 +84,10 @@ private:
void _bus_layout_changed();
- uint32_t area_mask;
+ uint32_t area_mask = 1;
- float max_distance;
- float attenuation;
+ float max_distance = 2000.0;
+ float attenuation = 1.0;
protected:
void _validate_property(PropertyInfo &property) const override;
diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp
index 91c887cb84..539a66b881 100644
--- a/scene/2d/back_buffer_copy.cpp
+++ b/scene/2d/back_buffer_copy.cpp
@@ -93,8 +93,6 @@ void BackBufferCopy::_bind_methods() {
}
BackBufferCopy::BackBufferCopy() {
- rect = Rect2(-100, -100, 200, 200);
- copy_mode = COPY_MODE_RECT;
_update_copy_mode();
}
diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h
index 0916d344f9..6bdb3aaab2 100644
--- a/scene/2d/back_buffer_copy.h
+++ b/scene/2d/back_buffer_copy.h
@@ -44,8 +44,8 @@ public:
};
private:
- Rect2 rect;
- CopyMode copy_mode;
+ Rect2 rect = Rect2(-100, -100, 200, 200);
+ CopyMode copy_mode = COPY_MODE_RECT;
void _update_copy_mode();
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 4f45325d3a..01045502d5 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -63,11 +63,11 @@ void Camera2D::_update_scroll() {
};
}
-void Camera2D::_update_process_mode() {
+void Camera2D::_update_process_callback() {
if (Engine::get_singleton()->is_editor_hint()) {
set_process_internal(false);
set_physics_process_internal(false);
- } else if (process_mode == CAMERA2D_PROCESS_IDLE) {
+ } else if (process_callback == CAMERA2D_PROCESS_IDLE) {
set_process_internal(true);
set_physics_process_internal(false);
} else {
@@ -157,7 +157,7 @@ Transform2D Camera2D::get_camera_transform() {
}
if (smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) {
- float c = smoothing * (process_mode == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time());
+ real_t c = smoothing * (process_callback == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time());
smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos;
ret_camera_pos = smoothed_camera_pos;
//camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing;
@@ -172,7 +172,7 @@ Transform2D Camera2D::get_camera_transform() {
Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom) : Point2());
- float angle = get_global_transform().get_rotation();
+ real_t angle = get_global_transform().get_rotation();
if (rotating) {
screen_offset = screen_offset.rotated(angle);
}
@@ -247,7 +247,7 @@ void Camera2D::_notification(int p_what) {
add_to_group(group_name);
add_to_group(canvas_group_name);
- _update_process_mode();
+ _update_process_callback();
_update_scroll();
first = true;
@@ -263,6 +263,7 @@ void Camera2D::_notification(int p_what) {
viewport = nullptr;
} break;
+#ifdef TOOLS_ENABLED
case NOTIFICATION_DRAW: {
if (!is_inside_tree() || !Engine::get_singleton()->is_editor_hint()) {
break;
@@ -270,7 +271,7 @@ void Camera2D::_notification(int p_what) {
if (screen_drawing_enabled) {
Color area_axis_color(0.5, 0.42, 0.87, 0.63);
- float area_axis_width = 1;
+ real_t area_axis_width = 1;
if (is_current()) {
area_axis_width = 3;
area_axis_color.a = 0.83;
@@ -295,7 +296,7 @@ void Camera2D::_notification(int p_what) {
if (limit_drawing_enabled) {
Color limit_drawing_color(1, 1, 0, 0.63);
- float limit_drawing_width = 1;
+ real_t limit_drawing_width = 1;
if (is_current()) {
limit_drawing_color.a = 0.83;
limit_drawing_width = 3;
@@ -317,7 +318,7 @@ void Camera2D::_notification(int p_what) {
if (margin_drawing_enabled) {
Color margin_drawing_color(0, 1, 1, 0.63);
- float margin_drawing_width = 1;
+ real_t margin_drawing_width = 1;
if (is_current()) {
margin_drawing_width = 3;
margin_drawing_color.a = 0.83;
@@ -339,8 +340,8 @@ void Camera2D::_notification(int p_what) {
draw_line(inv_transform.xform(margin_endpoints[i]), inv_transform.xform(margin_endpoints[(i + 1) % 4]), margin_drawing_color, margin_drawing_width);
}
}
-
} break;
+#endif
}
}
@@ -375,17 +376,17 @@ bool Camera2D::is_rotating() const {
return rotating;
}
-void Camera2D::set_process_mode(Camera2DProcessMode p_mode) {
- if (process_mode == p_mode) {
+void Camera2D::set_process_callback(Camera2DProcessCallback p_mode) {
+ if (process_callback == p_mode) {
return;
}
- process_mode = p_mode;
- _update_process_mode();
+ process_callback = p_mode;
+ _update_process_callback();
}
-Camera2D::Camera2DProcessMode Camera2D::get_process_mode() const {
- return process_mode;
+Camera2D::Camera2DProcessCallback Camera2D::get_process_callback() const {
+ return process_callback;
}
void Camera2D::_make_current(Object *p_which) {
@@ -445,13 +446,13 @@ bool Camera2D::is_limit_smoothing_enabled() const {
return limit_smoothing_enabled;
}
-void Camera2D::set_drag_margin(Side p_side, float p_drag_margin) {
+void Camera2D::set_drag_margin(Side p_side, real_t p_drag_margin) {
ERR_FAIL_INDEX((int)p_side, 4);
drag_margin[p_side] = p_drag_margin;
update();
}
-float Camera2D::get_drag_margin(Side p_side) const {
+real_t Camera2D::get_drag_margin(Side p_side) const {
ERR_FAIL_INDEX_V((int)p_side, 4, 0);
return drag_margin[p_side];
}
@@ -493,7 +494,7 @@ void Camera2D::align() {
_update_scroll();
}
-void Camera2D::set_follow_smoothing(float p_speed) {
+void Camera2D::set_follow_smoothing(real_t p_speed) {
smoothing = p_speed;
if (smoothing > 0 && !(is_inside_tree() && Engine::get_singleton()->is_editor_hint())) {
set_process_internal(true);
@@ -502,7 +503,7 @@ void Camera2D::set_follow_smoothing(float p_speed) {
}
}
-float Camera2D::get_follow_smoothing() const {
+real_t Camera2D::get_follow_smoothing() const {
return smoothing;
}
@@ -534,7 +535,7 @@ bool Camera2D::is_drag_vertical_enabled() const {
return drag_vertical_enabled;
}
-void Camera2D::set_drag_vertical_offset(float p_offset) {
+void Camera2D::set_drag_vertical_offset(real_t p_offset) {
drag_vertical_offset = p_offset;
drag_vertical_offset_changed = true;
Point2 old_smoothed_camera_pos = smoothed_camera_pos;
@@ -542,11 +543,11 @@ void Camera2D::set_drag_vertical_offset(float p_offset) {
smoothed_camera_pos = old_smoothed_camera_pos;
}
-float Camera2D::get_drag_vertical_offset() const {
+real_t Camera2D::get_drag_vertical_offset() const {
return drag_vertical_offset;
}
-void Camera2D::set_drag_horizontal_offset(float p_offset) {
+void Camera2D::set_drag_horizontal_offset(real_t p_offset) {
drag_horizontal_offset = p_offset;
drag_horizontal_offset_changed = true;
Point2 old_smoothed_camera_pos = smoothed_camera_pos;
@@ -554,11 +555,11 @@ void Camera2D::set_drag_horizontal_offset(float p_offset) {
smoothed_camera_pos = old_smoothed_camera_pos;
}
-float Camera2D::get_drag_horizontal_offset() const {
+real_t Camera2D::get_drag_horizontal_offset() const {
return drag_horizontal_offset;
}
-void Camera2D::_set_old_smoothing(float p_enable) {
+void Camera2D::_set_old_smoothing(real_t p_enable) {
//compatibility
if (p_enable > 0) {
smoothing_enabled = true;
@@ -568,6 +569,7 @@ void Camera2D::_set_old_smoothing(float p_enable) {
void Camera2D::set_enable_follow_smoothing(bool p_enabled) {
smoothing_enabled = p_enabled;
+ notify_property_list_changed();
}
bool Camera2D::is_follow_smoothing_enabled() const {
@@ -610,7 +612,9 @@ Node *Camera2D::get_custom_viewport() const {
void Camera2D::set_screen_drawing_enabled(bool enable) {
screen_drawing_enabled = enable;
+#ifdef TOOLS_ENABLED
update();
+#endif
}
bool Camera2D::is_screen_drawing_enabled() const {
@@ -619,7 +623,9 @@ bool Camera2D::is_screen_drawing_enabled() const {
void Camera2D::set_limit_drawing_enabled(bool enable) {
limit_drawing_enabled = enable;
+#ifdef TOOLS_ENABLED
update();
+#endif
}
bool Camera2D::is_limit_drawing_enabled() const {
@@ -628,13 +634,21 @@ bool Camera2D::is_limit_drawing_enabled() const {
void Camera2D::set_margin_drawing_enabled(bool enable) {
margin_drawing_enabled = enable;
+#ifdef TOOLS_ENABLED
update();
+#endif
}
bool Camera2D::is_margin_drawing_enabled() const {
return margin_drawing_enabled;
}
+void Camera2D::_validate_property(PropertyInfo &property) const {
+ if (!smoothing_enabled && property.name == "smoothing_speed") {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+}
+
void Camera2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_offset", "offset"), &Camera2D::set_offset);
ClassDB::bind_method(D_METHOD("get_offset"), &Camera2D::get_offset);
@@ -651,8 +665,8 @@ void Camera2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_scroll"), &Camera2D::_update_scroll);
- ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Camera2D::set_process_mode);
- ClassDB::bind_method(D_METHOD("get_process_mode"), &Camera2D::get_process_mode);
+ ClassDB::bind_method(D_METHOD("set_process_callback", "mode"), &Camera2D::set_process_callback);
+ ClassDB::bind_method(D_METHOD("get_process_callback"), &Camera2D::get_process_callback);
ClassDB::bind_method(D_METHOD("_set_current", "current"), &Camera2D::_set_current);
ClassDB::bind_method(D_METHOD("is_current"), &Camera2D::is_current);
@@ -714,7 +728,7 @@ void Camera2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "_set_current", "is_current");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom"), "set_zoom", "get_zoom");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", 0), "set_custom_viewport", "get_custom_viewport");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_mode", "get_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_callback", "get_process_callback");
ADD_GROUP("Limit", "limit_");
ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_left"), "set_limit", "get_limit", SIDE_LEFT);
@@ -749,9 +763,6 @@ void Camera2D::_bind_methods() {
}
Camera2D::Camera2D() {
- anchor_mode = ANCHOR_MODE_DRAG_CENTER;
- rotating = false;
- current = false;
limit[SIDE_LEFT] = -10000000;
limit[SIDE_TOP] = -10000000;
limit[SIDE_RIGHT] = 10000000;
@@ -761,27 +772,6 @@ Camera2D::Camera2D() {
drag_margin[SIDE_TOP] = 0.2;
drag_margin[SIDE_RIGHT] = 0.2;
drag_margin[SIDE_BOTTOM] = 0.2;
- camera_pos = Vector2();
- first = true;
- smoothing_enabled = false;
- limit_smoothing_enabled = false;
- custom_viewport = nullptr;
-
- process_mode = CAMERA2D_PROCESS_IDLE;
-
- smoothing = 5.0;
- zoom = Vector2(1, 1);
-
- screen_drawing_enabled = true;
- limit_drawing_enabled = false;
- margin_drawing_enabled = false;
-
- drag_horizontal_enabled = false;
- drag_vertical_enabled = false;
- drag_horizontal_offset = 0;
- drag_vertical_offset = 0;
- drag_horizontal_offset_changed = false;
- drag_vertical_offset_changed = false;
set_notify_transform(true);
}
diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h
index 8977d872f0..7494e526cc 100644
--- a/scene/2d/camera_2d.h
+++ b/scene/2d/camera_2d.h
@@ -43,7 +43,7 @@ public:
ANCHOR_MODE_DRAG_CENTER
};
- enum Camera2DProcessMode {
+ enum Camera2DProcessCallback {
CAMERA2D_PROCESS_PHYSICS,
CAMERA2D_PROCESS_IDLE
};
@@ -51,54 +51,56 @@ public:
protected:
Point2 camera_pos;
Point2 smoothed_camera_pos;
- bool first;
+ bool first = true;
ObjectID custom_viewport_id; // to check validity
- Viewport *custom_viewport;
- Viewport *viewport;
+ Viewport *custom_viewport = nullptr;
+ Viewport *viewport = nullptr;
StringName group_name;
StringName canvas_group_name;
RID canvas;
Vector2 offset;
- Vector2 zoom;
- AnchorMode anchor_mode;
- bool rotating;
- bool current;
- float smoothing;
- bool smoothing_enabled;
+ Vector2 zoom = Vector2(1, 1);
+ AnchorMode anchor_mode = ANCHOR_MODE_DRAG_CENTER;
+ bool rotating = false;
+ bool current = false;
+ real_t smoothing = 5.0;
+ bool smoothing_enabled = false;
int limit[4];
- bool limit_smoothing_enabled;
+ bool limit_smoothing_enabled = false;
- float drag_margin[4];
- bool drag_horizontal_enabled;
- bool drag_vertical_enabled;
- float drag_horizontal_offset;
- float drag_vertical_offset;
- bool drag_horizontal_offset_changed;
- bool drag_vertical_offset_changed;
+ real_t drag_margin[4];
+ bool drag_horizontal_enabled = false;
+ bool drag_vertical_enabled = false;
+ real_t drag_horizontal_offset = 0.0;
+ real_t drag_vertical_offset = 0.0;
+ bool drag_horizontal_offset_changed = false;
+ bool drag_vertical_offset_changed = false;
Point2 camera_screen_center;
- void _update_process_mode();
+ void _update_process_callback();
void _update_scroll();
void _make_current(Object *p_which);
void _set_current(bool p_current);
- void _set_old_smoothing(float p_enable);
+ void _set_old_smoothing(real_t p_enable);
- bool screen_drawing_enabled;
- bool limit_drawing_enabled;
- bool margin_drawing_enabled;
+ bool screen_drawing_enabled = true;
+ bool limit_drawing_enabled = false;
+ bool margin_drawing_enabled = false;
- Camera2DProcessMode process_mode;
+ Camera2DProcessCallback process_callback = CAMERA2D_PROCESS_IDLE;
Size2 _get_camera_screen_size() const;
protected:
virtual Transform2D get_camera_transform();
+
void _notification(int p_what);
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const override;
public:
void set_offset(const Vector2 &p_offset);
@@ -122,23 +124,23 @@ public:
void set_drag_vertical_enabled(bool p_enabled);
bool is_drag_vertical_enabled() const;
- void set_drag_margin(Side p_side, float p_drag_margin);
- float get_drag_margin(Side p_side) const;
+ void set_drag_margin(Side p_side, real_t p_drag_margin);
+ real_t get_drag_margin(Side p_side) const;
- void set_drag_horizontal_offset(float p_offset);
- float get_drag_horizontal_offset() const;
+ void set_drag_horizontal_offset(real_t p_offset);
+ real_t get_drag_horizontal_offset() const;
- void set_drag_vertical_offset(float p_offset);
- float get_drag_vertical_offset() const;
+ void set_drag_vertical_offset(real_t p_offset);
+ real_t get_drag_vertical_offset() const;
void set_enable_follow_smoothing(bool p_enabled);
bool is_follow_smoothing_enabled() const;
- void set_follow_smoothing(float p_speed);
- float get_follow_smoothing() const;
+ void set_follow_smoothing(real_t p_speed);
+ real_t get_follow_smoothing() const;
- void set_process_mode(Camera2DProcessMode p_mode);
- Camera2DProcessMode get_process_mode() const;
+ void set_process_callback(Camera2DProcessCallback p_mode);
+ Camera2DProcessCallback get_process_callback() const;
void make_current();
void clear_current();
@@ -170,6 +172,6 @@ public:
};
VARIANT_ENUM_CAST(Camera2D::AnchorMode);
-VARIANT_ENUM_CAST(Camera2D::Camera2DProcessMode);
+VARIANT_ENUM_CAST(Camera2D::Camera2DProcessCallback);
#endif // CAMERA_2D_H
diff --git a/scene/2d/canvas_group.cpp b/scene/2d/canvas_group.cpp
index 0f0e583ea7..ee025b6dfc 100644
--- a/scene/2d/canvas_group.cpp
+++ b/scene/2d/canvas_group.cpp
@@ -30,7 +30,7 @@
#include "canvas_group.h"
-void CanvasGroup::set_fit_margin(float p_fit_margin) {
+void CanvasGroup::set_fit_margin(real_t p_fit_margin) {
ERR_FAIL_COND(p_fit_margin < 0.0);
fit_margin = p_fit_margin;
@@ -39,11 +39,11 @@ void CanvasGroup::set_fit_margin(float p_fit_margin) {
update();
}
-float CanvasGroup::get_fit_margin() const {
+real_t CanvasGroup::get_fit_margin() const {
return fit_margin;
}
-void CanvasGroup::set_clear_margin(float p_clear_margin) {
+void CanvasGroup::set_clear_margin(real_t p_clear_margin) {
ERR_FAIL_COND(p_clear_margin < 0.0);
clear_margin = p_clear_margin;
@@ -52,7 +52,7 @@ void CanvasGroup::set_clear_margin(float p_clear_margin) {
update();
}
-float CanvasGroup::get_clear_margin() const {
+real_t CanvasGroup::get_clear_margin() const {
return clear_margin;
}
diff --git a/scene/2d/canvas_group.h b/scene/2d/canvas_group.h
index cecf7c24f4..b487d7a098 100644
--- a/scene/2d/canvas_group.h
+++ b/scene/2d/canvas_group.h
@@ -35,19 +35,19 @@
class CanvasGroup : public Node2D {
GDCLASS(CanvasGroup, Node2D)
- float fit_margin = 10.0;
- float clear_margin = 10.0;
+ real_t fit_margin = 10.0;
+ real_t clear_margin = 10.0;
bool use_mipmaps = false;
protected:
static void _bind_methods();
public:
- void set_fit_margin(float p_fit_margin);
- float get_fit_margin() const;
+ void set_fit_margin(real_t p_fit_margin);
+ real_t get_fit_margin() const;
- void set_clear_margin(float p_clear_margin);
- float get_clear_margin() const;
+ void set_clear_margin(real_t p_clear_margin);
+ real_t get_clear_margin() const;
void set_use_mipmaps(bool p_use_mipmaps);
bool is_using_mipmaps() const;
diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp
index 6e90afde21..5d5aaae505 100644
--- a/scene/2d/canvas_modulate.cpp
+++ b/scene/2d/canvas_modulate.cpp
@@ -94,7 +94,6 @@ String CanvasModulate::get_configuration_warning() const {
}
CanvasModulate::CanvasModulate() {
- color = Color(1, 1, 1, 1);
}
CanvasModulate::~CanvasModulate() {
diff --git a/scene/2d/canvas_modulate.h b/scene/2d/canvas_modulate.h
index 6efc0cab9b..4d55a5d9cb 100644
--- a/scene/2d/canvas_modulate.h
+++ b/scene/2d/canvas_modulate.h
@@ -36,7 +36,7 @@
class CanvasModulate : public Node2D {
GDCLASS(CanvasModulate, Node2D);
- Color color;
+ Color color = Color(1, 1, 1, 1);
protected:
void _notification(int p_what);
diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h
index 1cfaeaf649..e82b61d441 100644
--- a/scene/2d/collision_object_2d.h
+++ b/scene/2d/collision_object_2d.h
@@ -37,35 +37,29 @@
class CollisionObject2D : public Node2D {
GDCLASS(CollisionObject2D, Node2D);
- bool area;
+ bool area = false;
RID rid;
- bool pickable;
+ bool pickable = false;
struct ShapeData {
- Object *owner;
+ Object *owner = nullptr;
Transform2D xform;
struct Shape {
Ref<Shape2D> shape;
- int index;
+ int index = 0;
};
Vector<Shape> shapes;
- bool disabled;
- bool one_way_collision;
- real_t one_way_collision_margin;
-
- ShapeData() {
- disabled = false;
- one_way_collision = false;
- one_way_collision_margin = 0;
- owner = nullptr;
- }
+
+ bool disabled = false;
+ bool one_way_collision = false;
+ real_t one_way_collision_margin = 0.0;
};
- int total_subshapes;
+ int total_subshapes = 0;
Map<uint32_t, ShapeData> shapes;
- bool only_update_transform_changes; //this is used for sync physics in KinematicBody
+ bool only_update_transform_changes = false; //this is used for sync physics in KinematicBody
protected:
CollisionObject2D(RID p_rid, bool p_area);
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 505c0beb45..38198c496e 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -41,13 +41,13 @@
void CollisionPolygon2D::_build_polygon() {
parent->shape_owner_clear_shapes(owner_id);
- if (polygon.size() == 0) {
- return;
- }
-
bool solids = build_mode == BUILD_SOLIDS;
if (solids) {
+ if (polygon.size() < 3) {
+ return;
+ }
+
//here comes the sun, lalalala
//decompose concave into multiple convex polygons and add them
Vector<Vector<Vector2>> decomp = _decompose_in_convex();
@@ -58,6 +58,10 @@ void CollisionPolygon2D::_build_polygon() {
}
} else {
+ if (polygon.size() < 2) {
+ return;
+ }
+
Ref<ConcavePolygonShape2D> concave = memnew(ConcavePolygonShape2D);
Vector<Vector2> segments;
@@ -132,25 +136,28 @@ void CollisionPolygon2D::_notification(int p_what) {
break;
}
- for (int i = 0; i < polygon.size(); i++) {
+ int polygon_count = polygon.size();
+ for (int i = 0; i < polygon_count; i++) {
Vector2 p = polygon[i];
- Vector2 n = polygon[(i + 1) % polygon.size()];
+ Vector2 n = polygon[(i + 1) % polygon_count];
// draw line with width <= 1, so it does not scale with zoom and break pixel exact editing
draw_line(p, n, Color(0.9, 0.2, 0.0, 0.8), 1);
}
+
+ if (polygon_count > 2) {
#define DEBUG_DECOMPOSE
#if defined(TOOLS_ENABLED) && defined(DEBUG_DECOMPOSE)
+ Vector<Vector<Vector2>> decomp = _decompose_in_convex();
- Vector<Vector<Vector2>> decomp = _decompose_in_convex();
-
- Color c(0.4, 0.9, 0.1);
- for (int i = 0; i < decomp.size(); i++) {
- c.set_hsv(Math::fmod(c.get_h() + 0.738, 1), c.get_s(), c.get_v(), 0.5);
- draw_colored_polygon(decomp[i], c);
- }
+ Color c(0.4, 0.9, 0.1);
+ for (int i = 0; i < decomp.size(); i++) {
+ c.set_hsv(Math::fmod(c.get_h() + 0.738, 1), c.get_s(), c.get_v(), 0.5);
+ draw_colored_polygon(decomp[i], c);
+ }
#else
- draw_colored_polygon(polygon, get_tree()->get_debug_collisions_color());
+ draw_colored_polygon(polygon, get_tree()->get_debug_collisions_color());
#endif
+ }
if (one_way_collision) {
Color dcol = get_tree()->get_debug_collisions_color(); //0.9,0.2,0.2,0.4);
@@ -211,6 +218,8 @@ void CollisionPolygon2D::set_build_mode(BuildMode p_mode) {
_build_polygon();
_update_in_shape_owner();
}
+ update();
+ update_configuration_warning();
}
CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const {
@@ -241,11 +250,27 @@ String CollisionPolygon2D::get_configuration_warning() const {
warning += TTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape.");
}
- if (polygon.is_empty()) {
+ int polygon_count = polygon.size();
+ if (polygon_count == 0) {
if (!warning.is_empty()) {
warning += "\n\n";
}
warning += TTR("An empty CollisionPolygon2D has no effect on collision.");
+ } else {
+ bool solids = build_mode == BUILD_SOLIDS;
+ if (solids) {
+ if (polygon_count < 3) {
+ if (!warning.is_empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("Invalid polygon. At least 3 points are needed in 'Solids' build mode.");
+ }
+ } else if (polygon_count < 2) {
+ if (!warning.is_empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("Invalid polygon. At least 2 points are needed in 'Segments' build mode.");
+ }
}
return warning;
@@ -310,12 +335,5 @@ void CollisionPolygon2D::_bind_methods() {
}
CollisionPolygon2D::CollisionPolygon2D() {
- aabb = Rect2(-10, -10, 20, 20);
- build_mode = BUILD_SOLIDS;
set_notify_local_transform(true);
- parent = nullptr;
- owner_id = 0;
- disabled = false;
- one_way_collision = false;
- one_way_collision_margin = 1.0;
}
diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h
index 9c9e6f8f62..9df9802629 100644
--- a/scene/2d/collision_polygon_2d.h
+++ b/scene/2d/collision_polygon_2d.h
@@ -46,14 +46,14 @@ public:
};
protected:
- Rect2 aabb;
- BuildMode build_mode;
+ Rect2 aabb = Rect2(-10, -10, 20, 20);
+ BuildMode build_mode = BUILD_SOLIDS;
Vector<Point2> polygon;
- uint32_t owner_id;
- CollisionObject2D *parent;
- bool disabled;
- bool one_way_collision;
- real_t one_way_collision_margin;
+ uint32_t owner_id = 0;
+ CollisionObject2D *parent = nullptr;
+ bool disabled = false;
+ bool one_way_collision = false;
+ real_t one_way_collision_margin = 1.0;
Vector<Vector<Vector2>> _decompose_in_convex();
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index 381c2ad29a..93949f741b 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -110,6 +110,7 @@ void CollisionShape2D::_notification(int p_what) {
draw_col.r = g;
draw_col.g = g;
draw_col.b = g;
+ draw_col.a *= 0.5;
}
shape->draw(get_canvas_item(), draw_col);
@@ -243,11 +244,5 @@ void CollisionShape2D::_bind_methods() {
}
CollisionShape2D::CollisionShape2D() {
- rect = Rect2(-Point2(10, 10), Point2(20, 20));
set_notify_local_transform(true);
- owner_id = 0;
- parent = nullptr;
- disabled = false;
- one_way_collision = false;
- one_way_collision_margin = 1.0;
}
diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h
index 17cc4187c9..695d0c6657 100644
--- a/scene/2d/collision_shape_2d.h
+++ b/scene/2d/collision_shape_2d.h
@@ -39,13 +39,13 @@ class CollisionObject2D;
class CollisionShape2D : public Node2D {
GDCLASS(CollisionShape2D, Node2D);
Ref<Shape2D> shape;
- Rect2 rect;
- uint32_t owner_id;
- CollisionObject2D *parent;
+ Rect2 rect = Rect2(-Point2(10, 10), Point2(20, 20));
+ uint32_t owner_id = 0;
+ CollisionObject2D *parent = nullptr;
void _shape_changed();
- bool disabled;
- bool one_way_collision;
- real_t one_way_collision_margin;
+ bool disabled = false;
+ bool one_way_collision = false;
+ real_t one_way_collision_margin = 1.0;
void _update_in_shape_owner(bool p_xform_only = false);
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index f839e8c304..6a69a4c618 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -60,7 +60,7 @@ void CPUParticles2D::set_amount(int p_amount) {
}
particle_data.resize((8 + 4 + 4) * p_amount);
- RS::get_singleton()->multimesh_allocate(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_2D, true, true);
+ RS::get_singleton()->multimesh_allocate_data(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_2D, true, true);
particle_order.resize(p_amount);
}
@@ -78,11 +78,11 @@ void CPUParticles2D::set_pre_process_time(float p_time) {
pre_process_time = p_time;
}
-void CPUParticles2D::set_explosiveness_ratio(float p_ratio) {
+void CPUParticles2D::set_explosiveness_ratio(real_t p_ratio) {
explosiveness_ratio = p_ratio;
}
-void CPUParticles2D::set_randomness_ratio(float p_ratio) {
+void CPUParticles2D::set_randomness_ratio(real_t p_ratio) {
randomness_ratio = p_ratio;
}
@@ -95,7 +95,7 @@ void CPUParticles2D::set_use_local_coordinates(bool p_enable) {
set_notify_transform(!p_enable);
}
-void CPUParticles2D::set_speed_scale(float p_scale) {
+void CPUParticles2D::set_speed_scale(real_t p_scale) {
speed_scale = p_scale;
}
@@ -119,11 +119,11 @@ float CPUParticles2D::get_pre_process_time() const {
return pre_process_time;
}
-float CPUParticles2D::get_explosiveness_ratio() const {
+real_t CPUParticles2D::get_explosiveness_ratio() const {
return explosiveness_ratio;
}
-float CPUParticles2D::get_randomness_ratio() const {
+real_t CPUParticles2D::get_randomness_ratio() const {
return randomness_ratio;
}
@@ -135,7 +135,7 @@ bool CPUParticles2D::get_use_local_coordinates() const {
return local_coords;
}
-float CPUParticles2D::get_speed_scale() const {
+real_t CPUParticles2D::get_speed_scale() const {
return speed_scale;
}
@@ -289,39 +289,39 @@ Vector2 CPUParticles2D::get_direction() const {
return direction;
}
-void CPUParticles2D::set_spread(float p_spread) {
+void CPUParticles2D::set_spread(real_t p_spread) {
spread = p_spread;
}
-float CPUParticles2D::get_spread() const {
+real_t CPUParticles2D::get_spread() const {
return spread;
}
-void CPUParticles2D::set_param(Parameter p_param, float p_value) {
+void CPUParticles2D::set_param(Parameter p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
parameters[p_param] = p_value;
}
-float CPUParticles2D::get_param(Parameter p_param) const {
+real_t CPUParticles2D::get_param(Parameter p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return parameters[p_param];
}
-void CPUParticles2D::set_param_randomness(Parameter p_param, float p_value) {
+void CPUParticles2D::set_param_randomness(Parameter p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
randomness[p_param] = p_value;
}
-float CPUParticles2D::get_param_randomness(Parameter p_param) const {
+real_t CPUParticles2D::get_param_randomness(Parameter p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return randomness[p_param];
}
-static void _adjust_curve_range(const Ref<Curve> &p_curve, float p_min, float p_max) {
+static void _adjust_curve_range(const Ref<Curve> &p_curve, real_t p_min, real_t p_max) {
Ref<Curve> curve = p_curve;
if (!curve.is_valid()) {
return;
@@ -410,10 +410,10 @@ bool CPUParticles2D::get_particle_flag(ParticleFlags p_particle_flag) const {
void CPUParticles2D::set_emission_shape(EmissionShape p_shape) {
ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX);
emission_shape = p_shape;
- _change_notify();
+ notify_property_list_changed();
}
-void CPUParticles2D::set_emission_sphere_radius(float p_radius) {
+void CPUParticles2D::set_emission_sphere_radius(real_t p_radius) {
emission_sphere_radius = p_radius;
}
@@ -433,7 +433,7 @@ void CPUParticles2D::set_emission_colors(const Vector<Color> &p_colors) {
emission_colors = p_colors;
}
-float CPUParticles2D::get_emission_sphere_radius() const {
+real_t CPUParticles2D::get_emission_sphere_radius() const {
return emission_sphere_radius;
}
@@ -502,7 +502,7 @@ static uint32_t idhash(uint32_t x) {
return x;
}
-static float rand_from_seed(uint32_t &seed) {
+static real_t rand_from_seed(uint32_t &seed) {
int k;
int s = int(seed);
if (s == 0) {
@@ -514,7 +514,7 @@ static float rand_from_seed(uint32_t &seed) {
s += 2147483647;
}
seed = uint32_t(s);
- return float(seed % uint32_t(65536)) / 65535.0;
+ return (seed % uint32_t(65536)) / 65535.0;
}
void CPUParticles2D::_update_internal() {
@@ -599,7 +599,7 @@ void CPUParticles2D::_particles_process(float p_delta) {
cycle++;
if (one_shot && cycle > 0) {
set_emitting(false);
- _change_notify();
+ notify_property_list_changed();
}
}
@@ -625,7 +625,7 @@ void CPUParticles2D::_particles_process(float p_delta) {
// The phase is a ratio between 0 (birth) and 1 (end of life) for each particle.
// While we use time in tests later on, for randomness we use the phase as done in the
// original shader code, and we later multiply by lifetime to get the time.
- float restart_phase = float(i) / float(pcount);
+ real_t restart_phase = real_t(i) / real_t(pcount);
if (randomness_ratio > 0.0) {
uint32_t seed = cycle;
@@ -634,8 +634,8 @@ void CPUParticles2D::_particles_process(float p_delta) {
}
seed *= uint32_t(pcount);
seed += uint32_t(i);
- float random = float(idhash(seed) % uint32_t(65536)) / 65536.0;
- restart_phase += randomness_ratio * random * 1.0 / float(pcount);
+ real_t random = (idhash(seed) % uint32_t(65536)) / 65536.0;
+ restart_phase += randomness_ratio * random * 1.0 / pcount;
}
restart_phase *= (1.0 - explosiveness_ratio);
@@ -680,17 +680,17 @@ void CPUParticles2D::_particles_process(float p_delta) {
}
p.active = true;
- /*float tex_linear_velocity = 0;
+ /*real_t tex_linear_velocity = 0;
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(0);
}*/
- float tex_angle = 0.0;
+ real_t tex_angle = 0.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv);
}
- float tex_anim_offset = 0.0;
+ real_t tex_anim_offset = 0.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
tex_anim_offset = curve_parameters[PARAM_ANGLE]->interpolate(tv);
}
@@ -702,16 +702,16 @@ void CPUParticles2D::_particles_process(float p_delta) {
p.hue_rot_rand = Math::randf();
p.anim_offset_rand = Math::randf();
- float angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread);
+ real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread);
Vector2 rot = Vector2(Math::cos(angle1_rad), Math::sin(angle1_rad));
- p.velocity = rot * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]);
+ p.velocity = rot * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp((real_t)1.0, real_t(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]);
- float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]);
+ real_t base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp((real_t)1.0, p.angle_rand, randomness[PARAM_ANGLE]);
p.rotation = Math::deg2rad(base_angle);
p.custom[0] = 0.0; // unused
p.custom[1] = 0.0; // phase [0..1]
- p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]); //animation phase [0..1]
+ p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp((real_t)1.0, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]); //animation phase [0..1]
p.custom[3] = 0.0;
p.transform = Transform2D();
p.time = 0;
@@ -723,8 +723,8 @@ void CPUParticles2D::_particles_process(float p_delta) {
//do none
} break;
case EMISSION_SHAPE_SPHERE: {
- float s = Math::randf(), t = Math_TAU * Math::randf();
- float radius = emission_sphere_radius * Math::sqrt(1.0 - s * s);
+ real_t s = Math::randf(), t = Math_TAU * Math::randf();
+ real_t radius = emission_sphere_radius * Math::sqrt(1.0 - s * s);
p.transform[2] = Vector2(Math::cos(t), Math::sin(t)) * radius;
} break;
case EMISSION_SHAPE_RECTANGLE: {
@@ -775,51 +775,51 @@ void CPUParticles2D::_particles_process(float p_delta) {
p.custom[1] = p.time / lifetime;
tv = p.time / p.lifetime;
- float tex_linear_velocity = 0.0;
+ real_t tex_linear_velocity = 0.0;
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(tv);
}
- float tex_orbit_velocity = 0.0;
+ real_t tex_orbit_velocity = 0.0;
if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) {
tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(tv);
}
- float tex_angular_velocity = 0.0;
+ real_t tex_angular_velocity = 0.0;
if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) {
tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(tv);
}
- float tex_linear_accel = 0.0;
+ real_t tex_linear_accel = 0.0;
if (curve_parameters[PARAM_LINEAR_ACCEL].is_valid()) {
tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->interpolate(tv);
}
- float tex_tangential_accel = 0.0;
+ real_t tex_tangential_accel = 0.0;
if (curve_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) {
tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->interpolate(tv);
}
- float tex_radial_accel = 0.0;
+ real_t tex_radial_accel = 0.0;
if (curve_parameters[PARAM_RADIAL_ACCEL].is_valid()) {
tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->interpolate(tv);
}
- float tex_damping = 0.0;
+ real_t tex_damping = 0.0;
if (curve_parameters[PARAM_DAMPING].is_valid()) {
tex_damping = curve_parameters[PARAM_DAMPING]->interpolate(tv);
}
- float tex_angle = 0.0;
+ real_t tex_angle = 0.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv);
}
- float tex_anim_speed = 0.0;
+ real_t tex_anim_speed = 0.0;
if (curve_parameters[PARAM_ANIM_SPEED].is_valid()) {
tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->interpolate(tv);
}
- float tex_anim_offset = 0.0;
+ real_t tex_anim_offset = 0.0;
if (curve_parameters[PARAM_ANIM_OFFSET].is_valid()) {
tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->interpolate(tv);
}
@@ -828,20 +828,20 @@ void CPUParticles2D::_particles_process(float p_delta) {
Vector2 pos = p.transform[2];
//apply linear acceleration
- force += p.velocity.length() > 0.0 ? p.velocity.normalized() * (parameters[PARAM_LINEAR_ACCEL] + tex_linear_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_LINEAR_ACCEL]) : Vector2();
+ force += p.velocity.length() > 0.0 ? p.velocity.normalized() * (parameters[PARAM_LINEAR_ACCEL] + tex_linear_accel) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_LINEAR_ACCEL]) : Vector2();
//apply radial acceleration
Vector2 org = emission_xform[2];
Vector2 diff = pos - org;
- force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector2();
+ force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector2();
//apply tangential acceleration;
Vector2 yx = Vector2(diff.y, diff.x);
- force += yx.length() > 0.0 ? (yx * Vector2(-1.0, 1.0)).normalized() * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector2();
+ force += yx.length() > 0.0 ? (yx * Vector2(-1.0, 1.0)).normalized() * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector2();
//apply attractor forces
p.velocity += force * local_delta;
//orbit velocity
- float orbit_amount = (parameters[PARAM_ORBIT_VELOCITY] + tex_orbit_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ORBIT_VELOCITY]);
+ real_t orbit_amount = (parameters[PARAM_ORBIT_VELOCITY] + tex_orbit_velocity) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_ORBIT_VELOCITY]);
if (orbit_amount != 0.0) {
- float ang = orbit_amount * local_delta * Math_TAU;
+ real_t ang = orbit_amount * local_delta * Math_TAU;
// Not sure why the ParticlesMaterial code uses a clockwise rotation matrix,
// but we use -ang here to reproduce its behavior.
Transform2D rot = Transform2D(-ang, Vector2());
@@ -853,8 +853,8 @@ void CPUParticles2D::_particles_process(float p_delta) {
}
if (parameters[PARAM_DAMPING] + tex_damping > 0.0) {
- float v = p.velocity.length();
- float damp = (parameters[PARAM_DAMPING] + tex_damping) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_DAMPING]);
+ real_t v = p.velocity.length();
+ real_t damp = (parameters[PARAM_DAMPING] + tex_damping) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_DAMPING]);
v -= damp * local_delta;
if (v < 0.0) {
p.velocity = Vector2();
@@ -862,28 +862,28 @@ void CPUParticles2D::_particles_process(float p_delta) {
p.velocity = p.velocity.normalized() * v;
}
}
- float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]);
- base_angle += p.custom[1] * lifetime * (parameters[PARAM_ANGULAR_VELOCITY] + tex_angular_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed) * 2.0f - 1.0f, randomness[PARAM_ANGULAR_VELOCITY]);
+ real_t base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp((real_t)1.0, p.angle_rand, randomness[PARAM_ANGLE]);
+ base_angle += p.custom[1] * lifetime * (parameters[PARAM_ANGULAR_VELOCITY] + tex_angular_velocity) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed) * 2.0f - 1.0f, randomness[PARAM_ANGULAR_VELOCITY]);
p.rotation = Math::deg2rad(base_angle); //angle
- float animation_phase = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]) + p.custom[1] * (parameters[PARAM_ANIM_SPEED] + tex_anim_speed) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ANIM_SPEED]);
+ real_t animation_phase = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp((real_t)1.0, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]) + p.custom[1] * (parameters[PARAM_ANIM_SPEED] + tex_anim_speed) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_ANIM_SPEED]);
p.custom[2] = animation_phase;
}
//apply color
//apply hue rotation
- float tex_scale = 1.0;
+ real_t tex_scale = 1.0;
if (curve_parameters[PARAM_SCALE].is_valid()) {
tex_scale = curve_parameters[PARAM_SCALE]->interpolate(tv);
}
- float tex_hue_variation = 0.0;
+ real_t tex_hue_variation = 0.0;
if (curve_parameters[PARAM_HUE_VARIATION].is_valid()) {
tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->interpolate(tv);
}
- float hue_rot_angle = (parameters[PARAM_HUE_VARIATION] + tex_hue_variation) * Math_TAU * Math::lerp(1.0f, p.hue_rot_rand * 2.0f - 1.0f, randomness[PARAM_HUE_VARIATION]);
- float hue_rot_c = Math::cos(hue_rot_angle);
- float hue_rot_s = Math::sin(hue_rot_angle);
+ real_t hue_rot_angle = (parameters[PARAM_HUE_VARIATION] + tex_hue_variation) * Math_TAU * Math::lerp(1.0f, p.hue_rot_rand * 2.0f - 1.0f, randomness[PARAM_HUE_VARIATION]);
+ real_t hue_rot_c = Math::cos(hue_rot_angle);
+ real_t hue_rot_s = Math::sin(hue_rot_angle);
Basis hue_rot_mat;
{
@@ -921,7 +921,7 @@ void CPUParticles2D::_particles_process(float p_delta) {
}
//scale by scale
- float base_scale = tex_scale * Math::lerp(parameters[PARAM_SCALE], 1.0f, p.scale_rand * randomness[PARAM_SCALE]);
+ real_t base_scale = tex_scale * Math::lerp(parameters[PARAM_SCALE], (real_t)1.0, p.scale_rand * randomness[PARAM_SCALE]);
if (base_scale < 0.000001) {
base_scale = 0.000001;
}
@@ -1032,66 +1032,64 @@ void CPUParticles2D::_update_render_thread() {
}
void CPUParticles2D::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
- set_process_internal(emitting);
- }
-
- if (p_what == NOTIFICATION_EXIT_TREE) {
- _set_redraw(false);
- }
-
- if (p_what == NOTIFICATION_DRAW) {
- // first update before rendering to avoid one frame delay after emitting starts
- if (emitting && (time == 0)) {
- _update_internal();
- }
-
- if (!redraw) {
- return; // don't add to render list
- }
-
- RID texrid;
- if (texture.is_valid()) {
- texrid = texture->get_rid();
- }
-
- RS::get_singleton()->canvas_item_add_multimesh(get_canvas_item(), multimesh, texrid);
- }
-
- if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
- _update_internal();
- }
-
- if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
- inv_emission_transform = get_global_transform().affine_inverse();
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ set_process_internal(emitting);
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ _set_redraw(false);
+ } break;
+ case NOTIFICATION_DRAW: {
+ // first update before rendering to avoid one frame delay after emitting starts
+ if (emitting && (time == 0)) {
+ _update_internal();
+ }
- if (!local_coords) {
- int pc = particles.size();
+ if (!redraw) {
+ return; // don't add to render list
+ }
- float *w = particle_data.ptrw();
- const Particle *r = particles.ptr();
- float *ptr = w;
+ RID texrid;
+ if (texture.is_valid()) {
+ texrid = texture->get_rid();
+ }
- for (int i = 0; i < pc; i++) {
- Transform2D t = inv_emission_transform * r[i].transform;
+ RS::get_singleton()->canvas_item_add_multimesh(get_canvas_item(), multimesh, texrid);
+ } break;
+ case NOTIFICATION_INTERNAL_PROCESS: {
+ _update_internal();
+ } break;
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+ inv_emission_transform = get_global_transform().affine_inverse();
- if (r[i].active) {
- ptr[0] = t.elements[0][0];
- ptr[1] = t.elements[1][0];
- ptr[2] = 0;
- ptr[3] = t.elements[2][0];
- ptr[4] = t.elements[0][1];
- ptr[5] = t.elements[1][1];
- ptr[6] = 0;
- ptr[7] = t.elements[2][1];
+ if (!local_coords) {
+ int pc = particles.size();
+
+ float *w = particle_data.ptrw();
+ const Particle *r = particles.ptr();
+ float *ptr = w;
+
+ for (int i = 0; i < pc; i++) {
+ Transform2D t = inv_emission_transform * r[i].transform;
+
+ if (r[i].active) {
+ ptr[0] = t.elements[0][0];
+ ptr[1] = t.elements[1][0];
+ ptr[2] = 0;
+ ptr[3] = t.elements[2][0];
+ ptr[4] = t.elements[0][1];
+ ptr[5] = t.elements[1][1];
+ ptr[6] = 0;
+ ptr[7] = t.elements[2][1];
+
+ } else {
+ zeromem(ptr, sizeof(float) * 8);
+ }
- } else {
- zeromem(ptr, sizeof(float) * 8);
+ ptr += 16;
}
-
- ptr += 16;
}
- }
+ } break;
}
}
@@ -1369,34 +1367,14 @@ void CPUParticles2D::_bind_methods() {
}
CPUParticles2D::CPUParticles2D() {
- time = 0;
- inactive_time = 0;
- frame_remainder = 0;
- cycle = 0;
- redraw = false;
- emitting = false;
-
mesh = RenderingServer::get_singleton()->mesh_create();
multimesh = RenderingServer::get_singleton()->multimesh_create();
RenderingServer::get_singleton()->multimesh_set_mesh(multimesh, mesh);
set_emitting(true);
- set_one_shot(false);
set_amount(8);
- set_lifetime(1);
- set_fixed_fps(0);
- set_fractional_delta(true);
- set_pre_process_time(0);
- set_explosiveness_ratio(0);
- set_randomness_ratio(0);
- set_lifetime_randomness(0);
set_use_local_coordinates(true);
- set_draw_order(DRAW_ORDER_INDEX);
- set_speed_scale(1);
-
- set_direction(Vector2(1, 0));
- set_spread(45);
set_param(PARAM_INITIAL_LINEAR_VELOCITY, 0);
set_param(PARAM_ANGULAR_VELOCITY, 0);
set_param(PARAM_ORBIT_VELOCITY, 0);
@@ -1409,11 +1387,6 @@ CPUParticles2D::CPUParticles2D() {
set_param(PARAM_HUE_VARIATION, 0);
set_param(PARAM_ANIM_SPEED, 0);
set_param(PARAM_ANIM_OFFSET, 0);
- set_emission_shape(EMISSION_SHAPE_POINT);
- set_emission_sphere_radius(1);
- set_emission_rect_extents(Vector2(1, 1));
-
- set_gravity(Vector2(0, 98));
for (int i = 0; i < PARAM_MAX; i++) {
set_param_randomness(Parameter(i), 0);
diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h
index 3793f6a418..ab04ee4a57 100644
--- a/scene/2d/cpu_particles_2d.h
+++ b/scene/2d/cpu_particles_2d.h
@@ -78,31 +78,31 @@ public:
};
private:
- bool emitting;
+ bool emitting = false;
struct Particle {
Transform2D transform;
Color color;
- float custom[4];
- float rotation;
+ float custom[4] = {};
+ real_t rotation = 0.0;
Vector2 velocity;
- bool active;
- float angle_rand;
- float scale_rand;
- float hue_rot_rand;
- float anim_offset_rand;
- float time;
- float lifetime;
+ bool active = false;
+ real_t angle_rand = 0.0;
+ real_t scale_rand = 0.0;
+ real_t hue_rot_rand = 0.0;
+ real_t anim_offset_rand = 0.0;
+ float time = 0.0;
+ float lifetime = 0.0;
Color base_color;
- uint32_t seed;
+ uint32_t seed = 0;
};
- float time;
- float inactive_time;
- float frame_remainder;
- int cycle;
- bool redraw;
+ float time = 0.0;
+ float inactive_time = 0.0;
+ float frame_remainder = 0.0;
+ int cycle = 0;
+ bool redraw = false;
RID mesh;
RID multimesh;
@@ -112,7 +112,7 @@ private:
Vector<int> particle_order;
struct SortLifetime {
- const Particle *particles;
+ const Particle *particles = nullptr;
bool operator()(int p_a, int p_b) const {
return particles[p_a].time > particles[p_b].time;
@@ -120,7 +120,7 @@ private:
};
struct SortAxis {
- const Particle *particles;
+ const Particle *particles = nullptr;
Vector2 axis;
bool operator()(int p_a, int p_b) const {
return axis.dot(particles[p_a].transform[2]) < axis.dot(particles[p_b].transform[2]);
@@ -129,31 +129,31 @@ private:
//
- bool one_shot;
+ bool one_shot = false;
- float lifetime;
- float pre_process_time;
- float explosiveness_ratio;
- float randomness_ratio;
- float lifetime_randomness;
- float speed_scale;
+ float lifetime = 1.0;
+ float pre_process_time = 0.0;
+ real_t explosiveness_ratio = 0.0;
+ real_t randomness_ratio = 0.0;
+ real_t lifetime_randomness = 0.0;
+ real_t speed_scale = 1.0;
bool local_coords;
- int fixed_fps;
- bool fractional_delta;
+ int fixed_fps = 0;
+ bool fractional_delta = true;
Transform2D inv_emission_transform;
- DrawOrder draw_order;
+ DrawOrder draw_order = DRAW_ORDER_INDEX;
Ref<Texture2D> texture;
////////
- Vector2 direction;
- float spread;
+ Vector2 direction = Vector2(1, 0);
+ real_t spread = 45.0;
- float parameters[PARAM_MAX];
- float randomness[PARAM_MAX];
+ real_t parameters[PARAM_MAX];
+ real_t randomness[PARAM_MAX];
Ref<Curve> curve_parameters[PARAM_MAX];
Color color;
@@ -161,15 +161,15 @@ private:
bool particle_flags[PARTICLE_FLAG_MAX];
- EmissionShape emission_shape;
- float emission_sphere_radius;
- Vector2 emission_rect_extents;
+ EmissionShape emission_shape = EMISSION_SHAPE_POINT;
+ real_t emission_sphere_radius = 1.0;
+ Vector2 emission_rect_extents = Vector2(1, 1);
Vector<Vector2> emission_points;
Vector<Vector2> emission_normals;
Vector<Color> emission_colors;
- int emission_point_count;
+ int emission_point_count = 0;
- Vector2 gravity;
+ Vector2 gravity = Vector2(0, 98);
void _update_internal();
void _particles_process(float p_delta);
@@ -196,24 +196,24 @@ public:
void set_lifetime(float p_lifetime);
void set_one_shot(bool p_one_shot);
void set_pre_process_time(float p_time);
- void set_explosiveness_ratio(float p_ratio);
- void set_randomness_ratio(float p_ratio);
+ void set_explosiveness_ratio(real_t p_ratio);
+ void set_randomness_ratio(real_t p_ratio);
void set_lifetime_randomness(float p_random);
void set_visibility_aabb(const Rect2 &p_aabb);
void set_use_local_coordinates(bool p_enable);
- void set_speed_scale(float p_scale);
+ void set_speed_scale(real_t p_scale);
bool is_emitting() const;
int get_amount() const;
float get_lifetime() const;
bool get_one_shot() const;
float get_pre_process_time() const;
- float get_explosiveness_ratio() const;
- float get_randomness_ratio() const;
+ real_t get_explosiveness_ratio() const;
+ real_t get_randomness_ratio() const;
float get_lifetime_randomness() const;
Rect2 get_visibility_aabb() const;
bool get_use_local_coordinates() const;
- float get_speed_scale() const;
+ real_t get_speed_scale() const;
void set_fixed_fps(int p_count);
int get_fixed_fps() const;
@@ -235,14 +235,14 @@ public:
void set_direction(Vector2 p_direction);
Vector2 get_direction() const;
- void set_spread(float p_spread);
- float get_spread() const;
+ void set_spread(real_t p_spread);
+ real_t get_spread() const;
- void set_param(Parameter p_param, float p_value);
- float get_param(Parameter p_param) const;
+ void set_param(Parameter p_param, real_t p_value);
+ real_t get_param(Parameter p_param) const;
- void set_param_randomness(Parameter p_param, float p_value);
- float get_param_randomness(Parameter p_param) const;
+ void set_param_randomness(Parameter p_param, real_t p_value);
+ real_t get_param_randomness(Parameter p_param) const;
void set_param_curve(Parameter p_param, const Ref<Curve> &p_curve);
Ref<Curve> get_param_curve(Parameter p_param) const;
@@ -257,7 +257,7 @@ public:
bool get_particle_flag(ParticleFlags p_particle_flag) const;
void set_emission_shape(EmissionShape p_shape);
- void set_emission_sphere_radius(float p_radius);
+ void set_emission_sphere_radius(real_t p_radius);
void set_emission_rect_extents(Vector2 p_extents);
void set_emission_points(const Vector<Vector2> &p_points);
void set_emission_normals(const Vector<Vector2> &p_normals);
@@ -265,7 +265,7 @@ public:
void set_emission_point_count(int p_count);
EmissionShape get_emission_shape() const;
- float get_emission_sphere_radius() const;
+ real_t get_emission_sphere_radius() const;
Vector2 get_emission_rect_extents() const;
Vector<Vector2> get_emission_points() const;
Vector<Vector2> get_emission_normals() const;
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index 2e477a88a9..af70c47f7c 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -101,7 +101,6 @@ void GPUParticles2D::set_visibility_rect(const Rect2 &p_visibility_rect) {
RS::get_singleton()->particles_set_custom_aabb(particles, aabb);
- _change_notify("visibility_rect");
update();
}
@@ -305,7 +304,7 @@ void GPUParticles2D::_notification(int p_what) {
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
if (one_shot && !is_emitting()) {
- _change_notify();
+ notify_property_list_changed();
set_process_internal(false);
}
}
diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp
index 1a31f72a59..7d9cdd52ac 100644
--- a/scene/2d/joints_2d.cpp
+++ b/scene/2d/joints_2d.cpp
@@ -49,34 +49,22 @@ void Joint2D::_disconnect_signals() {
}
}
-void Joint2D::_body_exit_tree(const ObjectID &p_body_id) {
+void Joint2D::_body_exit_tree() {
_disconnect_signals();
- Object *object = ObjectDB::get_instance(p_body_id);
- PhysicsBody2D *body = Object::cast_to<PhysicsBody2D>(object);
- ERR_FAIL_NULL(body);
- RID body_rid = body->get_rid();
- if (ba == body_rid) {
- a = NodePath();
- }
- if (bb == body_rid) {
- b = NodePath();
- }
- _update_joint();
+ _update_joint(true);
}
void Joint2D::_update_joint(bool p_only_free) {
- if (joint.is_valid()) {
- if (ba.is_valid() && bb.is_valid() && exclude_from_collision) {
- PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, false);
- }
-
- PhysicsServer2D::get_singleton()->free(joint);
- joint = RID();
- ba = RID();
- bb = RID();
+ if (ba.is_valid() && bb.is_valid() && exclude_from_collision) {
+ PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, false);
}
+ ba = RID();
+ bb = RID();
+ configured = false;
+
if (p_only_free || !is_inside_tree()) {
+ PhysicsServer2D::get_singleton()->joint_clear(joint);
warning = String();
return;
}
@@ -88,30 +76,35 @@ void Joint2D::_update_joint(bool p_only_free) {
PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
if (node_a && !body_a && node_b && !body_b) {
+ PhysicsServer2D::get_singleton()->joint_clear(joint);
warning = TTR("Node A and Node B must be PhysicsBody2Ds");
update_configuration_warning();
return;
}
if (node_a && !body_a) {
+ PhysicsServer2D::get_singleton()->joint_clear(joint);
warning = TTR("Node A must be a PhysicsBody2D");
update_configuration_warning();
return;
}
if (node_b && !body_b) {
+ PhysicsServer2D::get_singleton()->joint_clear(joint);
warning = TTR("Node B must be a PhysicsBody2D");
update_configuration_warning();
return;
}
if (!body_a || !body_b) {
+ PhysicsServer2D::get_singleton()->joint_clear(joint);
warning = TTR("Joint is not connected to two PhysicsBody2Ds");
update_configuration_warning();
return;
}
if (body_a == body_b) {
+ PhysicsServer2D::get_singleton()->joint_clear(joint);
warning = TTR("Node A and Node B must be different PhysicsBody2Ds");
update_configuration_warning();
return;
@@ -128,7 +121,9 @@ void Joint2D::_update_joint(bool p_only_free) {
body_b->force_update_transform();
}
- joint = _configure_joint(body_a, body_b);
+ configured = true;
+
+ _configure_joint(joint, body_a, body_b);
ERR_FAIL_COND_MSG(!joint.is_valid(), "Failed to configure the joint.");
@@ -137,8 +132,8 @@ void Joint2D::_update_joint(bool p_only_free) {
ba = body_a->get_rid();
bb = body_b->get_rid();
- body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree), make_binds(body_a->get_instance_id()));
- body_b->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree), make_binds(body_b->get_instance_id()));
+ body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
+ body_b->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision);
}
@@ -249,8 +244,11 @@ void Joint2D::_bind_methods() {
}
Joint2D::Joint2D() {
- bias = 0;
- exclude_from_collision = true;
+ joint = PhysicsServer2D::get_singleton()->joint_create();
+}
+
+Joint2D::~Joint2D() {
+ PhysicsServer2D::get_singleton()->free(joint);
}
///////////////////////////////////////////////////////////////////////////////
@@ -274,16 +272,15 @@ void PinJoint2D::_notification(int p_what) {
}
}
-RID PinJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
- RID pj = PhysicsServer2D::get_singleton()->pin_joint_create(get_global_transform().get_origin(), body_a->get_rid(), body_b ? body_b->get_rid() : RID());
- PhysicsServer2D::get_singleton()->pin_joint_set_param(pj, PhysicsServer2D::PIN_JOINT_SOFTNESS, softness);
- return pj;
+void PinJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
+ PhysicsServer2D::get_singleton()->joint_make_pin(p_joint, get_global_transform().get_origin(), body_a->get_rid(), body_b ? body_b->get_rid() : RID());
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_SOFTNESS, softness);
}
void PinJoint2D::set_softness(real_t p_softness) {
softness = p_softness;
update();
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer2D::get_singleton()->pin_joint_set_param(get_joint(), PhysicsServer2D::PIN_JOINT_SOFTNESS, p_softness);
}
}
@@ -300,7 +297,6 @@ void PinJoint2D::_bind_methods() {
}
PinJoint2D::PinJoint2D() {
- softness = 0;
}
///////////////////////////////////////////////////////////////////////////////
@@ -326,13 +322,13 @@ void GrooveJoint2D::_notification(int p_what) {
}
}
-RID GrooveJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
+void GrooveJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
Transform2D gt = get_global_transform();
Vector2 groove_A1 = gt.get_origin();
Vector2 groove_A2 = gt.xform(Vector2(0, length));
Vector2 anchor_B = gt.xform(Vector2(0, initial_offset));
- return PhysicsServer2D::get_singleton()->groove_joint_create(groove_A1, groove_A2, anchor_B, body_a->get_rid(), body_b->get_rid());
+ PhysicsServer2D::get_singleton()->joint_make_groove(p_joint, groove_A1, groove_A2, anchor_B, body_a->get_rid(), body_b->get_rid());
}
void GrooveJoint2D::set_length(real_t p_length) {
@@ -364,8 +360,6 @@ void GrooveJoint2D::_bind_methods() {
}
GrooveJoint2D::GrooveJoint2D() {
- length = 50;
- initial_offset = 25;
}
///////////////////////////////////////////////////////////////////////////////
@@ -390,19 +384,17 @@ void DampedSpringJoint2D::_notification(int p_what) {
}
}
-RID DampedSpringJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
+void DampedSpringJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
Transform2D gt = get_global_transform();
Vector2 anchor_A = gt.get_origin();
Vector2 anchor_B = gt.xform(Vector2(0, length));
- RID dsj = PhysicsServer2D::get_singleton()->damped_spring_joint_create(anchor_A, anchor_B, body_a->get_rid(), body_b->get_rid());
+ PhysicsServer2D::get_singleton()->joint_make_damped_spring(p_joint, anchor_A, anchor_B, body_a->get_rid(), body_b->get_rid());
if (rest_length) {
- PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(dsj, PhysicsServer2D::DAMPED_SPRING_REST_LENGTH, rest_length);
+ PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_REST_LENGTH, rest_length);
}
- PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(dsj, PhysicsServer2D::DAMPED_SPRING_STIFFNESS, stiffness);
- PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(dsj, PhysicsServer2D::DAMPED_SPRING_DAMPING, damping);
-
- return dsj;
+ PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_STIFFNESS, stiffness);
+ PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_DAMPING, damping);
}
void DampedSpringJoint2D::set_length(real_t p_length) {
@@ -417,7 +409,7 @@ real_t DampedSpringJoint2D::get_length() const {
void DampedSpringJoint2D::set_rest_length(real_t p_rest_length) {
rest_length = p_rest_length;
update();
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_joint(), PhysicsServer2D::DAMPED_SPRING_REST_LENGTH, p_rest_length ? p_rest_length : length);
}
}
@@ -429,7 +421,7 @@ real_t DampedSpringJoint2D::get_rest_length() const {
void DampedSpringJoint2D::set_stiffness(real_t p_stiffness) {
stiffness = p_stiffness;
update();
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_joint(), PhysicsServer2D::DAMPED_SPRING_STIFFNESS, p_stiffness);
}
}
@@ -441,7 +433,7 @@ real_t DampedSpringJoint2D::get_stiffness() const {
void DampedSpringJoint2D::set_damping(real_t p_damping) {
damping = p_damping;
update();
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_joint(), PhysicsServer2D::DAMPED_SPRING_DAMPING, p_damping);
}
}
@@ -467,8 +459,4 @@ void DampedSpringJoint2D::_bind_methods() {
}
DampedSpringJoint2D::DampedSpringJoint2D() {
- length = 50;
- rest_length = 0;
- stiffness = 20;
- damping = 1;
}
diff --git a/scene/2d/joints_2d.h b/scene/2d/joints_2d.h
index d0fbb9fd3a..08e02ee29d 100644
--- a/scene/2d/joints_2d.h
+++ b/scene/2d/joints_2d.h
@@ -43,21 +43,24 @@ class Joint2D : public Node2D {
NodePath a;
NodePath b;
- real_t bias;
+ real_t bias = 0.0;
- bool exclude_from_collision;
+ bool exclude_from_collision = true;
+ bool configured = false;
String warning;
protected:
void _disconnect_signals();
- void _body_exit_tree(const ObjectID &p_body_id);
+ void _body_exit_tree();
void _update_joint(bool p_only_free = false);
void _notification(int p_what);
- virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) = 0;
+ virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) = 0;
static void _bind_methods();
+ _FORCE_INLINE_ bool is_configured() const { return configured; }
+
public:
virtual String get_configuration_warning() const override;
@@ -75,16 +78,17 @@ public:
RID get_joint() const { return joint; }
Joint2D();
+ ~Joint2D();
};
class PinJoint2D : public Joint2D {
GDCLASS(PinJoint2D, Joint2D);
- real_t softness;
+ real_t softness = 0.0;
protected:
void _notification(int p_what);
- virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
+ virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
static void _bind_methods();
public:
@@ -97,12 +101,12 @@ public:
class GrooveJoint2D : public Joint2D {
GDCLASS(GrooveJoint2D, Joint2D);
- real_t length;
- real_t initial_offset;
+ real_t length = 50.0;
+ real_t initial_offset = 25.0;
protected:
void _notification(int p_what);
- virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
+ virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
static void _bind_methods();
public:
@@ -118,14 +122,14 @@ public:
class DampedSpringJoint2D : public Joint2D {
GDCLASS(DampedSpringJoint2D, Joint2D);
- real_t stiffness;
- real_t damping;
- real_t rest_length;
- real_t length;
+ real_t stiffness = 20.0;
+ real_t damping = 1.0;
+ real_t rest_length = 0.0;
+ real_t length = 50.0;
protected:
void _notification(int p_what);
- virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
+ virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
static void _bind_methods();
public:
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index ba4372f040..99e35cad1d 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -84,21 +84,21 @@ Color Light2D::get_color() const {
return color;
}
-void Light2D::set_height(float p_height) {
+void Light2D::set_height(real_t p_height) {
height = p_height;
RS::get_singleton()->canvas_light_set_height(canvas_light, height);
}
-float Light2D::get_height() const {
+real_t Light2D::get_height() const {
return height;
}
-void Light2D::set_energy(float p_energy) {
+void Light2D::set_energy(real_t p_energy) {
energy = p_energy;
RS::get_singleton()->canvas_light_set_energy(canvas_light, energy);
}
-float Light2D::get_energy() const {
+real_t Light2D::get_energy() const {
return energy;
}
@@ -159,6 +159,7 @@ int Light2D::get_item_shadow_cull_mask() const {
void Light2D::set_shadow_enabled(bool p_enabled) {
shadow = p_enabled;
RS::get_singleton()->canvas_light_set_shadow_enabled(canvas_light, shadow);
+ notify_property_list_changed();
}
bool Light2D::is_shadow_enabled() const {
@@ -212,15 +213,21 @@ void Light2D::_notification(int p_what) {
}
}
-void Light2D::set_shadow_smooth(float p_amount) {
+void Light2D::set_shadow_smooth(real_t p_amount) {
shadow_smooth = p_amount;
RS::get_singleton()->canvas_light_set_shadow_smooth(canvas_light, shadow_smooth);
}
-float Light2D::get_shadow_smooth() const {
+real_t Light2D::get_shadow_smooth() const {
return shadow_smooth;
}
+void Light2D::_validate_property(PropertyInfo &property) const {
+ if (!shadow && (property.name == "shadow_color" || property.name == "shadow_filter" || property.name == "shadow_filter_smooth" || property.name == "shadow_item_cull_mask")) {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+}
+
void Light2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &Light2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &Light2D::is_enabled);
@@ -300,22 +307,6 @@ void Light2D::_bind_methods() {
Light2D::Light2D() {
canvas_light = RenderingServer::get_singleton()->canvas_light_create();
- enabled = true;
- editor_only = false;
- shadow = false;
- color = Color(1, 1, 1);
- height = 0;
- z_min = -1024;
- z_max = 1024;
- layer_min = 0;
- layer_max = 0;
- item_mask = 1;
- item_shadow_mask = 1;
- energy = 1.0;
- shadow_color = Color(0, 0, 0, 0);
- shadow_filter = SHADOW_FILTER_NONE;
- shadow_smooth = 0;
- blend_mode = BLEND_MODE_ADD;
set_notify_transform(true);
}
@@ -393,7 +384,6 @@ void PointLight2D::set_texture_offset(const Vector2 &p_offset) {
texture_offset = p_offset;
RS::get_singleton()->canvas_light_set_texture_offset(_get_light(), texture_offset);
item_rect_changed();
- _change_notify("offset");
}
Vector2 PointLight2D::get_texture_offset() const {
@@ -413,7 +403,7 @@ String PointLight2D::get_configuration_warning() const {
return warning;
}
-void PointLight2D::set_texture_scale(float p_scale) {
+void PointLight2D::set_texture_scale(real_t p_scale) {
_scale = p_scale;
// Avoid having 0 scale values, can lead to errors in physics and rendering.
if (_scale == 0) {
@@ -423,7 +413,7 @@ void PointLight2D::set_texture_scale(float p_scale) {
item_rect_changed();
}
-float PointLight2D::get_texture_scale() const {
+real_t PointLight2D::get_texture_scale() const {
return _scale;
}
@@ -449,12 +439,12 @@ PointLight2D::PointLight2D() {
//////////
-void DirectionalLight2D::set_max_distance(float p_distance) {
+void DirectionalLight2D::set_max_distance(real_t p_distance) {
max_distance = p_distance;
RS::get_singleton()->canvas_light_set_directional_distance(_get_light(), max_distance);
}
-float DirectionalLight2D::get_max_distance() const {
+real_t DirectionalLight2D::get_max_distance() const {
return max_distance;
}
diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h
index 0112ab1648..ae6cf6d0a0 100644
--- a/scene/2d/light_2d.h
+++ b/scene/2d/light_2d.h
@@ -52,24 +52,24 @@ public:
private:
RID canvas_light;
- bool enabled;
- bool editor_only;
- bool shadow;
- Color color;
- Color shadow_color;
- float height;
- float energy;
- int z_min;
- int z_max;
- int layer_min;
- int layer_max;
- int item_mask;
- int item_shadow_mask;
- float shadow_smooth;
+ bool enabled = true;
+ bool editor_only = false;
+ bool shadow = false;
+ Color color = Color(1, 1, 1);
+ Color shadow_color = Color(0, 0, 0, 0);
+ real_t height = 0.0;
+ real_t energy = 1.0;
+ int z_min = -1024;
+ int z_max = 1024;
+ int layer_min = 0;
+ int layer_max = 0;
+ int item_mask = 1;
+ int item_shadow_mask = 1;
+ real_t shadow_smooth = 0.0;
Ref<Texture2D> texture;
Vector2 texture_offset;
- ShadowFilter shadow_filter;
- BlendMode blend_mode;
+ ShadowFilter shadow_filter = SHADOW_FILTER_NONE;
+ BlendMode blend_mode = BLEND_MODE_ADD;
void _update_light_visibility();
@@ -77,6 +77,7 @@ protected:
_FORCE_INLINE_ RID _get_light() const { return canvas_light; }
void _notification(int p_what);
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const override;
public:
void set_enabled(bool p_enabled);
@@ -88,11 +89,11 @@ public:
void set_color(const Color &p_color);
Color get_color() const;
- void set_height(float p_height);
- float get_height() const;
+ void set_height(real_t p_height);
+ real_t get_height() const;
- void set_energy(float p_energy);
- float get_energy() const;
+ void set_energy(real_t p_energy);
+ real_t get_energy() const;
void set_z_range_min(int p_min_z);
int get_z_range_min() const;
@@ -121,8 +122,8 @@ public:
void set_shadow_color(const Color &p_shadow_color);
Color get_shadow_color() const;
- void set_shadow_smooth(float p_amount);
- float get_shadow_smooth() const;
+ void set_shadow_smooth(real_t p_amount);
+ real_t get_shadow_smooth() const;
void set_blend_mode(BlendMode p_mode);
BlendMode get_blend_mode() const;
@@ -138,7 +139,7 @@ class PointLight2D : public Light2D {
GDCLASS(PointLight2D, Light2D);
private:
- float _scale = 1.0;
+ real_t _scale = 1.0;
Ref<Texture2D> texture;
Vector2 texture_offset;
@@ -165,8 +166,8 @@ public:
void set_texture_offset(const Vector2 &p_offset);
Vector2 get_texture_offset() const;
- void set_texture_scale(float p_scale);
- float get_texture_scale() const;
+ void set_texture_scale(real_t p_scale);
+ real_t get_texture_scale() const;
String get_configuration_warning() const override;
@@ -176,14 +177,14 @@ public:
class DirectionalLight2D : public Light2D {
GDCLASS(DirectionalLight2D, Light2D);
- float max_distance = 10000.0;
+ real_t max_distance = 10000.0;
protected:
static void _bind_methods();
public:
- void set_max_distance(float p_distance);
- float get_max_distance() const;
+ void set_max_distance(real_t p_distance);
+ real_t get_max_distance() const;
DirectionalLight2D();
};
diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp
index 3146e64c08..9589702e2e 100644
--- a/scene/2d/light_occluder_2d.cpp
+++ b/scene/2d/light_occluder_2d.cpp
@@ -145,9 +145,6 @@ void OccluderPolygon2D::_bind_methods() {
OccluderPolygon2D::OccluderPolygon2D() {
occ_polygon = RS::get_singleton()->canvas_occluder_polygon_create();
- closed = true;
- cull = CULL_DISABLED;
- rect_cache_dirty = true;
}
OccluderPolygon2D::~OccluderPolygon2D() {
diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h
index 7944ccad3a..f567c6d965 100644
--- a/scene/2d/light_occluder_2d.h
+++ b/scene/2d/light_occluder_2d.h
@@ -46,11 +46,11 @@ public:
private:
RID occ_polygon;
Vector<Vector2> polygon;
- bool closed;
- CullMode cull;
+ bool closed = true;
+ CullMode cull = CULL_DISABLED;
mutable Rect2 item_rect;
- mutable bool rect_cache_dirty;
+ mutable bool rect_cache_dirty = true;
protected:
static void _bind_methods();
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index 0a3f5673f8..37eb45c21d 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -40,15 +40,6 @@ VARIANT_ENUM_CAST(Line2D::LineCapMode)
VARIANT_ENUM_CAST(Line2D::LineTextureMode)
Line2D::Line2D() {
- _joint_mode = LINE_JOINT_SHARP;
- _begin_cap_mode = LINE_CAP_NONE;
- _end_cap_mode = LINE_CAP_NONE;
- _width = 10;
- _default_color = Color(1, 1, 1);
- _texture_mode = LINE_TEXTURE_NONE;
- _sharp_limit = 2.f;
- _round_precision = 8;
- _antialiased = false;
}
#ifdef TOOLS_ENABLED
@@ -125,6 +116,7 @@ Vector<Vector2> Line2D::get_points() const {
}
void Line2D::set_point_position(int i, Vector2 p_pos) {
+ ERR_FAIL_INDEX(i, _points.size());
_points.set(i, p_pos);
update();
}
diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h
index e0b1cea60a..5e7eb4bac9 100644
--- a/scene/2d/line_2d.h
+++ b/scene/2d/line_2d.h
@@ -124,18 +124,18 @@ private:
private:
Vector<Vector2> _points;
- LineJointMode _joint_mode;
- LineCapMode _begin_cap_mode;
- LineCapMode _end_cap_mode;
- float _width;
+ LineJointMode _joint_mode = LINE_JOINT_SHARP;
+ LineCapMode _begin_cap_mode = LINE_CAP_NONE;
+ LineCapMode _end_cap_mode = LINE_CAP_NONE;
+ float _width = 10.0;
Ref<Curve> _curve;
- Color _default_color;
+ Color _default_color = Color(1, 1, 1);
Ref<Gradient> _gradient;
Ref<Texture2D> _texture;
- LineTextureMode _texture_mode;
- float _sharp_limit;
- int _round_precision;
- bool _antialiased;
+ LineTextureMode _texture_mode = LINE_TEXTURE_NONE;
+ float _sharp_limit = 2.f;
+ int _round_precision = 8;
+ bool _antialiased = false;
};
#endif // LINE2D_H
diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp
index 5e48a61ff7..c478f03356 100644
--- a/scene/2d/line_builder.cpp
+++ b/scene/2d/line_builder.cpp
@@ -94,20 +94,6 @@ static inline Vector2 interpolate(const Rect2 &r, const Vector2 &v) {
//----------------------------------------------------------------------------
LineBuilder::LineBuilder() {
- joint_mode = Line2D::LINE_JOINT_SHARP;
- width = 10;
- curve = nullptr;
- default_color = Color(0.4, 0.5, 1);
- gradient = nullptr;
- sharp_limit = 2.f;
- round_precision = 8;
- begin_cap_mode = Line2D::LINE_CAP_NONE;
- end_cap_mode = Line2D::LINE_CAP_NONE;
- tile_aspect = 1.f;
-
- _interpolate_color = false;
- _last_index[0] = 0;
- _last_index[1] = 0;
}
void LineBuilder::clear_output() {
@@ -389,7 +375,7 @@ void LineBuilder::build() {
}
if (intersection_result != SEGMENT_INTERSECT) {
- // In this case the joint is too corrputed to be re-used,
+ // In this case the joint is too corrupted to be re-used,
// start again the strip with fallback points
strip_begin(pos_up0, pos_down0, color1, uvx1);
}
@@ -499,7 +485,7 @@ void LineBuilder::strip_add_tri(Vector2 up, Orientation orientation) {
if (texture_mode != Line2D::LINE_TEXTURE_NONE) {
// UVs are just one slice of the texture all along
- // (otherwise we can't share the bottom vertice)
+ // (otherwise we can't share the bottom vertex)
uvs.push_back(uvs[_last_index[opposite_orientation]]);
}
@@ -534,7 +520,7 @@ void LineBuilder::strip_add_arc(Vector2 center, float angle_delta, Orientation o
strip_add_tri(rpos, orientation);
}
- // Last arc vertice
+ // Last arc vertex
rpos = center + Vector2(Math::cos(end_angle), Math::sin(end_angle)) * radius;
strip_add_tri(rpos, orientation);
}
@@ -583,7 +569,7 @@ void LineBuilder::new_arc(Vector2 center, Vector2 vbegin, float angle_delta, Col
}
}
- // Last arc vertice
+ // Last arc vertex
Vector2 sc = Vector2(Math::cos(end_angle), Math::sin(end_angle));
rpos = center + sc * radius;
vertices.push_back(rpos);
diff --git a/scene/2d/line_builder.h b/scene/2d/line_builder.h
index bd419d330b..654e61422b 100644
--- a/scene/2d/line_builder.h
+++ b/scene/2d/line_builder.h
@@ -41,17 +41,17 @@ public:
// TODO Move in a struct and reference it
// Input
Vector<Vector2> points;
- Line2D::LineJointMode joint_mode;
- Line2D::LineCapMode begin_cap_mode;
- Line2D::LineCapMode end_cap_mode;
- float width;
- Curve *curve;
- Color default_color;
- Gradient *gradient;
- Line2D::LineTextureMode texture_mode;
- float sharp_limit;
- int round_precision;
- float tile_aspect; // w/h
+ Line2D::LineJointMode joint_mode = Line2D::LINE_JOINT_SHARP;
+ Line2D::LineCapMode begin_cap_mode = Line2D::LINE_CAP_NONE;
+ Line2D::LineCapMode end_cap_mode = Line2D::LINE_CAP_NONE;
+ float width = 10.0;
+ Curve *curve = nullptr;
+ Color default_color = Color(0.4, 0.5, 1);
+ Gradient *gradient = nullptr;
+ Line2D::LineTextureMode texture_mode = Line2D::LineTextureMode::LINE_TEXTURE_NONE;
+ float sharp_limit = 2.f;
+ int round_precision = 8;
+ float tile_aspect = 1.f; // w/h
// TODO offset_joints option (offers alternative implementation of round joints)
// TODO Move in a struct and reference it
@@ -82,8 +82,8 @@ private:
void new_arc(Vector2 center, Vector2 vbegin, float angle_delta, Color color, Rect2 uv_rect);
private:
- bool _interpolate_color;
- int _last_index[2]; // Index of last up and down vertices of the strip
+ bool _interpolate_color = false;
+ int _last_index[2] = {}; // Index of last up and down vertices of the strip
};
#endif // LINE_BUILDER_H
diff --git a/scene/2d/mesh_instance_2d.cpp b/scene/2d/mesh_instance_2d.cpp
index 430e655fc6..b7a0028199 100644
--- a/scene/2d/mesh_instance_2d.cpp
+++ b/scene/2d/mesh_instance_2d.cpp
@@ -71,7 +71,6 @@ void MeshInstance2D::set_texture(const Ref<Texture2D> &p_texture) {
texture = p_texture;
update();
emit_signal("texture_changed");
- _change_notify("texture");
}
void MeshInstance2D::set_normal_map(const Ref<Texture2D> &p_texture) {
diff --git a/scene/2d/multimesh_instance_2d.cpp b/scene/2d/multimesh_instance_2d.cpp
index 5164e5c7e9..72a899370e 100644
--- a/scene/2d/multimesh_instance_2d.cpp
+++ b/scene/2d/multimesh_instance_2d.cpp
@@ -71,7 +71,6 @@ void MultiMeshInstance2D::set_texture(const Ref<Texture2D> &p_texture) {
texture = p_texture;
update();
emit_signal("texture_changed");
- _change_notify("texture");
}
Ref<Texture2D> MultiMeshInstance2D::get_texture() const {
diff --git a/scene/2d/navigation_2d.cpp b/scene/2d/navigation_2d.cpp
deleted file mode 100644
index bec5ee7984..0000000000
--- a/scene/2d/navigation_2d.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*************************************************************************/
-/* navigation_2d.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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_2d.h"
-#include "servers/navigation_server_2d.h"
-
-void Navigation2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_rid"), &Navigation2D::get_rid);
-
- ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation2D::get_simple_path, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Navigation2D::get_closest_point);
- ClassDB::bind_method(D_METHOD("get_closest_point_owner", "to_point"), &Navigation2D::get_closest_point_owner);
-
- ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation2D::set_cell_size);
- ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation2D::get_cell_size);
-
- ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation2D::set_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation2D::get_edge_connection_margin);
-
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size"), "set_cell_size", "get_cell_size");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin");
-}
-
-void Navigation2D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_READY: {
- NavigationServer2D::get_singleton()->map_set_active(map, true);
- } break;
- case NOTIFICATION_EXIT_TREE: {
- NavigationServer2D::get_singleton()->map_set_active(map, false);
- } break;
- }
-}
-
-void Navigation2D::set_cell_size(float p_cell_size) {
- cell_size = p_cell_size;
- NavigationServer2D::get_singleton()->map_set_cell_size(map, cell_size);
-}
-
-void Navigation2D::set_edge_connection_margin(float p_edge_connection_margin) {
- edge_connection_margin = p_edge_connection_margin;
- NavigationServer2D::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin);
-}
-
-Vector<Vector2> Navigation2D::get_simple_path(const Vector2 &p_start, const Vector2 &p_end, bool p_optimize) const {
- return NavigationServer2D::get_singleton()->map_get_path(map, p_start, p_end, p_optimize);
-}
-
-Vector2 Navigation2D::get_closest_point(const Vector2 &p_point) const {
- return NavigationServer2D::get_singleton()->map_get_closest_point(map, p_point);
-}
-
-RID Navigation2D::get_closest_point_owner(const Vector2 &p_point) const {
- return NavigationServer2D::get_singleton()->map_get_closest_point_owner(map, p_point);
-}
-
-Navigation2D::Navigation2D() {
- map = NavigationServer2D::get_singleton()->map_create();
- set_cell_size(10); // Ten pixels
- set_edge_connection_margin(100);
-}
-
-Navigation2D::~Navigation2D() {
- NavigationServer2D::get_singleton()->free(map);
-}
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 534e31b1f2..064fcc91a4 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -32,7 +32,6 @@
#include "core/config/engine.h"
#include "core/math/geometry_2d.h"
-#include "scene/2d/navigation_2d.h"
#include "servers/navigation_server_2d.h"
void NavigationAgent2D::_bind_methods() {
@@ -42,9 +41,6 @@ void NavigationAgent2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationAgent2D::set_radius);
ClassDB::bind_method(D_METHOD("get_radius"), &NavigationAgent2D::get_radius);
- ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationAgent2D::set_navigation_node);
- ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationAgent2D::get_navigation_node);
-
ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent2D::set_neighbor_dist);
ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent2D::get_neighbor_dist);
@@ -95,27 +91,10 @@ void NavigationAgent2D::_notification(int p_what) {
NavigationServer2D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
- // Search the navigation node and set it
- {
- Navigation2D *nav = nullptr;
- Node *p = get_parent();
- while (p != nullptr) {
- nav = Object::cast_to<Navigation2D>(p);
- if (nav != nullptr) {
- p = nullptr;
- } else {
- p = p->get_parent();
- }
- }
-
- set_navigation(nav);
- }
-
set_physics_process_internal(true);
} break;
case NOTIFICATION_EXIT_TREE: {
agent_parent = nullptr;
- set_navigation(nullptr);
set_physics_process_internal(false);
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
@@ -146,23 +125,13 @@ NavigationAgent2D::~NavigationAgent2D() {
agent = RID(); // Pointless
}
-void NavigationAgent2D::set_navigation(Navigation2D *p_nav) {
- if (navigation == p_nav) {
- return; // Pointless
- }
-
- navigation = p_nav;
- NavigationServer2D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid());
-}
-
-void NavigationAgent2D::set_navigation_node(Node *p_nav) {
- Navigation2D *nav = Object::cast_to<Navigation2D>(p_nav);
- ERR_FAIL_COND(nav == nullptr);
- set_navigation(nav);
+void NavigationAgent2D::set_navigable_layers(uint32_t p_layers) {
+ navigable_layers = p_layers;
+ update_navigation();
}
-Node *NavigationAgent2D::get_navigation_node() const {
- return Object::cast_to<Node>(navigation);
+uint32_t NavigationAgent2D::get_navigable_layers() const {
+ return navigable_layers;
}
void NavigationAgent2D::set_target_desired_distance(real_t p_dd) {
@@ -287,7 +256,7 @@ void NavigationAgent2D::update_navigation() {
if (agent_parent == nullptr) {
return;
}
- if (navigation == nullptr) {
+ if (!agent_parent->is_inside_tree()) {
return;
}
if (update_frame_id == Engine::get_singleton()->get_physics_frames()) {
@@ -319,7 +288,7 @@ void NavigationAgent2D::update_navigation() {
}
if (reload_path) {
- navigation_path = NavigationServer2D::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true);
+ navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true, navigable_layers);
navigation_finished = false;
nav_path_index = 0;
emit_signal("path_changed");
diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h
index 6b7da4a5f2..153ede8cec 100644
--- a/scene/2d/navigation_agent_2d.h
+++ b/scene/2d/navigation_agent_2d.h
@@ -35,16 +35,16 @@
#include "scene/main/node.h"
class Node2D;
-class Navigation2D;
class NavigationAgent2D : public Node {
GDCLASS(NavigationAgent2D, Node);
Node2D *agent_parent = nullptr;
- Navigation2D *navigation = nullptr;
RID agent;
+ uint32_t navigable_layers = 1;
+
real_t target_desired_distance = 1.0;
real_t radius;
real_t neighbor_dist;
@@ -74,18 +74,13 @@ public:
NavigationAgent2D();
virtual ~NavigationAgent2D();
- void set_navigation(Navigation2D *p_nav);
- const Navigation2D *get_navigation() const {
- return navigation;
- }
-
- void set_navigation_node(Node *p_nav);
- Node *get_navigation_node() const;
-
RID get_rid() const {
return agent;
}
+ void set_navigable_layers(uint32_t p_layers);
+ uint32_t get_navigable_layers() const;
+
void set_target_desired_distance(real_t p_dd);
real_t get_target_desired_distance() const {
return target_desired_distance;
diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp
index 7e1aefe5e2..965e2b6dc1 100644
--- a/scene/2d/navigation_obstacle_2d.cpp
+++ b/scene/2d/navigation_obstacle_2d.cpp
@@ -31,48 +31,31 @@
#include "navigation_obstacle_2d.h"
#include "scene/2d/collision_shape_2d.h"
-#include "scene/2d/navigation_2d.h"
#include "scene/2d/physics_body_2d.h"
#include "servers/navigation_server_2d.h"
void NavigationObstacle2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle2D::set_navigation_node);
- ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle2D::get_navigation_node);
}
void NavigationObstacle2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
- update_agent_shape();
-
- // Search the navigation node and set it
- {
- Navigation2D *nav = nullptr;
- Node *p = get_parent();
- while (p != nullptr) {
- nav = Object::cast_to<Navigation2D>(p);
- if (nav != nullptr) {
- p = nullptr;
- } else {
- p = p->get_parent();
- }
- }
-
- set_navigation(nav);
- }
-
set_physics_process_internal(true);
} break;
case NOTIFICATION_EXIT_TREE: {
- set_navigation(nullptr);
set_physics_process_internal(false);
} break;
+ case NOTIFICATION_PARENTED: {
+ parent_node2d = Object::cast_to<Node2D>(get_parent());
+ update_agent_shape();
+ } break;
+ case NOTIFICATION_UNPARENTED: {
+ parent_node2d = nullptr;
+ } break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
- Node2D *node = Object::cast_to<Node2D>(get_parent());
- if (node) {
- NavigationServer2D::get_singleton()->agent_set_position(agent, node->get_global_transform().get_origin());
+ if (parent_node2d) {
+ NavigationServer2D::get_singleton()->agent_set_position(agent, parent_node2d->get_global_transform().get_origin());
}
-
} break;
}
}
@@ -86,25 +69,6 @@ NavigationObstacle2D::~NavigationObstacle2D() {
agent = RID(); // Pointless
}
-void NavigationObstacle2D::set_navigation(Navigation2D *p_nav) {
- if (navigation == p_nav) {
- return; // Pointless
- }
-
- navigation = p_nav;
- NavigationServer2D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid());
-}
-
-void NavigationObstacle2D::set_navigation_node(Node *p_nav) {
- Navigation2D *nav = Object::cast_to<Navigation2D>(p_nav);
- ERR_FAIL_COND(nav == nullptr);
- set_navigation(nav);
-}
-
-Node *NavigationObstacle2D::get_navigation_node() const {
- return Object::cast_to<Node>(navigation);
-}
-
String NavigationObstacle2D::get_configuration_warning() const {
String warning = Node::get_configuration_warning();
@@ -119,40 +83,37 @@ String NavigationObstacle2D::get_configuration_warning() const {
}
void NavigationObstacle2D::update_agent_shape() {
- Node *node = get_parent();
-
- // Estimate the radius of this physics body
- real_t radius = 0.0;
- for (int i(0); i < node->get_child_count(); i++) {
- // For each collision shape
- CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(node->get_child(i));
- if (cs) {
- // Take the distance between the Body center to the shape center
- real_t r = cs->get_transform().get_origin().length();
- if (cs->get_shape().is_valid()) {
- // and add the enclosing shape radius
- r += cs->get_shape()->get_enclosing_radius();
+ if (parent_node2d) {
+ // Estimate the radius of this physics body
+ real_t radius = 0.0;
+ for (int i(0); i < parent_node2d->get_child_count(); i++) {
+ // For each collision shape
+ CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(parent_node2d->get_child(i));
+ if (cs) {
+ // Take the distance between the Body center to the shape center
+ real_t r = cs->get_transform().get_origin().length();
+ if (cs->get_shape().is_valid()) {
+ // and add the enclosing shape radius
+ r += cs->get_shape()->get_enclosing_radius();
+ }
+ Size2 s = cs->get_global_transform().get_scale();
+ r *= MAX(s.x, s.y);
+ // Takes the biggest radius
+ radius = MAX(radius, r);
}
- Size2 s = cs->get_global_transform().get_scale();
- r *= MAX(s.x, s.y);
- // Takes the biggest radius
- radius = MAX(radius, r);
}
- }
- Node2D *node_2d = Object::cast_to<Node2D>(node);
- if (node_2d) {
- Vector2 s = node_2d->get_global_transform().get_scale();
+ Vector2 s = parent_node2d->get_global_transform().get_scale();
radius *= MAX(s.x, s.y);
- }
- if (radius == 0.0) {
- radius = 1.0; // Never a 0 radius
- }
+ if (radius == 0.0) {
+ radius = 1.0; // Never a 0 radius
+ }
- // Initialize the Agent as an object
- NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
- NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, 0);
- NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, 0.0);
- NavigationServer2D::get_singleton()->agent_set_radius(agent, radius);
- NavigationServer2D::get_singleton()->agent_set_max_speed(agent, 0.0);
+ // Initialize the Agent as an object
+ NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
+ NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, 0);
+ NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, 0.0);
+ NavigationServer2D::get_singleton()->agent_set_radius(agent, radius);
+ NavigationServer2D::get_singleton()->agent_set_max_speed(agent, 0.0);
+ }
}
diff --git a/scene/2d/navigation_obstacle_2d.h b/scene/2d/navigation_obstacle_2d.h
index 421f8ca7cd..135ca4651e 100644
--- a/scene/2d/navigation_obstacle_2d.h
+++ b/scene/2d/navigation_obstacle_2d.h
@@ -31,15 +31,13 @@
#ifndef NAVIGATION_OBSTACLE_2D_H
#define NAVIGATION_OBSTACLE_2D_H
+#include "scene/2d/node_2d.h"
#include "scene/main/node.h"
-class Navigation2D;
-
class NavigationObstacle2D : public Node {
GDCLASS(NavigationObstacle2D, Node);
- Navigation2D *navigation = nullptr;
-
+ Node2D *parent_node2d = nullptr;
RID agent;
protected:
@@ -50,14 +48,6 @@ public:
NavigationObstacle2D();
virtual ~NavigationObstacle2D();
- void set_navigation(Navigation2D *p_nav);
- const Navigation2D *get_navigation() const {
- return navigation;
- }
-
- void set_navigation_node(Node *p_nav);
- Node *get_navigation_node() const;
-
RID get_rid() const {
return agent;
}
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index 7360fce330..8be8c8db4a 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -34,7 +34,6 @@
#include "core/core_string_names.h"
#include "core/math/geometry_2d.h"
#include "core/os/mutex.h"
-#include "navigation_2d.h"
#include "servers/navigation_server_2d.h"
#include "thirdparty/misc/polypartition.h"
@@ -365,10 +364,10 @@ void NavigationRegion2D::set_enabled(bool p_enabled) {
if (!enabled) {
NavigationServer2D::get_singleton()->region_set_map(region, RID());
+ NavigationServer2D::get_singleton()->disconnect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
} else {
- if (navigation) {
- NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid());
- }
+ NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
+ NavigationServer2D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
}
if (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) {
@@ -380,6 +379,14 @@ bool NavigationRegion2D::is_enabled() const {
return enabled;
}
+void NavigationRegion2D::set_layers(uint32_t p_layers) {
+ NavigationServer2D::get_singleton()->region_set_layers(region, p_layers);
+}
+
+uint32_t NavigationRegion2D::get_layers() const {
+ return NavigationServer2D::get_singleton()->region_get_layers(region);
+}
+
/////////////////////////////
#ifdef TOOLS_ENABLED
Rect2 NavigationRegion2D::_edit_get_rect() const {
@@ -394,35 +401,24 @@ bool NavigationRegion2D::_edit_is_selected_on_click(const Point2 &p_point, doubl
void NavigationRegion2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- Node2D *c = this;
- while (c) {
- navigation = Object::cast_to<Navigation2D>(c);
- if (navigation) {
- if (enabled) {
- NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid());
- }
- break;
- }
-
- c = Object::cast_to<Node2D>(c->get_parent());
+ if (enabled) {
+ NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
+ NavigationServer2D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
}
-
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
NavigationServer2D::get_singleton()->region_set_transform(region, get_global_transform());
-
} break;
case NOTIFICATION_EXIT_TREE: {
- if (navigation) {
- NavigationServer2D::get_singleton()->region_set_map(region, RID());
+ NavigationServer2D::get_singleton()->region_set_map(region, RID());
+ if (enabled) {
+ NavigationServer2D::get_singleton()->disconnect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
}
- navigation = nullptr;
} break;
case NOTIFICATION_DRAW: {
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) && navpoly.is_valid()) {
Vector<Vector2> verts = navpoly->get_vertices();
- int vsize = verts.size();
- if (vsize < 3) {
+ if (verts.size() < 3) {
return;
}
@@ -432,33 +428,47 @@ void NavigationRegion2D::_notification(int p_what) {
} else {
color = get_tree()->get_debug_navigation_disabled_color();
}
- Vector<Color> colors;
- Vector<Vector2> vertices;
- vertices.resize(vsize);
- colors.resize(vsize);
- {
- const Vector2 *vr = verts.ptr();
- for (int i = 0; i < vsize; i++) {
- vertices.write[i] = vr[i];
- colors.write[i] = color;
- }
- }
+ Color doors_color = color.lightened(0.2);
- Vector<int> indices;
+ RandomPCG rand;
for (int i = 0; i < navpoly->get_polygon_count(); i++) {
+ // An array of vertices for this polygon.
Vector<int> polygon = navpoly->get_polygon(i);
-
- for (int j = 2; j < polygon.size(); j++) {
- int kofs[3] = { 0, j - 1, j };
- for (int k = 0; k < 3; k++) {
- int idx = polygon[kofs[k]];
- ERR_FAIL_INDEX(idx, vsize);
- indices.push_back(idx);
- }
+ Vector<Vector2> vertices;
+ vertices.resize(polygon.size());
+ for (int j = 0; j < polygon.size(); j++) {
+ ERR_FAIL_INDEX(polygon[j], verts.size());
+ vertices.write[j] = verts[polygon[j]];
}
+
+ // Generate the polygon color, slightly randomly modified from the settings one.
+ Color random_variation_color;
+ random_variation_color.set_hsv(color.get_h() + rand.random(-1.0, 1.0) * 0.05, color.get_s(), color.get_v() + rand.random(-1.0, 1.0) * 0.1);
+ random_variation_color.a = color.a;
+ Vector<Color> colors;
+ colors.push_back(random_variation_color);
+
+ RS::get_singleton()->canvas_item_add_polygon(get_canvas_item(), vertices, colors);
+ }
+
+ // Draw the region
+ Transform2D xform = get_global_transform();
+ const NavigationServer2D *ns = NavigationServer2D::get_singleton();
+ float radius = ns->map_get_edge_connection_margin(get_world_2d()->get_navigation_map()) / 2.0;
+ for (int i = 0; i < ns->region_get_connections_count(region); i++) {
+ // Two main points
+ Vector2 a = ns->region_get_connection_pathway_start(region, i);
+ a = xform.affine_inverse().xform(a);
+ Vector2 b = ns->region_get_connection_pathway_end(region, i);
+ b = xform.affine_inverse().xform(b);
+ draw_line(a, b, doors_color);
+
+ // Draw a circle to illustrate the margins.
+ float angle = (b - a).angle();
+ draw_arc(a, radius, angle + Math_PI / 2.0, angle - Math_PI / 2.0 + Math_TAU, 10, doors_color);
+ draw_arc(b, radius, angle - Math_PI / 2.0, angle + Math_PI / 2.0, 10, doors_color);
}
- RS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, vertices, colors);
}
} break;
}
@@ -481,7 +491,6 @@ void NavigationRegion2D::set_navigation_polygon(const Ref<NavigationPolygon> &p_
}
_navpoly_changed();
- _change_notify("navpoly");
update_configuration_warning();
}
@@ -494,6 +503,11 @@ void NavigationRegion2D::_navpoly_changed() {
update();
}
}
+void NavigationRegion2D::_map_changed(RID p_map) {
+ if (enabled && get_world_2d()->get_navigation_map() == p_map) {
+ update();
+ }
+}
String NavigationRegion2D::get_configuration_warning() const {
if (!is_visible_in_tree() || !is_inside_tree()) {
@@ -508,18 +522,8 @@ String NavigationRegion2D::get_configuration_warning() const {
}
warning += TTR("A NavigationPolygon resource must be set or created for this node to work. Please set a property or draw a polygon.");
}
- const Node2D *c = this;
- while (c) {
- if (Object::cast_to<Navigation2D>(c)) {
- return warning;
- }
- c = Object::cast_to<Node2D>(c->get_parent());
- }
- if (!warning.is_empty()) {
- warning += "\n\n";
- }
- return warning + TTR("NavigationRegion2D must be a child or grandchild to a Navigation2D node. It only provides navigation data.");
+ return warning;
}
void NavigationRegion2D::_bind_methods() {
@@ -529,10 +533,14 @@ void NavigationRegion2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion2D::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_layers", "layers"), &NavigationRegion2D::set_layers);
+ ClassDB::bind_method(D_METHOD("get_layers"), &NavigationRegion2D::get_layers);
+
ClassDB::bind_method(D_METHOD("_navpoly_changed"), &NavigationRegion2D::_navpoly_changed);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navpoly", 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, "layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_layers", "get_layers");
}
NavigationRegion2D::NavigationRegion2D() {
diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h
index 0b9a258a25..58f04599be 100644
--- a/scene/2d/navigation_region_2d.h
+++ b/scene/2d/navigation_region_2d.h
@@ -91,17 +91,15 @@ public:
~NavigationPolygon() {}
};
-class Navigation2D;
-
class NavigationRegion2D : public Node2D {
GDCLASS(NavigationRegion2D, Node2D);
bool enabled = true;
RID region;
- Navigation2D *navigation = nullptr;
Ref<NavigationPolygon> navpoly;
void _navpoly_changed();
+ void _map_changed(RID p_RID);
protected:
void _notification(int p_what);
@@ -116,6 +114,9 @@ public:
void set_enabled(bool p_enabled);
bool is_enabled() const;
+ void set_layers(uint32_t p_layers);
+ uint32_t get_layers() const;
+
void set_navigation_polygon(const Ref<NavigationPolygon> &p_navpoly);
Ref<NavigationPolygon> get_navigation_polygon() const;
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 70a4e3f0fb..8afc43ddc9 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -53,12 +53,6 @@ void Node2D::_edit_set_state(const Dictionary &p_state) {
skew = p_state["skew"];
_update_transform();
- _change_notify("rotation");
- _change_notify("rotation_degrees");
- _change_notify("scale");
- _change_notify("skew");
- _change_notify("skew_degrees");
- _change_notify("position");
}
void Node2D::_edit_set_position(const Point2 &p_position) {
@@ -77,14 +71,12 @@ Size2 Node2D::_edit_get_scale() const {
return _scale;
}
-void Node2D::_edit_set_rotation(float p_rotation) {
+void Node2D::_edit_set_rotation(real_t p_rotation) {
angle = p_rotation;
_update_transform();
- _change_notify("rotation");
- _change_notify("rotation_degrees");
}
-float Node2D::_edit_get_rotation() const {
+real_t Node2D::_edit_get_rotation() const {
return angle;
}
@@ -124,8 +116,6 @@ void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) {
_scale *= new_scale;
_update_transform();
- _change_notify("scale");
- _change_notify("position");
}
#endif
@@ -156,34 +146,29 @@ void Node2D::set_position(const Point2 &p_pos) {
}
pos = p_pos;
_update_transform();
- _change_notify("position");
}
-void Node2D::set_rotation(float p_radians) {
+void Node2D::set_rotation(real_t p_radians) {
if (_xform_dirty) {
((Node2D *)this)->_update_xform_values();
}
angle = p_radians;
_update_transform();
- _change_notify("rotation");
- _change_notify("rotation_degrees");
}
-void Node2D::set_skew(float p_radians) {
+void Node2D::set_skew(real_t p_radians) {
if (_xform_dirty) {
((Node2D *)this)->_update_xform_values();
}
skew = p_radians;
_update_transform();
- _change_notify("skew");
- _change_notify("skew_degrees");
}
-void Node2D::set_rotation_degrees(float p_degrees) {
+void Node2D::set_rotation_degrees(real_t p_degrees) {
set_rotation(Math::deg2rad(p_degrees));
}
-void Node2D::set_skew_degrees(float p_degrees) {
+void Node2D::set_skew_degrees(real_t p_degrees) {
set_skew(Math::deg2rad(p_degrees));
}
@@ -200,7 +185,6 @@ void Node2D::set_scale(const Size2 &p_scale) {
_scale.y = CMP_EPSILON;
}
_update_transform();
- _change_notify("scale");
}
Point2 Node2D::get_position() const {
@@ -210,7 +194,7 @@ Point2 Node2D::get_position() const {
return pos;
}
-float Node2D::get_rotation() const {
+real_t Node2D::get_rotation() const {
if (_xform_dirty) {
((Node2D *)this)->_update_xform_values();
}
@@ -218,7 +202,7 @@ float Node2D::get_rotation() const {
return angle;
}
-float Node2D::get_skew() const {
+real_t Node2D::get_skew() const {
if (_xform_dirty) {
((Node2D *)this)->_update_xform_values();
}
@@ -226,11 +210,11 @@ float Node2D::get_skew() const {
return skew;
}
-float Node2D::get_rotation_degrees() const {
+real_t Node2D::get_rotation_degrees() const {
return Math::rad2deg(get_rotation());
}
-float Node2D::get_skew_degrees() const {
+real_t Node2D::get_skew_degrees() const {
return Math::rad2deg(get_skew());
}
@@ -246,7 +230,7 @@ Transform2D Node2D::get_transform() const {
return _mat;
}
-void Node2D::rotate(float p_radians) {
+void Node2D::rotate(real_t p_radians) {
set_rotation(get_rotation() + p_radians);
}
@@ -262,7 +246,7 @@ void Node2D::apply_scale(const Size2 &p_amount) {
set_scale(get_scale() * p_amount);
}
-void Node2D::move_x(float p_delta, bool p_scaled) {
+void Node2D::move_x(real_t p_delta, bool p_scaled) {
Transform2D t = get_transform();
Vector2 m = t[0];
if (!p_scaled) {
@@ -271,7 +255,7 @@ void Node2D::move_x(float p_delta, bool p_scaled) {
set_position(t[2] + m * p_delta);
}
-void Node2D::move_y(float p_delta, bool p_scaled) {
+void Node2D::move_y(real_t p_delta, bool p_scaled) {
Transform2D t = get_transform();
Vector2 m = t[1];
if (!p_scaled) {
@@ -295,25 +279,25 @@ void Node2D::set_global_position(const Point2 &p_pos) {
}
}
-float Node2D::get_global_rotation() const {
+real_t Node2D::get_global_rotation() const {
return get_global_transform().get_rotation();
}
-void Node2D::set_global_rotation(float p_radians) {
+void Node2D::set_global_rotation(real_t p_radians) {
CanvasItem *pi = get_parent_item();
if (pi) {
- const float parent_global_rot = pi->get_global_transform().get_rotation();
+ const real_t parent_global_rot = pi->get_global_transform().get_rotation();
set_rotation(p_radians - parent_global_rot);
} else {
set_rotation(p_radians);
}
}
-float Node2D::get_global_rotation_degrees() const {
+real_t Node2D::get_global_rotation_degrees() const {
return Math::rad2deg(get_global_rotation());
}
-void Node2D::set_global_rotation_degrees(float p_degrees) {
+void Node2D::set_global_rotation_degrees(real_t p_degrees) {
set_global_rotation(Math::deg2rad(p_degrees));
}
@@ -358,7 +342,6 @@ void Node2D::set_z_index(int p_z) {
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);
- _change_notify("z_index");
}
void Node2D::set_z_as_relative(bool p_enabled) {
@@ -396,7 +379,7 @@ void Node2D::look_at(const Vector2 &p_pos) {
rotate(get_angle_to(p_pos));
}
-float Node2D::get_angle_to(const Vector2 &p_pos) const {
+real_t Node2D::get_angle_to(const Vector2 &p_pos) const {
return (to_local(p_pos) * get_scale()).angle();
}
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index a5ae5dae0e..358b7e6520 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -37,9 +37,9 @@ class Node2D : public CanvasItem {
GDCLASS(Node2D, CanvasItem);
Point2 pos;
- float angle = 0;
+ real_t angle = 0.0;
Size2 _scale = Vector2(1, 1);
- float skew = 0;
+ real_t skew = 0.0;
int z_index = 0;
bool z_relative = true;
@@ -65,51 +65,51 @@ public:
virtual void _edit_set_scale(const Size2 &p_scale) override;
virtual Size2 _edit_get_scale() const override;
- virtual void _edit_set_rotation(float p_rotation) override;
- virtual float _edit_get_rotation() const override;
+ virtual void _edit_set_rotation(real_t p_rotation) override;
+ virtual real_t _edit_get_rotation() const override;
virtual bool _edit_use_rotation() const override;
virtual void _edit_set_rect(const Rect2 &p_edit_rect) override;
#endif
void set_position(const Point2 &p_pos);
- void set_rotation(float p_radians);
- void set_rotation_degrees(float p_degrees);
- void set_skew(float p_radians);
- void set_skew_degrees(float p_radians);
+ void set_rotation(real_t p_radians);
+ void set_rotation_degrees(real_t p_degrees);
+ void set_skew(real_t p_radians);
+ void set_skew_degrees(real_t p_radians);
void set_scale(const Size2 &p_scale);
- void rotate(float p_radians);
- void move_x(float p_delta, bool p_scaled = false);
- void move_y(float p_delta, bool p_scaled = false);
+ void rotate(real_t p_radians);
+ void move_x(real_t p_delta, bool p_scaled = false);
+ void move_y(real_t p_delta, bool p_scaled = false);
void translate(const Vector2 &p_amount);
void global_translate(const Vector2 &p_amount);
void apply_scale(const Size2 &p_amount);
Point2 get_position() const;
- float get_rotation() const;
- float get_skew() const;
- float get_rotation_degrees() const;
- float get_skew_degrees() const;
+ real_t get_rotation() const;
+ real_t get_skew() const;
+ real_t get_rotation_degrees() const;
+ real_t get_skew_degrees() const;
Size2 get_scale() const;
Point2 get_global_position() const;
- float get_global_rotation() const;
- float get_global_rotation_degrees() const;
+ real_t get_global_rotation() const;
+ real_t get_global_rotation_degrees() const;
Size2 get_global_scale() const;
void set_transform(const Transform2D &p_transform);
void set_global_transform(const Transform2D &p_transform);
void set_global_position(const Point2 &p_pos);
- void set_global_rotation(float p_radians);
- void set_global_rotation_degrees(float p_degrees);
+ void set_global_rotation(real_t p_radians);
+ void set_global_rotation_degrees(real_t p_degrees);
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);
- float get_angle_to(const Vector2 &p_pos) const;
+ real_t get_angle_to(const Vector2 &p_pos) const;
Point2 to_local(Point2 p_global) const;
Point2 to_global(Point2 p_local) const;
diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp
index a35ffaa668..4870ae614b 100644
--- a/scene/2d/parallax_background.cpp
+++ b/scene/2d/parallax_background.cpp
@@ -51,11 +51,11 @@ void ParallaxBackground::_camera_moved(const Transform2D &p_transform, const Poi
set_scroll_offset(p_transform.get_origin());
}
-void ParallaxBackground::set_scroll_scale(float p_scale) {
+void ParallaxBackground::set_scroll_scale(real_t p_scale) {
scale = p_scale;
}
-float ParallaxBackground::get_scroll_scale() const {
+real_t ParallaxBackground::get_scroll_scale() const {
return scale;
}
@@ -185,9 +185,5 @@ void ParallaxBackground::_bind_methods() {
}
ParallaxBackground::ParallaxBackground() {
- scale = 1.0;
set_layer(-100); //behind all by default
-
- base_scale = Vector2(1, 1);
- ignore_camera_zoom = false;
}
diff --git a/scene/2d/parallax_background.h b/scene/2d/parallax_background.h
index 578e615be9..27134dab29 100644
--- a/scene/2d/parallax_background.h
+++ b/scene/2d/parallax_background.h
@@ -39,15 +39,15 @@ class ParallaxBackground : public CanvasLayer {
GDCLASS(ParallaxBackground, CanvasLayer);
Point2 offset;
- float scale;
+ real_t scale = 1.0;
Point2 base_offset;
- Point2 base_scale;
+ Point2 base_scale = Vector2(1, 1);
Point2 screen_offset;
String group_name;
Point2 limit_begin;
Point2 limit_end;
Point2 final_offset;
- bool ignore_camera_zoom;
+ bool ignore_camera_zoom = false;
void _update_scroll();
@@ -61,8 +61,8 @@ public:
void set_scroll_offset(const Point2 &p_ofs);
Point2 get_scroll_offset() const;
- void set_scroll_scale(float p_scale);
- float get_scroll_scale() const;
+ void set_scroll_scale(real_t p_scale);
+ real_t get_scroll_scale() const;
void set_scroll_base_offset(const Point2 &p_ofs);
Point2 get_scroll_base_offset() const;
diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp
index 129082cb91..725e858a43 100644
--- a/scene/2d/parallax_layer.cpp
+++ b/scene/2d/parallax_layer.cpp
@@ -39,7 +39,7 @@ void ParallaxLayer::set_motion_scale(const Size2 &p_scale) {
ParallaxBackground *pb = Object::cast_to<ParallaxBackground>(get_parent());
if (pb && is_inside_tree()) {
Vector2 ofs = pb->get_final_offset();
- float scale = pb->get_scroll_scale();
+ real_t scale = pb->get_scroll_scale();
set_base_offset_and_scale(ofs, scale, screen_offset);
}
}
@@ -54,7 +54,7 @@ void ParallaxLayer::set_motion_offset(const Size2 &p_offset) {
ParallaxBackground *pb = Object::cast_to<ParallaxBackground>(get_parent());
if (pb && is_inside_tree()) {
Vector2 ofs = pb->get_final_offset();
- float scale = pb->get_scroll_scale();
+ real_t scale = pb->get_scroll_scale();
set_base_offset_and_scale(ofs, scale, screen_offset);
}
}
@@ -107,7 +107,7 @@ void ParallaxLayer::_notification(int p_what) {
}
}
-void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, float p_scale, const Point2 &p_screen_offset) {
+void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, real_t p_scale, const Point2 &p_screen_offset) {
screen_offset = p_screen_offset;
if (!is_inside_tree()) {
@@ -163,5 +163,4 @@ void ParallaxLayer::_bind_methods() {
}
ParallaxLayer::ParallaxLayer() {
- motion_scale = Size2(1, 1);
}
diff --git a/scene/2d/parallax_layer.h b/scene/2d/parallax_layer.h
index b6895b0aca..e826e6da9c 100644
--- a/scene/2d/parallax_layer.h
+++ b/scene/2d/parallax_layer.h
@@ -38,7 +38,7 @@ class ParallaxLayer : public Node2D {
Point2 orig_offset;
Point2 orig_scale;
- Size2 motion_scale;
+ Size2 motion_scale = Size2(1, 1);
Vector2 motion_offset;
Vector2 mirroring;
void _update_mirroring();
@@ -59,7 +59,7 @@ public:
void set_mirroring(const Size2 &p_mirroring);
Size2 get_mirroring() const;
- void set_base_offset_and_scale(const Point2 &p_offset, float p_scale, const Point2 &p_screen_offset);
+ void set_base_offset_and_scale(const Point2 &p_offset, real_t p_scale, const Point2 &p_screen_offset);
virtual String get_configuration_warning() const override;
ParallaxLayer();
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index 41c91115ad..be160ee1dd 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -96,9 +96,9 @@ void Path2D::_notification(int p_what) {
}
#ifdef TOOLS_ENABLED
- const float line_width = 2 * EDSCALE;
+ const real_t line_width = 2 * EDSCALE;
#else
- const float line_width = 2;
+ const real_t line_width = 2;
#endif
const Color color = Color(0.5, 0.6, 1.0, 0.7);
@@ -164,14 +164,14 @@ void PathFollow2D::_update_transform() {
return;
}
- float path_length = c->get_baked_length();
+ real_t path_length = c->get_baked_length();
if (path_length == 0) {
return;
}
Vector2 pos = c->interpolate_baked(offset, cubic);
if (rotates) {
- float ahead = offset + lookahead;
+ real_t ahead = offset + lookahead;
if (loop && ahead >= path_length) {
// If our lookahead will loop, we need to check if the path is closed.
@@ -240,7 +240,7 @@ bool PathFollow2D::get_cubic_interpolation() const {
void PathFollow2D::_validate_property(PropertyInfo &property) const {
if (property.name == "offset") {
- float max = 10000;
+ real_t max = 10000.0;
if (path && path->get_curve().is_valid()) {
max = path->get_curve()->get_baked_length();
}
@@ -301,11 +301,11 @@ void PathFollow2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001"), "set_lookahead", "get_lookahead");
}
-void PathFollow2D::set_offset(float p_offset) {
+void PathFollow2D::set_offset(real_t p_offset) {
offset = p_offset;
if (path) {
if (path->get_curve().is_valid()) {
- float path_length = path->get_curve()->get_baked_length();
+ real_t path_length = path->get_curve()->get_baked_length();
if (loop) {
offset = Math::fposmod(offset, path_length);
@@ -319,43 +319,41 @@ void PathFollow2D::set_offset(float p_offset) {
_update_transform();
}
- _change_notify("offset");
- _change_notify("unit_offset");
}
-void PathFollow2D::set_h_offset(float p_h_offset) {
+void PathFollow2D::set_h_offset(real_t p_h_offset) {
h_offset = p_h_offset;
if (path) {
_update_transform();
}
}
-float PathFollow2D::get_h_offset() const {
+real_t PathFollow2D::get_h_offset() const {
return h_offset;
}
-void PathFollow2D::set_v_offset(float p_v_offset) {
+void PathFollow2D::set_v_offset(real_t p_v_offset) {
v_offset = p_v_offset;
if (path) {
_update_transform();
}
}
-float PathFollow2D::get_v_offset() const {
+real_t PathFollow2D::get_v_offset() const {
return v_offset;
}
-float PathFollow2D::get_offset() const {
+real_t PathFollow2D::get_offset() const {
return offset;
}
-void PathFollow2D::set_unit_offset(float p_unit_offset) {
+void PathFollow2D::set_unit_offset(real_t p_unit_offset) {
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
set_offset(p_unit_offset * path->get_curve()->get_baked_length());
}
}
-float PathFollow2D::get_unit_offset() const {
+real_t PathFollow2D::get_unit_offset() const {
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
return get_offset() / path->get_curve()->get_baked_length();
} else {
@@ -363,11 +361,11 @@ float PathFollow2D::get_unit_offset() const {
}
}
-void PathFollow2D::set_lookahead(float p_lookahead) {
+void PathFollow2D::set_lookahead(real_t p_lookahead) {
lookahead = p_lookahead;
}
-float PathFollow2D::get_lookahead() const {
+real_t PathFollow2D::get_lookahead() const {
return lookahead;
}
diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h
index 3c5e0e4180..671ab493c3 100644
--- a/scene/2d/path_2d.h
+++ b/scene/2d/path_2d.h
@@ -64,10 +64,10 @@ class PathFollow2D : public Node2D {
public:
private:
Path2D *path = nullptr;
- real_t offset = 0;
- real_t h_offset = 0;
- real_t v_offset = 0;
- real_t lookahead = 4;
+ real_t offset = 0.0;
+ real_t h_offset = 0.0;
+ real_t v_offset = 0.0;
+ real_t lookahead = 4.0;
bool cubic = true;
bool loop = true;
bool rotates = true;
@@ -81,20 +81,20 @@ protected:
static void _bind_methods();
public:
- void set_offset(float p_offset);
- float get_offset() const;
+ void set_offset(real_t p_offset);
+ real_t get_offset() const;
- void set_h_offset(float p_h_offset);
- float get_h_offset() const;
+ void set_h_offset(real_t p_h_offset);
+ real_t get_h_offset() const;
- void set_v_offset(float p_v_offset);
- float get_v_offset() const;
+ void set_v_offset(real_t p_v_offset);
+ real_t get_v_offset() const;
- void set_unit_offset(float p_unit_offset);
- float get_unit_offset() const;
+ void set_unit_offset(real_t p_unit_offset);
+ real_t get_unit_offset() const;
- void set_lookahead(float p_lookahead);
- float get_lookahead() const;
+ void set_lookahead(real_t p_lookahead);
+ real_t get_lookahead() const;
void set_loop(bool p_loop);
bool has_loop() const;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index ee625fb6f9..a615d96687 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -111,8 +111,6 @@ bool PhysicsBody2D::get_collision_layer_bit(int p_bit) const {
PhysicsBody2D::PhysicsBody2D(PhysicsServer2D::BodyMode p_mode) :
CollisionObject2D(PhysicsServer2D::get_singleton()->body_create(), false) {
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), p_mode);
- collision_layer = 1;
- collision_mask = 1;
set_pickable(false);
}
@@ -197,7 +195,6 @@ void StaticBody2D::_bind_methods() {
StaticBody2D::StaticBody2D() :
PhysicsBody2D(PhysicsServer2D::BODY_MODE_STATIC) {
- constant_angular_velocity = 0;
}
StaticBody2D::~StaticBody2D() {
@@ -320,8 +317,8 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
struct _RigidBody2DInOut {
ObjectID id;
- int shape;
- int local_shape;
+ int shape = 0;
+ int local_shape = 0;
};
bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, const Ref<PhysicsTestMotionResult2D> &p_result) {
@@ -414,13 +411,13 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
}
}
- //process remotions
+ //process removals
for (int i = 0; i < toremove_count; i++) {
_body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
}
- //process aditions
+ //process additions
for (int i = 0; i < toadd_count; i++) {
_body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
@@ -841,25 +838,6 @@ void RigidBody2D::_bind_methods() {
RigidBody2D::RigidBody2D() :
PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) {
- mode = MODE_RIGID;
-
- mass = 1;
-
- gravity_scale = 1;
- linear_damp = -1;
- angular_damp = -1;
-
- max_contacts_reported = 0;
- state = nullptr;
-
- angular_velocity = 0;
- sleeping = false;
- ccd_mode = CCD_MODE_DISABLED;
-
- custom_integrator = false;
- contact_monitor = nullptr;
- can_sleep = true;
-
PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
}
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index b2a4aed019..2dc853b23b 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -41,8 +41,8 @@ class KinematicCollision2D;
class PhysicsBody2D : public CollisionObject2D {
GDCLASS(PhysicsBody2D, CollisionObject2D);
- uint32_t collision_layer;
- uint32_t collision_mask;
+ uint32_t collision_layer = 1;
+ uint32_t collision_mask = 1;
protected:
void _notification(int p_what);
@@ -74,7 +74,7 @@ class StaticBody2D : public PhysicsBody2D {
GDCLASS(StaticBody2D, PhysicsBody2D);
Vector2 constant_linear_velocity;
- real_t constant_angular_velocity;
+ real_t constant_angular_velocity = 0.0;
Ref<PhysicsMaterial> physics_material_override;
@@ -116,30 +116,30 @@ public:
};
private:
- bool can_sleep;
- PhysicsDirectBodyState2D *state;
- Mode mode;
+ bool can_sleep = true;
+ PhysicsDirectBodyState2D *state = nullptr;
+ Mode mode = MODE_RIGID;
- real_t mass;
+ real_t mass = 1.0;
Ref<PhysicsMaterial> physics_material_override;
- real_t gravity_scale;
- real_t linear_damp;
- real_t angular_damp;
+ real_t gravity_scale = 1.0;
+ real_t linear_damp = -1.0;
+ real_t angular_damp = -1.0;
Vector2 linear_velocity;
- real_t angular_velocity;
- bool sleeping;
+ real_t angular_velocity = 0.0;
+ bool sleeping = false;
- int max_contacts_reported;
+ int max_contacts_reported = 0;
- bool custom_integrator;
+ bool custom_integrator = false;
- CCDMode ccd_mode;
+ CCDMode ccd_mode = CCD_MODE_DISABLED;
struct ShapePair {
- int body_shape;
- int local_shape;
- bool tagged;
+ int body_shape = 0;
+ int local_shape = 0;
+ bool tagged = false;
bool operator<(const ShapePair &p_sp) const {
if (body_shape == p_sp.body_shape) {
return local_shape < p_sp.local_shape;
@@ -160,16 +160,16 @@ private:
};
struct BodyState {
//int rc;
- bool in_scene;
+ bool in_scene = false;
VSet<ShapePair> shapes;
};
struct ContactMonitor {
- bool locked;
+ bool locked = false;
Map<ObjectID, BodyState> body_map;
};
- ContactMonitor *contact_monitor;
+ ContactMonitor *contact_monitor = nullptr;
void _body_enter_tree(ObjectID p_id);
void _body_exit_tree(ObjectID p_id);
@@ -268,11 +268,11 @@ public:
Vector2 collider_vel;
ObjectID collider;
RID collider_rid;
- int collider_shape;
+ int collider_shape = 0;
Variant collider_metadata;
Vector2 remainder;
Vector2 travel;
- int local_shape;
+ int local_shape = 0;
};
private:
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 82e1b7ac96..1a7038bb80 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -90,6 +90,12 @@ bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toler
}
#endif
+void Polygon2D::_validate_property(PropertyInfo &property) const {
+ if (!invert && property.name == "invert_border") {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+}
+
void Polygon2D::_skeleton_bone_setup_changed() {
update();
}
@@ -154,8 +160,8 @@ void Polygon2D::_notification(int p_what) {
if (invert) {
Rect2 bounds;
int highest_idx = -1;
- float highest_y = -1e20;
- float sum = 0;
+ real_t highest_y = -1e20;
+ real_t sum = 0.0;
for (int i = 0; i < len; i++) {
if (i == 0) {
@@ -273,7 +279,7 @@ void Polygon2D::_notification(int p_what) {
//normalize the weights
for (int i = 0; i < vc; i++) {
- float tw = 0;
+ real_t tw = 0.0;
for (int j = 0; j < 4; j++) {
tw += weightsw[i * 4 + j];
}
@@ -426,20 +432,20 @@ Vector2 Polygon2D::get_texture_offset() const {
return tex_ofs;
}
-void Polygon2D::set_texture_rotation(float p_rot) {
+void Polygon2D::set_texture_rotation(real_t p_rot) {
tex_rot = p_rot;
update();
}
-float Polygon2D::get_texture_rotation() const {
+real_t Polygon2D::get_texture_rotation() const {
return tex_rot;
}
-void Polygon2D::set_texture_rotation_degrees(float p_rot) {
+void Polygon2D::set_texture_rotation_degrees(real_t p_rot) {
set_texture_rotation(Math::deg2rad(p_rot));
}
-float Polygon2D::get_texture_rotation_degrees() const {
+real_t Polygon2D::get_texture_rotation_degrees() const {
return Math::rad2deg(get_texture_rotation());
}
@@ -455,6 +461,7 @@ Size2 Polygon2D::get_texture_scale() const {
void Polygon2D::set_invert(bool p_invert) {
invert = p_invert;
update();
+ notify_property_list_changed();
}
bool Polygon2D::get_invert() const {
@@ -470,12 +477,12 @@ bool Polygon2D::get_antialiased() const {
return antialiased;
}
-void Polygon2D::set_invert_border(float p_invert_border) {
+void Polygon2D::set_invert_border(real_t p_invert_border) {
invert_border = p_invert_border;
update();
}
-float Polygon2D::get_invert_border() const {
+real_t Polygon2D::get_invert_border() const {
return invert_border;
}
@@ -483,7 +490,6 @@ void Polygon2D::set_offset(const Vector2 &p_offset) {
offset = p_offset;
rect_cache_dirty = true;
update();
- _change_notify("offset");
}
Vector2 Polygon2D::get_offset() const {
@@ -649,13 +655,4 @@ void Polygon2D::_bind_methods() {
}
Polygon2D::Polygon2D() {
- invert = false;
- invert_border = 100;
- antialiased = false;
- tex_rot = 0;
- tex_tile = true;
- tex_scale = Vector2(1, 1);
- color = Color(1, 1, 1);
- rect_cache_dirty = true;
- internal_vertices = 0;
}
diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h
index cdb3052225..c207024a53 100644
--- a/scene/2d/polygon_2d.h
+++ b/scene/2d/polygon_2d.h
@@ -40,7 +40,7 @@ class Polygon2D : public Node2D {
Vector<Vector2> uv;
Vector<Color> vertex_colors;
Array polygons;
- int internal_vertices;
+ int internal_vertices = 0;
struct Bone {
NodePath path;
@@ -49,19 +49,19 @@ class Polygon2D : public Node2D {
Vector<Bone> bone_weights;
- Color color;
+ Color color = Color(1, 1, 1);
Ref<Texture2D> texture;
- Size2 tex_scale;
+ Size2 tex_scale = Vector2(1, 1);
Vector2 tex_ofs;
- bool tex_tile;
- float tex_rot;
- bool invert;
- float invert_border;
- bool antialiased;
+ bool tex_tile = true;
+ real_t tex_rot = 0.0;
+ bool invert = false;
+ real_t invert_border = 100.0;
+ bool antialiased = false;
Vector2 offset;
- mutable bool rect_cache_dirty;
+ mutable bool rect_cache_dirty = true;
mutable Rect2 item_rect;
NodePath skeleton;
@@ -75,6 +75,7 @@ class Polygon2D : public Node2D {
protected:
void _notification(int p_what);
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const override;
public:
#ifdef TOOLS_ENABLED
@@ -114,11 +115,11 @@ public:
void set_texture_offset(const Vector2 &p_offset);
Vector2 get_texture_offset() const;
- void set_texture_rotation(float p_rot);
- float get_texture_rotation() const;
+ void set_texture_rotation(real_t p_rot);
+ real_t get_texture_rotation() const;
- void set_texture_rotation_degrees(float p_rot);
- float get_texture_rotation_degrees() const;
+ void set_texture_rotation_degrees(real_t p_rot);
+ real_t get_texture_rotation_degrees() const;
void set_texture_scale(const Size2 &p_scale);
Size2 get_texture_scale() const;
@@ -129,8 +130,8 @@ public:
void set_antialiased(bool p_antialiased);
bool get_antialiased() const;
- void set_invert_border(float p_invert_border);
- float get_invert_border() const;
+ void set_invert_border(real_t p_invert_border);
+ real_t get_invert_border() const;
void set_offset(const Vector2 &p_offset);
Vector2 get_offset() const;
diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp
index ff7a0dbac3..5c7d65e3e0 100644
--- a/scene/2d/position_2d.cpp
+++ b/scene/2d/position_2d.cpp
@@ -33,10 +33,10 @@
#include "core/config/engine.h"
#include "scene/resources/texture.h"
-const float DEFAULT_GIZMO_EXTENTS = 10.0;
+const real_t DEFAULT_GIZMO_EXTENTS = 10.0;
void Position2D::_draw_cross() {
- float extents = get_gizmo_extents();
+ real_t extents = get_gizmo_extents();
// Colors taken from `axis_x_color` and `axis_y_color` (defined in `editor/editor_themes.cpp`)
draw_line(Point2(-extents, 0), Point2(+extents, 0), Color(0.96, 0.20, 0.32));
draw_line(Point2(0, -extents), Point2(0, +extents), Color(0.53, 0.84, 0.01));
@@ -44,7 +44,7 @@ void Position2D::_draw_cross() {
#ifdef TOOLS_ENABLED
Rect2 Position2D::_edit_get_rect() const {
- float extents = get_gizmo_extents();
+ real_t extents = get_gizmo_extents();
return Rect2(Point2(-extents, -extents), Size2(extents * 2, extents * 2));
}
@@ -70,7 +70,7 @@ void Position2D::_notification(int p_what) {
}
}
-void Position2D::set_gizmo_extents(float p_extents) {
+void Position2D::set_gizmo_extents(real_t p_extents) {
if (p_extents == DEFAULT_GIZMO_EXTENTS) {
set_meta("_gizmo_extents_", Variant());
} else {
@@ -80,7 +80,7 @@ void Position2D::set_gizmo_extents(float p_extents) {
update();
}
-float Position2D::get_gizmo_extents() const {
+real_t Position2D::get_gizmo_extents() const {
if (has_meta("_gizmo_extents_")) {
return get_meta("_gizmo_extents_");
} else {
diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h
index fcaef0e6a3..9ed622c8f6 100644
--- a/scene/2d/position_2d.h
+++ b/scene/2d/position_2d.h
@@ -48,8 +48,8 @@ public:
virtual bool _edit_use_rect() const override;
#endif
- void set_gizmo_extents(float p_extents);
- float get_gizmo_extents() const;
+ void set_gizmo_extents(real_t p_extents);
+ real_t get_gizmo_extents() const;
Position2D();
};
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp
index 2c4a549acf..50625a0f39 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/ray_cast_2d.cpp
@@ -159,30 +159,7 @@ void RayCast2D::_notification(int p_what) {
if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
break;
}
- Transform2D xf;
- xf.rotate(target_position.angle());
- xf.translate(Vector2(target_position.length(), 0));
-
- // Draw an arrow indicating where the RayCast is pointing to
- Color draw_col = get_tree()->get_debug_collisions_color();
- if (!enabled) {
- float g = draw_col.get_v();
- draw_col.r = g;
- draw_col.g = g;
- draw_col.b = g;
- }
- draw_line(Vector2(), target_position, draw_col, 2);
- Vector<Vector2> pts;
- float tsize = 8;
- pts.push_back(xf.xform(Vector2(tsize, 0)));
- pts.push_back(xf.xform(Vector2(0, Math_SQRT12 * tsize)));
- pts.push_back(xf.xform(Vector2(0, -Math_SQRT12 * tsize)));
- Vector<Color> cols;
- for (int i = 0; i < 3; i++) {
- cols.push_back(draw_col);
- }
-
- draw_primitive(pts, cols, Vector<Vector2>());
+ _draw_debug_shape();
} break;
@@ -212,7 +189,7 @@ void RayCast2D::_update_raycast_state() {
}
PhysicsDirectSpaceState2D::RayResult rr;
-
+ bool prev_collision_state = collided;
if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, collide_with_bodies, collide_with_areas)) {
collided = true;
against = rr.collider_id;
@@ -224,6 +201,48 @@ void RayCast2D::_update_raycast_state() {
against = ObjectID();
against_shape = 0;
}
+
+ if (prev_collision_state != collided) {
+ update();
+ }
+}
+
+void RayCast2D::_draw_debug_shape() {
+ Color draw_col = collided ? Color(1.0, 0.01, 0) : get_tree()->get_debug_collisions_color();
+ if (!enabled) {
+ float g = draw_col.get_v();
+ draw_col.r = g;
+ draw_col.g = g;
+ draw_col.b = g;
+ }
+
+ // Draw an arrow indicating where the RayCast is pointing to
+ const float max_arrow_size = 6;
+ const float line_width = 1.4;
+ bool no_line = target_position.length() < line_width;
+ float arrow_size = CLAMP(target_position.length() * 2 / 3, line_width, max_arrow_size);
+
+ if (no_line) {
+ arrow_size = target_position.length();
+ } else {
+ draw_line(Vector2(), target_position - target_position.normalized() * arrow_size, draw_col, line_width);
+ }
+
+ Transform2D xf;
+ xf.rotate(target_position.angle());
+ xf.translate(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
+
+ Vector<Vector2> pts;
+ pts.push_back(xf.xform(Vector2(arrow_size, 0)));
+ pts.push_back(xf.xform(Vector2(0, 0.5 * arrow_size)));
+ pts.push_back(xf.xform(Vector2(0, -0.5 * arrow_size)));
+
+ Vector<Color> cols;
+ for (int i = 0; i < 3; i++) {
+ cols.push_back(draw_col);
+ }
+
+ draw_primitive(pts, cols, Vector<Vector2>());
}
void RayCast2D::force_raycast_update() {
@@ -325,12 +344,4 @@ void RayCast2D::_bind_methods() {
}
RayCast2D::RayCast2D() {
- enabled = true;
- collided = false;
- against_shape = 0;
- collision_mask = 1;
- target_position = Vector2(0, 50);
- exclude_parent_body = true;
- collide_with_bodies = true;
- collide_with_areas = false;
}
diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h
index ff7a970ebf..984c6bda49 100644
--- a/scene/2d/ray_cast_2d.h
+++ b/scene/2d/ray_cast_2d.h
@@ -36,20 +36,22 @@
class RayCast2D : public Node2D {
GDCLASS(RayCast2D, Node2D);
- bool enabled;
- bool collided;
+ bool enabled = true;
+ bool collided = false;
ObjectID against;
- int against_shape;
+ int against_shape = 0;
Vector2 collision_point;
Vector2 collision_normal;
Set<RID> exclude;
- uint32_t collision_mask;
- bool exclude_parent_body;
+ uint32_t collision_mask = 1;
+ bool exclude_parent_body = true;
- Vector2 target_position;
+ Vector2 target_position = Vector2(0, 50);
- bool collide_with_areas;
- bool collide_with_bodies;
+ bool collide_with_areas = false;
+ bool collide_with_bodies = true;
+
+ void _draw_debug_shape();
protected:
void _notification(int p_what);
diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp
index 4ed4c3a8ff..f10714e28a 100644
--- a/scene/2d/remote_transform_2d.cpp
+++ b/scene/2d/remote_transform_2d.cpp
@@ -223,10 +223,5 @@ void RemoteTransform2D::_bind_methods() {
}
RemoteTransform2D::RemoteTransform2D() {
- use_global_coordinates = true;
- update_remote_position = true;
- update_remote_rotation = true;
- update_remote_scale = true;
-
set_notify_transform(true);
}
diff --git a/scene/2d/remote_transform_2d.h b/scene/2d/remote_transform_2d.h
index cb4bd37f1f..4a26d7b339 100644
--- a/scene/2d/remote_transform_2d.h
+++ b/scene/2d/remote_transform_2d.h
@@ -40,10 +40,10 @@ class RemoteTransform2D : public Node2D {
ObjectID cache;
- bool use_global_coordinates;
- bool update_remote_position;
- bool update_remote_rotation;
- bool update_remote_scale;
+ bool use_global_coordinates = true;
+ bool update_remote_position = true;
+ bool update_remote_rotation = true;
+ bool update_remote_scale = true;
void _update_remote();
void _update_cache();
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index bb5a309f65..2d19d254b1 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -119,11 +119,11 @@ void Bone2D::apply_rest() {
set_transform(rest);
}
-void Bone2D::set_default_length(float p_length) {
+void Bone2D::set_default_length(real_t p_length) {
default_length = p_length;
}
-float Bone2D::get_default_length() const {
+real_t Bone2D::get_default_length() const {
return default_length;
}
@@ -157,10 +157,6 @@ String Bone2D::get_configuration_warning() const {
}
Bone2D::Bone2D() {
- skeleton = nullptr;
- parent_bone = nullptr;
- skeleton_index = -1;
- default_length = 16;
set_notify_local_transform(true);
//this is a clever hack so the bone knows no rest has been set yet, allowing to show an error.
for (int i = 0; i < 3; i++) {
@@ -186,9 +182,9 @@ void Skeleton2D::_update_bone_setup() {
}
bone_setup_dirty = false;
- RS::get_singleton()->skeleton_allocate(skeleton, bones.size(), true);
+ RS::get_singleton()->skeleton_allocate_data(skeleton, bones.size(), true);
- bones.sort(); //sorty so they are always in the same order/index
+ bones.sort(); //sorting so that they are always in the same order/index
for (int i = 0; i < bones.size(); i++) {
bones.write[i].rest_inverse = bones[i].bone->get_skeleton_rest().affine_inverse(); //bind pose
@@ -293,9 +289,6 @@ void Skeleton2D::_bind_methods() {
}
Skeleton2D::Skeleton2D() {
- bone_setup_dirty = true;
- transform_dirty = true;
-
skeleton = RS::get_singleton()->skeleton_create();
set_notify_transform(true);
}
diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h
index 36b9e1b339..1f43ea742b 100644
--- a/scene/2d/skeleton_2d.h
+++ b/scene/2d/skeleton_2d.h
@@ -43,12 +43,12 @@ class Bone2D : public Node2D {
friend class AnimatedValuesBackup;
#endif
- Bone2D *parent_bone;
- Skeleton2D *skeleton;
+ Bone2D *parent_bone = nullptr;
+ Skeleton2D *skeleton = nullptr;
Transform2D rest;
- float default_length;
+ real_t default_length = 16.0;
- int skeleton_index;
+ int skeleton_index = -1;
protected:
void _notification(int p_what);
@@ -62,8 +62,8 @@ public:
String get_configuration_warning() const override;
- void set_default_length(float p_length);
- float get_default_length() const;
+ void set_default_length(real_t p_length);
+ real_t get_default_length() const;
int get_index_in_skeleton() const;
@@ -82,19 +82,19 @@ class Skeleton2D : public Node2D {
bool operator<(const Bone &p_bone) const {
return p_bone.bone->is_greater_than(bone);
}
- Bone2D *bone;
- int parent_index;
+ Bone2D *bone = nullptr;
+ int parent_index = 0;
Transform2D accum_transform;
Transform2D rest_inverse;
};
Vector<Bone> bones;
- bool bone_setup_dirty;
+ bool bone_setup_dirty = true;
void _make_bone_setup_dirty();
void _update_bone_setup();
- bool transform_dirty;
+ bool transform_dirty = true;
void _make_transform_dirty();
void _update_transform();
diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp
index 773214deeb..7c93edbff9 100644
--- a/scene/2d/sprite_2d.cpp
+++ b/scene/2d/sprite_2d.cpp
@@ -77,14 +77,14 @@ Rect2 Sprite2D::get_anchorable_rect() const {
return get_rect();
}
-void Sprite2D::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const {
+void Sprite2D::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip_enabled) const {
Rect2 base_rect;
- if (region) {
- r_filter_clip = region_filter_clip;
+ if (region_enabled) {
+ r_filter_clip_enabled = region_filter_clip_enabled;
base_rect = region_rect;
} else {
- r_filter_clip = false;
+ r_filter_clip_enabled = false;
base_rect = Rect2(0, 0, texture->get_width(), texture->get_height());
}
@@ -129,10 +129,10 @@ void Sprite2D::_notification(int p_what) {
*/
Rect2 src_rect, dst_rect;
- bool filter_clip;
- _get_rects(src_rect, dst_rect, filter_clip);
+ bool filter_clip_enabled;
+ _get_rects(src_rect, dst_rect, filter_clip_enabled);
- texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, filter_clip);
+ texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, filter_clip_enabled);
} break;
}
}
@@ -155,7 +155,6 @@ void Sprite2D::set_texture(const Ref<Texture2D> &p_texture) {
update();
emit_signal("texture_changed");
item_rect_changed();
- _change_notify("texture");
}
Ref<Texture2D> Sprite2D::get_texture() const {
@@ -176,7 +175,6 @@ void Sprite2D::set_offset(const Point2 &p_offset) {
offset = p_offset;
update();
item_rect_changed();
- _change_notify("offset");
}
Point2 Sprite2D::get_offset() const {
@@ -201,17 +199,18 @@ bool Sprite2D::is_flipped_v() const {
return vflip;
}
-void Sprite2D::set_region(bool p_region) {
- if (p_region == region) {
+void Sprite2D::set_region_enabled(bool p_region_enabled) {
+ if (p_region_enabled == region_enabled) {
return;
}
- region = p_region;
+ region_enabled = p_region_enabled;
update();
+ notify_property_list_changed();
}
-bool Sprite2D::is_region() const {
- return region;
+bool Sprite2D::is_region_enabled() const {
+ return region_enabled;
}
void Sprite2D::set_region_rect(const Rect2 &p_region_rect) {
@@ -221,24 +220,22 @@ void Sprite2D::set_region_rect(const Rect2 &p_region_rect) {
region_rect = p_region_rect;
- if (region) {
+ if (region_enabled) {
item_rect_changed();
}
-
- _change_notify("region_rect");
}
Rect2 Sprite2D::get_region_rect() const {
return region_rect;
}
-void Sprite2D::set_region_filter_clip(bool p_enable) {
- region_filter_clip = p_enable;
+void Sprite2D::set_region_filter_clip_enabled(bool p_region_filter_clip_enabled) {
+ region_filter_clip_enabled = p_region_filter_clip_enabled;
update();
}
bool Sprite2D::is_region_filter_clip_enabled() const {
- return region_filter_clip;
+ return region_filter_clip_enabled;
}
void Sprite2D::set_frame(int p_frame) {
@@ -250,8 +247,6 @@ void Sprite2D::set_frame(int p_frame) {
frame = p_frame;
- _change_notify("frame");
- _change_notify("frame_coords");
emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
@@ -275,7 +270,7 @@ void Sprite2D::set_vframes(int p_amount) {
vframes = p_amount;
update();
item_rect_changed();
- _change_notify();
+ notify_property_list_changed();
}
int Sprite2D::get_vframes() const {
@@ -287,7 +282,7 @@ void Sprite2D::set_hframes(int p_amount) {
hframes = p_amount;
update();
item_rect_changed();
- _change_notify();
+ notify_property_list_changed();
}
int Sprite2D::get_hframes() const {
@@ -304,8 +299,8 @@ bool Sprite2D::is_pixel_opaque(const Point2 &p_point) const {
}
Rect2 src_rect, dst_rect;
- bool filter_clip;
- _get_rects(src_rect, dst_rect, filter_clip);
+ bool filter_clip_enabled;
+ _get_rects(src_rect, dst_rect, filter_clip_enabled);
dst_rect.size = dst_rect.size.abs();
if (!dst_rect.has_point(p_point)) {
@@ -355,7 +350,7 @@ Rect2 Sprite2D::get_rect() const {
Size2i s;
- if (region) {
+ if (region_enabled) {
s = region_rect.size;
} else {
s = texture->get_size();
@@ -389,6 +384,10 @@ void Sprite2D::_validate_property(PropertyInfo &property) const {
if (property.name == "frame_coords") {
property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS;
}
+
+ if (!region_enabled && (property.name == "region_rect" || property.name == "region_filter_clip")) {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
}
void Sprite2D::_texture_changed() {
@@ -415,15 +414,15 @@ void Sprite2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flip_v", "flip_v"), &Sprite2D::set_flip_v);
ClassDB::bind_method(D_METHOD("is_flipped_v"), &Sprite2D::is_flipped_v);
- ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite2D::set_region);
- ClassDB::bind_method(D_METHOD("is_region"), &Sprite2D::is_region);
+ ClassDB::bind_method(D_METHOD("set_region_enabled", "enabled"), &Sprite2D::set_region_enabled);
+ ClassDB::bind_method(D_METHOD("is_region_enabled"), &Sprite2D::is_region_enabled);
ClassDB::bind_method(D_METHOD("is_pixel_opaque", "pos"), &Sprite2D::is_pixel_opaque);
ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite2D::set_region_rect);
ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite2D::get_region_rect);
- ClassDB::bind_method(D_METHOD("set_region_filter_clip", "enabled"), &Sprite2D::set_region_filter_clip);
+ ClassDB::bind_method(D_METHOD("set_region_filter_clip_enabled", "enabled"), &Sprite2D::set_region_filter_clip_enabled);
ClassDB::bind_method(D_METHOD("is_region_filter_clip_enabled"), &Sprite2D::is_region_filter_clip_enabled);
ClassDB::bind_method(D_METHOD("set_frame", "frame"), &Sprite2D::set_frame);
@@ -456,22 +455,12 @@ void Sprite2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
ADD_GROUP("Region", "region_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_filter_clip"), "set_region_filter_clip", "is_region_filter_clip_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_filter_clip_enabled"), "set_region_filter_clip_enabled", "is_region_filter_clip_enabled");
}
Sprite2D::Sprite2D() {
- centered = true;
- hflip = false;
- vflip = false;
- region = false;
- region_filter_clip = false;
-
- frame = 0;
-
- vframes = 1;
- hframes = 1;
}
Sprite2D::~Sprite2D() {
diff --git a/scene/2d/sprite_2d.h b/scene/2d/sprite_2d.h
index 716882d485..9db74cfe26 100644
--- a/scene/2d/sprite_2d.h
+++ b/scene/2d/sprite_2d.h
@@ -39,23 +39,23 @@ class Sprite2D : public Node2D {
Ref<Texture2D> texture;
Color specular_color;
- float shininess;
+ real_t shininess = 0.0;
- bool centered;
+ bool centered = true;
Point2 offset;
- bool hflip;
- bool vflip;
- bool region;
+ bool hflip = false;
+ bool vflip = false;
+ bool region_enabled = false;
Rect2 region_rect;
- bool region_filter_clip;
+ bool region_filter_clip_enabled = false;
- int frame;
+ int frame = 0;
- int vframes;
- int hframes;
+ int vframes = 1;
+ int hframes = 1;
- void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const;
+ void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip_enabled) const;
void _texture_changed();
@@ -97,10 +97,10 @@ public:
void set_flip_v(bool p_flip);
bool is_flipped_v() const;
- void set_region(bool p_region);
- bool is_region() const;
+ void set_region_enabled(bool p_enabled);
+ bool is_region_enabled() const;
- void set_region_filter_clip(bool p_enable);
+ void set_region_filter_clip_enabled(bool p_enabled);
bool is_region_filter_clip_enabled() const;
void set_region_rect(const Rect2 &p_region_rect);
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 01b7a9c260..81a5b0b28c 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -48,16 +48,6 @@ int TileMap::_get_quadrant_size() const {
void TileMap::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- Node2D *c = this;
- while (c) {
- navigation = Object::cast_to<Navigation2D>(c);
- if (navigation) {
- break;
- }
-
- c = Object::cast_to<Node2D>(c->get_parent());
- }
-
if (use_parent) {
_clear_quadrants();
collision_parent = Object::cast_to<CollisionObject2D>(get_parent());
@@ -77,12 +67,10 @@ void TileMap::_notification(int p_what) {
_update_quadrant_space(RID());
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
Quadrant &q = E->get();
- if (navigation) {
- for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) {
- NavigationServer2D::get_singleton()->region_set_map(F->get().region, RID());
- }
- q.navpoly_ids.clear();
+ for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) {
+ NavigationServer2D::get_singleton()->region_set_map(F->get().region, RID());
}
+ q.navpoly_ids.clear();
if (collision_parent) {
collision_parent->remove_shape_owner(q.shape_owner_id);
@@ -96,8 +84,6 @@ void TileMap::_notification(int p_what) {
}
collision_parent = nullptr;
- navigation = nullptr;
-
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -135,11 +121,6 @@ void TileMap::_update_quadrant_transform() {
local_transform = get_transform();
}
- Transform2D nav_rel;
- if (navigation) {
- nav_rel = get_relative_transform_to_parent(navigation);
- }
-
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
Quadrant &q = E->get();
Transform2D xform;
@@ -150,9 +131,9 @@ void TileMap::_update_quadrant_transform() {
PhysicsServer2D::get_singleton()->body_set_state(q.body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
}
- if (navigation) {
+ if (bake_navigation) {
for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) {
- NavigationServer2D::get_singleton()->region_set_transform(F->get().region, nav_rel * F->get().xform);
+ NavigationServer2D::get_singleton()->region_set_transform(F->get().region, F->get().xform);
}
}
@@ -165,7 +146,6 @@ void TileMap::_update_quadrant_transform() {
void TileMap::set_tileset(const Ref<TileSet> &p_tileset) {
if (tile_set.is_valid()) {
tile_set->disconnect("changed", callable_mp(this, &TileMap::_recreate_quadrants));
- tile_set->remove_change_receptor(this);
}
_clear_quadrants();
@@ -173,7 +153,6 @@ void TileMap::set_tileset(const Ref<TileSet> &p_tileset) {
if (tile_set.is_valid()) {
tile_set->connect("changed", callable_mp(this, &TileMap::_recreate_quadrants));
- tile_set->add_change_receptor(this);
} else {
clear();
}
@@ -317,11 +296,6 @@ void TileMap::update_dirty_quadrants() {
RenderingServer *vs = RenderingServer::get_singleton();
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
Vector2 tofs = get_cell_draw_offset();
- Transform2D nav_rel;
- if (navigation) {
- nav_rel = get_relative_transform_to_parent(navigation);
- }
-
Vector2 qofs;
SceneTree *st = SceneTree::get_singleton();
@@ -354,12 +328,10 @@ void TileMap::update_dirty_quadrants() {
}
int shape_idx = 0;
- if (navigation) {
- for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) {
- NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID());
- }
- q.navpoly_ids.clear();
+ for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) {
+ NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID());
}
+ q.navpoly_ids.clear();
for (Map<PosKey, Quadrant::Occluder>::Element *E = q.occluder_instances.front(); E; E = E->next()) {
RS::get_singleton()->free(E->get().id);
@@ -581,7 +553,7 @@ void TileMap::update_dirty_quadrants() {
vs->canvas_item_add_set_transform(debug_canvas_item, Transform2D());
}
- if (navigation) {
+ if (bake_navigation) {
Ref<NavigationPolygon> navpoly;
Vector2 npoly_ofs;
if (tile_set->tile_get_tile_mode(c.id) == TileSet::AUTO_TILE || tile_set->tile_get_tile_mode(c.id) == TileSet::ATLAS_TILE) {
@@ -598,8 +570,8 @@ void TileMap::update_dirty_quadrants() {
_fix_cell_transform(xform, c, npoly_ofs, s);
RID region = NavigationServer2D::get_singleton()->region_create();
- NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid());
- NavigationServer2D::get_singleton()->region_set_transform(region, nav_rel * xform);
+ NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
+ NavigationServer2D::get_singleton()->region_set_transform(region, xform);
NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly);
Quadrant::NavPoly np;
@@ -789,12 +761,10 @@ void TileMap::_erase_quadrant(Map<PosKey, Quadrant>::Element *Q) {
dirty_quadrant_list.remove(&q.dirty_list);
}
- if (navigation) {
- for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) {
- NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID());
- }
- q.navpoly_ids.clear();
+ for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) {
+ NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID());
}
+ q.navpoly_ids.clear();
for (Map<PosKey, Quadrant::Occluder>::Element *E = q.occluder_instances.front(); E; E = E->next()) {
RS::get_singleton()->free(E->get().id);
@@ -1330,7 +1300,7 @@ void TileMap::set_collision_use_parent(bool p_use_parent) {
}
_recreate_quadrants();
- _change_notify();
+ notify_property_list_changed();
update_configuration_warning();
}
@@ -1362,6 +1332,17 @@ float TileMap::get_collision_bounce() const {
return bounce;
}
+void TileMap::set_bake_navigation(bool p_bake_navigation) {
+ bake_navigation = p_bake_navigation;
+ for (Map<PosKey, Quadrant>::Element *F = quadrant_map.front(); F; F = F->next()) {
+ _make_quadrant_dirty(F);
+ }
+}
+
+bool TileMap::is_baking_navigation() {
+ return bake_navigation;
+}
+
uint32_t TileMap::get_collision_layer() const {
return collision_layer;
}
@@ -1786,6 +1767,9 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_bounce", "value"), &TileMap::set_collision_bounce);
ClassDB::bind_method(D_METHOD("get_collision_bounce"), &TileMap::get_collision_bounce);
+ ClassDB::bind_method(D_METHOD("set_bake_navigation", "bake_navigation"), &TileMap::set_bake_navigation);
+ ClassDB::bind_method(D_METHOD("is_baking_navigation"), &TileMap::is_baking_navigation);
+
ClassDB::bind_method(D_METHOD("set_occluder_light_mask", "mask"), &TileMap::set_occluder_light_mask);
ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &TileMap::get_occluder_light_mask);
@@ -1844,6 +1828,9 @@ void TileMap::_bind_methods() {
ADD_GROUP("Occluder", "occluder_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "occluder_light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_occluder_light_mask", "get_occluder_light_mask");
+ ADD_GROUP("Navigation", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_navigation"), "set_bake_navigation", "is_baking_navigation");
+
ADD_PROPERTY_DEFAULT("format", FORMAT_1);
ADD_SIGNAL(MethodInfo("settings_changed"));
@@ -1865,47 +1852,11 @@ void TileMap::_bind_methods() {
BIND_ENUM_CONSTANT(TILE_ORIGIN_BOTTOM_LEFT);
}
-void TileMap::_changed_callback(Object *p_changed, const char *p_prop) {
- if (tile_set.is_valid() && tile_set.ptr() == p_changed) {
- emit_signal("settings_changed");
- }
-}
-
TileMap::TileMap() {
- rect_cache_dirty = true;
- used_size_cache_dirty = true;
- pending_update = false;
- quadrant_order_dirty = false;
- quadrant_size = 16;
- cell_size = Size2(64, 64);
- custom_transform = Transform2D(64, 0, 0, 64, 0, 0);
- collision_layer = 1;
- collision_mask = 1;
- friction = 1;
- bounce = 0;
- mode = MODE_SQUARE;
- half_offset = HALF_OFFSET_DISABLED;
- use_parent = false;
- collision_parent = nullptr;
- use_kinematic = false;
- navigation = nullptr;
- use_y_sort = false;
- compatibility_mode = false;
- centered_textures = false;
- occluder_light_mask = 1;
- clip_uv = false;
- format = FORMAT_1; // Assume lowest possible format if none is present
-
- fp_adjust = 0.00001;
- tile_origin = TILE_ORIGIN_TOP_LEFT;
set_notify_transform(true);
set_notify_local_transform(false);
}
TileMap::~TileMap() {
- if (tile_set.is_valid()) {
- tile_set->remove_change_receptor(this);
- }
-
clear();
}
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index b1e54aafae..26c84a0bb9 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -33,7 +33,6 @@
#include "core/templates/self_list.h"
#include "core/templates/vset.h"
-#include "scene/2d/navigation_2d.h"
#include "scene/2d/node_2d.h"
#include "scene/resources/tile_set.h"
@@ -70,22 +69,22 @@ private:
};
Ref<TileSet> tile_set;
- Size2i cell_size;
- int quadrant_size;
- Mode mode;
- Transform2D custom_transform;
- HalfOffset half_offset;
- bool use_parent;
- CollisionObject2D *collision_parent;
- bool use_kinematic;
- Navigation2D *navigation;
+ Size2i cell_size = Size2(64, 64);
+ int quadrant_size = 16;
+ Mode mode = MODE_SQUARE;
+ Transform2D custom_transform = Transform2D(64, 0, 0, 64, 0, 0);
+ HalfOffset half_offset = HALF_OFFSET_DISABLED;
+ bool use_parent = false;
+ CollisionObject2D *collision_parent = nullptr;
+ bool use_kinematic = false;
+ bool bake_navigation = false;
union PosKey {
struct {
int16_t x;
int16_t y;
};
- uint32_t key;
+ uint32_t key = 0;
//using a more precise comparison so the regions can be sorted later
bool operator<(const PosKey &p_k) const { return (y == p_k.y) ? x < p_k.x : y < p_k.y; }
@@ -119,8 +118,7 @@ private:
int16_t autotile_coord_y : 16;
};
- uint64_t _u64t;
- Cell() { _u64t = 0; }
+ uint64_t _u64t = 0;
};
Map<PosKey, Cell> tile_map;
@@ -130,7 +128,7 @@ private:
Vector2 pos;
List<RID> canvas_items;
RID body;
- uint32_t shape_owner_id;
+ uint32_t shape_owner_id = 0;
SelfList<Quadrant> dirty_list;
@@ -176,27 +174,27 @@ private:
SelfList<Quadrant>::List dirty_quadrant_list;
- bool pending_update;
+ bool pending_update = false;
Rect2 rect_cache;
- bool rect_cache_dirty;
+ bool rect_cache_dirty = true;
Rect2 used_size_cache;
- bool used_size_cache_dirty;
- bool quadrant_order_dirty;
- bool use_y_sort;
- bool compatibility_mode;
- bool centered_textures;
- bool clip_uv;
- float fp_adjust;
- float friction;
- float bounce;
- uint32_t collision_layer;
- uint32_t collision_mask;
- mutable DataFormat format;
-
- TileOrigin tile_origin;
-
- int occluder_light_mask;
+ bool used_size_cache_dirty = true;
+ bool quadrant_order_dirty = false;
+ bool use_y_sort = false;
+ bool compatibility_mode = false;
+ bool centered_textures = false;
+ bool clip_uv = false;
+ float fp_adjust = 0.00001;
+ float friction = 1.0;
+ float bounce = 0.0;
+ uint32_t collision_layer = 1;
+ uint32_t collision_mask = 1;
+ mutable DataFormat format = FORMAT_1; // Assume lowest possible format if none is present
+
+ TileOrigin tile_origin = TILE_ORIGIN_TOP_LEFT;
+
+ int occluder_light_mask = 1;
void _fix_cell_transform(Transform2D &xform, const Cell &p_cell, const Vector2 &p_offset, const Size2 &p_sc);
@@ -233,7 +231,6 @@ protected:
static void _bind_methods();
virtual void _validate_property(PropertyInfo &property) const override;
- virtual void _changed_callback(Object *p_changed, const char *p_prop) override;
public:
enum {
@@ -297,6 +294,9 @@ public:
void set_collision_bounce(float p_bounce);
float get_collision_bounce() const;
+ void set_bake_navigation(bool p_bake_navigation);
+ bool is_baking_navigation();
+
void set_mode(Mode p_mode);
Mode get_mode() const;
diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp
index 04a1aedcd3..9d6868a1b2 100644
--- a/scene/2d/touch_screen_button.cpp
+++ b/scene/2d/touch_screen_button.cpp
@@ -129,8 +129,11 @@ void TouchScreenButton::_notification(int p_what) {
if (shape.is_valid()) {
Color draw_col = get_tree()->get_debug_collisions_color();
- Vector2 size = texture.is_null() ? shape->get_rect().size : texture->get_size();
- Vector2 pos = shape_centered ? size * 0.5f : Vector2();
+ Vector2 pos;
+ if (shape_centered && texture.is_valid()) {
+ pos = texture->get_size() * 0.5;
+ }
+
draw_set_transform_matrix(get_canvas_transform().translated(pos));
shape->draw(get_canvas_item(), draw_col);
}
@@ -251,9 +254,12 @@ bool TouchScreenButton::_is_point_inside(const Point2 &p_point) {
if (shape.is_valid()) {
check_rect = false;
- Vector2 size = texture.is_null() ? shape->get_rect().size : texture->get_size();
- Transform2D xform = shape_centered ? Transform2D().translated(size * 0.5f) : Transform2D();
- touched = shape->collide(xform, unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5)));
+ Vector2 pos;
+ if (shape_centered && texture.is_valid()) {
+ pos = texture->get_size() * 0.5;
+ }
+
+ touched = shape->collide(Transform2D().translated(pos), unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5)));
}
if (bitmask.is_valid()) {
@@ -399,11 +405,6 @@ void TouchScreenButton::_bind_methods() {
}
TouchScreenButton::TouchScreenButton() {
- finger_pressed = -1;
- passby_press = false;
- visibility = VISIBILITY_ALWAYS;
- shape_centered = true;
- shape_visible = true;
unit_rect = Ref<RectangleShape2D>(memnew(RectangleShape2D));
unit_rect->set_size(Vector2(1, 1));
}
diff --git a/scene/2d/touch_screen_button.h b/scene/2d/touch_screen_button.h
index f4ae3ca26c..10820ad059 100644
--- a/scene/2d/touch_screen_button.h
+++ b/scene/2d/touch_screen_button.h
@@ -50,16 +50,16 @@ private:
Ref<Texture2D> texture_pressed;
Ref<BitMap> bitmask;
Ref<Shape2D> shape;
- bool shape_centered;
- bool shape_visible;
+ bool shape_centered = true;
+ bool shape_visible = true;
Ref<RectangleShape2D> unit_rect;
StringName action;
- bool passby_press;
- int finger_pressed;
+ bool passby_press = false;
+ int finger_pressed = -1;
- VisibilityMode visibility;
+ VisibilityMode visibility = VISIBILITY_ALWAYS;
void _input(const Ref<InputEvent> &p_event);
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index f3dddd5af8..916038a1f3 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -89,8 +89,6 @@ void VisibilityNotifier2D::set_rect(const Rect2 &p_rect) {
item_rect_changed();
}
}
-
- _change_notify("rect");
}
Rect2 VisibilityNotifier2D::get_rect() const {
@@ -363,6 +361,4 @@ VisibilityEnabler2D::VisibilityEnabler2D() {
}
enabler[ENABLER_PARENT_PROCESS] = false;
enabler[ENABLER_PARENT_PHYSICS_PROCESS] = false;
-
- visible = false;
}
diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h
index ea3b5df37b..3d1701a1e5 100644
--- a/scene/2d/visibility_notifier_2d.h
+++ b/scene/2d/visibility_notifier_2d.h
@@ -85,7 +85,7 @@ protected:
virtual void _screen_enter() override;
virtual void _screen_exit() override;
- bool visible;
+ bool visible = false;
void _find_nodes(Node *p_node);
diff --git a/scene/2d/y_sort.cpp b/scene/2d/y_sort.cpp
index 987e4581f4..7e7bc27cc2 100644
--- a/scene/2d/y_sort.cpp
+++ b/scene/2d/y_sort.cpp
@@ -48,6 +48,5 @@ void YSort::_bind_methods() {
}
YSort::YSort() {
- sort_enabled = true;
RS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), true);
}
diff --git a/scene/2d/y_sort.h b/scene/2d/y_sort.h
index 0882a88e3a..7d36ee3391 100644
--- a/scene/2d/y_sort.h
+++ b/scene/2d/y_sort.h
@@ -35,7 +35,7 @@
class YSort : public Node2D {
GDCLASS(YSort, Node2D);
- bool sort_enabled;
+ bool sort_enabled = true;
static void _bind_methods();
public:
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp
index 36312482cd..749cf4ff9d 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -211,7 +211,7 @@ void Area3D::_clear_monitoring() {
Object *obj = ObjectDB::get_instance(E->key());
Node *node = Object::cast_to<Node>(obj);
- if (!node) { //node may have been deleted in previous frame or at other legiminate point
+ if (!node) { //node may have been deleted in previous frame or at other legitimate point
continue;
}
//ERR_CONTINUE(!node);
@@ -240,7 +240,7 @@ void Area3D::_clear_monitoring() {
Object *obj = ObjectDB::get_instance(E->key());
Node *node = Object::cast_to<Node>(obj);
- if (!node) { //node may have been deleted in previous frame or at other legiminate point
+ if (!node) { //node may have been deleted in previous frame or at other legitimate point
continue;
}
//ERR_CONTINUE(!node);
@@ -640,10 +640,10 @@ void Area3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area3D::set_reverb_uniformity);
ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area3D::get_reverb_uniformity);
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
+ ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
@@ -681,29 +681,10 @@ void Area3D::_bind_methods() {
Area3D::Area3D() :
CollisionObject3D(PhysicsServer3D::get_singleton()->area_create(), true) {
- space_override = SPACE_OVERRIDE_DISABLED;
set_gravity(9.8);
- locked = false;
set_gravity_vector(Vector3(0, -1, 0));
- gravity_is_point = false;
- gravity_distance_scale = 0;
- linear_damp = 0.1;
- angular_damp = 0.1;
- priority = 0;
- monitoring = false;
- monitorable = false;
- collision_mask = 1;
- collision_layer = 1;
set_monitoring(true);
set_monitorable(true);
-
- audio_bus_override = false;
- audio_bus = "Master";
-
- use_reverb_bus = false;
- reverb_bus = "Master";
- reverb_amount = 0.0;
- reverb_uniformity = 0.0;
}
Area3D::~Area3D() {
diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h
index 5d8e1933ba..6d976115f7 100644
--- a/scene/3d/area_3d.h
+++ b/scene/3d/area_3d.h
@@ -47,19 +47,19 @@ public:
};
private:
- SpaceOverride space_override;
+ SpaceOverride space_override = SPACE_OVERRIDE_DISABLED;
Vector3 gravity_vec;
real_t gravity;
- bool gravity_is_point;
- real_t gravity_distance_scale;
- real_t angular_damp;
- real_t linear_damp;
- uint32_t collision_mask;
- uint32_t collision_layer;
- int priority;
- bool monitoring;
- bool monitorable;
- bool locked;
+ bool gravity_is_point = false;
+ real_t gravity_distance_scale = 0.0;
+ real_t angular_damp = 0.1;
+ real_t linear_damp = 0.1;
+ uint32_t collision_mask = 1;
+ uint32_t collision_layer = 1;
+ int priority = 0;
+ bool monitoring = false;
+ bool monitorable = false;
+ bool locked = false;
void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape);
@@ -67,8 +67,8 @@ private:
void _body_exit_tree(ObjectID p_id);
struct ShapePair {
- int body_shape;
- int area_shape;
+ int body_shape = 0;
+ int area_shape = 0;
bool operator<(const ShapePair &p_sp) const {
if (body_shape == p_sp.body_shape) {
return area_shape < p_sp.area_shape;
@@ -85,8 +85,8 @@ private:
};
struct BodyState {
- int rc;
- bool in_tree;
+ int rc = 0;
+ bool in_tree = false;
VSet<ShapePair> shapes;
};
@@ -98,8 +98,8 @@ private:
void _area_exit_tree(ObjectID p_id);
struct AreaShapePair {
- int area_shape;
- int self_shape;
+ int area_shape = 0;
+ int self_shape = 0;
bool operator<(const AreaShapePair &p_sp) const {
if (area_shape == p_sp.area_shape) {
return self_shape < p_sp.self_shape;
@@ -116,21 +116,21 @@ private:
};
struct AreaState {
- int rc;
- bool in_tree;
+ int rc = 0;
+ bool in_tree = false;
VSet<AreaShapePair> shapes;
};
Map<ObjectID, AreaState> area_map;
void _clear_monitoring();
- bool audio_bus_override;
- StringName audio_bus;
+ bool audio_bus_override = false;
+ StringName audio_bus = "Master";
- bool use_reverb_bus;
- StringName reverb_bus;
- float reverb_amount;
- float reverb_uniformity;
+ bool use_reverb_bus = false;
+ StringName reverb_bus = "Master";
+ float reverb_amount = 0.0;
+ float reverb_uniformity = 0.0;
void _validate_property(PropertyInfo &property) const override;
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 2bcf898ced..72392be5bd 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -42,8 +42,8 @@ class Spcap {
private:
struct Speaker {
Vector3 direction;
- real_t effective_number_of_speakers; // precalculated
- mutable real_t squared_gain; // temporary
+ real_t effective_number_of_speakers = 0; // precalculated
+ mutable real_t squared_gain = 0; // temporary
};
Vector<Speaker> speakers;
@@ -138,15 +138,15 @@ void AudioStreamPlayer3D::_calc_output_vol(const Vector3 &source_dir, real_t tig
}
void AudioStreamPlayer3D::_mix_audio() {
- if (!stream_playback.is_valid() || !active ||
+ if (!stream_playback.is_valid() || !active.is_set() ||
(stream_paused && !stream_paused_fade_out)) {
return;
}
bool started = false;
- if (setseek >= 0.0) {
- stream_playback->start(setseek);
- setseek = -1.0; //reset seek
+ if (setseek.get() >= 0.0) {
+ stream_playback->start(setseek.get());
+ setseek.set(-1.0); //reset seek
started = true;
}
@@ -160,14 +160,14 @@ void AudioStreamPlayer3D::_mix_audio() {
}
// Mix if we're not paused or we're fading out
- if ((output_count > 0 || out_of_range_mode == OUT_OF_RANGE_MIX)) {
+ if ((output_count.get() > 0 || out_of_range_mode == OUT_OF_RANGE_MIX)) {
float output_pitch_scale = 0.0;
- if (output_count) {
+ if (output_count.get()) {
//used for doppler, not realistic but good enough
- for (int i = 0; i < output_count; i++) {
+ for (int i = 0; i < output_count.get(); i++) {
output_pitch_scale += outputs[i].pitch_scale;
}
- output_pitch_scale /= float(output_count);
+ output_pitch_scale /= float(output_count.get());
} else {
output_pitch_scale = 1.0;
}
@@ -176,7 +176,7 @@ void AudioStreamPlayer3D::_mix_audio() {
}
//write all outputs
- for (int i = 0; i < output_count; i++) {
+ for (int i = 0; i < output_count.get(); i++) {
Output current = outputs[i];
//see if current output exists, to keep volume ramp
@@ -285,14 +285,14 @@ void AudioStreamPlayer3D::_mix_audio() {
prev_outputs[i] = current;
}
- prev_output_count = output_count;
+ prev_output_count = output_count.get();
//stream is no longer active, disable this.
if (!stream_playback->is_playing()) {
- active = false;
+ active.clear();
}
- output_ready = false;
+ output_ready.clear();
stream_paused_fade_in = false;
stream_paused_fade_out = false;
}
@@ -360,7 +360,7 @@ void AudioStreamPlayer3D::_notification(int p_what) {
if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
//update anything related to position first, if possible of course
- if (!output_ready) {
+ if (!output_ready.is_set()) {
Vector3 linear_velocity;
//compute linear velocity for doppler
@@ -596,24 +596,20 @@ void AudioStreamPlayer3D::_notification(int p_what) {
}
}
- output_count = new_output_count;
- output_ready = true;
+ output_count.set(new_output_count);
+ output_ready.set();
}
//start playing if requested
- if (setplay >= 0.0) {
- setseek = setplay;
- active = true;
- setplay = -1;
- //do not update, this makes it easier to animate (will shut off otherwise)
- ///_change_notify("playing"); //update property in editor
+ if (setplay.get() >= 0.0) {
+ setseek.set(setplay.get());
+ active.set();
+ setplay.set(-1);
}
//stop playing if no longer active
- if (!active) {
+ if (!active.is_set()) {
set_physics_process_internal(false);
- //do not update, this makes it easier to animate (will shut off otherwise)
- //_change_notify("playing"); //update property in editor
emit_signal("finished");
}
}
@@ -627,8 +623,8 @@ void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) {
if (stream_playback.is_valid()) {
stream_playback.unref();
stream.unref();
- active = false;
- setseek = -1;
+ active.clear();
+ setseek.set(-1);
}
if (p_stream.is_valid()) {
@@ -687,30 +683,29 @@ void AudioStreamPlayer3D::play(float p_from_pos) {
}
if (stream_playback.is_valid()) {
- active = true;
- setplay = p_from_pos;
- output_ready = false;
+ setplay.set(p_from_pos);
+ output_ready.clear();
set_physics_process_internal(true);
}
}
void AudioStreamPlayer3D::seek(float p_seconds) {
if (stream_playback.is_valid()) {
- setseek = p_seconds;
+ setseek.set(p_seconds);
}
}
void AudioStreamPlayer3D::stop() {
if (stream_playback.is_valid()) {
- active = false;
+ active.clear();
set_physics_process_internal(false);
- setplay = -1;
+ setplay.set(-1);
}
}
bool AudioStreamPlayer3D::is_playing() const {
if (stream_playback.is_valid()) {
- return active; // && stream_playback->is_playing();
+ return active.is_set() || setplay.get() >= 0;
}
return false;
@@ -718,6 +713,10 @@ bool AudioStreamPlayer3D::is_playing() const {
float AudioStreamPlayer3D::get_playback_position() {
if (stream_playback.is_valid()) {
+ float ss = setseek.get();
+ if (ss >= 0.0) {
+ return ss;
+ }
return stream_playback->get_playback_position();
}
@@ -757,7 +756,7 @@ void AudioStreamPlayer3D::_set_playing(bool p_enable) {
}
bool AudioStreamPlayer3D::_is_active() const {
- return active;
+ return active.is_set();
}
void AudioStreamPlayer3D::_validate_property(PropertyInfo &property) const {
@@ -776,7 +775,7 @@ void AudioStreamPlayer3D::_validate_property(PropertyInfo &property) const {
}
void AudioStreamPlayer3D::_bus_layout_changed() {
- _change_notify();
+ notify_property_list_changed();
}
void AudioStreamPlayer3D::set_max_distance(float p_metres) {
@@ -809,7 +808,6 @@ void AudioStreamPlayer3D::set_emission_angle(float p_angle) {
ERR_FAIL_COND(p_angle < 0 || p_angle > 90);
emission_angle = p_angle;
update_gizmo();
- _change_notify("emission_angle");
}
float AudioStreamPlayer3D::get_emission_angle() const {
@@ -1002,31 +1000,6 @@ void AudioStreamPlayer3D::_bind_methods() {
}
AudioStreamPlayer3D::AudioStreamPlayer3D() {
- unit_db = 0;
- unit_size = 1;
- attenuation_model = ATTENUATION_INVERSE_DISTANCE;
- max_db = 3;
- pitch_scale = 1.0;
- autoplay = false;
- setseek = -1;
- active = false;
- output_count = 0;
- prev_output_count = 0;
- max_distance = 0;
- setplay = -1;
- output_ready = false;
- area_mask = 1;
- emission_angle = 45;
- emission_angle_enabled = false;
- emission_angle_filter_attenuation_db = -12;
- attenuation_filter_cutoff_hz = 5000;
- attenuation_filter_db = -24;
- out_of_range_mode = OUT_OF_RANGE_MIX;
- doppler_tracking = DOPPLER_TRACKING_DISABLED;
- stream_paused = false;
- stream_paused_fade_in = false;
- stream_paused_fade_out = false;
-
velocity_tracker.instance();
AudioServer::get_singleton()->connect("bus_layout_changed", callable_mp(this, &AudioStreamPlayer3D::_bus_layout_changed));
set_disable_scale(true);
diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h
index bcfe2b2229..70c535bd89 100644
--- a/scene/3d/audio_stream_player_3d.h
+++ b/scene/3d/audio_stream_player_3d.h
@@ -31,6 +31,7 @@
#ifndef AUDIO_STREAM_PLAYER_3D_H
#define AUDIO_STREAM_PLAYER_3D_H
+#include "core/templates/safe_refcount.h"
#include "scene/3d/node_3d.h"
#include "scene/3d/velocity_tracker_3d.h"
#include "servers/audio/audio_filter_sw.h"
@@ -71,46 +72,39 @@ private:
AudioFilterSW filter;
AudioFilterSW::Processor filter_process[8];
AudioFrame vol[4];
- float filter_gain;
- float pitch_scale;
- int bus_index;
- int reverb_bus_index;
+ float filter_gain = 0.0;
+ float pitch_scale = 0.0;
+ int bus_index = -1;
+ int reverb_bus_index = -1;
AudioFrame reverb_vol[4];
- Viewport *viewport; //pointer only used for reference to previous mix
-
- Output() {
- filter_gain = 0;
- viewport = nullptr;
- reverb_bus_index = -1;
- bus_index = -1;
- }
+ Viewport *viewport = nullptr; //pointer only used for reference to previous mix
};
Output outputs[MAX_OUTPUTS];
- volatile int output_count;
- volatile bool output_ready;
+ SafeNumeric<int> output_count;
+ SafeFlag output_ready;
//these are used by audio thread to have a reference of previous volumes (for ramping volume and avoiding clicks)
Output prev_outputs[MAX_OUTPUTS];
- int prev_output_count;
+ int prev_output_count = 0;
Ref<AudioStreamPlayback> stream_playback;
Ref<AudioStream> stream;
Vector<AudioFrame> mix_buffer;
- volatile float setseek;
- volatile bool active;
- volatile float setplay;
-
- AttenuationModel attenuation_model;
- float unit_db;
- float unit_size;
- float max_db;
- float pitch_scale;
- bool autoplay;
- bool stream_paused;
- bool stream_paused_fade_in;
- bool stream_paused_fade_out;
+ SafeNumeric<float> setseek{ -1.0 };
+ SafeFlag active;
+ SafeNumeric<float> setplay{ -1.0 };
+
+ AttenuationModel attenuation_model = ATTENUATION_INVERSE_DISTANCE;
+ float unit_db = 0.0;
+ float unit_size = 1.0;
+ float max_db = 3.0;
+ float pitch_scale = 1.0;
+ bool autoplay = false;
+ bool stream_paused = false;
+ bool stream_paused_fade_in = false;
+ bool stream_paused_fade_out = false;
StringName bus;
static void _calc_output_vol(const Vector3 &source_dir, real_t tightness, Output &output);
@@ -122,21 +116,21 @@ private:
void _bus_layout_changed();
- uint32_t area_mask;
+ uint32_t area_mask = 1;
- bool emission_angle_enabled;
- float emission_angle;
- float emission_angle_filter_attenuation_db;
- float attenuation_filter_cutoff_hz;
- float attenuation_filter_db;
+ bool emission_angle_enabled = false;
+ float emission_angle = 45.0;
+ float emission_angle_filter_attenuation_db = -12.0;
+ float attenuation_filter_cutoff_hz = 5000.0;
+ float attenuation_filter_db = -24.0;
- float max_distance;
+ float max_distance = 0.0;
Ref<VelocityTracker3D> velocity_tracker;
- DopplerTracking doppler_tracking;
+ DopplerTracking doppler_tracking = DOPPLER_TRACKING_DISABLED;
- OutOfRangeMode out_of_range_mode;
+ OutOfRangeMode out_of_range_mode = OUT_OF_RANGE_MIX;
float _get_attenuation_db(float p_distance) const;
diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp
index 14c8755d99..95ffbe48c1 100644
--- a/scene/3d/baked_lightmap.cpp
+++ b/scene/3d/baked_lightmap.cpp
@@ -78,6 +78,7 @@ void BakedLightmapData::clear_users() {
}
void BakedLightmapData::_set_user_data(const Array &p_data) {
+ ERR_FAIL_COND(p_data.size() <= 0);
ERR_FAIL_COND((p_data.size() % 4) != 0);
for (int i = 0; i < p_data.size(); i += 4) {
@@ -195,7 +196,7 @@ void BakedLightmapData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &BakedLightmapData::set_uses_spherical_harmonics);
ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &BakedLightmapData::is_using_spherical_harmonics);
- ClassDB::bind_method(D_METHOD("add_user", "path", "lightmap", "offset"), &BakedLightmapData::add_user);
+ ClassDB::bind_method(D_METHOD("add_user", "path", "uv_scale", "slice_index", "sub_instance"), &BakedLightmapData::add_user);
ClassDB::bind_method(D_METHOD("get_user_count"), &BakedLightmapData::get_user_count);
ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &BakedLightmapData::get_user_path);
ClassDB::bind_method(D_METHOD("clear_users"), &BakedLightmapData::clear_users);
@@ -448,7 +449,7 @@ int32_t BakedLightmap::_compute_bsp_tree(const Vector<Vector3> &p_points, const
ERR_FAIL_COND_V(p_simplex_indices.size() <= 1, 0); //should not happen, this is a bug
// Failed to separate the tetrahedrons using planes
- // this means Delaunay borked at some point.
+ // this means Delaunay broke at some point.
// Luckily, because we are using tetrahedrons, we can resort to
// less precise but still working ways to generate the separating plane
// this will most likely look bad when interpolating, but at least it will not crash.
@@ -510,7 +511,7 @@ int32_t BakedLightmap::_compute_bsp_tree(const Vector<Vector3> &p_points, const
node.plane = best_plane;
if (indices_under.size() == 0) {
- //noting to do here
+ //nothing to do here
node.under = BSPNode::EMPTY_LEAF;
} else if (indices_under.size() == 1) {
node.under = -(indices_under[0] + 1);
@@ -519,7 +520,7 @@ int32_t BakedLightmap::_compute_bsp_tree(const Vector<Vector3> &p_points, const
}
if (indices_over.size() == 0) {
- //noting to do here
+ //nothing to do here
node.over = BSPNode::EMPTY_LEAF;
} else if (indices_over.size() == 1) {
node.over = -(indices_over[0] + 1);
@@ -659,7 +660,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_d
}
// create mesh data for insert
- //get the base material textures, help compute altlas size and bounds
+ //get the base material textures, help compute atlas size and bounds
for (int m_i = 0; m_i < meshes_found.size(); m_i++) {
if (p_bake_step) {
float p = (float)(m_i) / meshes_found.size();
@@ -973,7 +974,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_d
for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) {
images.push_back(lightmapper->get_bake_texture(i));
}
- //we assume they are all the same, so lets create a large one for saving
+ //we assume they are all the same, so let's create a large one for saving
Ref<Image> large_image;
large_image.instance();
@@ -1302,7 +1303,7 @@ bool BakedLightmap::is_interior() const {
void BakedLightmap::set_environment_mode(EnvironmentMode p_mode) {
environment_mode = p_mode;
- _change_notify();
+ notify_property_list_changed();
}
BakedLightmap::EnvironmentMode BakedLightmap::get_environment_mode() const {
@@ -1466,17 +1467,4 @@ void BakedLightmap::_bind_methods() {
}
BakedLightmap::BakedLightmap() {
- environment_mode = ENVIRONMENT_MODE_DISABLED;
- environment_custom_color = Color(0.2, 0.7, 1.0);
- environment_custom_energy = 1.0;
-
- bake_quality = BAKE_QUALITY_MEDIUM;
- interior = false;
- directional = false;
-
- gen_probes = GENERATE_PROBES_DISABLED;
- use_denoiser = true;
- bounces = 1;
- bias = 0.0005;
- max_texture_size = 16384;
}
diff --git a/scene/3d/baked_lightmap.h b/scene/3d/baked_lightmap.h
index 7fd1cf892e..e2d89ab2d0 100644
--- a/scene/3d/baked_lightmap.h
+++ b/scene/3d/baked_lightmap.h
@@ -53,9 +53,9 @@ class BakedLightmapData : public Resource {
struct User {
NodePath path;
- int32_t sub_instance;
+ int32_t sub_instance = 0;
Rect2 uv_scale;
- int slice_index;
+ int slice_index = 0;
};
Vector<User> users;
@@ -136,32 +136,32 @@ public:
};
private:
- BakeQuality bake_quality;
- bool use_denoiser;
- int bounces;
- float bias;
- int max_texture_size;
- bool interior;
- EnvironmentMode environment_mode;
+ BakeQuality bake_quality = BAKE_QUALITY_MEDIUM;
+ bool use_denoiser = true;
+ int bounces = 1;
+ float bias = 0.0005;
+ int max_texture_size = 16384;
+ bool interior = false;
+ EnvironmentMode environment_mode = ENVIRONMENT_MODE_DISABLED;
Ref<Sky> environment_custom_sky;
- Color environment_custom_color;
- float environment_custom_energy;
- bool directional;
- GenerateProbes gen_probes;
+ Color environment_custom_color = Color(0.2, 0.7, 1.0);
+ float environment_custom_energy = 1.0;
+ bool directional = false;
+ GenerateProbes gen_probes = GENERATE_PROBES_DISABLED;
Ref<BakedLightmapData> light_data;
struct LightsFound {
Transform xform;
- Light3D *light;
+ Light3D *light = nullptr;
};
struct MeshesFound {
Transform xform;
NodePath node_path;
- int32_t subindex;
+ int32_t subindex = 0;
Ref<Mesh> mesh;
- int32_t lightmap_scale;
+ int32_t lightmap_scale = 0;
Vector<Ref<Material>> overrides;
};
@@ -172,19 +172,20 @@ private:
struct BakeTimeData {
String text;
- int pass;
- uint64_t last_step;
+ int pass = 0;
+ uint64_t last_step = 0;
};
struct BSPSimplex {
- int vertices[4];
- int planes[4];
+ int vertices[4] = {};
+ int planes[4] = {};
};
struct BSPNode {
static const int32_t EMPTY_LEAF = INT32_MIN;
Plane plane;
- int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
+ int32_t over = EMPTY_LEAF;
+ int32_t under = EMPTY_LEAF;
};
int _bsp_get_simplex_side(const Vector<Vector3> &p_points, const LocalVector<BSPSimplex> &p_simplices, const Plane &p_plane, uint32_t p_simplex) const;
@@ -192,16 +193,16 @@ private:
struct BakeStepUD {
Lightmapper::BakeStepFunc func;
- void *ud;
- float from_percent;
- float to_percent;
+ void *ud = nullptr;
+ float from_percent = 0.0;
+ float to_percent = 0.0;
};
static bool _lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh);
struct GenProbesOctree {
Vector3i offset;
- uint32_t size;
+ uint32_t size = 0;
GenProbesOctree *children[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
~GenProbesOctree() {
for (int i = 0; i < 8; i++) {
diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp
index 30fe1ecea8..5315e685a0 100644
--- a/scene/3d/bone_attachment_3d.cpp
+++ b/scene/3d/bone_attachment_3d.cpp
@@ -105,7 +105,6 @@ void BoneAttachment3D::_notification(int p_what) {
}
BoneAttachment3D::BoneAttachment3D() {
- bound = false;
}
void BoneAttachment3D::_bind_methods() {
diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h
index 0dddaa1028..0c6d5f12b1 100644
--- a/scene/3d/bone_attachment_3d.h
+++ b/scene/3d/bone_attachment_3d.h
@@ -36,7 +36,7 @@
class BoneAttachment3D : public Node3D {
GDCLASS(BoneAttachment3D, Node3D);
- bool bound;
+ bool bound = false;
String bone_name;
void _check_bind();
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 53c3204b3e..cd8d02233b 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -102,7 +102,7 @@ void Camera3D::_update_camera() {
void Camera3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_WORLD: {
- // Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD
+ // Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD
// and Spatial will handle it first, including clearing its reference to the Viewport,
// therefore making it impossible to subclasses to access it
viewport = get_viewport();
@@ -209,7 +209,7 @@ void Camera3D::set_projection(Camera3D::Projection p_mode) {
if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM) {
mode = p_mode;
_update_camera_mode();
- _change_notify();
+ notify_property_list_changed();
}
}
@@ -432,7 +432,7 @@ void Camera3D::set_keep_aspect_mode(KeepAspect p_aspect) {
keep_aspect = p_aspect;
RenderingServer::get_singleton()->camera_set_use_vertical_aspect(camera, p_aspect == KEEP_WIDTH);
_update_camera_mode();
- _change_notify();
+ notify_property_list_changed();
}
Camera3D::KeepAspect Camera3D::get_keep_aspect_mode() const {
@@ -562,14 +562,12 @@ void Camera3D::set_fov(float p_fov) {
ERR_FAIL_COND(p_fov < 1 || p_fov > 179);
fov = p_fov;
_update_camera_mode();
- _change_notify("fov");
}
void Camera3D::set_size(float p_size) {
ERR_FAIL_COND(p_size < 0.1 || p_size > 16384);
size = p_size;
_update_camera_mode();
- _change_notify("size");
}
void Camera3D::set_near(float p_near) {
@@ -653,24 +651,10 @@ Vector3 Camera3D::get_doppler_tracked_velocity() const {
Camera3D::Camera3D() {
camera = RenderingServer::get_singleton()->camera_create();
- size = 1;
- fov = 0;
- frustum_offset = Vector2();
- near = 0;
- far = 0;
- current = false;
- viewport = nullptr;
- force_change = false;
- mode = PROJECTION_PERSPECTIVE;
set_perspective(75.0, 0.05, 4000.0);
- keep_aspect = KEEP_HEIGHT;
- layers = 0xfffff;
- v_offset = 0;
- h_offset = 0;
RenderingServer::get_singleton()->camera_set_cull_mask(camera, layers);
//active=false;
velocity_tracker.instance();
- doppler_tracking = DOPPLER_TRACKING_DISABLED;
set_notify_transform(true);
set_disable_scale(true);
}
@@ -689,17 +673,17 @@ float ClippedCamera3D::get_margin() const {
return margin;
}
-void ClippedCamera3D::set_process_mode(ProcessMode p_mode) {
- if (process_mode == p_mode) {
+void ClippedCamera3D::set_process_callback(ClipProcessCallback p_mode) {
+ if (process_callback == p_mode) {
return;
}
- process_mode = p_mode;
- set_process_internal(process_mode == CLIP_PROCESS_IDLE);
- set_physics_process_internal(process_mode == CLIP_PROCESS_PHYSICS);
+ process_callback = p_mode;
+ set_process_internal(process_callback == CLIP_PROCESS_IDLE);
+ set_physics_process_internal(process_callback == CLIP_PROCESS_PHYSICS);
}
-ClippedCamera3D::ProcessMode ClippedCamera3D::get_process_mode() const {
- return process_mode;
+ClippedCamera3D::ClipProcessCallback ClippedCamera3D::get_process_callback() const {
+ return process_callback;
}
Transform ClippedCamera3D::get_camera_transform() const {
@@ -731,7 +715,7 @@ void ClippedCamera3D::_notification(int p_what) {
Vector3 ray_from = parent_plane.project(cam_pos);
- clip_offset = 0; //reset by defau;t
+ clip_offset = 0; //reset by default
{ //check if points changed
Vector<Vector3> local_points = get_near_plane_points();
@@ -844,8 +828,8 @@ void ClippedCamera3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_margin", "margin"), &ClippedCamera3D::set_margin);
ClassDB::bind_method(D_METHOD("get_margin"), &ClippedCamera3D::get_margin);
- ClassDB::bind_method(D_METHOD("set_process_mode", "process_mode"), &ClippedCamera3D::set_process_mode);
- ClassDB::bind_method(D_METHOD("get_process_mode"), &ClippedCamera3D::get_process_mode);
+ ClassDB::bind_method(D_METHOD("set_process_callback", "process_callback"), &ClippedCamera3D::set_process_callback);
+ ClassDB::bind_method(D_METHOD("get_process_callback"), &ClippedCamera3D::get_process_callback);
ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &ClippedCamera3D::set_collision_mask);
ClassDB::bind_method(D_METHOD("get_collision_mask"), &ClippedCamera3D::get_collision_mask);
@@ -870,7 +854,7 @@ void ClippedCamera3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_exceptions"), &ClippedCamera3D::clear_exceptions);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_margin", "get_margin");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_mode", "get_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_callback", "get_process_callback");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_GROUP("Clip To", "clip_to");
@@ -882,16 +866,10 @@ void ClippedCamera3D::_bind_methods() {
}
ClippedCamera3D::ClippedCamera3D() {
- margin = 0;
- clip_offset = 0;
- process_mode = CLIP_PROCESS_PHYSICS;
set_physics_process_internal(true);
- collision_mask = 1;
set_notify_local_transform(Engine::get_singleton()->is_editor_hint());
points.resize(5);
pyramid_shape = PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CONVEX_POLYGON);
- clip_to_areas = false;
- clip_to_bodies = true;
}
ClippedCamera3D::~ClippedCamera3D() {
diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h
index aa36c8800d..cea61e4db8 100644
--- a/scene/3d/camera_3d.h
+++ b/scene/3d/camera_3d.h
@@ -57,26 +57,27 @@ public:
};
private:
- bool force_change;
- bool current;
- Viewport *viewport;
+ bool force_change = false;
+ bool current = false;
+ Viewport *viewport = nullptr;
- Projection mode;
+ Projection mode = PROJECTION_PERSPECTIVE;
- float fov;
- float size;
+ float fov = 0.0;
+ float size = 1.0;
Vector2 frustum_offset;
- float near, far;
- float v_offset;
- float h_offset;
- KeepAspect keep_aspect;
+ float near = 0.0;
+ float far = 0.0;
+ float v_offset = 0.0;
+ float h_offset = 0.0;
+ KeepAspect keep_aspect = KEEP_HEIGHT;
RID camera;
RID scenario_id;
// String camera_group;
- uint32_t layers;
+ uint32_t layers = 0xfffff;
Ref<Environment> environment;
Ref<CameraEffects> effects;
@@ -87,7 +88,7 @@ private:
friend class Viewport;
void _update_audio_listener_state();
- DopplerTracking doppler_tracking;
+ DopplerTracking doppler_tracking = DOPPLER_TRACKING_DISABLED;
Ref<VelocityTracker3D> velocity_tracker;
protected:
@@ -185,19 +186,19 @@ class ClippedCamera3D : public Camera3D {
GDCLASS(ClippedCamera3D, Camera3D);
public:
- enum ProcessMode {
+ enum ClipProcessCallback {
CLIP_PROCESS_PHYSICS,
CLIP_PROCESS_IDLE,
};
private:
- ProcessMode process_mode;
+ ClipProcessCallback process_callback = CLIP_PROCESS_PHYSICS;
RID pyramid_shape;
- float margin;
- float clip_offset;
- uint32_t collision_mask;
- bool clip_to_areas;
- bool clip_to_bodies;
+ float margin = 0.0;
+ float clip_offset = 0.0;
+ uint32_t collision_mask = 1;
+ bool clip_to_areas = false;
+ bool clip_to_bodies = true;
Set<RID> exclude;
@@ -218,8 +219,8 @@ public:
void set_margin(float p_margin);
float get_margin() const;
- void set_process_mode(ProcessMode p_mode);
- ProcessMode get_process_mode() const;
+ void set_process_callback(ClipProcessCallback p_mode);
+ ClipProcessCallback get_process_callback() const;
void set_collision_mask(uint32_t p_mask);
uint32_t get_collision_mask() const;
@@ -239,5 +240,5 @@ public:
~ClippedCamera3D();
};
-VARIANT_ENUM_CAST(ClippedCamera3D::ProcessMode);
+VARIANT_ENUM_CAST(ClippedCamera3D::ClipProcessCallback);
#endif
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index f1d7ac64b2..39880db29c 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -30,6 +30,8 @@
#include "collision_object_3d.h"
+#include "core/config/engine.h"
+#include "mesh_instance_3d.h"
#include "scene/scene_string_names.h"
#include "servers/physics_server_3d.h"
@@ -110,6 +112,42 @@ void CollisionObject3D::_update_pickable() {
}
}
+void CollisionObject3D::_update_debug_shapes() {
+ for (Set<uint32_t>::Element *shapedata_idx = debug_shapes_to_update.front(); shapedata_idx; shapedata_idx = shapedata_idx->next()) {
+ if (shapes.has(shapedata_idx->get())) {
+ ShapeData &shapedata = shapes[shapedata_idx->get()];
+ for (int i = 0; i < shapedata.shapes.size(); i++) {
+ ShapeData::ShapeBase &s = shapedata.shapes.write[i];
+ if (s.debug_shape) {
+ s.debug_shape->queue_delete();
+ s.debug_shape = nullptr;
+ }
+ if (s.shape.is_null() || shapedata.disabled) {
+ continue;
+ }
+
+ Ref<Mesh> mesh = s.shape->get_debug_mesh();
+ MeshInstance3D *mi = memnew(MeshInstance3D);
+ mi->set_transform(shapedata.xform);
+ mi->set_mesh(mesh);
+ add_child(mi);
+ mi->force_update_transform();
+ s.debug_shape = mi;
+ }
+ }
+ }
+ debug_shapes_to_update.clear();
+}
+
+void CollisionObject3D::_update_shape_data(uint32_t p_owner) {
+ if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint()) {
+ if (debug_shapes_to_update.is_empty()) {
+ call_deferred("_update_debug_shapes");
+ }
+ debug_shapes_to_update.insert(p_owner);
+ }
+}
+
void CollisionObject3D::set_ray_pickable(bool p_ray_pickable) {
ray_pickable = p_ray_pickable;
_update_pickable();
@@ -141,6 +179,8 @@ void CollisionObject3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject3D::shape_owner_clear_shapes);
ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject3D::shape_find_owner);
+ ClassDB::bind_method(D_METHOD("_update_debug_shapes"), &CollisionObject3D::_update_debug_shapes);
+
BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
@@ -188,6 +228,7 @@ void CollisionObject3D::shape_owner_set_disabled(uint32_t p_owner, bool p_disabl
PhysicsServer3D::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled);
}
}
+ _update_shape_data(p_owner);
}
bool CollisionObject3D::is_shape_owner_disabled(uint32_t p_owner) const {
@@ -223,6 +264,8 @@ void CollisionObject3D::shape_owner_set_transform(uint32_t p_owner, const Transf
PhysicsServer3D::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform);
}
}
+
+ _update_shape_data(p_owner);
}
Transform CollisionObject3D::shape_owner_get_transform(uint32_t p_owner) const {
@@ -245,6 +288,7 @@ void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3
ShapeData::ShapeBase s;
s.index = total_subshapes;
s.shape = p_shape;
+
if (area) {
PhysicsServer3D::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled);
} else {
@@ -253,6 +297,8 @@ void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3
sd.shapes.push_back(s);
total_subshapes++;
+
+ _update_shape_data(p_owner);
}
int CollisionObject3D::shape_owner_get_shape_count(uint32_t p_owner) const {
@@ -279,13 +325,19 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape)
ERR_FAIL_COND(!shapes.has(p_owner));
ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size());
- int index_to_remove = shapes[p_owner].shapes[p_shape].index;
+ const ShapeData::ShapeBase &s = shapes[p_owner].shapes[p_shape];
+ int index_to_remove = s.index;
+
if (area) {
PhysicsServer3D::get_singleton()->area_remove_shape(rid, index_to_remove);
} else {
PhysicsServer3D::get_singleton()->body_remove_shape(rid, index_to_remove);
}
+ if (s.debug_shape) {
+ s.debug_shape->queue_delete();
+ }
+
shapes[p_owner].shapes.remove(p_shape);
for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
@@ -325,10 +377,7 @@ uint32_t CollisionObject3D::shape_find_owner(int p_shape_index) const {
CollisionObject3D::CollisionObject3D(RID p_rid, bool p_area) {
rid = p_rid;
area = p_area;
- capture_input_on_drag = false;
- ray_pickable = true;
set_notify_transform(true);
- total_subshapes = 0;
if (p_area) {
PhysicsServer3D::get_singleton()->area_attach_object_instance_id(rid, get_instance_id());
@@ -360,8 +409,6 @@ String CollisionObject3D::get_configuration_warning() const {
}
CollisionObject3D::CollisionObject3D() {
- capture_input_on_drag = false;
- ray_pickable = true;
set_notify_transform(true);
//owner=
diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h
index da65791b9c..fe20176984 100644
--- a/scene/3d/collision_object_3d.h
+++ b/scene/3d/collision_object_3d.h
@@ -37,36 +37,36 @@
class CollisionObject3D : public Node3D {
GDCLASS(CollisionObject3D, Node3D);
- bool area;
+ bool area = false;
RID rid;
struct ShapeData {
- Object *owner;
+ Object *owner = nullptr;
Transform xform;
struct ShapeBase {
+ Node *debug_shape = nullptr;
Ref<Shape3D> shape;
- int index;
+ int index = 0;
};
Vector<ShapeBase> shapes;
- bool disabled;
-
- ShapeData() {
- disabled = false;
- owner = nullptr;
- }
+ bool disabled = false;
};
- int total_subshapes;
+ int total_subshapes = 0;
Map<uint32_t, ShapeData> shapes;
- bool capture_input_on_drag;
- bool ray_pickable;
+ bool capture_input_on_drag = false;
+ bool ray_pickable = true;
+
+ Set<uint32_t> debug_shapes_to_update;
void _update_pickable();
+ void _update_shape_data(uint32_t p_owner);
+
protected:
CollisionObject3D(RID p_rid, bool p_area);
@@ -77,6 +77,8 @@ protected:
virtual void _mouse_enter();
virtual void _mouse_exit();
+ void _update_debug_shapes();
+
public:
uint32_t create_shape_owner(Object *p_owner);
void remove_shape_owner(uint32_t owner);
diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp
index 742387b32d..e3e2eb4669 100644
--- a/scene/3d/collision_polygon_3d.cpp
+++ b/scene/3d/collision_polygon_3d.cpp
@@ -70,6 +70,7 @@ void CollisionPolygon3D::_build_polygon() {
}
convex->set_points(cp);
+ convex->set_margin(margin);
parent->shape_owner_add_shape(owner_id, convex);
parent->shape_owner_set_disabled(owner_id, disabled);
}
@@ -155,6 +156,17 @@ bool CollisionPolygon3D::is_disabled() const {
return disabled;
}
+real_t CollisionPolygon3D::get_margin() const {
+ return margin;
+}
+
+void CollisionPolygon3D::set_margin(real_t p_margin) {
+ margin = p_margin;
+ if (parent) {
+ _build_polygon();
+ }
+}
+
String CollisionPolygon3D::get_configuration_warning() const {
String warning = Node3D::get_configuration_warning();
@@ -189,18 +201,17 @@ void CollisionPolygon3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionPolygon3D::set_disabled);
ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionPolygon3D::is_disabled);
+ ClassDB::bind_method(D_METHOD("set_margin", "margin"), &CollisionPolygon3D::set_margin);
+ ClassDB::bind_method(D_METHOD("get_margin"), &CollisionPolygon3D::get_margin);
+
ClassDB::bind_method(D_METHOD("_is_editable_3d_polygon"), &CollisionPolygon3D::_is_editable_3d_polygon);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth"), "set_depth", "get_depth");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_margin", "get_margin");
}
CollisionPolygon3D::CollisionPolygon3D() {
- aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
- depth = 1.0;
set_notify_local_transform(true);
- parent = nullptr;
- owner_id = 0;
- disabled = false;
}
diff --git a/scene/3d/collision_polygon_3d.h b/scene/3d/collision_polygon_3d.h
index ba6ad2a3f0..750751b509 100644
--- a/scene/3d/collision_polygon_3d.h
+++ b/scene/3d/collision_polygon_3d.h
@@ -37,16 +37,17 @@
class CollisionObject3D;
class CollisionPolygon3D : public Node3D {
GDCLASS(CollisionPolygon3D, Node3D);
+ real_t margin = 0.04;
protected:
- real_t depth;
- AABB aabb;
+ real_t depth = 1.0;
+ AABB aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
Vector<Point2> polygon;
- uint32_t owner_id;
- CollisionObject3D *parent;
+ uint32_t owner_id = 0;
+ CollisionObject3D *parent = nullptr;
- bool disabled;
+ bool disabled = false;
void _build_polygon();
@@ -70,6 +71,9 @@ public:
virtual AABB get_item_rect() const;
+ real_t get_margin() const;
+ void set_margin(real_t p_margin);
+
String get_configuration_warning() const override;
CollisionPolygon3D();
diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp
index 503d1be104..242d82ab4c 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/collision_shape_3d.cpp
@@ -93,15 +93,13 @@ void CollisionShape3D::_notification(int p_what) {
if (shape.is_valid()) {
parent->shape_owner_add_shape(owner_id, shape);
}
+ _update_in_shape_owner();
}
} break;
case NOTIFICATION_ENTER_TREE: {
if (parent) {
_update_in_shape_owner();
}
- if (get_tree()->is_debugging_collisions_hint()) {
- _update_debug_shape();
- }
} break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
if (parent) {
@@ -162,8 +160,6 @@ void CollisionShape3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("make_convex_from_siblings"), &CollisionShape3D::make_convex_from_siblings);
ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_siblings", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
- ClassDB::bind_method(D_METHOD("_update_debug_shape"), &CollisionShape3D::_update_debug_shape);
-
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
}
@@ -213,10 +209,6 @@ bool CollisionShape3D::is_disabled() const {
CollisionShape3D::CollisionShape3D() {
//indicator = RenderingServer::get_singleton()->mesh_create();
- disabled = false;
- debug_shape = nullptr;
- parent = nullptr;
- owner_id = 0;
set_notify_local_transform(true);
}
@@ -227,34 +219,9 @@ CollisionShape3D::~CollisionShape3D() {
//RenderingServer::get_singleton()->free(indicator);
}
-void CollisionShape3D::_update_debug_shape() {
- debug_shape_dirty = false;
-
- if (debug_shape) {
- debug_shape->queue_delete();
- debug_shape = nullptr;
- }
-
- Ref<Shape3D> s = get_shape();
- if (s.is_null()) {
- return;
- }
-
- Ref<Mesh> mesh = s->get_debug_mesh();
- MeshInstance3D *mi = memnew(MeshInstance3D);
- mi->set_mesh(mesh);
- add_child(mi);
- debug_shape = mi;
-}
-
void CollisionShape3D::_shape_changed() {
// If this is a heightfield shape our center may have changed
if (parent) {
_update_in_shape_owner(true);
}
-
- if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !debug_shape_dirty) {
- debug_shape_dirty = true;
- call_deferred("_update_debug_shape");
- }
}
diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h
index 5f556b01a9..5512417f75 100644
--- a/scene/3d/collision_shape_3d.h
+++ b/scene/3d/collision_shape_3d.h
@@ -40,17 +40,13 @@ class CollisionShape3D : public Node3D {
Ref<Shape3D> shape;
- uint32_t owner_id;
- CollisionObject3D *parent;
-
- Node *debug_shape;
- bool debug_shape_dirty;
+ uint32_t owner_id = 0;
+ CollisionObject3D *parent = nullptr;
void resource_changed(RES res);
- bool disabled;
+ bool disabled = false;
protected:
- void _update_debug_shape();
void _shape_changed();
void _update_in_shape_owner(bool p_xform_only = false);
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 85b502e7a0..d22d7ff3ab 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -73,7 +73,7 @@ void CPUParticles3D::set_amount(int p_amount) {
}
particle_data.resize((12 + 4 + 4) * p_amount);
- RS::get_singleton()->multimesh_allocate(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_3D, true, true);
+ RS::get_singleton()->multimesh_allocate_data(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_3D, true, true);
particle_order.resize(p_amount);
}
@@ -152,6 +152,7 @@ float CPUParticles3D::get_speed_scale() const {
}
void CPUParticles3D::set_draw_order(DrawOrder p_order) {
+ ERR_FAIL_INDEX(p_order, DRAW_ORDER_MAX);
draw_order = p_order;
}
@@ -372,7 +373,7 @@ void CPUParticles3D::set_particle_flag(ParticleFlags p_particle_flag, bool p_ena
ERR_FAIL_INDEX(p_particle_flag, PARTICLE_FLAG_MAX);
particle_flags[p_particle_flag] = p_enable;
if (p_particle_flag == PARTICLE_FLAG_DISABLE_Z) {
- _change_notify();
+ notify_property_list_changed();
}
}
@@ -575,7 +576,7 @@ void CPUParticles3D::_particles_process(float p_delta) {
cycle++;
if (one_shot && cycle > 0) {
set_emitting(false);
- _change_notify();
+ notify_property_list_changed();
}
}
@@ -1011,6 +1012,7 @@ void CPUParticles3D::_update_particle_data_buffer() {
sorter.compare.particles = r;
sorter.sort(order, pc);
} else if (draw_order == DRAW_ORDER_VIEW_DEPTH) {
+ ERR_FAIL_NULL(get_viewport());
Camera3D *c = get_viewport()->get_camera();
if (c) {
Vector3 dir = c->get_global_transform().basis.get_axis(2); //far away to close
@@ -1072,7 +1074,7 @@ void CPUParticles3D::_update_particle_data_buffer() {
ptr += 20;
}
- can_update = true;
+ can_update.set();
}
void CPUParticles3D::_set_redraw(bool p_redraw) {
@@ -1101,9 +1103,9 @@ void CPUParticles3D::_set_redraw(bool p_redraw) {
void CPUParticles3D::_update_render_thread() {
MutexLock lock(update_mutex);
- if (can_update) {
+ if (can_update.is_set()) {
RS::get_singleton()->multimesh_set_buffer(multimesh, particle_data);
- can_update = false; //wait for next time
+ can_update.clear(); //wait for next time
}
}
@@ -1165,7 +1167,7 @@ void CPUParticles3D::_notification(int p_what) {
ptr += 20;
}
- can_update = true;
+ can_update.set();
}
}
}
@@ -1445,13 +1447,6 @@ void CPUParticles3D::_bind_methods() {
}
CPUParticles3D::CPUParticles3D() {
- time = 0;
- inactive_time = 0;
- frame_remainder = 0;
- cycle = 0;
- redraw = false;
- emitting = false;
-
set_notify_transform(true);
multimesh = RenderingServer::get_singleton()->multimesh_create();
@@ -1459,23 +1454,8 @@ CPUParticles3D::CPUParticles3D() {
set_base(multimesh);
set_emitting(true);
- set_one_shot(false);
set_amount(8);
- set_lifetime(1);
- set_fixed_fps(0);
- set_fractional_delta(true);
- set_pre_process_time(0);
- set_explosiveness_ratio(0);
- set_randomness_ratio(0);
- set_lifetime_randomness(0);
- set_use_local_coordinates(true);
-
- set_draw_order(DRAW_ORDER_INDEX);
- set_speed_scale(1);
-
- set_direction(Vector3(1, 0, 0));
- set_spread(45);
- set_flatness(0);
+
set_param(PARAM_INITIAL_LINEAR_VELOCITY, 0);
set_param(PARAM_ANGULAR_VELOCITY, 0);
set_param(PARAM_ORBIT_VELOCITY, 0);
@@ -1502,8 +1482,6 @@ CPUParticles3D::CPUParticles3D() {
particle_flags[i] = false;
}
- can_update = false;
-
set_color(Color(1, 1, 1, 1));
}
diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h
index 3ee03ff3d8..10ac32622d 100644
--- a/scene/3d/cpu_particles_3d.h
+++ b/scene/3d/cpu_particles_3d.h
@@ -32,6 +32,7 @@
#define CPU_PARTICLES_H
#include "core/templates/rid.h"
+#include "core/templates/safe_refcount.h"
#include "scene/3d/visual_instance_3d.h"
class CPUParticles3D : public GeometryInstance3D {
@@ -43,6 +44,7 @@ public:
DRAW_ORDER_INDEX,
DRAW_ORDER_LIFETIME,
DRAW_ORDER_VIEW_DEPTH,
+ DRAW_ORDER_MAX
};
enum Parameter {
@@ -78,30 +80,30 @@ public:
};
private:
- bool emitting;
+ bool emitting = false;
struct Particle {
Transform transform;
Color color;
- float custom[4];
+ float custom[4] = {};
Vector3 velocity;
- bool active;
- float angle_rand;
- float scale_rand;
- float hue_rot_rand;
- float anim_offset_rand;
- float time;
- float lifetime;
+ bool active = false;
+ float angle_rand = 0.0;
+ float scale_rand = 0.0;
+ float hue_rot_rand = 0.0;
+ float anim_offset_rand = 0.0;
+ float time = 0.0;
+ float lifetime = 0.0;
Color base_color;
- uint32_t seed;
+ uint32_t seed = 0;
};
- float time;
- float inactive_time;
- float frame_remainder;
- int cycle;
- bool redraw;
+ float time = 0.0;
+ float inactive_time = 0.0;
+ float frame_remainder = 0.0;
+ int cycle = 0;
+ bool redraw = false;
RID multimesh;
@@ -110,7 +112,7 @@ private:
Vector<int> particle_order;
struct SortLifetime {
- const Particle *particles;
+ const Particle *particles = nullptr;
bool operator()(int p_a, int p_b) const {
return particles[p_a].time > particles[p_b].time;
@@ -118,7 +120,7 @@ private:
};
struct SortAxis {
- const Particle *particles;
+ const Particle *particles = nullptr;
Vector3 axis;
bool operator()(int p_a, int p_b) const {
return axis.dot(particles[p_a].transform.origin) < axis.dot(particles[p_b].transform.origin);
@@ -127,50 +129,50 @@ private:
//
- bool one_shot;
+ bool one_shot = false;
- float lifetime;
- float pre_process_time;
- float explosiveness_ratio;
- float randomness_ratio;
- float lifetime_randomness;
- float speed_scale;
- bool local_coords;
- int fixed_fps;
- bool fractional_delta;
+ float lifetime = 1.0;
+ float pre_process_time = 0.0;
+ float explosiveness_ratio = 0.0;
+ float randomness_ratio = 0.0;
+ float lifetime_randomness = 0.0;
+ float speed_scale = 1.0;
+ bool local_coords = true;
+ int fixed_fps = 0;
+ bool fractional_delta = true;
Transform inv_emission_transform;
- volatile bool can_update;
+ SafeFlag can_update;
- DrawOrder draw_order;
+ DrawOrder draw_order = DRAW_ORDER_INDEX;
Ref<Mesh> mesh;
////////
- Vector3 direction;
- float spread;
- float flatness;
+ Vector3 direction = Vector3(1, 0, 0);
+ float spread = 45.0;
+ float flatness = 0.0;
float parameters[PARAM_MAX];
- float randomness[PARAM_MAX];
+ float randomness[PARAM_MAX] = {};
Ref<Curve> curve_parameters[PARAM_MAX];
- Color color;
+ Color color = Color(1, 1, 1, 1);
Ref<Gradient> color_ramp;
- bool particle_flags[PARTICLE_FLAG_MAX];
+ bool particle_flags[PARTICLE_FLAG_MAX] = {};
- EmissionShape emission_shape;
- float emission_sphere_radius;
- Vector3 emission_box_extents;
+ EmissionShape emission_shape = EMISSION_SHAPE_POINT;
+ float emission_sphere_radius = 1.0;
+ Vector3 emission_box_extents = Vector3(1, 1, 1);
Vector<Vector3> emission_points;
Vector<Vector3> emission_normals;
Vector<Color> emission_colors;
- int emission_point_count;
+ int emission_point_count = 0;
- Vector3 gravity;
+ Vector3 gravity = Vector3(0, -9.8, 0);
void _update_internal();
void _particles_process(float p_delta);
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index e67802cfc4..7d6abe458a 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -34,7 +34,6 @@ void Decal::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->decal_set_extents(decal, p_extents);
update_gizmo();
- _change_notify("extents");
}
Vector3 Decal::get_extents() const {
@@ -110,6 +109,7 @@ Color Decal::get_modulate() const {
void Decal::set_enable_distance_fade(bool p_enable) {
distance_fade_enabled = p_enable;
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
+ notify_property_list_changed();
}
bool Decal::is_distance_fade_enabled() const {
@@ -154,6 +154,12 @@ Vector<Face3> Decal::get_faces(uint32_t p_usage_flags) const {
return Vector<Face3>();
}
+void Decal::_validate_property(PropertyInfo &property) const {
+ if (!distance_fade_enabled && (property.name == "distance_fade_begin" || property.name == "distance_fade_length")) {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+}
+
void Decal::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &Decal::set_extents);
ClassDB::bind_method(D_METHOD("get_extents"), &Decal::get_extents);
@@ -220,18 +226,6 @@ void Decal::_bind_methods() {
}
Decal::Decal() {
- extents = Vector3(1, 1, 1);
- emission_energy = 1.0;
- modulate = Color(1, 1, 1, 1);
- albedo_mix = 1.0;
- cull_mask = (1 << 20) - 1;
- upper_fade = 0.3;
- lower_fade = 0.3;
- normal_fade = 0;
- distance_fade_enabled = false;
- distance_fade_begin = 10;
- distance_fade_length = 1;
-
decal = RenderingServer::get_singleton()->decal_create();
RS::get_singleton()->instance_set_base(get_instance(), decal);
}
diff --git a/scene/3d/decal.h b/scene/3d/decal.h
index 500a1425f2..ce19e76de1 100644
--- a/scene/3d/decal.h
+++ b/scene/3d/decal.h
@@ -49,21 +49,22 @@ public:
private:
RID decal;
- Vector3 extents;
+ Vector3 extents = Vector3(1, 1, 1);
Ref<Texture2D> textures[TEXTURE_MAX];
- float emission_energy;
- float albedo_mix;
- Color modulate;
- uint32_t cull_mask;
- float normal_fade;
- float upper_fade;
- float lower_fade;
- bool distance_fade_enabled;
- float distance_fade_begin;
- float distance_fade_length;
+ float emission_energy = 1.0;
+ float albedo_mix = 1.0;
+ Color modulate = Color(1, 1, 1, 1);
+ uint32_t cull_mask = (1 << 20) - 1;
+ float normal_fade = 0.0;
+ float upper_fade = 0.3;
+ float lower_fade = 0.3;
+ bool distance_fade_enabled = false;
+ float distance_fade_begin = 10.0;
+ float distance_fade_length = 1.0;
protected:
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const override;
public:
void set_extents(const Vector3 &p_extents);
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index 0565193437..43f820e5d4 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -91,7 +91,7 @@ Dictionary GIProbeData::_get_data() const {
}
void GIProbeData::allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
- RS::get_singleton()->gi_probe_allocate(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts);
+ RS::get_singleton()->gi_probe_allocate_data(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts);
bounds = p_aabb;
to_cell_xform = p_to_cell_xform;
octree_size = p_octree_size;
@@ -221,7 +221,7 @@ RID GIProbeData::get_rid() const {
void GIProbeData::_validate_property(PropertyInfo &property) const {
if (property.name == "anisotropy_strength") {
- bool anisotropy_enabled = ProjectSettings::get_singleton()->get("rendering/quality/gi_probes/anisotropic");
+ bool anisotropy_enabled = ProjectSettings::get_singleton()->get("rendering/global_illumination/gi_probes/anisotropic");
if (!anisotropy_enabled) {
property.usage = PROPERTY_USAGE_NOEDITOR;
}
@@ -286,17 +286,6 @@ void GIProbeData::_bind_methods() {
}
GIProbeData::GIProbeData() {
- ao = 0.0;
- ao_size = 0.5;
- dynamic_range = 4;
- energy = 1.0;
- bias = 1.5;
- normal_bias = 0.0;
- propagation = 0.7;
- anisotropy_strength = 0.5;
- interior = false;
- use_two_bounces = false;
-
probe = RS::get_singleton()->gi_probe_create();
}
@@ -334,7 +323,6 @@ GIProbe::Subdiv GIProbe::get_subdiv() const {
void GIProbe::set_extents(const Vector3 &p_extents) {
extents = p_extents;
update_gizmo();
- _change_notify("extents");
}
Vector3 GIProbe::get_extents() const {
@@ -427,13 +415,16 @@ Vector3i GIProbe::get_estimated_cell_size() const {
void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 };
+ p_from_node = p_from_node ? p_from_node : get_parent();
+ ERR_FAIL_NULL(p_from_node);
+
Voxelizer baker;
baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0));
List<PlotMesh> mesh_list;
- _find_meshes(p_from_node ? p_from_node : get_parent(), mesh_list);
+ _find_meshes(p_from_node, mesh_list);
if (bake_begin_function) {
bake_begin_function(mesh_list.size() + 1);
@@ -497,7 +488,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
bake_end_function();
}
- _change_notify(); //bake property may have changed
+ notify_property_list_changed(); //bake property may have changed
}
void GIProbe::_debug_bake() {
@@ -553,9 +544,6 @@ void GIProbe::_bind_methods() {
}
GIProbe::GIProbe() {
- subdiv = SUBDIV_128;
- extents = Vector3(10, 10, 10);
-
gi_probe = RS::get_singleton()->gi_probe_create();
set_disable_scale(true);
}
diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h
index afea94fe12..534b425557 100644
--- a/scene/3d/gi_probe.h
+++ b/scene/3d/gi_probe.h
@@ -46,16 +46,16 @@ class GIProbeData : public Resource {
AABB bounds;
Vector3 octree_size;
- float dynamic_range;
- float energy;
- float bias;
- float normal_bias;
- float propagation;
- float anisotropy_strength;
- float ao;
- float ao_size;
- bool interior;
- bool use_two_bounces;
+ float dynamic_range = 4.0;
+ float energy = 1.0;
+ float bias = 1.5;
+ float normal_bias = 0.0;
+ float propagation = 0.7;
+ float anisotropy_strength = 0.5;
+ float ao = 0.0;
+ float ao_size = 0.5;
+ bool interior = false;
+ bool use_two_bounces = false;
protected:
static void _bind_methods();
@@ -129,8 +129,8 @@ private:
RID gi_probe;
- Subdiv subdiv;
- Vector3 extents;
+ Subdiv subdiv = SUBDIV_128;
+ Vector3 extents = Vector3(10, 10, 10);
struct PlotMesh {
Ref<Material> override_material;
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 7d77578b01..e2cfc2ed87 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -100,7 +100,6 @@ void GPUParticles3D::set_visibility_aabb(const AABB &p_aabb) {
visibility_aabb = p_aabb;
RS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb);
update_gizmo();
- _change_notify("visibility_aabb");
}
void GPUParticles3D::set_use_local_coordinates(bool p_enable) {
@@ -190,7 +189,7 @@ void GPUParticles3D::set_draw_passes(int p_count) {
ERR_FAIL_COND(p_count < 1);
draw_passes.resize(p_count);
RS::get_singleton()->particles_set_draw_passes(particles, p_count);
- _change_notify();
+ notify_property_list_changed();
}
int GPUParticles3D::get_draw_passes() const {
@@ -349,11 +348,11 @@ void GPUParticles3D::_notification(int p_what) {
}
}
- // Use internal process when emitting and one_shot are on so that when
+ // Use internal process when emitting and one_shot is on so that when
// the shot ends the editor can properly update
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
if (one_shot && !is_emitting()) {
- _change_notify();
+ notify_property_list_changed();
set_process_internal(false);
}
}
diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h
index 7d6301ee50..81c33663f3 100644
--- a/scene/3d/gpu_particles_collision_3d.h
+++ b/scene/3d/gpu_particles_collision_3d.h
@@ -130,16 +130,16 @@ private:
LEAF_MASK = LEAF_BIT - 1
};
AABB bounds;
- uint32_t children[2];
+ uint32_t children[2] = {};
};
struct FacePos {
Vector3 center;
- uint32_t index;
+ uint32_t index = 0;
};
struct FaceSort {
- uint32_t axis;
+ uint32_t axis = 0;
bool operator()(const FacePos &p_left, const FacePos &p_right) const {
return p_left.center[axis] < p_right.center[axis];
}
@@ -148,13 +148,13 @@ private:
uint32_t _create_bvh(LocalVector<BVH> &bvh_tree, FacePos *p_faces, uint32_t p_face_count, const Face3 *p_triangles, float p_thickness);
struct ComputeSDFParams {
- float *cells;
+ float *cells = nullptr;
Vector3i size;
- float cell_size;
+ float cell_size = 0.0;
Vector3 cell_offset;
- const BVH *bvh;
- const Face3 *triangles;
- float thickness;
+ const BVH *bvh = nullptr;
+ const Face3 *triangles = nullptr;
+ float thickness = 0.0;
};
void _find_closest_distance(const Vector3 &p_pos, const BVH *bvh, uint32_t p_bvh_cell, const Face3 *triangles, float thickness, float &closest_distance);
diff --git a/scene/3d/immediate_geometry_3d.cpp b/scene/3d/immediate_geometry_3d.cpp
index 47242cf196..d64babaa9d 100644
--- a/scene/3d/immediate_geometry_3d.cpp
+++ b/scene/3d/immediate_geometry_3d.cpp
@@ -150,7 +150,6 @@ void ImmediateGeometry3D::_bind_methods() {
ImmediateGeometry3D::ImmediateGeometry3D() {
im = RenderingServer::get_singleton()->immediate_create();
set_base(im);
- empty = true;
}
ImmediateGeometry3D::~ImmediateGeometry3D() {
diff --git a/scene/3d/immediate_geometry_3d.h b/scene/3d/immediate_geometry_3d.h
index 8e546e27e7..ee4938d9f7 100644
--- a/scene/3d/immediate_geometry_3d.h
+++ b/scene/3d/immediate_geometry_3d.h
@@ -41,7 +41,7 @@ class ImmediateGeometry3D : public GeometryInstance3D {
//a list of textures drawn need to be kept, to avoid references
// in RenderingServer from becoming invalid if the texture is no longer used
List<Ref<Texture2D>> cached_textures;
- bool empty;
+ bool empty = true;
AABB aabb;
protected:
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index b998a1a400..f109640aef 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -48,11 +48,7 @@ void Light3D::set_param(Param p_param, float p_value) {
update_gizmo();
if (p_param == PARAM_SPOT_ANGLE) {
- _change_notify("spot_angle");
update_configuration_warning();
- } else if (p_param == PARAM_RANGE) {
- _change_notify("omni_range");
- _change_notify("spot_range");
}
}
}
@@ -69,6 +65,8 @@ void Light3D::set_shadow(bool p_enable) {
if (type == RenderingServer::LIGHT_SPOT || type == RenderingServer::LIGHT_OMNI) {
update_configuration_warning();
}
+
+ notify_property_list_changed();
}
bool Light3D::has_shadow() const {
@@ -184,8 +182,6 @@ void Light3D::_update_visibility() {
#endif
RS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree() && editor_ok);
-
- _change_notify("geometry/visible");
}
void Light3D::_notification(int p_what) {
@@ -208,6 +204,10 @@ bool Light3D::is_editor_only() const {
}
void Light3D::_validate_property(PropertyInfo &property) const {
+ if (!shadow && (property.name == "shadow_color" || property.name == "shadow_bias" || property.name == "shadow_normal_bias" || property.name == "shadow_reverse_cull_face" || property.name == "shadow_transmittance_bias" || property.name == "shadow_fog_fade" || property.name == "shadow_blur")) {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+
if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_size") {
property.usage = 0;
}
@@ -324,10 +324,6 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
RS::get_singleton()->instance_set_base(get_instance(), light);
- reverse_cull = false;
- bake_mode = BAKE_DYNAMIC;
-
- editor_only = false;
set_color(Color(1, 1, 1, 1));
set_shadow(false);
set_negative(false);
@@ -351,13 +347,12 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
set_param(PARAM_SHADOW_BIAS, 0.02);
set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
set_param(PARAM_TRANSMITTANCE_BIAS, 0.05);
- set_param(PARAM_SHADOW_VOLUMETRIC_FOG_FADE, 1.0);
+ set_param(PARAM_SHADOW_VOLUMETRIC_FOG_FADE, 0.1);
set_param(PARAM_SHADOW_FADE_START, 1);
set_disable_scale(true);
}
Light3D::Light3D() {
- type = RenderingServer::LIGHT_DIRECTIONAL;
ERR_PRINT("Light3D should not be instanced directly; use the DirectionalLight3D, OmniLight3D or SpotLight3D subtypes instead.");
}
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index 833598c4a1..311db54bce 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -71,16 +71,16 @@ public:
private:
Color color;
- float param[PARAM_MAX];
+ float param[PARAM_MAX] = {};
Color shadow_color;
- bool shadow;
- bool negative;
- bool reverse_cull;
- uint32_t cull_mask;
- RS::LightType type;
- bool editor_only;
+ bool shadow = false;
+ bool negative = false;
+ bool reverse_cull = false;
+ uint32_t cull_mask = 0;
+ RS::LightType type = RenderingServer::LIGHT_DIRECTIONAL;
+ bool editor_only = false;
void _update_visibility();
- BakeMode bake_mode;
+ BakeMode bake_mode = BAKE_DYNAMIC;
Ref<Texture2D> projector;
// bind helpers
diff --git a/scene/3d/listener_3d.cpp b/scene/3d/listener_3d.cpp
index 23adb0aa19..9842f152d7 100644
--- a/scene/3d/listener_3d.cpp
+++ b/scene/3d/listener_3d.cpp
@@ -159,8 +159,6 @@ void Listener3D::_bind_methods() {
}
Listener3D::Listener3D() {
- current = false;
- force_change = false;
set_notify_transform(true);
//active=false;
}
diff --git a/scene/3d/listener_3d.h b/scene/3d/listener_3d.h
index 2a78efb2c7..85657a8e53 100644
--- a/scene/3d/listener_3d.h
+++ b/scene/3d/listener_3d.h
@@ -38,8 +38,8 @@ class Listener3D : public Node3D {
GDCLASS(Listener3D, Node3D);
private:
- bool force_change;
- bool current;
+ bool force_change = false;
+ bool current = false;
RID scenario_id;
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index 44dd6e0e5f..b997c64b29 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -95,7 +95,7 @@ void MeshInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
ls.sort();
for (List<String>::Element *E = ls.front(); E; E = E->next()) {
- p_list->push_back(PropertyInfo(Variant::FLOAT, E->get(), PROPERTY_HINT_RANGE, "0,1,0.00001"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, E->get(), PROPERTY_HINT_RANGE, "-1,1,0.00001"));
}
if (mesh.is_valid()) {
@@ -135,7 +135,7 @@ void MeshInstance3D::set_mesh(const Ref<Mesh> &p_mesh) {
update_gizmo();
- _change_notify();
+ notify_property_list_changed();
}
Ref<Mesh> MeshInstance3D::get_mesh() const {
@@ -152,7 +152,7 @@ void MeshInstance3D::_resolve_skeleton_path() {
if (skin_internal.is_null()) {
//a skin was created for us
skin_internal = new_skin_reference->get_skin();
- _change_notify();
+ notify_property_list_changed();
}
}
}
@@ -319,6 +319,7 @@ Ref<Material> MeshInstance3D::get_active_material(int p_surface) const {
}
void MeshInstance3D::_mesh_changed() {
+ ERR_FAIL_COND(mesh.is_null());
materials.resize(mesh->get_surface_count());
}
@@ -428,7 +429,6 @@ void MeshInstance3D::_bind_methods() {
}
MeshInstance3D::MeshInstance3D() {
- skeleton_path = NodePath("..");
}
MeshInstance3D::~MeshInstance3D() {
diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h
index 822e04e656..eb300784b1 100644
--- a/scene/3d/mesh_instance_3d.h
+++ b/scene/3d/mesh_instance_3d.h
@@ -44,15 +44,11 @@ protected:
Ref<Skin> skin;
Ref<Skin> skin_internal;
Ref<SkinReference> skin_ref;
- NodePath skeleton_path;
+ NodePath skeleton_path = NodePath("..");
struct BlendShapeTrack {
- int idx;
- float value;
- BlendShapeTrack() {
- idx = 0;
- value = 0;
- }
+ int idx = 0;
+ float value = 0.0;
};
Map<StringName, BlendShapeTrack> blend_shape_tracks;
diff --git a/scene/3d/navigation_3d.cpp b/scene/3d/navigation_3d.cpp
deleted file mode 100644
index 2a7195be1a..0000000000
--- a/scene/3d/navigation_3d.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*************************************************************************/
-/* navigation_3d.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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_3d.h"
-
-#include "servers/navigation_server_3d.h"
-
-Vector<Vector3> Navigation3D::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) const {
- return NavigationServer3D::get_singleton()->map_get_path(map, p_start, p_end, p_optimize);
-}
-
-Vector3 Navigation3D::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision) const {
- return NavigationServer3D::get_singleton()->map_get_closest_point_to_segment(map, p_from, p_to, p_use_collision);
-}
-
-Vector3 Navigation3D::get_closest_point(const Vector3 &p_point) const {
- return NavigationServer3D::get_singleton()->map_get_closest_point(map, p_point);
-}
-
-Vector3 Navigation3D::get_closest_point_normal(const Vector3 &p_point) const {
- return NavigationServer3D::get_singleton()->map_get_closest_point_normal(map, p_point);
-}
-
-RID Navigation3D::get_closest_point_owner(const Vector3 &p_point) const {
- return NavigationServer3D::get_singleton()->map_get_closest_point_owner(map, p_point);
-}
-
-void Navigation3D::set_up_vector(const Vector3 &p_up) {
- up = p_up;
- NavigationServer3D::get_singleton()->map_set_up(map, up);
-}
-
-Vector3 Navigation3D::get_up_vector() const {
- return up;
-}
-
-void Navigation3D::set_cell_size(float p_cell_size) {
- cell_size = p_cell_size;
- NavigationServer3D::get_singleton()->map_set_cell_size(map, cell_size);
-}
-
-void Navigation3D::set_edge_connection_margin(float p_edge_connection_margin) {
- edge_connection_margin = p_edge_connection_margin;
- NavigationServer3D::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin);
-}
-
-void Navigation3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_rid"), &Navigation3D::get_rid);
-
- ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation3D::get_simple_path, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "start", "end", "use_collision"), &Navigation3D::get_closest_point_to_segment, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Navigation3D::get_closest_point);
- ClassDB::bind_method(D_METHOD("get_closest_point_normal", "to_point"), &Navigation3D::get_closest_point_normal);
- ClassDB::bind_method(D_METHOD("get_closest_point_owner", "to_point"), &Navigation3D::get_closest_point_owner);
-
- ClassDB::bind_method(D_METHOD("set_up_vector", "up"), &Navigation3D::set_up_vector);
- ClassDB::bind_method(D_METHOD("get_up_vector"), &Navigation3D::get_up_vector);
-
- ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation3D::set_cell_size);
- ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation3D::get_cell_size);
-
- ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation3D::set_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation3D::get_edge_connection_margin);
-
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_vector"), "set_up_vector", "get_up_vector");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size"), "set_cell_size", "get_cell_size");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin");
-}
-
-void Navigation3D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_READY: {
- NavigationServer3D::get_singleton()->map_set_active(map, true);
- } break;
- case NOTIFICATION_EXIT_TREE: {
- NavigationServer3D::get_singleton()->map_set_active(map, false);
- } break;
- }
-}
-
-Navigation3D::Navigation3D() {
- map = NavigationServer3D::get_singleton()->map_create();
-
- set_cell_size(0.3);
- set_edge_connection_margin(5.0); // Five meters, depends a lot on the agent's radius
-
- up = Vector3(0, 1, 0);
-}
-
-Navigation3D::~Navigation3D() {
- NavigationServer3D::get_singleton()->free(map);
-}
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index 8917cc4664..21ca3d70dd 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -31,7 +31,6 @@
#include "navigation_agent_3d.h"
#include "core/config/engine.h"
-#include "scene/3d/navigation_3d.h"
#include "servers/navigation_server_3d.h"
void NavigationAgent3D::_bind_methods() {
@@ -47,9 +46,6 @@ void NavigationAgent3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_ignore_y", "ignore"), &NavigationAgent3D::set_ignore_y);
ClassDB::bind_method(D_METHOD("get_ignore_y"), &NavigationAgent3D::get_ignore_y);
- ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationAgent3D::set_navigation_node);
- ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationAgent3D::get_navigation_node);
-
ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent3D::set_neighbor_dist);
ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent3D::get_neighbor_dist);
@@ -101,28 +97,10 @@ void NavigationAgent3D::_notification(int p_what) {
agent_parent = Object::cast_to<Node3D>(get_parent());
NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
-
- // Search the navigation node and set it
- {
- Navigation3D *nav = nullptr;
- Node *p = get_parent();
- while (p != nullptr) {
- nav = Object::cast_to<Navigation3D>(p);
- if (nav != nullptr) {
- p = nullptr;
- } else {
- p = p->get_parent();
- }
- }
-
- set_navigation(nav);
- }
-
set_physics_process_internal(true);
} break;
case NOTIFICATION_EXIT_TREE: {
agent_parent = nullptr;
- set_navigation(nullptr);
set_physics_process_internal(false);
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
@@ -154,25 +132,6 @@ NavigationAgent3D::~NavigationAgent3D() {
agent = RID(); // Pointless
}
-void NavigationAgent3D::set_navigation(Navigation3D *p_nav) {
- if (navigation == p_nav) {
- return; // Pointless
- }
-
- navigation = p_nav;
- NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid());
-}
-
-void NavigationAgent3D::set_navigation_node(Node *p_nav) {
- Navigation3D *nav = Object::cast_to<Navigation3D>(p_nav);
- ERR_FAIL_COND(nav == nullptr);
- set_navigation(nav);
-}
-
-Node *NavigationAgent3D::get_navigation_node() const {
- return Object::cast_to<Node>(navigation);
-}
-
void NavigationAgent3D::set_target_desired_distance(real_t p_dd) {
target_desired_distance = p_dd;
}
@@ -303,7 +262,7 @@ void NavigationAgent3D::update_navigation() {
if (agent_parent == nullptr) {
return;
}
- if (navigation == nullptr) {
+ if (!agent_parent->is_inside_tree()) {
return;
}
if (update_frame_id == Engine::get_singleton()->get_physics_frames()) {
@@ -337,7 +296,7 @@ void NavigationAgent3D::update_navigation() {
}
if (reload_path) {
- navigation_path = NavigationServer3D::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true);
+ navigation_path = NavigationServer3D::get_singleton()->map_get_path(agent_parent->get_world_3d()->get_navigation_map(), o, target_location, true);
navigation_finished = false;
nav_path_index = 0;
emit_signal("path_changed");
diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h
index bd890a051b..22db889618 100644
--- a/scene/3d/navigation_agent_3d.h
+++ b/scene/3d/navigation_agent_3d.h
@@ -35,13 +35,11 @@
#include "scene/main/node.h"
class Node3D;
-class Navigation3D;
class NavigationAgent3D : public Node {
GDCLASS(NavigationAgent3D, Node);
Node3D *agent_parent = nullptr;
- Navigation3D *navigation = nullptr;
RID agent;
@@ -76,14 +74,6 @@ public:
NavigationAgent3D();
virtual ~NavigationAgent3D();
- void set_navigation(Navigation3D *p_nav);
- const Navigation3D *get_navigation() const {
- return navigation;
- }
-
- void set_navigation_node(Node *p_nav);
- Node *get_navigation_node() const;
-
RID get_rid() const {
return agent;
}
diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp
index 01bf7de913..df03bca4fd 100644
--- a/scene/3d/navigation_obstacle_3d.cpp
+++ b/scene/3d/navigation_obstacle_3d.cpp
@@ -31,55 +31,38 @@
#include "navigation_obstacle_3d.h"
#include "scene/3d/collision_shape_3d.h"
-#include "scene/3d/navigation_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "servers/navigation_server_3d.h"
void NavigationObstacle3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle3D::set_navigation_node);
- ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle3D::get_navigation_node);
}
void NavigationObstacle3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
- update_agent_shape();
-
- // Search the navigation node and set it
- {
- Navigation3D *nav = nullptr;
- Node *p = get_parent();
- while (p != nullptr) {
- nav = Object::cast_to<Navigation3D>(p);
- if (nav != nullptr) {
- p = nullptr;
- } else {
- p = p->get_parent();
- }
- }
-
- set_navigation(nav);
- }
-
set_physics_process_internal(true);
} break;
case NOTIFICATION_EXIT_TREE: {
- set_navigation(nullptr);
set_physics_process_internal(false);
} break;
+ case NOTIFICATION_PARENTED: {
+ parent_node3d = Object::cast_to<Node3D>(get_parent());
+ update_agent_shape();
+ } break;
+ case NOTIFICATION_UNPARENTED: {
+ parent_node3d = nullptr;
+ } break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
- Node3D *spatial = Object::cast_to<Node3D>(get_parent());
- if (spatial) {
- NavigationServer3D::get_singleton()->agent_set_position(agent, spatial->get_global_transform().origin);
- }
-
- PhysicsBody3D *rigid = Object::cast_to<PhysicsBody3D>(get_parent());
- if (rigid) {
- Vector3 v = rigid->get_linear_velocity();
- NavigationServer3D::get_singleton()->agent_set_velocity(agent, v);
- NavigationServer3D::get_singleton()->agent_set_target_velocity(agent, v);
+ if (parent_node3d) {
+ NavigationServer3D::get_singleton()->agent_set_position(agent, parent_node3d->get_global_transform().origin);
+
+ PhysicsBody3D *rigid = Object::cast_to<PhysicsBody3D>(get_parent());
+ if (rigid) {
+ Vector3 v = rigid->get_linear_velocity();
+ NavigationServer3D::get_singleton()->agent_set_velocity(agent, v);
+ NavigationServer3D::get_singleton()->agent_set_target_velocity(agent, v);
+ }
}
-
} break;
}
}
@@ -93,29 +76,10 @@ NavigationObstacle3D::~NavigationObstacle3D() {
agent = RID(); // Pointless
}
-void NavigationObstacle3D::set_navigation(Navigation3D *p_nav) {
- if (navigation == p_nav) {
- return; // Pointless
- }
-
- navigation = p_nav;
- NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid());
-}
-
-void NavigationObstacle3D::set_navigation_node(Node *p_nav) {
- Navigation3D *nav = Object::cast_to<Navigation3D>(p_nav);
- ERR_FAIL_COND(nav == nullptr);
- set_navigation(nav);
-}
-
-Node *NavigationObstacle3D::get_navigation_node() const {
- return Object::cast_to<Node>(navigation);
-}
-
String NavigationObstacle3D::get_configuration_warning() const {
String warning = Node::get_configuration_warning();
- if (!Object::cast_to<Node3D>(get_parent())) {
+ if (!parent_node3d) {
if (!warning.is_empty()) {
warning += "\n\n";
}
@@ -126,40 +90,38 @@ String NavigationObstacle3D::get_configuration_warning() const {
}
void NavigationObstacle3D::update_agent_shape() {
- Node *node = get_parent();
-
- // Estimate the radius of this physics body
- real_t radius = 0.0;
- for (int i(0); i < node->get_child_count(); i++) {
- // For each collision shape
- CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(node->get_child(i));
- if (cs) {
- // Take the distance between the Body center to the shape center
- real_t r = cs->get_transform().origin.length();
- if (cs->get_shape().is_valid()) {
- // and add the enclosing shape radius
- r += cs->get_shape()->get_enclosing_radius();
+ if (parent_node3d) {
+ // Estimate the radius of this physics body
+ real_t radius = 0.0;
+ for (int i(0); i < parent_node3d->get_child_count(); i++) {
+ // For each collision shape
+ CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(parent_node3d->get_child(i));
+ if (cs) {
+ // Take the distance between the Body center to the shape center
+ real_t r = cs->get_transform().origin.length();
+ if (cs->get_shape().is_valid()) {
+ // and add the enclosing shape radius
+ r += cs->get_shape()->get_enclosing_radius();
+ }
+ Vector3 s = cs->get_global_transform().basis.get_scale();
+ r *= MAX(s.x, MAX(s.y, s.z));
+ // Takes the biggest radius
+ radius = MAX(radius, r);
}
- Vector3 s = cs->get_global_transform().basis.get_scale();
- r *= MAX(s.x, MAX(s.y, s.z));
- // Takes the biggest radius
- radius = MAX(radius, r);
}
- }
- Node3D *spa = Object::cast_to<Node3D>(node);
- if (spa) {
- Vector3 s = spa->get_global_transform().basis.get_scale();
+
+ Vector3 s = parent_node3d->get_global_transform().basis.get_scale();
radius *= MAX(s.x, MAX(s.y, s.z));
- }
- if (radius == 0.0) {
- radius = 1.0; // Never a 0 radius
- }
+ if (radius == 0.0) {
+ radius = 1.0; // Never a 0 radius
+ }
- // Initialize the Agent as an object
- NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
- NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0);
- NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0);
- NavigationServer3D::get_singleton()->agent_set_radius(agent, radius);
- NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0);
+ // Initialize the Agent as an object
+ NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
+ NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0);
+ NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0);
+ NavigationServer3D::get_singleton()->agent_set_radius(agent, radius);
+ NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0);
+ }
}
diff --git a/scene/3d/navigation_obstacle_3d.h b/scene/3d/navigation_obstacle_3d.h
index b8d05b8a87..b1bb53724a 100644
--- a/scene/3d/navigation_obstacle_3d.h
+++ b/scene/3d/navigation_obstacle_3d.h
@@ -31,15 +31,13 @@
#ifndef NAVIGATION_OBSTACLE_H
#define NAVIGATION_OBSTACLE_H
+#include "scene/3d/node_3d.h"
#include "scene/main/node.h"
-class Navigation3D;
-
class NavigationObstacle3D : public Node {
GDCLASS(NavigationObstacle3D, Node);
- Navigation3D *navigation = nullptr;
-
+ Node3D *parent_node3d = nullptr;
RID agent;
protected:
@@ -50,14 +48,6 @@ public:
NavigationObstacle3D();
virtual ~NavigationObstacle3D();
- void set_navigation(Navigation3D *p_nav);
- const Navigation3D *get_navigation() const {
- return navigation;
- }
-
- void set_navigation_node(Node *p_nav);
- Node *get_navigation_node() const;
-
RID get_rid() const {
return agent;
}
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index e8cfa05a4b..3ca704e4b8 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -32,7 +32,6 @@
#include "core/os/thread.h"
#include "mesh_instance_3d.h"
-#include "navigation_3d.h"
#include "servers/navigation_server_3d.h"
void NavigationRegion3D::set_enabled(bool p_enabled) {
@@ -48,9 +47,7 @@ void NavigationRegion3D::set_enabled(bool p_enabled) {
if (!enabled) {
NavigationServer3D::get_singleton()->region_set_map(region, RID());
} else {
- if (navigation) {
- NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid());
- }
+ NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
}
if (debug_view) {
@@ -69,22 +66,21 @@ bool NavigationRegion3D::is_enabled() const {
return enabled;
}
+void NavigationRegion3D::set_layers(uint32_t p_layers) {
+ NavigationServer3D::get_singleton()->region_set_layers(region, p_layers);
+}
+
+uint32_t NavigationRegion3D::get_layers() const {
+ return NavigationServer3D::get_singleton()->region_get_layers(region);
+}
+
/////////////////////////////
void NavigationRegion3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- Node3D *c = this;
- while (c) {
- navigation = Object::cast_to<Navigation3D>(c);
- if (navigation) {
- if (enabled) {
- NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid());
- }
- break;
- }
-
- c = c->get_parent_spatial();
+ if (enabled) {
+ NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
}
if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) {
@@ -105,15 +101,12 @@ void NavigationRegion3D::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
- if (navigation) {
- NavigationServer3D::get_singleton()->region_set_map(region, RID());
- }
+ NavigationServer3D::get_singleton()->region_set_map(region, RID());
if (debug_view) {
debug_view->queue_delete();
debug_view = nullptr;
}
- navigation = nullptr;
} break;
}
}
@@ -124,13 +117,13 @@ void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmes
}
if (navmesh.is_valid()) {
- navmesh->remove_change_receptor(this);
+ navmesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
}
navmesh = p_navmesh;
if (navmesh.is_valid()) {
- navmesh->add_change_receptor(this);
+ navmesh->connect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
}
NavigationServer3D::get_singleton()->region_set_navmesh(region, p_navmesh);
@@ -150,7 +143,7 @@ Ref<NavigationMesh> NavigationRegion3D::get_navigation_mesh() const {
}
struct BakeThreadsArgs {
- NavigationRegion3D *nav_region;
+ NavigationRegion3D *nav_region = nullptr;
};
void _bake_navigation_mesh(void *p_user_data) {
@@ -198,19 +191,7 @@ String NavigationRegion3D::get_configuration_warning() const {
warning += TTR("A NavigationMesh resource must be set or created for this node to work.");
}
- const Node3D *c = this;
- while (c) {
- if (Object::cast_to<Navigation3D>(c)) {
- return warning;
- }
-
- c = Object::cast_to<Node3D>(c->get_parent());
- }
-
- if (!warning.is_empty()) {
- warning += "\n\n";
- }
- return warning + TTR("NavigationRegion3D must be a child or grandchild to a Navigation3D node. It only provides navigation data.");
+ return warning;
}
void NavigationRegion3D::_bind_methods() {
@@ -220,17 +201,21 @@ void NavigationRegion3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion3D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion3D::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_layers", "layers"), &NavigationRegion3D::set_layers);
+ ClassDB::bind_method(D_METHOD("get_layers"), &NavigationRegion3D::get_layers);
+
ClassDB::bind_method(D_METHOD("bake_navigation_mesh"), &NavigationRegion3D::bake_navigation_mesh);
ClassDB::bind_method(D_METHOD("_bake_finished", "nav_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::BOOL, "enabled"), "set_enabled", "is_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_layers", "get_layers");
ADD_SIGNAL(MethodInfo("navigation_mesh_changed"));
ADD_SIGNAL(MethodInfo("bake_finished"));
}
-void NavigationRegion3D::_changed_callback(Object *p_changed, const char *p_prop) {
+void NavigationRegion3D::_navigation_changed() {
update_gizmo();
update_configuration_warning();
}
@@ -242,7 +227,7 @@ NavigationRegion3D::NavigationRegion3D() {
NavigationRegion3D::~NavigationRegion3D() {
if (navmesh.is_valid()) {
- navmesh->remove_change_receptor(this);
+ navmesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
}
NavigationServer3D::get_singleton()->free(region);
}
diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h
index e966523b64..52fa2d6159 100644
--- a/scene/3d/navigation_region_3d.h
+++ b/scene/3d/navigation_region_3d.h
@@ -35,8 +35,6 @@
#include "scene/resources/mesh.h"
#include "scene/resources/navigation_mesh.h"
-class Navigation3D;
-
class NavigationRegion3D : public Node3D {
GDCLASS(NavigationRegion3D, Node3D);
@@ -44,19 +42,22 @@ class NavigationRegion3D : public Node3D {
RID region;
Ref<NavigationMesh> navmesh;
- Navigation3D *navigation = nullptr;
Node *debug_view = nullptr;
Thread bake_thread;
+ void _navigation_changed();
+
protected:
void _notification(int p_what);
static void _bind_methods();
- void _changed_callback(Object *p_changed, const char *p_prop) override;
public:
void set_enabled(bool p_enabled);
bool is_enabled() const;
+ void set_layers(uint32_t p_layers);
+ uint32_t get_layers() const;
+
void set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh);
Ref<NavigationMesh> get_navigation_mesh() const;
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 57bead022b..ba0f8cc870 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -48,7 +48,7 @@
a) If above is invalid, don't keep invalidating upwards
2) If a node sets a GLOBAL, it is converted to LOCAL (and forces validation of everything pending below)
- drawback: setting/reading globals is useful and used very very often, and using affine inverses is slow
+ drawback: setting/reading globals is useful and used very often, and using affine inverses is slow
---
@@ -226,10 +226,6 @@ void Node3D::_notification(int p_what) {
void Node3D::set_transform(const Transform &p_transform) {
data.local_transform = p_transform;
data.dirty |= DIRTY_VECTORS;
- _change_notify("translation");
- _change_notify("rotation");
- _change_notify("rotation_degrees");
- _change_notify("scale");
_propagate_transform_changed(this);
if (data.notify_local_transform) {
notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
@@ -307,7 +303,6 @@ Transform Node3D::get_relative_transform(const Node *p_parent) const {
void Node3D::set_translation(const Vector3 &p_translation) {
data.local_transform.origin = p_translation;
- _change_notify("transform");
_propagate_transform_changed(this);
if (data.notify_local_transform) {
notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
@@ -322,7 +317,6 @@ void Node3D::set_rotation(const Vector3 &p_euler_rad) {
data.rotation = p_euler_rad;
data.dirty |= DIRTY_LOCAL;
- _change_notify("transform");
_propagate_transform_changed(this);
if (data.notify_local_transform) {
notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
@@ -341,7 +335,6 @@ void Node3D::set_scale(const Vector3 &p_scale) {
data.scale = p_scale;
data.dirty |= DIRTY_LOCAL;
- _change_notify("transform");
_propagate_transform_changed(this);
if (data.notify_local_transform) {
notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
@@ -495,7 +488,6 @@ Ref<World3D> Node3D::get_world_3d() const {
void Node3D::_propagate_visibility_changed() {
notification(NOTIFICATION_VISIBILITY_CHANGED);
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
- _change_notify("visible");
#ifdef TOOLS_ENABLED
if (data.gizmo.is_valid()) {
_update_gizmo();
@@ -755,8 +747,8 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("orthonormalize"), &Node3D::orthonormalize);
ClassDB::bind_method(D_METHOD("set_identity"), &Node3D::set_identity);
- ClassDB::bind_method(D_METHOD("look_at", "target", "up"), &Node3D::look_at);
- ClassDB::bind_method(D_METHOD("look_at_from_position", "position", "target", "up"), &Node3D::look_at_from_position);
+ ClassDB::bind_method(D_METHOD("look_at", "target", "up"), &Node3D::look_at, DEFVAL(Vector3(0, 1, 0)));
+ ClassDB::bind_method(D_METHOD("look_at_from_position", "position", "target", "up"), &Node3D::look_at_from_position, DEFVAL(Vector3(0, 1, 0)));
ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Node3D::to_local);
ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Node3D::to_global);
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h
index 8610e2c0bd..a62c7b31a8 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -173,8 +173,8 @@ public:
void global_scale(const Vector3 &p_scale);
void global_translate(const Vector3 &p_offset);
- void look_at(const Vector3 &p_target, const Vector3 &p_up);
- void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up);
+ void look_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
+ void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
Vector3 to_local(Vector3 p_global) const;
Vector3 to_global(Vector3 p_local) const;
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index 3f048beb71..7e2601902b 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -323,8 +323,6 @@ void PathFollow3D::set_offset(float p_offset) {
_update_transform();
}
- _change_notify("offset");
- _change_notify("unit_offset");
}
void PathFollow3D::set_h_offset(float p_h_offset) {
diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h
index 15e38c95e7..17ee47593e 100644
--- a/scene/3d/path_3d.h
+++ b/scene/3d/path_3d.h
@@ -66,10 +66,10 @@ public:
private:
Path3D *path = nullptr;
- real_t delta_offset = 0; // Change in offset since last _update_transform.
- real_t offset = 0;
- real_t h_offset = 0;
- real_t v_offset = 0;
+ real_t delta_offset = 0.0; // Change in offset since last _update_transform.
+ real_t offset = 0.0;
+ real_t h_offset = 0.0;
+ real_t v_offset = 0.0;
bool cubic = true;
bool loop = true;
RotationMode rotation_mode = ROTATION_XYZ;
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 71be943232..e225c1f22d 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -148,7 +148,8 @@ void PhysicsBody3D::_bind_methods() {
}
PhysicsBody3D::PhysicsBody3D(PhysicsServer3D::BodyMode p_mode) :
- CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(p_mode), false) {
+ CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(), false) {
+ PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), p_mode);
collision_layer = 1;
collision_mask = 1;
}
@@ -330,8 +331,8 @@ void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
struct _RigidBodyInOut {
ObjectID id;
- int shape;
- int local_shape;
+ int shape = 0;
+ int local_shape = 0;
};
void RigidBody3D::_direct_state_changed(Object *p_state) {
@@ -415,13 +416,13 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
}
}
- //process remotions
+ //process removals
for (int i = 0; i < toremove_count; i++) {
_body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
}
- //process aditions
+ //process additions
for (int i = 0; i < toadd_count; i++) {
_body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
@@ -825,24 +826,6 @@ void RigidBody3D::_bind_methods() {
RigidBody3D::RigidBody3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) {
- mode = MODE_RIGID;
-
- mass = 1;
- max_contacts_reported = 0;
- state = nullptr;
-
- gravity_scale = 1;
- linear_damp = -1;
- angular_damp = -1;
-
- //angular_velocity=0;
- sleeping = false;
- ccd = false;
-
- custom_integrator = false;
- contact_monitor = nullptr;
- can_sleep = true;
-
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
}
@@ -1221,11 +1204,6 @@ void KinematicBody3D::_direct_state_changed(Object *p_state) {
KinematicBody3D::KinematicBody3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
- locked_axis = 0;
- on_floor = false;
- on_ceiling = false;
- on_wall = false;
-
set_safe_margin(0.001);
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
}
@@ -2034,7 +2012,7 @@ void PhysicalBone3D::_notification(int p_what) {
update_bone_id();
reset_to_rest_position();
reset_physics_simulation_state();
- if (!joint.is_valid() && joint_data) {
+ if (joint_data) {
_reload_joint();
}
break;
@@ -2045,10 +2023,7 @@ void PhysicalBone3D::_notification(int p_what) {
}
}
parent_skeleton = nullptr;
- if (joint.is_valid()) {
- PhysicsServer3D::get_singleton()->free(joint);
- joint = RID();
- }
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
break;
case NOTIFICATION_TRANSFORM_CHANGED:
if (Engine::get_singleton()->is_editor_hint()) {
@@ -2198,17 +2173,14 @@ void PhysicalBone3D::_fix_joint_offset() {
}
void PhysicalBone3D::_reload_joint() {
- if (joint.is_valid()) {
- PhysicsServer3D::get_singleton()->free(joint);
- joint = RID();
- }
-
if (!parent_skeleton) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
return;
}
PhysicalBone3D *body_a = parent_skeleton->get_physical_bone_parent(bone_id);
if (!body_a) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
return;
}
@@ -2218,7 +2190,7 @@ void PhysicalBone3D::_reload_joint() {
switch (get_joint_type()) {
case JOINT_TYPE_PIN: {
- joint = PhysicsServer3D::get_singleton()->joint_create_pin(body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin);
+ PhysicsServer3D::get_singleton()->joint_make_pin(joint, body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin);
const PinJointData *pjd(static_cast<const PinJointData *>(joint_data));
PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_BIAS, pjd->bias);
PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_DAMPING, pjd->damping);
@@ -2226,7 +2198,7 @@ void PhysicalBone3D::_reload_joint() {
} break;
case JOINT_TYPE_CONE: {
- joint = PhysicsServer3D::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, get_rid(), joint_offset);
+ PhysicsServer3D::get_singleton()->joint_make_cone_twist(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
const ConeJointData *cjd(static_cast<const ConeJointData *>(joint_data));
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, cjd->swing_span);
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN, cjd->twist_span);
@@ -2236,7 +2208,7 @@ void PhysicalBone3D::_reload_joint() {
} break;
case JOINT_TYPE_HINGE: {
- joint = PhysicsServer3D::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, get_rid(), joint_offset);
+ PhysicsServer3D::get_singleton()->joint_make_hinge(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
const HingeJointData *hjd(static_cast<const HingeJointData *>(joint_data));
PhysicsServer3D::get_singleton()->hinge_joint_set_flag(joint, PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT, hjd->angular_limit_enabled);
PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, hjd->angular_limit_upper);
@@ -2247,7 +2219,7 @@ void PhysicalBone3D::_reload_joint() {
} break;
case JOINT_TYPE_SLIDER: {
- joint = PhysicsServer3D::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, get_rid(), joint_offset);
+ PhysicsServer3D::get_singleton()->joint_make_slider(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
const SliderJointData *sjd(static_cast<const SliderJointData *>(joint_data));
PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER, sjd->linear_limit_upper);
PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER, sjd->linear_limit_lower);
@@ -2262,7 +2234,7 @@ void PhysicalBone3D::_reload_joint() {
} break;
case JOINT_TYPE_6DOF: {
- joint = PhysicsServer3D::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, get_rid(), joint_offset);
+ PhysicsServer3D::get_singleton()->joint_make_generic_6dof(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
const SixDOFJointData *g6dofjd(static_cast<const SixDOFJointData *>(joint_data));
for (int axis = 0; axis < 3; ++axis) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, g6dofjd->axis_data[axis].linear_limit_enabled);
@@ -2355,7 +2327,7 @@ void PhysicalBone3D::set_joint_type(JointType p_joint_type) {
_reload_joint();
#ifdef TOOLS_ENABLED
- _change_notify();
+ notify_property_list_changed();
if (get_gizmo().is_valid()) {
get_gizmo()->redraw();
}
@@ -2370,7 +2342,6 @@ void PhysicalBone3D::set_joint_offset(const Transform &p_offset) {
joint_offset = p_offset;
_update_joint_offset();
- _change_notify("joint_rotation_degrees");
}
const Transform &PhysicalBone3D::get_joint_offset() const {
@@ -2381,7 +2352,6 @@ void PhysicalBone3D::set_joint_rotation(const Vector3 &p_euler_rad) {
joint_offset.basis.set_euler_scale(p_euler_rad, joint_offset.basis.get_scale());
_update_joint_offset();
- _change_notify("joint_offset");
}
Vector3 PhysicalBone3D::get_joint_rotation() const {
@@ -2516,6 +2486,7 @@ bool PhysicalBone3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const {
PhysicalBone3D::PhysicalBone3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC) {
+ joint = PhysicsServer3D::get_singleton()->joint_create();
reset_physics_simulation_state();
}
@@ -2523,6 +2494,7 @@ PhysicalBone3D::~PhysicalBone3D() {
if (joint_data) {
memdelete(joint_data);
}
+ PhysicsServer3D::get_singleton()->free(joint);
}
void PhysicalBone3D::update_bone_id() {
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 469c6b222c..1450fce6a6 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -111,31 +111,31 @@ public:
};
protected:
- bool can_sleep;
- PhysicsDirectBodyState3D *state;
- Mode mode;
+ bool can_sleep = true;
+ PhysicsDirectBodyState3D *state = nullptr;
+ Mode mode = MODE_RIGID;
- real_t mass;
+ real_t mass = 1.0;
Ref<PhysicsMaterial> physics_material_override;
Vector3 linear_velocity;
Vector3 angular_velocity;
Basis inverse_inertia_tensor;
- real_t gravity_scale;
- real_t linear_damp;
- real_t angular_damp;
+ real_t gravity_scale = 1.0;
+ real_t linear_damp = -1.0;
+ real_t angular_damp = -1.0;
- bool sleeping;
- bool ccd;
+ bool sleeping = false;
+ bool ccd = false;
- int max_contacts_reported;
+ int max_contacts_reported = 0;
- bool custom_integrator;
+ bool custom_integrator = false;
struct ShapePair {
- int body_shape;
- int local_shape;
- bool tagged;
+ int body_shape = 0;
+ int local_shape = 0;
+ bool tagged = false;
bool operator<(const ShapePair &p_sp) const {
if (body_shape == p_sp.body_shape) {
return local_shape < p_sp.local_shape;
@@ -157,16 +157,16 @@ protected:
};
struct BodyState {
//int rc;
- bool in_tree;
+ bool in_tree = false;
VSet<ShapePair> shapes;
};
struct ContactMonitor {
- bool locked;
+ bool locked = false;
Map<ObjectID, BodyState> body_map;
};
- ContactMonitor *contact_monitor;
+ ContactMonitor *contact_monitor = nullptr;
void _body_enter_tree(ObjectID p_id);
void _body_exit_tree(ObjectID p_id);
@@ -261,27 +261,27 @@ public:
Vector3 collider_vel;
ObjectID collider;
RID collider_rid;
- int collider_shape;
+ int collider_shape = 0;
Variant collider_metadata;
Vector3 remainder;
Vector3 travel;
- int local_shape;
+ int local_shape = 0;
};
private:
Vector3 linear_velocity;
Vector3 angular_velocity;
- uint16_t locked_axis;
+ uint16_t locked_axis = 0;
real_t margin;
Vector3 floor_normal;
Vector3 floor_velocity;
RID on_floor_body;
- bool on_floor;
- bool on_ceiling;
- bool on_wall;
+ bool on_floor = false;
+ bool on_ceiling = false;
+ bool on_wall = false;
Vector<Collision> colliders;
Vector<Ref<KinematicCollision3D>> slide_colliders;
Ref<KinematicCollision3D> motion_cache;
@@ -385,10 +385,8 @@ public:
virtual void _get_property_list(List<PropertyInfo> *p_list) const;
real_t bias = 0.3;
- real_t damping = 1.;
- real_t impulse_clamp = 0;
-
- PinJointData() {}
+ real_t damping = 1.0;
+ real_t impulse_clamp = 0.0;
};
struct ConeJointData : public JointData {
@@ -398,14 +396,11 @@ public:
virtual bool _get(const StringName &p_name, Variant &r_ret) const;
virtual void _get_property_list(List<PropertyInfo> *p_list) const;
- real_t swing_span;
+ real_t swing_span = Math_PI * 0.25;
real_t twist_span = Math_PI;
real_t bias = 0.3;
real_t softness = 0.8;
real_t relaxation = 1.;
-
- ConeJointData() :
- swing_span(Math_PI * 0.25) {}
};
struct HingeJointData : public JointData {
@@ -416,16 +411,11 @@ public:
virtual void _get_property_list(List<PropertyInfo> *p_list) const;
bool angular_limit_enabled = false;
- real_t angular_limit_upper;
- real_t angular_limit_lower;
+ real_t angular_limit_upper = Math_PI * 0.5;
+ real_t angular_limit_lower = -Math_PI * 0.5;
real_t angular_limit_bias = 0.3;
real_t angular_limit_softness = 0.9;
real_t angular_limit_relaxation = 1.;
-
- HingeJointData() :
-
- angular_limit_upper(Math_PI * 0.5),
- angular_limit_lower(-Math_PI * 0.5) {}
};
struct SliderJointData : public JointData {
@@ -435,45 +425,41 @@ public:
virtual bool _get(const StringName &p_name, Variant &r_ret) const;
virtual void _get_property_list(List<PropertyInfo> *p_list) const;
- real_t linear_limit_upper = 1.;
- real_t linear_limit_lower = -1.;
- real_t linear_limit_softness = 1.;
+ real_t linear_limit_upper = 1.0;
+ real_t linear_limit_lower = -1.0;
+ real_t linear_limit_softness = 1.0;
real_t linear_limit_restitution = 0.7;
- real_t linear_limit_damping = 1.;
- real_t angular_limit_upper = 0;
- real_t angular_limit_lower = 0;
- real_t angular_limit_softness = 1.;
+ real_t linear_limit_damping = 1.0;
+ real_t angular_limit_upper = 0.0;
+ real_t angular_limit_lower = 0.0;
+ real_t angular_limit_softness = 1.0;
real_t angular_limit_restitution = 0.7;
- real_t angular_limit_damping = 1.;
-
- SliderJointData() {}
+ real_t angular_limit_damping = 1.0;
};
struct SixDOFJointData : public JointData {
struct SixDOFAxisData {
bool linear_limit_enabled = true;
- real_t linear_limit_upper = 0;
- real_t linear_limit_lower = 0;
+ real_t linear_limit_upper = 0.0;
+ real_t linear_limit_lower = 0.0;
real_t linear_limit_softness = 0.7;
real_t linear_restitution = 0.5;
- real_t linear_damping = 1.;
+ real_t linear_damping = 1.0;
bool linear_spring_enabled = false;
- real_t linear_spring_stiffness = 0;
- real_t linear_spring_damping = 0;
- real_t linear_equilibrium_point = 0;
+ real_t linear_spring_stiffness = 0.0;
+ real_t linear_spring_damping = 0.0;
+ real_t linear_equilibrium_point = 0.0;
bool angular_limit_enabled = true;
- real_t angular_limit_upper = 0;
- real_t angular_limit_lower = 0;
+ real_t angular_limit_upper = 0.0;
+ real_t angular_limit_lower = 0.0;
real_t angular_limit_softness = 0.5;
- real_t angular_restitution = 0;
- real_t angular_damping = 1.;
+ real_t angular_restitution = 0.0;
+ real_t angular_damping = 1.0;
real_t erp = 0.5;
bool angular_spring_enabled = false;
- real_t angular_spring_stiffness = 0;
- real_t angular_spring_damping = 0.;
- real_t angular_equilibrium_point = 0;
-
- SixDOFAxisData() {}
+ real_t angular_spring_stiffness = 0.0;
+ real_t angular_spring_damping = 0.0;
+ real_t angular_equilibrium_point = 0.0;
};
virtual JointType get_joint_type() { return JOINT_TYPE_6DOF; }
@@ -505,12 +491,12 @@ private:
int bone_id = -1;
String bone_name;
- real_t bounce = 0;
- real_t mass = 1;
- real_t friction = 1;
- real_t gravity_scale = 1;
- real_t linear_damp = -1;
- real_t angular_damp = -1;
+ real_t bounce = 0.0;
+ real_t mass = 1.0;
+ real_t friction = 1.0;
+ real_t gravity_scale = 1.0;
+ real_t linear_damp = -1.0;
+ real_t angular_damp = -1.0;
bool can_sleep = true;
protected:
diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp
index b8d8af2385..de9c75621b 100644
--- a/scene/3d/physics_joint_3d.cpp
+++ b/scene/3d/physics_joint_3d.cpp
@@ -46,34 +46,24 @@ void Joint3D::_disconnect_signals() {
}
}
-void Joint3D::_body_exit_tree(const ObjectID &p_body_id) {
+void Joint3D::_body_exit_tree() {
_disconnect_signals();
- Object *object = ObjectDB::get_instance(p_body_id);
- PhysicsBody3D *body = Object::cast_to<PhysicsBody3D>(object);
- ERR_FAIL_NULL(body);
- RID body_rid = body->get_rid();
- if (ba == body_rid) {
- a = NodePath();
- }
- if (bb == body_rid) {
- b = NodePath();
- }
- _update_joint();
+ _update_joint(true);
}
void Joint3D::_update_joint(bool p_only_free) {
- if (joint.is_valid()) {
- if (ba.is_valid() && bb.is_valid()) {
- PhysicsServer3D::get_singleton()->body_remove_collision_exception(ba, bb);
- }
-
- PhysicsServer3D::get_singleton()->free(joint);
- joint = RID();
- ba = RID();
- bb = RID();
+ if (ba.is_valid() && bb.is_valid()) {
+ PhysicsServer3D::get_singleton()->body_remove_collision_exception(ba, bb);
+ PhysicsServer3D::get_singleton()->body_remove_collision_exception(bb, ba);
}
+ ba = RID();
+ bb = RID();
+
+ configured = false;
+
if (p_only_free || !is_inside_tree()) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
warning = String();
return;
}
@@ -85,30 +75,35 @@ void Joint3D::_update_joint(bool p_only_free) {
PhysicsBody3D *body_b = Object::cast_to<PhysicsBody3D>(node_b);
if (node_a && !body_a && node_b && !body_b) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
warning = TTR("Node A and Node B must be PhysicsBody3Ds");
update_configuration_warning();
return;
}
if (node_a && !body_a) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
warning = TTR("Node A must be a PhysicsBody3D");
update_configuration_warning();
return;
}
if (node_b && !body_b) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
warning = TTR("Node B must be a PhysicsBody3D");
update_configuration_warning();
return;
}
if (!body_a && !body_b) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
warning = TTR("Joint is not connected to any PhysicsBody3Ds");
update_configuration_warning();
return;
}
if (body_a == body_b) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
warning = TTR("Node A and Node B must be different PhysicsBody3Ds");
update_configuration_warning();
return;
@@ -117,24 +112,24 @@ void Joint3D::_update_joint(bool p_only_free) {
warning = String();
update_configuration_warning();
+ configured = true;
+
if (body_a) {
- joint = _configure_joint(body_a, body_b);
+ _configure_joint(joint, body_a, body_b);
} else if (body_b) {
- joint = _configure_joint(body_b, nullptr);
+ _configure_joint(joint, body_b, nullptr);
}
- ERR_FAIL_COND_MSG(!joint.is_valid(), "Failed to configure the joint.");
-
PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority);
if (body_a) {
ba = body_a->get_rid();
- body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree), make_binds(body_a->get_instance_id()));
+ body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
}
if (body_b) {
bb = body_b->get_rid();
- body_b->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree), make_binds(body_b->get_instance_id()));
+ body_b->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
}
PhysicsServer3D::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision);
@@ -245,9 +240,12 @@ void Joint3D::_bind_methods() {
}
Joint3D::Joint3D() {
- exclude_from_collision = true;
- solver_priority = 1;
set_notify_transform(true);
+ joint = PhysicsServer3D::get_singleton()->joint_create();
+}
+
+Joint3D::~Joint3D() {
+ PhysicsServer3D::get_singleton()->free(joint);
}
///////////////////////////////////
@@ -268,7 +266,7 @@ void PinJoint3D::_bind_methods() {
void PinJoint3D::set_param(Param p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, 3);
params[p_param] = p_value;
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer3D::get_singleton()->pin_joint_set_param(get_joint(), PhysicsServer3D::PinJointParam(p_param), p_value);
}
}
@@ -278,7 +276,7 @@ real_t PinJoint3D::get_param(Param p_param) const {
return params[p_param];
}
-RID PinJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+void PinJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
Vector3 pinpos = get_global_transform().origin;
Vector3 local_a = body_a->get_global_transform().affine_inverse().xform(pinpos);
Vector3 local_b;
@@ -289,11 +287,10 @@ RID PinJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
local_b = pinpos;
}
- RID j = PhysicsServer3D::get_singleton()->joint_create_pin(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+ PhysicsServer3D::get_singleton()->joint_make_pin(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
for (int i = 0; i < 3; i++) {
- PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PinJointParam(i), params[i]);
+ PhysicsServer3D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer3D::PinJointParam(i), params[i]);
}
- return j;
}
PinJoint3D::PinJoint3D() {
@@ -366,7 +363,7 @@ void HingeJoint3D::_bind_methods() {
void HingeJoint3D::set_param(Param p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params[p_param] = p_value;
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer3D::get_singleton()->hinge_joint_set_param(get_joint(), PhysicsServer3D::HingeJointParam(p_param), p_value);
}
@@ -381,7 +378,7 @@ real_t HingeJoint3D::get_param(Param p_param) const {
void HingeJoint3D::set_flag(Flag p_flag, bool p_value) {
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
flags[p_flag] = p_value;
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer3D::get_singleton()->hinge_joint_set_flag(get_joint(), PhysicsServer3D::HingeJointFlag(p_flag), p_value);
}
@@ -393,7 +390,7 @@ bool HingeJoint3D::get_flag(Flag p_flag) const {
return flags[p_flag];
}
-RID HingeJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+void HingeJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
Transform gt = get_global_transform();
Transform ainv = body_a->get_global_transform().affine_inverse();
@@ -408,15 +405,14 @@ RID HingeJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b)
local_b.orthonormalize();
- RID j = PhysicsServer3D::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+ PhysicsServer3D::get_singleton()->joint_make_hinge(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
for (int i = 0; i < PARAM_MAX; i++) {
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HingeJointParam(i), params[i]);
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(p_joint, PhysicsServer3D::HingeJointParam(i), params[i]);
}
for (int i = 0; i < FLAG_MAX; i++) {
set_flag(Flag(i), flags[i]);
- PhysicsServer3D::get_singleton()->hinge_joint_set_flag(j, PhysicsServer3D::HingeJointFlag(i), flags[i]);
+ PhysicsServer3D::get_singleton()->hinge_joint_set_flag(p_joint, PhysicsServer3D::HingeJointFlag(i), flags[i]);
}
- return j;
}
HingeJoint3D::HingeJoint3D() {
@@ -517,7 +513,7 @@ void SliderJoint3D::_bind_methods() {
void SliderJoint3D::set_param(Param p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params[p_param] = p_value;
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(get_joint(), PhysicsServer3D::SliderJointParam(p_param), p_value);
}
update_gizmo();
@@ -528,7 +524,7 @@ real_t SliderJoint3D::get_param(Param p_param) const {
return params[p_param];
}
-RID SliderJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+void SliderJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
Transform gt = get_global_transform();
Transform ainv = body_a->get_global_transform().affine_inverse();
@@ -543,12 +539,10 @@ RID SliderJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b
local_b.orthonormalize();
- RID j = PhysicsServer3D::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+ PhysicsServer3D::get_singleton()->joint_make_slider(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
for (int i = 0; i < PARAM_MAX; i++) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SliderJointParam(i), params[i]);
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(p_joint, PhysicsServer3D::SliderJointParam(i), params[i]);
}
-
- return j;
}
SliderJoint3D::SliderJoint3D() {
@@ -623,7 +617,7 @@ void ConeTwistJoint3D::_bind_methods() {
void ConeTwistJoint3D::set_param(Param p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params[p_param] = p_value;
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(get_joint(), PhysicsServer3D::ConeTwistJointParam(p_param), p_value);
}
@@ -635,7 +629,7 @@ real_t ConeTwistJoint3D::get_param(Param p_param) const {
return params[p_param];
}
-RID ConeTwistJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+void ConeTwistJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
Transform gt = get_global_transform();
//Vector3 cone_twistpos = gt.origin;
//Vector3 cone_twistdir = gt.basis.get_axis(2);
@@ -653,12 +647,10 @@ RID ConeTwistJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *bod
local_b.orthonormalize();
- RID j = PhysicsServer3D::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+ PhysicsServer3D::get_singleton()->joint_make_cone_twist(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
for (int i = 0; i < PARAM_MAX; i++) {
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::ConeTwistJointParam(i), params[i]);
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(p_joint, PhysicsServer3D::ConeTwistJointParam(i), params[i]);
}
-
- return j;
}
ConeTwistJoint3D::ConeTwistJoint3D() {
@@ -880,7 +872,7 @@ void Generic6DOFJoint3D::_bind_methods() {
void Generic6DOFJoint3D::set_param_x(Param p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params_x[p_param] = p_value;
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
}
@@ -895,7 +887,7 @@ real_t Generic6DOFJoint3D::get_param_x(Param p_param) const {
void Generic6DOFJoint3D::set_param_y(Param p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params_y[p_param] = p_value;
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
}
update_gizmo();
@@ -909,7 +901,7 @@ real_t Generic6DOFJoint3D::get_param_y(Param p_param) const {
void Generic6DOFJoint3D::set_param_z(Param p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
params_z[p_param] = p_value;
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
}
update_gizmo();
@@ -923,7 +915,7 @@ real_t Generic6DOFJoint3D::get_param_z(Param p_param) const {
void Generic6DOFJoint3D::set_flag_x(Flag p_flag, bool p_enabled) {
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
flags_x[p_flag] = p_enabled;
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
}
update_gizmo();
@@ -937,7 +929,7 @@ bool Generic6DOFJoint3D::get_flag_x(Flag p_flag) const {
void Generic6DOFJoint3D::set_flag_y(Flag p_flag, bool p_enabled) {
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
flags_y[p_flag] = p_enabled;
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
}
update_gizmo();
@@ -951,7 +943,7 @@ bool Generic6DOFJoint3D::get_flag_y(Flag p_flag) const {
void Generic6DOFJoint3D::set_flag_z(Flag p_flag, bool p_enabled) {
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
flags_z[p_flag] = p_enabled;
- if (get_joint().is_valid()) {
+ if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
}
update_gizmo();
@@ -962,7 +954,7 @@ bool Generic6DOFJoint3D::get_flag_z(Flag p_flag) const {
return flags_z[p_flag];
}
-RID Generic6DOFJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+void Generic6DOFJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
Transform gt = get_global_transform();
//Vector3 cone_twistpos = gt.origin;
//Vector3 cone_twistdir = gt.basis.get_axis(2);
@@ -980,19 +972,17 @@ RID Generic6DOFJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *b
local_b.orthonormalize();
- RID j = PhysicsServer3D::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+ PhysicsServer3D::get_singleton()->joint_make_generic_6dof(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
for (int i = 0; i < PARAM_MAX; i++) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisParam(i), params_x[i]);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisParam(i), params_y[i]);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisParam(i), params_z[i]);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(p_joint, Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisParam(i), params_x[i]);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(p_joint, Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisParam(i), params_y[i]);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(p_joint, Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisParam(i), params_z[i]);
}
for (int i = 0; i < FLAG_MAX; i++) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_x[i]);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_y[i]);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_z[i]);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(p_joint, Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_x[i]);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(p_joint, Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_y[i]);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(p_joint, Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_z[i]);
}
-
- return j;
}
Generic6DOFJoint3D::Generic6DOFJoint3D() {
diff --git a/scene/3d/physics_joint_3d.h b/scene/3d/physics_joint_3d.h
index e5fd6e6c87..f624ba602b 100644
--- a/scene/3d/physics_joint_3d.h
+++ b/scene/3d/physics_joint_3d.h
@@ -44,21 +44,24 @@ class Joint3D : public Node3D {
NodePath a;
NodePath b;
- int solver_priority;
- bool exclude_from_collision;
+ int solver_priority = 1;
+ bool exclude_from_collision = true;
String warning;
+ bool configured = false;
protected:
void _disconnect_signals();
- void _body_exit_tree(const ObjectID &p_body_id);
+ void _body_exit_tree();
void _update_joint(bool p_only_free = false);
void _notification(int p_what);
- virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) = 0;
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) = 0;
static void _bind_methods();
+ _FORCE_INLINE_ bool is_configured() const { return configured; }
+
public:
virtual String get_configuration_warning() const override;
@@ -76,6 +79,7 @@ public:
RID get_joint() const { return joint; }
Joint3D();
+ ~Joint3D();
};
///////////////////////////////////////////
@@ -92,7 +96,7 @@ public:
protected:
real_t params[3];
- virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
static void _bind_methods();
public:
@@ -129,7 +133,7 @@ public:
protected:
real_t params[PARAM_MAX];
bool flags[FLAG_MAX];
- virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
static void _bind_methods();
void _set_upper_limit(real_t p_limit);
@@ -191,7 +195,7 @@ protected:
real_t _get_lower_limit_angular() const;
real_t params[PARAM_MAX];
- virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
static void _bind_methods();
public:
@@ -224,7 +228,7 @@ protected:
real_t _get_twist_span() const;
real_t params[PARAM_MAX];
- virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
static void _bind_methods();
public:
@@ -302,7 +306,7 @@ protected:
real_t params_z[PARAM_MAX];
bool flags_z[FLAG_MAX];
- virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
static void _bind_methods();
public:
diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp
index 0b7c15a023..66f3e539a2 100644
--- a/scene/3d/ray_cast_3d.cpp
+++ b/scene/3d/ray_cast_3d.cpp
@@ -37,10 +37,13 @@
void RayCast3D::set_target_position(const Vector3 &p_point) {
target_position = p_point;
- if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) {
- update_gizmo();
- }
- if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) {
+ update_gizmo();
+
+ if (Engine::get_singleton()->is_editor_hint()) {
+ if (is_inside_tree()) {
+ _update_debug_shape_vertices();
+ }
+ } else if (debug_shape) {
_update_debug_shape();
}
}
@@ -146,6 +149,9 @@ bool RayCast3D::get_exclude_parent_body() const {
void RayCast3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ _update_debug_shape_vertices();
+ }
if (enabled && !Engine::get_singleton()->is_editor_hint()) {
set_physics_process_internal(true);
} else {
@@ -183,10 +189,7 @@ void RayCast3D::_notification(int p_what) {
bool prev_collision_state = collided;
_update_raycast_state();
if (prev_collision_state != collided && get_tree()->is_debugging_collisions_hint()) {
- if (debug_material.is_valid()) {
- Ref<StandardMaterial3D> line_material = static_cast<Ref<StandardMaterial3D>>(debug_material);
- line_material->set_albedo(collided ? Color(1.0, 0, 0) : Color(1.0, 0.8, 0.6));
- }
+ _update_debug_shape_material(true);
}
} break;
@@ -310,6 +313,12 @@ void RayCast3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &RayCast3D::set_collide_with_bodies);
ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &RayCast3D::is_collide_with_bodies_enabled);
+ ClassDB::bind_method(D_METHOD("set_debug_shape_custom_color", "debug_shape_custom_color"), &RayCast3D::set_debug_shape_custom_color);
+ ClassDB::bind_method(D_METHOD("get_debug_shape_custom_color"), &RayCast3D::get_debug_shape_custom_color);
+
+ ClassDB::bind_method(D_METHOD("set_debug_shape_thickness", "debug_shape_thickness"), &RayCast3D::set_debug_shape_thickness);
+ ClassDB::bind_method(D_METHOD("get_debug_shape_thickness"), &RayCast3D::get_debug_shape_thickness);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position"), "set_target_position", "get_target_position");
@@ -318,16 +327,80 @@ void RayCast3D::_bind_methods() {
ADD_GROUP("Collide With", "collide_with");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_bodies", "is_collide_with_bodies_enabled");
+
+ ADD_GROUP("Debug Shape", "debug_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_shape_custom_color"), "set_debug_shape_custom_color", "get_debug_shape_custom_color");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_shape_thickness", PROPERTY_HINT_RANGE, "1,5"), "set_debug_shape_thickness", "get_debug_shape_thickness");
}
-void RayCast3D::_create_debug_shape() {
- if (!debug_material.is_valid()) {
- debug_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+float RayCast3D::get_debug_shape_thickness() const {
+ return debug_shape_thickness;
+}
+
+void RayCast3D::_update_debug_shape_vertices() {
+ debug_shape_vertices.clear();
+ debug_line_vertices.clear();
- Ref<StandardMaterial3D> line_material = static_cast<Ref<StandardMaterial3D>>(debug_material);
- line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
- line_material->set_albedo(Color(1.0, 0.8, 0.6));
+ if (target_position == Vector3()) {
+ return;
+ }
+
+ debug_line_vertices.push_back(Vector3());
+ debug_line_vertices.push_back(target_position);
+
+ if (debug_shape_thickness > 1) {
+ float scale_factor = 100.0;
+ Vector3 dir = Vector3(target_position).normalized();
+ // Draw truncated pyramid
+ Vector3 normal = (fabs(dir.x) + fabs(dir.y) > CMP_EPSILON) ? Vector3(-dir.y, dir.x, 0).normalized() : Vector3(0, -dir.z, dir.y).normalized();
+ normal *= debug_shape_thickness / scale_factor;
+ int vertices_strip_order[14] = { 4, 5, 0, 1, 2, 5, 6, 4, 7, 0, 3, 2, 7, 6 };
+ for (int v = 0; v < 14; v++) {
+ Vector3 vertex = vertices_strip_order[v] < 4 ? normal : normal / 3.0 + target_position;
+ debug_shape_vertices.push_back(vertex.rotated(dir, Math_PI * (0.5 * (vertices_strip_order[v] % 4) + 0.25)));
+ }
+ }
+}
+
+void RayCast3D::set_debug_shape_thickness(const float p_debug_shape_thickness) {
+ debug_shape_thickness = p_debug_shape_thickness;
+ update_gizmo();
+
+ if (Engine::get_singleton()->is_editor_hint()) {
+ if (is_inside_tree()) {
+ _update_debug_shape_vertices();
+ }
+ } else if (debug_shape) {
+ _update_debug_shape();
}
+}
+
+const Vector<Vector3> &RayCast3D::get_debug_shape_vertices() const {
+ return debug_shape_vertices;
+}
+
+const Vector<Vector3> &RayCast3D::get_debug_line_vertices() const {
+ return debug_line_vertices;
+}
+
+void RayCast3D::set_debug_shape_custom_color(const Color &p_color) {
+ debug_shape_custom_color = p_color;
+ if (debug_material.is_valid()) {
+ _update_debug_shape_material();
+ }
+}
+
+Ref<StandardMaterial3D> RayCast3D::get_debug_material() {
+ _update_debug_shape_material();
+ return debug_material;
+}
+
+const Color &RayCast3D::get_debug_shape_custom_color() const {
+ return debug_shape_custom_color;
+}
+
+void RayCast3D::_create_debug_shape() {
+ _update_debug_shape_material();
Ref<ArrayMesh> mesh = memnew(ArrayMesh);
@@ -338,6 +411,35 @@ void RayCast3D::_create_debug_shape() {
debug_shape = mi;
}
+void RayCast3D::_update_debug_shape_material(bool p_check_collision) {
+ if (!debug_material.is_valid()) {
+ Ref<StandardMaterial3D> material = memnew(StandardMaterial3D);
+ debug_material = material;
+
+ material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ material->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA);
+ }
+
+ Color color = debug_shape_custom_color;
+ if (color == Color(0.0, 0.0, 0.0)) {
+ // Use the default debug shape color defined in the Project Settings.
+ color = get_tree()->get_debug_collisions_color();
+ }
+
+ if (p_check_collision) {
+ if ((color.get_h() < 0.055 || color.get_h() > 0.945) && color.get_s() > 0.5 && color.get_v() > 0.5) {
+ // If base color is already quite reddish, highlight collision with green color
+ color = Color(0.0, 1.0, 0.0, color.a);
+ } else {
+ // Else, highlight collision with red color
+ color = Color(1.0, 0, 0, color.a);
+ }
+ }
+
+ Ref<StandardMaterial3D> material = static_cast<Ref<StandardMaterial3D>>(debug_material);
+ material->set_albedo(color);
+}
+
void RayCast3D::_update_debug_shape() {
if (!enabled) {
return;
@@ -353,26 +455,28 @@ void RayCast3D::_update_debug_shape() {
return;
}
- Vector<Vector3> verts;
- verts.push_back(Vector3());
- verts.push_back(target_position);
+ _update_debug_shape_vertices();
+
+ mesh->clear_surfaces();
- if (mesh->get_surface_count() == 0) {
- Array a;
- a.resize(Mesh::ARRAY_MAX);
- a[Mesh::ARRAY_VERTEX] = verts;
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
- uint32_t flags = Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE;
+ uint32_t flags = 0;
+ int surface_count = 0;
+ if (!debug_line_vertices.is_empty()) {
+ a[Mesh::ARRAY_VERTEX] = debug_line_vertices;
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags);
- mesh->surface_set_material(0, debug_material);
- } else {
- Vector<uint8_t> byte_array;
- int array_size = sizeof(Vector3) * verts.size();
- byte_array.resize(array_size);
- copymem(byte_array.ptrw(), verts.ptr(), array_size);
+ mesh->surface_set_material(surface_count, debug_material);
+ ++surface_count;
+ }
- RS::get_singleton()->mesh_surface_update_region(mesh->get_rid(), 0, 0, byte_array);
+ if (!debug_shape_vertices.is_empty()) {
+ a[Mesh::ARRAY_VERTEX] = debug_shape_vertices;
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLE_STRIP, a, Array(), Dictionary(), flags);
+ mesh->surface_set_material(surface_count, debug_material);
+ ++surface_count;
}
}
@@ -392,13 +496,4 @@ void RayCast3D::_clear_debug_shape() {
}
RayCast3D::RayCast3D() {
- enabled = true;
- collided = false;
- against_shape = 0;
- collision_mask = 1;
- target_position = Vector3(0, -1, 0);
- debug_shape = nullptr;
- exclude_parent_body = true;
- collide_with_areas = false;
- collide_with_bodies = true;
}
diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h
index 4109853280..968cede9f2 100644
--- a/scene/3d/ray_cast_3d.h
+++ b/scene/3d/ray_cast_3d.h
@@ -36,28 +36,34 @@
class RayCast3D : public Node3D {
GDCLASS(RayCast3D, Node3D);
- bool enabled;
- bool collided;
+ bool enabled = true;
+ bool collided = false;
ObjectID against;
- int against_shape;
+ int against_shape = 0;
Vector3 collision_point;
Vector3 collision_normal;
- Vector3 target_position;
+ Vector3 target_position = Vector3(0, -1, 0);
Set<RID> exclude;
- uint32_t collision_mask;
- bool exclude_parent_body;
+ uint32_t collision_mask = 1;
+ bool exclude_parent_body = true;
- Node *debug_shape;
+ Node *debug_shape = nullptr;
Ref<Material> debug_material;
+ Color debug_shape_custom_color = Color(0.0, 0.0, 0.0);
+ int debug_shape_thickness = 2;
+ Vector<Vector3> debug_shape_vertices;
+ Vector<Vector3> debug_line_vertices;
void _create_debug_shape();
void _update_debug_shape();
+ void _update_debug_shape_material(bool p_check_collision = false);
+ void _update_debug_shape_vertices();
void _clear_debug_shape();
- bool collide_with_areas;
- bool collide_with_bodies;
+ bool collide_with_areas = false;
+ bool collide_with_bodies = true;
protected:
void _notification(int p_what);
@@ -86,6 +92,17 @@ public:
void set_exclude_parent_body(bool p_exclude_parent_body);
bool get_exclude_parent_body() const;
+ const Color &get_debug_shape_custom_color() const;
+ void set_debug_shape_custom_color(const Color &p_color);
+
+ const Vector<Vector3> &get_debug_shape_vertices() const;
+ const Vector<Vector3> &get_debug_line_vertices() const;
+
+ Ref<StandardMaterial3D> get_debug_material();
+
+ float get_debug_shape_thickness() const;
+ void set_debug_shape_thickness(const float p_debug_thickness);
+
void force_raycast_update();
bool is_colliding() const;
Object *get_collider() const;
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index 63fa0c06c3..ad24f39bce 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -42,7 +42,7 @@ float ReflectionProbe::get_intensity() const {
void ReflectionProbe::set_ambient_mode(AmbientMode p_mode) {
ambient_mode = p_mode;
RS::get_singleton()->reflection_probe_set_ambient_mode(probe, RS::ReflectionProbeAmbientMode(p_mode));
- _change_notify();
+ notify_property_list_changed();
}
ReflectionProbe::AmbientMode ReflectionProbe::get_ambient_mode() const {
@@ -95,13 +95,12 @@ void ReflectionProbe::set_extents(const Vector3 &p_extents) {
if (extents[i] - 0.01 < ABS(origin_offset[i])) {
origin_offset[i] = SGN(origin_offset[i]) * (extents[i] - 0.01);
- _change_notify("origin_offset");
}
}
RS::get_singleton()->reflection_probe_set_extents(probe, extents);
RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset);
- _change_notify("extents");
+
update_gizmo();
}
@@ -120,7 +119,6 @@ void ReflectionProbe::set_origin_offset(const Vector3 &p_extents) {
RS::get_singleton()->reflection_probe_set_extents(probe, extents);
RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset);
- _change_notify("origin_offset");
update_gizmo();
}
@@ -257,20 +255,6 @@ void ReflectionProbe::_bind_methods() {
}
ReflectionProbe::ReflectionProbe() {
- intensity = 1.0;
- ambient_mode = AMBIENT_ENVIRONMENT;
- ambient_color = Color(0, 0, 0);
- ambient_color_energy = 1.0;
- max_distance = 0;
- extents = Vector3(1, 1, 1);
- origin_offset = Vector3(0, 0, 0);
- box_projection = false;
- interior = false;
- enable_shadows = false;
- cull_mask = (1 << 20) - 1;
- update_mode = UPDATE_ONCE;
- lod_threshold = 1.0;
-
probe = RenderingServer::get_singleton()->reflection_probe_create();
RS::get_singleton()->instance_set_base(get_instance(), probe);
set_disable_scale(true);
diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h
index a43d4e2422..15c2da3ae0 100644
--- a/scene/3d/reflection_probe.h
+++ b/scene/3d/reflection_probe.h
@@ -53,20 +53,20 @@ public:
private:
RID probe;
- float intensity;
- float max_distance;
- Vector3 extents;
- Vector3 origin_offset;
- bool box_projection;
- bool enable_shadows;
- bool interior;
- AmbientMode ambient_mode;
- Color ambient_color;
- float ambient_color_energy;
- float lod_threshold;
-
- uint32_t cull_mask;
- UpdateMode update_mode;
+ float intensity = 1.0;
+ float max_distance = 0.0;
+ Vector3 extents = Vector3(1, 1, 1);
+ Vector3 origin_offset = Vector3(0, 0, 0);
+ bool box_projection = false;
+ bool enable_shadows = false;
+ bool interior = false;
+ AmbientMode ambient_mode = AMBIENT_ENVIRONMENT;
+ Color ambient_color = Color(0, 0, 0);
+ float ambient_color_energy = 1.0;
+ float lod_threshold = 1.0;
+
+ uint32_t cull_mask = (1 << 20) - 1;
+ UpdateMode update_mode = UPDATE_ONCE;
protected:
static void _bind_methods();
diff --git a/scene/3d/remote_transform_3d.cpp b/scene/3d/remote_transform_3d.cpp
index 4afbb80779..83ac813c53 100644
--- a/scene/3d/remote_transform_3d.cpp
+++ b/scene/3d/remote_transform_3d.cpp
@@ -217,10 +217,5 @@ void RemoteTransform3D::_bind_methods() {
}
RemoteTransform3D::RemoteTransform3D() {
- use_global_coordinates = true;
- update_remote_position = true;
- update_remote_rotation = true;
- update_remote_scale = true;
-
set_notify_transform(true);
}
diff --git a/scene/3d/remote_transform_3d.h b/scene/3d/remote_transform_3d.h
index 3b30c835be..21005d92d1 100644
--- a/scene/3d/remote_transform_3d.h
+++ b/scene/3d/remote_transform_3d.h
@@ -40,10 +40,10 @@ class RemoteTransform3D : public Node3D {
ObjectID cache;
- bool use_global_coordinates;
- bool update_remote_position;
- bool update_remote_rotation;
- bool update_remote_scale;
+ bool use_global_coordinates = true;
+ bool update_remote_position = true;
+ bool update_remote_rotation = true;
+ bool update_remote_scale = true;
void _update_remote();
void _update_cache();
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index 5e09a15b80..be62fe801f 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -304,7 +304,7 @@ void Skeleton3D::_notification(int p_what) {
uint32_t bind_count = skin->get_bind_count();
if (E->get()->bind_count != bind_count) {
- RS::get_singleton()->skeleton_allocate(skeleton, bind_count);
+ RS::get_singleton()->skeleton_allocate_data(skeleton, bind_count);
E->get()->bind_count = bind_count;
E->get()->skin_bone_indices.resize(bind_count);
E->get()->skin_bone_indices_ptrs = E->get()->skin_bone_indices.ptrw();
@@ -927,10 +927,6 @@ void Skeleton3D::_bind_methods() {
}
Skeleton3D::Skeleton3D() {
- animate_physical_bones = true;
- dirty = false;
- version = 1;
- process_order_dirty = true;
}
Skeleton3D::~Skeleton3D() {
diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h
index 73417dce21..9772bfcc95 100644
--- a/scene/3d/skeleton_3d.h
+++ b/scene/3d/skeleton_3d.h
@@ -74,57 +74,44 @@ private:
struct Bone {
String name;
- bool enabled;
- int parent;
- int sort_index; //used for re-sorting process order
+ bool enabled = true;
+ int parent = -1;
+ int sort_index = 0; //used for re-sorting process order
- bool disable_rest;
+ bool disable_rest = false;
Transform rest;
Transform pose;
Transform pose_global;
- bool custom_pose_enable;
+ bool custom_pose_enable = false;
Transform custom_pose;
- float global_pose_override_amount;
- bool global_pose_override_reset;
+ float global_pose_override_amount = 0.0;
+ bool global_pose_override_reset = false;
Transform global_pose_override;
#ifndef _3D_DISABLED
- PhysicalBone3D *physical_bone;
- PhysicalBone3D *cache_parent_physical_bone;
+ PhysicalBone3D *physical_bone = nullptr;
+ PhysicalBone3D *cache_parent_physical_bone = nullptr;
#endif // _3D_DISABLED
List<ObjectID> nodes_bound;
-
- Bone() {
- parent = -1;
- enabled = true;
- disable_rest = false;
- custom_pose_enable = false;
- global_pose_override_amount = 0;
- global_pose_override_reset = false;
-#ifndef _3D_DISABLED
- physical_bone = nullptr;
- cache_parent_physical_bone = nullptr;
-#endif // _3D_DISABLED
- }
};
Set<SkinReference *> skin_bindings;
void _skin_changed();
- bool animate_physical_bones;
+ bool animate_physical_bones = true;
Vector<Bone> bones;
Vector<int> process_order;
- bool process_order_dirty;
+ bool process_order_dirty = true;
void _make_dirty();
- bool dirty;
+ bool dirty = false;
- uint64_t version;
+ uint64_t version = 1;
// bind helpers
Array _get_bound_child_nodes_to_bone(int p_bone) const {
diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp
index cb486a12ae..85da546430 100644
--- a/scene/3d/skeleton_ik_3d.cpp
+++ b/scene/3d/skeleton_ik_3d.cpp
@@ -63,7 +63,6 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
chain.chain_root.bone = p_task->root_bone;
chain.chain_root.initial_transform = p_task->skeleton->get_bone_global_pose(chain.chain_root.bone);
chain.chain_root.current_pos = chain.chain_root.initial_transform.origin;
- chain.chain_root.pb = p_task->skeleton->get_physical_bone(chain.chain_root.bone);
chain.middle_chain_item = nullptr;
// Holds all IDs that are composing a single chain in reverse order
@@ -96,8 +95,6 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
if (!child_ci) {
child_ci = sub_chain->add_child(chain_ids[i]);
- child_ci->pb = p_task->skeleton->get_physical_bone(child_ci->bone);
-
child_ci->initial_transform = p_task->skeleton->get_bone_global_pose(child_ci->bone);
child_ci->current_pos = child_ci->initial_transform.origin;
@@ -123,7 +120,7 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
if (p_force_simple_chain) {
// NOTE:
- // This is an "hack" that force to create only one tip per chain since the solver of multi tip (end effector)
+ // This is a "hack" that force to create only one tip per chain since the solver of multi tip (end effector)
// is not yet created.
// Remove this code when this is done
break;
@@ -132,20 +129,6 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
return true;
}
-void FabrikInverseKinematic::update_chain(const Skeleton3D *p_sk, ChainItem *p_chain_item) {
- if (!p_chain_item) {
- return;
- }
-
- p_chain_item->initial_transform = p_sk->get_bone_global_pose(p_chain_item->bone);
- p_chain_item->current_pos = p_chain_item->initial_transform.origin;
-
- ChainItem *items = p_chain_item->children.ptrw();
- for (int i = 0; i < p_chain_item->children.size(); i += 1) {
- update_chain(p_sk, items + i);
- }
-}
-
void FabrikInverseKinematic::solve_simple(Task *p_task, bool p_solve_magnet) {
real_t distance_to_goal(1e4);
real_t previous_distance_to_goal(0);
@@ -263,7 +246,7 @@ void FabrikInverseKinematic::make_goal(Task *p_task, const Transform &p_inverse_
p_task->end_effectors.write[0].goal_transform = p_inverse_transf * p_task->goal_global_transform;
} else {
// End effector in local transform
- const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose(p_task->end_effectors.write[0].tip_bone));
+ const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose(p_task->end_effectors[0].tip_bone));
// Update the end_effector (local transform) by blending with current pose
p_task->end_effectors.write[0].goal_transform = end_effector_pose.interpolate_with(p_inverse_transf * p_task->goal_global_transform, blending_delta);
@@ -285,9 +268,11 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
p_task->skeleton->set_bone_global_pose_override(p_task->chain.tips[i].chain_item->bone, Transform(), 0.0, true);
}
- make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse().scaled(p_task->skeleton->get_global_transform().get_basis().get_scale()), blending_delta);
+ // Update the initial root transform
+ p_task->chain.chain_root.initial_transform = p_task->skeleton->get_bone_global_pose(p_task->chain.chain_root.bone);
+ p_task->chain.chain_root.current_pos = p_task->chain.chain_root.initial_transform.origin;
- update_chain(p_task->skeleton, &p_task->chain.chain_root);
+ make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse(), blending_delta);
if (p_use_magnet && p_task->chain.middle_chain_item) {
p_task->chain.magnet_position = p_task->chain.middle_chain_item->initial_transform.origin.lerp(p_magnet_position, blending_delta);
@@ -310,6 +295,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
const real_t rot_angle(Math::acos(CLAMP(initial_ori.dot(ci->current_ori), -1, 1)));
new_bone_pose.basis.rotate(rot_axis, rot_angle);
}
+
} else {
// Set target orientation to tip
if (override_tip_basis) {
@@ -319,6 +305,10 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
}
}
+ // IK should not affect scale, so undo any scaling
+ new_bone_pose.basis.orthonormalize();
+ new_bone_pose.basis.scale(p_task->skeleton->get_bone_global_pose(ci->bone).basis.get_scale());
+
p_task->skeleton->set_bone_global_pose_override(ci->bone, new_bone_pose, 1.0, true);
if (!ci->children.is_empty()) {
diff --git a/scene/3d/skeleton_ik_3d.h b/scene/3d/skeleton_ik_3d.h
index 557647aa62..c98f55804c 100644
--- a/scene/3d/skeleton_ik_3d.h
+++ b/scene/3d/skeleton_ik_3d.h
@@ -52,17 +52,14 @@ class FabrikInverseKinematic {
// Bone info
BoneId bone = -1;
- PhysicalBone3D *pb = nullptr;
- real_t length = 0;
+ real_t length = 0.0;
/// Positions relative to root bone
Transform initial_transform;
Vector3 current_pos;
// Direction from this bone to child
Vector3 current_ori;
- ChainItem() {}
-
ChainItem *find_child(const BoneId p_bone_id);
ChainItem *add_child(const BoneId p_bone_id);
};
@@ -80,7 +77,7 @@ class FabrikInverseKinematic {
struct Chain {
ChainItem chain_root;
- ChainItem *middle_chain_item;
+ ChainItem *middle_chain_item = nullptr;
Vector<ChainTip> tips;
Vector3 magnet_position;
};
@@ -109,8 +106,6 @@ private:
/// Init a chain that starts from the root to tip
static bool build_chain(Task *p_task, bool p_force_simple_chain = true);
- static void update_chain(const Skeleton3D *p_sk, ChainItem *p_chain_item);
-
static void solve_simple(Task *p_task, bool p_solve_magnet);
/// Special solvers that solve only chains with one end effector
static void solve_simple_backwards(Chain &r_chain, bool p_solve_magnet);
@@ -130,7 +125,7 @@ class SkeletonIK3D : public Node {
StringName root_bone;
StringName tip_bone;
- real_t interpolation = 1;
+ real_t interpolation = 1.0;
Transform target;
NodePath target_node_path_override;
bool override_tip_basis = true;
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index 785465f28e..3fde4d6ef3 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -37,7 +37,6 @@
#include "scene/3d/collision_object_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/3d/skeleton_3d.h"
-#include "servers/physics_server_3d.h"
SoftBodyRenderingServerHandler::SoftBodyRenderingServerHandler() {}
@@ -48,27 +47,28 @@ void SoftBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) {
mesh = p_mesh;
surface = p_surface;
-#ifndef _MSC_VER
-#warning Softbody is not working, needs to be redone considering that these functions no longer exist
-#endif
-#if 0
- const uint32_t surface_format = RS::get_singleton()->mesh_surface_get_format(mesh, surface);
- const int surface_vertex_len = RS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface);
- const int surface_index_len = RS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface);
+
+ RS::SurfaceData surface_data = RS::get_singleton()->mesh_get_surface(mesh, surface);
+
uint32_t surface_offsets[RS::ARRAY_MAX];
+ uint32_t vertex_stride;
+ uint32_t attrib_stride;
+ uint32_t skin_stride;
+ RS::get_singleton()->mesh_surface_make_offsets_from_format(surface_data.format, surface_data.vertex_count, surface_data.index_count, surface_offsets, vertex_stride, attrib_stride, skin_stride);
- buffer = RS::get_singleton()->mesh_surface_get_array(mesh, surface);
- stride = RS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets);
+ buffer = surface_data.vertex_data;
+ stride = vertex_stride;
offset_vertices = surface_offsets[RS::ARRAY_VERTEX];
offset_normal = surface_offsets[RS::ARRAY_NORMAL];
-#endif
}
void SoftBodyRenderingServerHandler::clear() {
- if (mesh.is_valid()) {
- buffer.resize(0);
- }
+ buffer.resize(0);
+ stride = 0;
+ offset_vertices = 0;
+ offset_normal = 0;
+ surface = 0;
mesh = RID();
}
@@ -77,7 +77,7 @@ void SoftBodyRenderingServerHandler::open() {
}
void SoftBodyRenderingServerHandler::close() {
- //write_buffer.release();
+ write_buffer = nullptr;
}
void SoftBodyRenderingServerHandler::commit_changes() {
@@ -245,13 +245,11 @@ bool SoftBody3D::_get_property_pinned_points(int p_item, const String &p_what, V
return true;
}
-void SoftBody3D::_changed_callback(Object *p_changed, const char *p_prop) {
+void SoftBody3D::_softbody_changed() {
prepare_physics_server();
_reset_points_offsets();
#ifdef TOOLS_ENABLED
- if (p_changed == this) {
- update_configuration_warning();
- }
+ update_configuration_warning();
#endif
}
@@ -259,7 +257,9 @@ void SoftBody3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_WORLD: {
if (Engine::get_singleton()->is_editor_hint()) {
- add_change_receptor(this);
+ // I have no idea what this is supposed to do, it's really weird
+ // leaving for upcoming PK work on physics
+ //add_change_receptor(this);
}
RID space = get_world_3d()->get_space();
@@ -309,6 +309,8 @@ void SoftBody3D::_notification(int p_what) {
}
void SoftBody3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_physics_rid"), &SoftBody3D::get_physics_rid);
+
ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftBody3D::set_collision_mask);
ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftBody3D::get_collision_mask);
@@ -337,18 +339,9 @@ void SoftBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftBody3D::set_linear_stiffness);
ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftBody3D::get_linear_stiffness);
- ClassDB::bind_method(D_METHOD("set_areaAngular_stiffness", "areaAngular_stiffness"), &SoftBody3D::set_areaAngular_stiffness);
- ClassDB::bind_method(D_METHOD("get_areaAngular_stiffness"), &SoftBody3D::get_areaAngular_stiffness);
-
- ClassDB::bind_method(D_METHOD("set_volume_stiffness", "volume_stiffness"), &SoftBody3D::set_volume_stiffness);
- ClassDB::bind_method(D_METHOD("get_volume_stiffness"), &SoftBody3D::get_volume_stiffness);
-
ClassDB::bind_method(D_METHOD("set_pressure_coefficient", "pressure_coefficient"), &SoftBody3D::set_pressure_coefficient);
ClassDB::bind_method(D_METHOD("get_pressure_coefficient"), &SoftBody3D::get_pressure_coefficient);
- ClassDB::bind_method(D_METHOD("set_pose_matching_coefficient", "pose_matching_coefficient"), &SoftBody3D::set_pose_matching_coefficient);
- ClassDB::bind_method(D_METHOD("get_pose_matching_coefficient"), &SoftBody3D::get_pose_matching_coefficient);
-
ClassDB::bind_method(D_METHOD("set_damping_coefficient", "damping_coefficient"), &SoftBody3D::set_damping_coefficient);
ClassDB::bind_method(D_METHOD("get_damping_coefficient"), &SoftBody3D::get_damping_coefficient);
@@ -366,12 +359,9 @@ void SoftBody3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "simulation_precision", PROPERTY_HINT_RANGE, "1,100,1"), "set_simulation_precision", "get_simulation_precision");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_mass", PROPERTY_HINT_RANGE, "0.01,10000,1"), "set_total_mass", "get_total_mass");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_linear_stiffness", "get_linear_stiffness");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "areaAngular_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_areaAngular_stiffness", "get_areaAngular_stiffness");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_volume_stiffness", "get_volume_stiffness");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure_coefficient"), "set_pressure_coefficient", "get_pressure_coefficient");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_damping_coefficient", "get_damping_coefficient");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drag_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_coefficient", "get_drag_coefficient");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pose_matching_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_pose_matching_coefficient", "get_pose_matching_coefficient");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ray_pickable"), "set_ray_pickable", "is_ray_pickable");
}
@@ -612,34 +602,10 @@ real_t SoftBody3D::get_linear_stiffness() {
return PhysicsServer3D::get_singleton()->soft_body_get_linear_stiffness(physics_rid);
}
-void SoftBody3D::set_areaAngular_stiffness(real_t p_areaAngular_stiffness) {
- PhysicsServer3D::get_singleton()->soft_body_set_areaAngular_stiffness(physics_rid, p_areaAngular_stiffness);
-}
-
-real_t SoftBody3D::get_areaAngular_stiffness() {
- return PhysicsServer3D::get_singleton()->soft_body_get_areaAngular_stiffness(physics_rid);
-}
-
-void SoftBody3D::set_volume_stiffness(real_t p_volume_stiffness) {
- PhysicsServer3D::get_singleton()->soft_body_set_volume_stiffness(physics_rid, p_volume_stiffness);
-}
-
-real_t SoftBody3D::get_volume_stiffness() {
- return PhysicsServer3D::get_singleton()->soft_body_get_volume_stiffness(physics_rid);
-}
-
real_t SoftBody3D::get_pressure_coefficient() {
return PhysicsServer3D::get_singleton()->soft_body_get_pressure_coefficient(physics_rid);
}
-void SoftBody3D::set_pose_matching_coefficient(real_t p_pose_matching_coefficient) {
- PhysicsServer3D::get_singleton()->soft_body_set_pose_matching_coefficient(physics_rid, p_pose_matching_coefficient);
-}
-
-real_t SoftBody3D::get_pose_matching_coefficient() {
- return PhysicsServer3D::get_singleton()->soft_body_get_pose_matching_coefficient(physics_rid);
-}
-
void SoftBody3D::set_pressure_coefficient(real_t p_pressure_coefficient) {
PhysicsServer3D::get_singleton()->soft_body_set_pressure_coefficient(physics_rid, p_pressure_coefficient);
}
@@ -768,7 +734,9 @@ void SoftBody3D::_reset_points_offsets() {
PinnedPoint *w = pinned_points.ptrw();
for (int i = pinned_points.size() - 1; 0 <= i; --i) {
if (!r[i].spatial_attachment) {
- w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(r[i].spatial_attachment_path));
+ if (!r[i].spatial_attachment_path.is_empty() && has_node(r[i].spatial_attachment_path)) {
+ w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(r[i].spatial_attachment_path));
+ }
}
if (!r[i].spatial_attachment) {
diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h
index d3c5dc022f..f98df39209 100644
--- a/scene/3d/soft_body_3d.h
+++ b/scene/3d/soft_body_3d.h
@@ -32,20 +32,21 @@
#define SOFT_PHYSICS_BODY_H
#include "scene/3d/mesh_instance_3d.h"
+#include "servers/physics_server_3d.h"
class SoftBody3D;
-class SoftBodyRenderingServerHandler {
+class SoftBodyRenderingServerHandler : public RenderingServerHandler {
friend class SoftBody3D;
RID mesh;
- int surface;
+ int surface = 0;
Vector<uint8_t> buffer;
- uint32_t stride;
- uint32_t offset_vertices;
- uint32_t offset_normal;
+ uint32_t stride = 0;
+ uint32_t offset_vertices = 0;
+ uint32_t offset_normal = 0;
- uint8_t *write_buffer;
+ uint8_t *write_buffer = nullptr;
private:
SoftBodyRenderingServerHandler();
@@ -57,9 +58,9 @@ private:
void commit_changes();
public:
- void set_vertex(int p_vertex_id, const void *p_vector3);
- void set_normal(int p_vertex_id, const void *p_vector3);
- void set_aabb(const AABB &p_aabb);
+ void set_vertex(int p_vertex_id, const void *p_vector3) override;
+ void set_normal(int p_vertex_id, const void *p_vector3) override;
+ void set_aabb(const AABB &p_aabb) override;
};
class SoftBody3D : public MeshInstance3D {
@@ -91,13 +92,15 @@ private:
bool pinned_points_cache_dirty = true;
Ref<ArrayMesh> debug_mesh_cache;
- class MeshInstance3D *debug_mesh;
+ class MeshInstance3D *debug_mesh = nullptr;
- bool capture_input_on_drag;
+ bool capture_input_on_drag = false;
bool ray_pickable = true;
void _update_pickable();
+ void _softbody_changed();
+
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -107,8 +110,6 @@ protected:
bool _set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value);
bool _get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const;
- virtual void _changed_callback(Object *p_changed, const char *p_prop) override;
-
void _notification(int p_what);
static void _bind_methods();
@@ -122,6 +123,8 @@ public:
void prepare_physics_server();
void become_mesh_owner();
+ RID get_physics_rid() const { return physics_rid; }
+
void set_collision_mask(uint32_t p_mask);
uint32_t get_collision_mask() const;
@@ -149,18 +152,9 @@ public:
void set_linear_stiffness(real_t p_linear_stiffness);
real_t get_linear_stiffness();
- void set_areaAngular_stiffness(real_t p_areaAngular_stiffness);
- real_t get_areaAngular_stiffness();
-
- void set_volume_stiffness(real_t p_volume_stiffness);
- real_t get_volume_stiffness();
-
void set_pressure_coefficient(real_t p_pressure_coefficient);
real_t get_pressure_coefficient();
- void set_pose_matching_coefficient(real_t p_pose_matching_coefficient);
- real_t get_pose_matching_coefficient();
-
void set_damping_coefficient(real_t p_damping_coefficient);
real_t get_damping_coefficient();
diff --git a/scene/3d/spring_arm_3d.h b/scene/3d/spring_arm_3d.h
index 864919c631..63505ab9d3 100644
--- a/scene/3d/spring_arm_3d.h
+++ b/scene/3d/spring_arm_3d.h
@@ -38,8 +38,8 @@ class SpringArm3D : public Node3D {
Ref<Shape3D> shape;
Set<RID> excluded_objects;
- real_t spring_length = 1;
- real_t current_spring_length = 0;
+ real_t spring_length = 1.0;
+ real_t current_spring_length = 0.0;
bool keep_child_basis = false;
uint32_t mask = 1;
real_t margin = 0.01;
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 3e49750366..0be54e7243 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -339,24 +339,10 @@ void SpriteBase3D::_bind_methods() {
}
SpriteBase3D::SpriteBase3D() {
- color_dirty = true;
- centered = true;
- hflip = false;
- vflip = false;
- parent_sprite = nullptr;
- pI = nullptr;
-
for (int i = 0; i < FLAG_MAX; i++) {
flags[i] = i == FLAG_TRANSPARENT || i == FLAG_DOUBLE_SIDED;
}
- alpha_cut = ALPHA_CUT_DISABLED;
- billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED;
- axis = Vector3::AXIS_Z;
- pixel_size = 0.01;
- modulate = Color(1, 1, 1, 1);
- pending_update = false;
- opacity = 1.0;
immediate = RenderingServer::get_singleton()->immediate_create();
set_base(immediate);
}
@@ -380,7 +366,7 @@ void Sprite3D::_draw() {
}
Rect2 base_rect;
- if (region) {
+ if (region_enabled) {
base_rect = region_rect;
} else {
base_rect = Rect2(0, 0, texture->get_width(), texture->get_height());
@@ -525,23 +511,24 @@ Ref<Texture2D> Sprite3D::get_texture() const {
return texture;
}
-void Sprite3D::set_region(bool p_region) {
- if (p_region == region) {
+void Sprite3D::set_region_enabled(bool p_region_enabled) {
+ if (p_region_enabled == region_enabled) {
return;
}
- region = p_region;
+ region_enabled = p_region_enabled;
_queue_update();
+ notify_property_list_changed();
}
-bool Sprite3D::is_region() const {
- return region;
+bool Sprite3D::is_region_enabled() const {
+ return region_enabled;
}
void Sprite3D::set_region_rect(const Rect2 &p_region_rect) {
bool changed = region_rect != p_region_rect;
region_rect = p_region_rect;
- if (region && changed) {
+ if (region_enabled && changed) {
_queue_update();
}
}
@@ -557,8 +544,6 @@ void Sprite3D::set_frame(int p_frame) {
_queue_update();
- _change_notify("frame");
- _change_notify("frame_coords");
emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
@@ -581,7 +566,7 @@ void Sprite3D::set_vframes(int p_amount) {
ERR_FAIL_COND(p_amount < 1);
vframes = p_amount;
_queue_update();
- _change_notify();
+ notify_property_list_changed();
}
int Sprite3D::get_vframes() const {
@@ -592,7 +577,7 @@ void Sprite3D::set_hframes(int p_amount) {
ERR_FAIL_COND(p_amount < 1);
hframes = p_amount;
_queue_update();
- _change_notify();
+ notify_property_list_changed();
}
int Sprite3D::get_hframes() const {
@@ -610,7 +595,7 @@ Rect2 Sprite3D::get_item_rect() const {
Size2i s;
- if (region) {
+ if (region_enabled) {
s = region_rect.size;
} else {
s = texture->get_size();
@@ -639,14 +624,18 @@ void Sprite3D::_validate_property(PropertyInfo &property) const {
if (property.name == "frame_coords") {
property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS;
}
+
+ if (!region_enabled && property.name == "region_rect") {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
}
void Sprite3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite3D::set_texture);
ClassDB::bind_method(D_METHOD("get_texture"), &Sprite3D::get_texture);
- ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite3D::set_region);
- ClassDB::bind_method(D_METHOD("is_region"), &Sprite3D::is_region);
+ ClassDB::bind_method(D_METHOD("set_region_enabled", "enabled"), &Sprite3D::set_region_enabled);
+ ClassDB::bind_method(D_METHOD("is_region_enabled"), &Sprite3D::is_region_enabled);
ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite3D::set_region_rect);
ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite3D::get_region_rect);
@@ -670,14 +659,14 @@ void Sprite3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
ADD_GROUP("Region", "region_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
ADD_SIGNAL(MethodInfo("frame_changed"));
}
Sprite3D::Sprite3D() {
- region = false;
+ region_enabled = false;
frame = 0;
vframes = 1;
hframes = 1;
@@ -703,7 +692,7 @@ void AnimatedSprite3D::_draw() {
Ref<Texture2D> texture = frames->get_frame(animation, frame);
if (!texture.is_valid()) {
- return; //no texuture no life
+ return; //no texture no life
}
Vector2 tsize = texture->get_size();
if (tsize.x == 0 || tsize.y == 0) {
@@ -904,12 +893,13 @@ void AnimatedSprite3D::_notification(int p_what) {
} else {
frame = fc - 1;
}
+ emit_signal(SceneStringNames::get_singleton()->animation_finished);
} else {
frame++;
}
_queue_update();
- _change_notify("frame");
+ emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
float to_process = MIN(timeout, remaining);
@@ -935,7 +925,7 @@ void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
set_frame(frame);
}
- _change_notify();
+ notify_property_list_changed();
_reset_timeout();
_queue_update();
update_configuration_warning();
@@ -968,7 +958,7 @@ void AnimatedSprite3D::set_frame(int p_frame) {
frame = p_frame;
_reset_timeout();
_queue_update();
- _change_notify("frame");
+
emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
@@ -1004,8 +994,6 @@ Rect2 AnimatedSprite3D::get_item_rect() const {
void AnimatedSprite3D::_res_changed() {
set_frame(frame);
- _change_notify("frame");
- _change_notify("animation");
_queue_update();
}
@@ -1062,7 +1050,7 @@ void AnimatedSprite3D::set_animation(const StringName &p_animation) {
animation = p_animation;
_reset_timeout();
set_frame(0);
- _change_notify();
+ notify_property_list_changed();
_queue_update();
}
@@ -1101,6 +1089,7 @@ void AnimatedSprite3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_frame"), &AnimatedSprite3D::get_frame);
ADD_SIGNAL(MethodInfo("frame_changed"));
+ ADD_SIGNAL(MethodInfo("animation_finished"));
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation");
@@ -1109,8 +1098,4 @@ void AnimatedSprite3D::_bind_methods() {
}
AnimatedSprite3D::AnimatedSprite3D() {
- frame = 0;
- playing = false;
- animation = "default";
- timeout = 0;
}
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index 3e38d4581e..b48660eb2d 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -31,8 +31,8 @@
#ifndef SPRITE_3D_H
#define SPRITE_3D_H
-#include "scene/2d/animated_sprite_2d.h"
#include "scene/3d/visual_instance_3d.h"
+#include "scene/resources/sprite_frames.h"
class SpriteBase3D : public GeometryInstance3D {
GDCLASS(SpriteBase3D, GeometryInstance3D);
@@ -55,32 +55,32 @@ public:
};
private:
- bool color_dirty;
+ bool color_dirty = true;
Color color_accum;
- SpriteBase3D *parent_sprite;
+ SpriteBase3D *parent_sprite = nullptr;
List<SpriteBase3D *> children;
- List<SpriteBase3D *>::Element *pI;
+ List<SpriteBase3D *>::Element *pI = nullptr;
- bool centered;
+ bool centered = true;
Point2 offset;
- bool hflip;
- bool vflip;
+ bool hflip = false;
+ bool vflip = false;
- Color modulate;
- float opacity;
+ Color modulate = Color(1, 1, 1, 1);
+ float opacity = 1.0;
- Vector3::Axis axis;
- float pixel_size;
+ Vector3::Axis axis = Vector3::AXIS_Z;
+ float pixel_size = 0.01;
AABB aabb;
RID immediate;
bool flags[FLAG_MAX];
- AlphaCutMode alpha_cut;
- StandardMaterial3D::BillboardMode billboard_mode;
- bool pending_update;
+ AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED;
+ StandardMaterial3D::BillboardMode billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED;
+ bool pending_update = false;
void _im_update();
void _propagate_color_changed();
@@ -107,8 +107,8 @@ public:
void set_flip_v(bool p_flip);
bool is_flipped_v() const;
- void set_region(bool p_region);
- bool is_region() const;
+ void set_region_enabled(bool p_region_enabled);
+ bool is_region_enabled() const;
void set_region_rect(const Rect2 &p_region_rect);
Rect2 get_region_rect() const;
@@ -147,7 +147,7 @@ class Sprite3D : public SpriteBase3D {
GDCLASS(Sprite3D, SpriteBase3D);
Ref<Texture2D> texture;
- bool region;
+ bool region_enabled;
Rect2 region_rect;
int frame;
@@ -167,8 +167,8 @@ public:
void set_texture(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_texture() const;
- void set_region(bool p_region);
- bool is_region() const;
+ void set_region_enabled(bool p_region_enabled);
+ bool is_region_enabled() const;
void set_region_rect(const Rect2 &p_region_rect);
Rect2 get_region_rect() const;
@@ -195,16 +195,16 @@ class AnimatedSprite3D : public SpriteBase3D {
GDCLASS(AnimatedSprite3D, SpriteBase3D);
Ref<SpriteFrames> frames;
- bool playing;
- StringName animation;
- int frame;
+ bool playing = false;
+ StringName animation = "default";
+ int frame = 0;
- bool centered;
+ bool centered = true;
- float timeout;
+ float timeout = 0.0;
- bool hflip;
- bool vflip;
+ bool hflip = 1;
+ bool vflip = 1;
Color modulate;
diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp
index ec8a300653..5b0b3b89d3 100644
--- a/scene/3d/vehicle_body_3d.cpp
+++ b/scene/3d/vehicle_body_3d.cpp
@@ -344,30 +344,6 @@ real_t VehicleWheel3D::get_rpm() const {
}
VehicleWheel3D::VehicleWheel3D() {
- steers = false;
- engine_traction = false;
- m_steering = real_t(0.);
- m_engineForce = real_t(0.);
- m_rotation = real_t(0.);
- m_deltaRotation = real_t(0.);
- m_brake = real_t(0.);
- m_rollInfluence = real_t(0.1);
-
- m_suspensionRestLength = 0.15;
- m_wheelRadius = 0.5; //0.28;
- m_suspensionStiffness = 5.88;
- m_wheelsDampingCompression = 0.83;
- m_wheelsDampingRelaxation = 0.88;
- m_frictionSlip = 10.5;
- m_bIsFrontWheel = false;
- m_maxSuspensionTravelCm = 500;
- m_maxSuspensionForce = 6000;
-
- m_suspensionRelativeVelocity = 0;
- m_clippedInvContactDotSuspension = 1.0;
- m_raycastInfo.m_isInContact = false;
-
- body = nullptr;
}
void VehicleBody3D::_update_wheel_transform(VehicleWheel3D &wheel, PhysicsDirectBodyState3D *s) {
@@ -431,7 +407,7 @@ real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState3D *s) {
PhysicsDirectSpaceState3D *ss = s->get_space_state();
- bool col = ss->intersect_ray(source, target, rr, exclude);
+ bool col = ss->intersect_ray(source, target, rr, exclude, get_collision_mask());
wheel.m_raycastInfo.m_groundObject = nullptr;
@@ -587,7 +563,7 @@ void VehicleBody3D::_resolve_single_bilateral(PhysicsDirectBodyState3D *s, const
b2invmass);
// FIXME: rel_vel assignment here is overwritten by the following assignment.
- // What seems to be intended in the next next assignment is: rel_vel = normal.dot(rel_vel);
+ // What seems to be intended in the next assignment is: rel_vel = normal.dot(rel_vel);
// Investigate why.
real_t rel_vel = jac.getRelativeVelocity(
s->get_linear_velocity(),
@@ -948,16 +924,6 @@ void VehicleBody3D::_bind_methods() {
}
VehicleBody3D::VehicleBody3D() {
- m_pitchControl = 0;
- m_currentVehicleSpeedKmHour = real_t(0.);
- m_steeringValue = real_t(0.);
-
- engine_force = 0;
- brake = 0;
-
- state = nullptr;
- ccd = false;
-
exclude.insert(get_rid());
//PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h
index 790179a8f0..860fa7e3b7 100644
--- a/scene/3d/vehicle_body_3d.h
+++ b/scene/3d/vehicle_body_3d.h
@@ -42,52 +42,52 @@ class VehicleWheel3D : public Node3D {
Transform m_worldTransform;
Transform local_xform;
- bool engine_traction;
- bool steers;
+ bool engine_traction = false;
+ bool steers = false;
Vector3 m_chassisConnectionPointCS; //const
Vector3 m_wheelDirectionCS; //const
Vector3 m_wheelAxleCS; // const or modified by steering
- real_t m_suspensionRestLength;
- real_t m_maxSuspensionTravelCm;
- real_t m_wheelRadius;
+ real_t m_suspensionRestLength = 0.15;
+ real_t m_maxSuspensionTravelCm = 500.0;
+ real_t m_wheelRadius = 0.5;
- real_t m_suspensionStiffness;
- real_t m_wheelsDampingCompression;
- real_t m_wheelsDampingRelaxation;
- real_t m_frictionSlip;
- real_t m_maxSuspensionForce;
- bool m_bIsFrontWheel;
+ real_t m_suspensionStiffness = 5.88;
+ real_t m_wheelsDampingCompression = 0.83;
+ real_t m_wheelsDampingRelaxation = 0.88;
+ real_t m_frictionSlip = 10.5;
+ real_t m_maxSuspensionForce = 6000.0;
+ bool m_bIsFrontWheel = false;
- VehicleBody3D *body;
+ VehicleBody3D *body = nullptr;
//btVector3 m_wheelAxleCS; // const or modified by steering ?
- real_t m_steering;
- real_t m_rotation;
- real_t m_deltaRotation;
- real_t m_rpm;
- real_t m_rollInfluence;
- real_t m_engineForce;
- real_t m_brake;
+ real_t m_steering = 0.0;
+ real_t m_rotation = 0.0;
+ real_t m_deltaRotation = 0.0;
+ real_t m_rpm = 0.0;
+ real_t m_rollInfluence = 0.1;
+ real_t m_engineForce = 0.0;
+ real_t m_brake = 0.0;
- real_t m_clippedInvContactDotSuspension;
- real_t m_suspensionRelativeVelocity;
+ real_t m_clippedInvContactDotSuspension = 1.0;
+ real_t m_suspensionRelativeVelocity = 0.0;
//calculated by suspension
- real_t m_wheelsSuspensionForce;
- real_t m_skidInfo;
+ real_t m_wheelsSuspensionForce = 0.0;
+ real_t m_skidInfo = 0.0;
struct RaycastInfo {
//set by raycaster
Vector3 m_contactNormalWS; //contactnormal
Vector3 m_contactPointWS; //raycast hitpoint
- real_t m_suspensionLength;
+ real_t m_suspensionLength = 0.0;
Vector3 m_hardPointWS; //raycast starting point
Vector3 m_wheelDirectionWS; //direction in worldspace
Vector3 m_wheelAxleWS; // axle in worldspace
- bool m_isInContact;
- PhysicsBody3D *m_groundObject; //could be general void* ptr
+ bool m_isInContact = false;
+ PhysicsBody3D *m_groundObject = nullptr; //could be general void* ptr
} m_raycastInfo;
void _update(PhysicsDirectBodyState3D *s);
@@ -153,12 +153,12 @@ public:
class VehicleBody3D : public RigidBody3D {
GDCLASS(VehicleBody3D, RigidBody3D);
- real_t engine_force;
- real_t brake;
+ real_t engine_force = 0.0;
+ real_t brake = 0.0;
- real_t m_pitchControl;
- real_t m_steeringValue;
- real_t m_currentVehicleSpeedKmHour;
+ real_t m_pitchControl = 0.0;
+ real_t m_steeringValue = 0.0;
+ real_t m_currentVehicleSpeedKmHour = 0.0;
Set<RID> exclude;
@@ -168,12 +168,12 @@ class VehicleBody3D : public RigidBody3D {
Vector<real_t> m_sideImpulse;
struct btVehicleWheelContactPoint {
- PhysicsDirectBodyState3D *m_s;
- PhysicsBody3D *m_body1;
+ PhysicsDirectBodyState3D *m_s = nullptr;
+ PhysicsBody3D *m_body1 = nullptr;
Vector3 m_frictionPositionWorld;
Vector3 m_frictionDirectionWorld;
- real_t m_jacDiagABInv;
- real_t m_maxImpulse;
+ real_t m_jacDiagABInv = 0.0;
+ real_t m_maxImpulse = 0.0;
btVehicleWheelContactPoint(PhysicsDirectBodyState3D *s, PhysicsBody3D *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse);
};
diff --git a/scene/3d/velocity_tracker_3d.cpp b/scene/3d/velocity_tracker_3d.cpp
index 35d00f3639..5b5cc06456 100644
--- a/scene/3d/velocity_tracker_3d.cpp
+++ b/scene/3d/velocity_tracker_3d.cpp
@@ -128,6 +128,4 @@ void VelocityTracker3D::_bind_methods() {
VelocityTracker3D::VelocityTracker3D() {
position_history.resize(4); // should be configurable
- position_history_len = 0;
- physics_step = false;
}
diff --git a/scene/3d/velocity_tracker_3d.h b/scene/3d/velocity_tracker_3d.h
index 3fc89cc7fb..e971f4755a 100644
--- a/scene/3d/velocity_tracker_3d.h
+++ b/scene/3d/velocity_tracker_3d.h
@@ -37,13 +37,13 @@ class VelocityTracker3D : public Reference {
GDCLASS(VelocityTracker3D, Reference);
struct PositionHistory {
- uint64_t frame;
+ uint64_t frame = 0;
Vector3 position;
};
- bool physics_step;
+ bool physics_step = false;
Vector<PositionHistory> position_history;
- int position_history_len;
+ int position_history_len = 0;
protected:
static void _bind_methods();
diff --git a/scene/3d/visibility_notifier_3d.cpp b/scene/3d/visibility_notifier_3d.cpp
index 14c7659de4..471838b9d1 100644
--- a/scene/3d/visibility_notifier_3d.cpp
+++ b/scene/3d/visibility_notifier_3d.cpp
@@ -69,7 +69,6 @@ void VisibilityNotifier3D::set_aabb(const AABB &p_aabb) {
get_world_3d()->_update_notifier(this, get_global_transform().xform(aabb));
}
- _change_notify("aabb");
update_gizmo();
}
@@ -112,7 +111,6 @@ void VisibilityNotifier3D::_bind_methods() {
}
VisibilityNotifier3D::VisibilityNotifier3D() {
- aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
set_notify_transform(true);
}
@@ -252,6 +250,4 @@ VisibilityEnabler3D::VisibilityEnabler3D() {
for (int i = 0; i < ENABLER_MAX; i++) {
enabler[i] = true;
}
-
- visible = false;
}
diff --git a/scene/3d/visibility_notifier_3d.h b/scene/3d/visibility_notifier_3d.h
index d566b7e40b..9f7705067f 100644
--- a/scene/3d/visibility_notifier_3d.h
+++ b/scene/3d/visibility_notifier_3d.h
@@ -41,7 +41,7 @@ class VisibilityNotifier3D : public Node3D {
Ref<World3D> world;
Set<Camera3D *> cameras;
- AABB aabb;
+ AABB aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
protected:
virtual void _screen_enter() {}
@@ -76,7 +76,7 @@ protected:
virtual void _screen_enter() override;
virtual void _screen_exit() override;
- bool visible;
+ bool visible = false;
void _find_nodes(Node *p_node);
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index 1d0a830383..394c67e873 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -43,7 +43,6 @@ void VisualInstance3D::_update_visibility() {
return;
}
- _change_notify("visible");
RS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree());
}
@@ -135,7 +134,6 @@ RID VisualInstance3D::get_base() const {
VisualInstance3D::VisualInstance3D() {
instance = RenderingServer::get_singleton()->instance_create();
RenderingServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id());
- layers = 1;
set_notify_transform(true);
}
@@ -371,7 +369,7 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_gi_mode", "mode"), &GeometryInstance3D::set_gi_mode);
ClassDB::bind_method(D_METHOD("get_gi_mode"), &GeometryInstance3D::get_gi_mode);
- ClassDB::bind_method(D_METHOD("set_lod_bias", "p_bias"), &GeometryInstance3D::set_lod_bias);
+ ClassDB::bind_method(D_METHOD("set_lod_bias", "bias"), &GeometryInstance3D::set_lod_bias);
ClassDB::bind_method(D_METHOD("get_lod_bias"), &GeometryInstance3D::get_lod_bias);
ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &GeometryInstance3D::set_custom_aabb);
@@ -412,17 +410,5 @@ void GeometryInstance3D::_bind_methods() {
}
GeometryInstance3D::GeometryInstance3D() {
- lod_min_distance = 0;
- lod_max_distance = 0;
- lod_min_hysteresis = 0;
- lod_max_hysteresis = 0;
-
- lod_bias = 1.0;
-
- gi_mode = GI_MODE_DISABLED;
- lightmap_scale = LIGHTMAP_SCALE_1X;
-
- shadow_casting_setting = SHADOW_CASTING_SETTING_ON;
- extra_cull_margin = 0;
//RS::get_singleton()->instance_geometry_set_baked_light_texture_index(get_instance(),0);
}
diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h
index f370f29cb0..7fed8095ef 100644
--- a/scene/3d/visual_instance_3d.h
+++ b/scene/3d/visual_instance_3d.h
@@ -42,7 +42,7 @@ class VisualInstance3D : public Node3D {
RID base;
RID instance;
- uint32_t layers;
+ uint32_t layers = 1;
RID _get_visual_instance_rid() const;
@@ -105,21 +105,21 @@ public:
};
private:
- ShadowCastingSetting shadow_casting_setting;
+ ShadowCastingSetting shadow_casting_setting = SHADOW_CASTING_SETTING_ON;
Ref<Material> material_override;
- float lod_min_distance;
- float lod_max_distance;
- float lod_min_hysteresis;
- float lod_max_hysteresis;
+ float lod_min_distance = 0.0;
+ float lod_max_distance = 0.0;
+ float lod_min_hysteresis = 0.0;
+ float lod_max_hysteresis = 0.0;
- float lod_bias;
+ float lod_bias = 1.0;
mutable HashMap<StringName, Variant> instance_uniforms;
mutable HashMap<StringName, StringName> instance_uniform_property_remap;
- float extra_cull_margin;
- LightmapScale lightmap_scale;
- GIMode gi_mode;
+ float extra_cull_margin = 0.0;
+ LightmapScale lightmap_scale = LIGHTMAP_SCALE_1X;
+ GIMode gi_mode = GI_MODE_DISABLED;
const StringName *_instance_uniform_get_remap(const StringName p_name) const;
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp
index b99d753dde..16718b956f 100644
--- a/scene/3d/voxelizer.cpp
+++ b/scene/3d/voxelizer.cpp
@@ -151,7 +151,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
Vector2 uv;
Vector3 lnormal;
get_uv_and_normal(intersection, p_vtx, p_uv, p_normal, uv, lnormal);
- if (lnormal == Vector3()) { //just in case normal as nor provided
+ if (lnormal == Vector3()) { //just in case normal is not provided
lnormal = normal;
}
@@ -183,7 +183,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
Vector3 lnormal;
Vector2 uv;
get_uv_and_normal(inters, p_vtx, p_uv, p_normal, uv, normal);
- if (lnormal == Vector3()) { //just in case normal as nor provided
+ if (lnormal == Vector3()) { //just in case normal is not provided
lnormal = normal;
}
@@ -1007,7 +1007,4 @@ Transform Voxelizer::get_to_cell_space_xform() const {
}
Voxelizer::Voxelizer() {
- sorted = false;
- color_scan_cell_width = 4;
- bake_texture_size = 128;
}
diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h
index a0b581d625..87f949e7db 100644
--- a/scene/3d/voxelizer.h
+++ b/scene/3d/voxelizer.h
@@ -44,35 +44,25 @@ private:
struct Cell {
uint32_t children[8];
- float albedo[3]; //albedo in RGB24
- float emission[3]; //accumulated light in 16:16 fixed point (needs to be integer for moving lights fast)
- float normal[3];
- uint32_t used_sides;
- float alpha; //used for upsampling
- uint16_t x;
- uint16_t y;
- uint16_t z;
- uint16_t level;
+ float albedo[3] = {}; //albedo in RGB24
+ float emission[3] = {}; //accumulated light in 16:16 fixed point (needs to be integer for moving lights fast)
+ float normal[3] = {};
+ uint32_t used_sides = 0;
+ float alpha = 0.0; //used for upsampling
+ uint16_t x = 0;
+ uint16_t y = 0;
+ uint16_t z = 0;
+ uint16_t level = 0;
Cell() {
for (int i = 0; i < 8; i++) {
children[i] = CHILD_EMPTY;
}
-
- for (int i = 0; i < 3; i++) {
- emission[i] = 0;
- albedo[i] = 0;
- normal[i] = 0;
- }
- alpha = 0;
- used_sides = 0;
- x = y = z = 0;
- level = 0;
}
};
Vector<Cell> bake_cells;
- int cell_subdiv;
+ int cell_subdiv = 0;
struct CellSort {
union {
@@ -82,10 +72,10 @@ private:
uint64_t x : 16;
uint64_t level : 16;
};
- uint64_t key;
+ uint64_t key = 0;
};
- int32_t index;
+ int32_t index = 0;
_FORCE_INLINE_ bool operator<(const CellSort &p_cell_sort) const {
return key < p_cell_sort.key;
@@ -101,16 +91,16 @@ private:
Map<Ref<Material>, MaterialCache> material_cache;
AABB original_bounds;
AABB po2_bounds;
- int axis_cell_size[3];
+ int axis_cell_size[3] = {};
Transform to_cell_space;
- int color_scan_cell_width;
- int bake_texture_size;
- float cell_size;
+ int color_scan_cell_width = 4;
+ int bake_texture_size = 128;
+ float cell_size = 0.0;
- int max_original_cells;
- int leaf_voxel_count;
+ int max_original_cells = 0;
+ int leaf_voxel_count = 0;
Vector<Color> _get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add);
MaterialCache _get_material_cache(Ref<Material> p_material);
@@ -119,7 +109,7 @@ private:
void _fixup_plot(int p_idx, int p_level);
void _debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx);
- bool sorted;
+ bool sorted = false;
void _sort();
public:
diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp
index cf1c319acc..214ffd6bd5 100644
--- a/scene/3d/world_environment.cpp
+++ b/scene/3d/world_environment.cpp
@@ -35,51 +35,69 @@
void WorldEnvironment::_notification(int p_what) {
if (p_what == Node3D::NOTIFICATION_ENTER_WORLD || p_what == Node3D::NOTIFICATION_ENTER_TREE) {
if (environment.is_valid()) {
- if (get_viewport()->find_world_3d()->get_environment().is_valid()) {
- WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding.");
- }
- get_viewport()->find_world_3d()->set_environment(environment);
add_to_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
+ _update_current_environment();
}
if (camera_effects.is_valid()) {
- if (get_viewport()->find_world_3d()->get_camera_effects().is_valid()) {
- WARN_PRINT("World already has a camera effects (Another WorldEnvironment?), overriding.");
- }
- get_viewport()->find_world_3d()->set_camera_effects(camera_effects);
add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
+ _update_current_camera_effects();
}
} else if (p_what == Node3D::NOTIFICATION_EXIT_WORLD || p_what == Node3D::NOTIFICATION_EXIT_TREE) {
- if (environment.is_valid() && get_viewport()->find_world_3d()->get_environment() == environment) {
- get_viewport()->find_world_3d()->set_environment(Ref<Environment>());
+ if (environment.is_valid()) {
remove_from_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
+ _update_current_environment();
}
- if (camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() == camera_effects) {
- get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>());
+ if (camera_effects.is_valid()) {
remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
+ _update_current_camera_effects();
}
}
}
-void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) {
- if (is_inside_tree() && environment.is_valid() && get_viewport()->find_world_3d()->get_environment() == environment) {
+void WorldEnvironment::_update_current_environment() {
+ WorldEnvironment *first = Object::cast_to<WorldEnvironment>(get_tree()->get_first_node_in_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())));
+
+ if (first) {
+ get_viewport()->find_world_3d()->set_environment(first->environment);
+ } else {
get_viewport()->find_world_3d()->set_environment(Ref<Environment>());
+ }
+ get_tree()->call_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warning");
+}
+
+void WorldEnvironment::_update_current_camera_effects() {
+ WorldEnvironment *first = Object::cast_to<WorldEnvironment>(get_tree()->get_first_node_in_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())));
+ if (first) {
+ get_viewport()->find_world_3d()->set_camera_effects(first->camera_effects);
+ } else {
+ get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>());
+ }
+
+ get_tree()->call_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warning");
+}
+
+void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) {
+ if (environment == p_environment) {
+ return;
+ }
+ if (is_inside_tree() && environment.is_valid()) {
remove_from_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
- //clean up
}
environment = p_environment;
+
if (is_inside_tree() && environment.is_valid()) {
- if (get_viewport()->find_world_3d()->get_environment().is_valid()) {
- WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding.");
- }
- get_viewport()->find_world_3d()->set_environment(environment);
add_to_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
- update_configuration_warning();
+ if (is_inside_tree()) {
+ _update_current_environment();
+ } else {
+ update_configuration_warning();
+ }
}
Ref<Environment> WorldEnvironment::get_environment() const {
@@ -87,22 +105,24 @@ Ref<Environment> WorldEnvironment::get_environment() const {
}
void WorldEnvironment::set_camera_effects(const Ref<CameraEffects> &p_camera_effects) {
+ if (camera_effects == p_camera_effects) {
+ return;
+ }
+
if (is_inside_tree() && camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() == camera_effects) {
- get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>());
remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
- //clean up
}
camera_effects = p_camera_effects;
if (is_inside_tree() && camera_effects.is_valid()) {
- if (get_viewport()->find_world_3d()->get_camera_effects().is_valid()) {
- WARN_PRINT("World already has an camera_effects (Another WorldEnvironment?), overriding.");
- }
- get_viewport()->find_world_3d()->set_camera_effects(camera_effects);
add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
- update_configuration_warning();
+ if (is_inside_tree()) {
+ _update_current_camera_effects();
+ } else {
+ update_configuration_warning();
+ }
}
Ref<CameraEffects> WorldEnvironment::get_camera_effects() const {
@@ -123,14 +143,18 @@ String WorldEnvironment::get_configuration_warning() const {
return warning;
}
- List<Node *> nodes;
- get_tree()->get_nodes_in_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), &nodes);
+ if (environment.is_valid() && get_viewport()->find_world_3d()->get_environment() != environment) {
+ if (!warning.is_empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("Only the first Environment has an effect in a scene (or set of instantiated scenes).");
+ }
- if (nodes.size() > 1) {
+ if (camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() != camera_effects) {
if (!warning.is_empty()) {
warning += "\n\n";
}
- warning += TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes).");
+ warning += TTR("Only the first CameraEffects has an effect in a scene (or set of instantiated scenes).");
}
return warning;
diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h
index 3dfba20bf0..e3f28d6d6b 100644
--- a/scene/3d/world_environment.h
+++ b/scene/3d/world_environment.h
@@ -41,6 +41,9 @@ class WorldEnvironment : public Node {
Ref<Environment> environment;
Ref<CameraEffects> camera_effects;
+ void _update_current_environment();
+ void _update_current_camera_effects();
+
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 41e1318b1f..15f562242f 100644
--- a/scene/animation/animation_blend_space_1d.cpp
+++ b/scene/animation/animation_blend_space_1d.cpp
@@ -311,14 +311,6 @@ AnimationNodeBlendSpace1D::AnimationNodeBlendSpace1D() {
for (int i = 0; i < MAX_BLEND_POINTS; i++) {
blend_points[i].name = itos(i);
}
- blend_points_used = 0;
- max_space = 1;
- min_space = -1;
-
- snap = 0.1;
- value_label = "value";
-
- blend_position = "blend_position";
}
AnimationNodeBlendSpace1D::~AnimationNodeBlendSpace1D() {
diff --git a/scene/animation/animation_blend_space_1d.h b/scene/animation/animation_blend_space_1d.h
index 6edbc4e319..8886e6c679 100644
--- a/scene/animation/animation_blend_space_1d.h
+++ b/scene/animation/animation_blend_space_1d.h
@@ -43,24 +43,24 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode {
struct BlendPoint {
StringName name;
Ref<AnimationRootNode> node;
- float position;
+ float position = 0.0;
};
BlendPoint blend_points[MAX_BLEND_POINTS];
- int blend_points_used;
+ int blend_points_used = 0;
- float max_space;
- float min_space;
+ float max_space = 1.0;
+ float min_space = -1.0;
- float snap;
+ float snap = 0.1;
- String value_label;
+ String value_label = "value";
void _add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node);
void _tree_changed();
- StringName blend_position;
+ StringName blend_position = "blend_position";
protected:
virtual void _validate_property(PropertyInfo &property) const override;
diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp
index c32cc82bd8..9c4bc107dd 100644
--- a/scene/animation/animation_blend_space_2d.cpp
+++ b/scene/animation/animation_blend_space_2d.cpp
@@ -437,7 +437,7 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
Vector2 blend_pos = get_parameter(blend_position);
int closest = get_parameter(this->closest);
float length_internal = get_parameter(this->length_internal);
- float mind = 0; //time of min distance point
+ float mind = 0.0; //time of min distance point
if (blend_mode == BLEND_MODE_INTERPOLATED) {
if (triangles.size() == 0) {
@@ -529,7 +529,7 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
}
if (new_closest != closest && new_closest != -1) {
- float from = 0;
+ float from = 0.0;
if (blend_mode == BLEND_MODE_DISCRETE_CARRY && closest != -1) {
//see how much animation remains
from = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, true, 0.0, FILTER_IGNORE, false) - length_internal;
@@ -665,18 +665,6 @@ AnimationNodeBlendSpace2D::AnimationNodeBlendSpace2D() {
for (int i = 0; i < MAX_BLEND_POINTS; i++) {
blend_points[i].name = itos(i);
}
- auto_triangles = true;
- blend_points_used = 0;
- max_space = Vector2(1, 1);
- min_space = Vector2(-1, -1);
- snap = Vector2(0.1, 0.1);
- x_label = "x";
- y_label = "y";
- trianges_dirty = false;
- blend_position = "blend_position";
- closest = "closest";
- length_internal = "length_internal";
- blend_mode = BLEND_MODE_INTERPOLATED;
}
AnimationNodeBlendSpace2D::~AnimationNodeBlendSpace2D() {
diff --git a/scene/animation/animation_blend_space_2d.h b/scene/animation/animation_blend_space_2d.h
index c74afcb8ce..65d09a550d 100644
--- a/scene/animation/animation_blend_space_2d.h
+++ b/scene/animation/animation_blend_space_2d.h
@@ -55,23 +55,23 @@ protected:
};
BlendPoint blend_points[MAX_BLEND_POINTS];
- int blend_points_used;
+ int blend_points_used = 0;
struct BlendTriangle {
- int points[3];
+ int points[3] = {};
};
Vector<BlendTriangle> triangles;
- StringName blend_position;
- StringName closest;
- StringName length_internal;
- Vector2 max_space;
- Vector2 min_space;
- Vector2 snap;
- String x_label;
- String y_label;
- BlendMode blend_mode;
+ StringName blend_position = "blend_position";
+ StringName closest = "closest";
+ StringName length_internal = "length_internal";
+ Vector2 max_space = Vector2(1, 1);
+ Vector2 min_space = Vector2(-1, -1);
+ Vector2 snap = Vector2(0.1, 0.1);
+ String x_label = "x";
+ String y_label = "y";
+ BlendMode blend_mode = BLEND_MODE_INTERPOLATED;
void _add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node);
void _set_triangles(const Vector<int> &p_triangles);
@@ -79,8 +79,8 @@ protected:
void _blend_triangle(const Vector2 &p_pos, const Vector2 *p_points, float *r_weights);
- bool auto_triangles;
- bool trianges_dirty;
+ bool auto_triangles = true;
+ bool trianges_dirty = false;
void _update_triangles();
void _queue_auto_triangles();
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 24ae01e9d8..79a1dc1ac0 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -34,7 +34,6 @@
void AnimationNodeAnimation::set_animation(const StringName &p_name) {
animation = p_name;
- _change_notify("animation");
}
StringName AnimationNodeAnimation::get_animation() const {
@@ -125,9 +124,6 @@ void AnimationNodeAnimation::_bind_methods() {
}
AnimationNodeAnimation::AnimationNodeAnimation() {
- last_version = 0;
- skip = false;
- time = "time";
}
////////////////////////////////////////////////////////
@@ -346,21 +342,6 @@ void AnimationNodeOneShot::_bind_methods() {
AnimationNodeOneShot::AnimationNodeOneShot() {
add_input("in");
add_input("shot");
-
- fade_in = 0.1;
- fade_out = 0.1;
- autorestart = false;
- autorestart_delay = 1;
- autorestart_random_delay = 0;
-
- mix = MIX_MODE_BLEND;
- sync = false;
-
- active = "active";
- prev_active = "prev_active";
- time = "time";
- remaining = "remaining";
- time_to_restart = "time_to_restart";
}
////////////////////////////////////////////////
@@ -405,10 +386,8 @@ void AnimationNodeAdd2::_bind_methods() {
}
AnimationNodeAdd2::AnimationNodeAdd2() {
- add_amount = "add_amount";
add_input("in");
add_input("add");
- sync = false;
}
////////////////////////////////////////////////
@@ -454,11 +433,9 @@ void AnimationNodeAdd3::_bind_methods() {
}
AnimationNodeAdd3::AnimationNodeAdd3() {
- add_amount = "add_amount";
add_input("-add");
add_input("in");
add_input("+add");
- sync = false;
}
/////////////////////////////////////////////
@@ -504,10 +481,8 @@ void AnimationNodeBlend2::_bind_methods() {
}
AnimationNodeBlend2::AnimationNodeBlend2() {
- blend_amount = "blend_amount";
add_input("in");
add_input("blend");
- sync = false;
}
//////////////////////////////////////
@@ -583,7 +558,6 @@ void AnimationNodeTimeScale::_bind_methods() {
}
AnimationNodeTimeScale::AnimationNodeTimeScale() {
- scale = "scale";
add_input("in");
}
@@ -608,7 +582,6 @@ float AnimationNodeTimeSeek::process(float p_time, bool p_seek) {
} else if (seek_pos >= 0) {
float ret = blend_input(0, seek_pos, true, 1.0, FILTER_IGNORE, false);
set_parameter(this->seek_pos, -1.0); //reset
- _change_notify("seek_pos");
return ret;
} else {
return blend_input(0, p_time, false, 1.0, FILTER_IGNORE, false);
@@ -620,7 +593,6 @@ void AnimationNodeTimeSeek::_bind_methods() {
AnimationNodeTimeSeek::AnimationNodeTimeSeek() {
add_input("in");
- seek_pos = "seek_position";
}
/////////////////////////////////////////////////
@@ -728,7 +700,7 @@ float AnimationNodeTransition::process(float p_time, bool p_seek) {
return 0;
}
- float rem = 0;
+ float rem = 0.0;
if (prev < 0) { // process current animation, check for transition
@@ -811,16 +783,7 @@ void AnimationNodeTransition::_bind_methods() {
}
AnimationNodeTransition::AnimationNodeTransition() {
- prev_xfading = "prev_xfading";
- prev = "prev";
- time = "time";
- current = "current";
- prev_current = "prev_current";
- xfade = 0.0;
-
- enabled_inputs = 0;
for (int i = 0; i < MAX_INPUTS; i++) {
- inputs[i].auto_advance = false;
inputs[i].name = "state " + itos(i);
}
}
@@ -1158,6 +1121,13 @@ void AnimationNodeBlendTree::_get_property_list(List<PropertyInfo> *p_list) cons
p_list->push_back(PropertyInfo(Variant::ARRAY, "node_connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
}
+void AnimationNodeBlendTree::reset_state() {
+ graph_offset = Vector2();
+ nodes.clear();
+ emit_changed();
+ emit_signal("tree_changed");
+}
+
void AnimationNodeBlendTree::_tree_changed() {
emit_signal("tree_changed");
}
diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h
index 45a9f2e7e1..d82658c8c2 100644
--- a/scene/animation/animation_blend_tree.h
+++ b/scene/animation/animation_blend_tree.h
@@ -37,10 +37,10 @@ class AnimationNodeAnimation : public AnimationRootNode {
GDCLASS(AnimationNodeAnimation, AnimationRootNode);
StringName animation;
- StringName time;
+ StringName time = "time";
- uint64_t last_version;
- bool skip;
+ uint64_t last_version = 0;
+ bool skip = false;
protected:
void _validate_property(PropertyInfo &property) const override;
@@ -71,26 +71,26 @@ public:
};
private:
- float fade_in;
- float fade_out;
+ float fade_in = 0.1;
+ float fade_out = 0.1;
- bool autorestart;
- float autorestart_delay;
- float autorestart_random_delay;
- MixMode mix;
+ bool autorestart = false;
+ float autorestart_delay = 1.0;
+ float autorestart_random_delay = 0.0;
+ MixMode mix = MIX_MODE_BLEND;
- bool sync;
+ bool sync = false;
/* bool active;
bool do_start;
float time;
float remaining;*/
- StringName active;
- StringName prev_active;
- StringName time;
- StringName remaining;
- StringName time_to_restart;
+ StringName active = "active";
+ StringName prev_active = "prev_active";
+ StringName time = "time";
+ StringName remaining = "remaining";
+ StringName time_to_restart = "time_to_restart";
protected:
static void _bind_methods();
@@ -132,8 +132,8 @@ VARIANT_ENUM_CAST(AnimationNodeOneShot::MixMode)
class AnimationNodeAdd2 : public AnimationNode {
GDCLASS(AnimationNodeAdd2, AnimationNode);
- StringName add_amount;
- bool sync;
+ StringName add_amount = "add_amount";
+ bool sync = false;
protected:
static void _bind_methods();
@@ -156,8 +156,8 @@ public:
class AnimationNodeAdd3 : public AnimationNode {
GDCLASS(AnimationNodeAdd3, AnimationNode);
- StringName add_amount;
- bool sync;
+ StringName add_amount = "add_amount";
+ bool sync = false;
protected:
static void _bind_methods();
@@ -180,8 +180,8 @@ public:
class AnimationNodeBlend2 : public AnimationNode {
GDCLASS(AnimationNodeBlend2, AnimationNode);
- StringName blend_amount;
- bool sync;
+ StringName blend_amount = "blend_amount";
+ bool sync = false;
protected:
static void _bind_methods();
@@ -225,7 +225,7 @@ public:
class AnimationNodeTimeScale : public AnimationNode {
GDCLASS(AnimationNodeTimeScale, AnimationNode);
- StringName scale;
+ StringName scale = "scale";
protected:
static void _bind_methods();
@@ -244,7 +244,7 @@ public:
class AnimationNodeTimeSeek : public AnimationNode {
GDCLASS(AnimationNodeTimeSeek, AnimationNode);
- StringName seek_pos;
+ StringName seek_pos = "seek_position";
protected:
static void _bind_methods();
@@ -268,12 +268,11 @@ class AnimationNodeTransition : public AnimationNode {
};
struct InputData {
String name;
- bool auto_advance;
- InputData() { auto_advance = false; }
+ bool auto_advance = false;
};
InputData inputs[MAX_INPUTS];
- int enabled_inputs;
+ int enabled_inputs = 0;
/*
float prev_xfading;
@@ -282,13 +281,13 @@ class AnimationNodeTransition : public AnimationNode {
int current;
int prev_current; */
- StringName prev_xfading;
- StringName prev;
- StringName time;
- StringName current;
- StringName prev_current;
+ StringName prev_xfading = "prev_xfading";
+ StringName prev = "prev";
+ StringName time = "time";
+ StringName current = "current";
+ StringName prev_current = "prev_current";
- float xfade;
+ float xfade = 0.0;
void _update_inputs();
@@ -352,6 +351,8 @@ protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ virtual void reset_state() override;
+
public:
enum ConnectionError {
CONNECTION_OK,
@@ -381,7 +382,7 @@ public:
struct NodeConnection {
StringName input_node;
- int input_index;
+ int input_index = 0;
StringName output_node;
};
diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp
index 6ef2da6977..689acdd57b 100644
--- a/scene/animation/animation_cache.cpp
+++ b/scene/animation/animation_cache.cpp
@@ -308,7 +308,4 @@ void AnimationCache::set_root(Node *p_root) {
}
AnimationCache::AnimationCache() {
- root = nullptr;
- cache_dirty = true;
- cache_valid = false;
}
diff --git a/scene/animation/animation_cache.h b/scene/animation/animation_cache.h
index 484b710b06..07c9d09ae0 100644
--- a/scene/animation/animation_cache.h
+++ b/scene/animation/animation_cache.h
@@ -39,31 +39,23 @@ class AnimationCache : public Object {
struct Path {
RES resource;
- Object *object;
- Skeleton3D *skeleton; // haxor
- Node *node;
- Node3D *spatial;
+ Object *object = nullptr;
+ Skeleton3D *skeleton = nullptr; // haxor
+ Node *node = nullptr;
+ Node3D *spatial = nullptr;
- int bone_idx;
+ int bone_idx = -1;
Vector<StringName> subpath;
- bool valid;
- Path() {
- object = nullptr;
- skeleton = nullptr;
- node = nullptr;
- bone_idx = -1;
- valid = false;
- spatial = nullptr;
- }
+ bool valid = false;
};
Set<Node *> connected_nodes;
Vector<Path> path_cache;
- Node *root;
+ Node *root = nullptr;
Ref<Animation> animation;
- bool cache_dirty;
- bool cache_valid;
+ bool cache_dirty = true;
+ bool cache_valid = false;
void _node_exit_tree(Node *p_node);
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index ef9f531f04..d46f24752e 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -130,11 +130,6 @@ void AnimationNodeStateMachineTransition::_bind_methods() {
}
AnimationNodeStateMachineTransition::AnimationNodeStateMachineTransition() {
- switch_mode = SWITCH_MODE_IMMEDIATE;
- auto_advance = false;
- xfade = 0;
- disabled = false;
- priority = 1;
}
////////////////////////////////////////////////////////
@@ -322,7 +317,7 @@ float AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_st
// stopped, invalid state
String node_name = start_request;
start_request = StringName(); //clear start request
- ERR_FAIL_V_MSG(0, "Can't travel to '" + node_name + "' if state machine is not playing.");
+ ERR_FAIL_V_MSG(0, "Can't travel to '" + node_name + "' if state machine is not playing. Maybe you need to enable Autoplay on Load for one of the nodes in your state machine or call .start() first?");
}
} else {
if (!_travel(p_state_machine, start_request)) {
@@ -398,7 +393,7 @@ float AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_st
//find next
StringName next;
- float next_xfade = 0;
+ float next_xfade = 0.0;
AnimationNodeStateMachineTransition::SwitchMode switch_mode = AnimationNodeStateMachineTransition::SWITCH_MODE_IMMEDIATE;
if (path.size()) {
@@ -502,16 +497,6 @@ void AnimationNodeStateMachinePlayback::_bind_methods() {
AnimationNodeStateMachinePlayback::AnimationNodeStateMachinePlayback() {
set_local_to_scene(true); //only one per instanced scene
-
- playing = false;
- len_current = 0;
- fading_time = 0;
- stop_request = false;
- len_total = 0.0;
- pos_current = 0.0;
- loops_current = 0;
- fading_pos = 0.0;
- start_request_travel = false;
}
///////////////////////////////////////////////////////
@@ -929,6 +914,18 @@ void AnimationNodeStateMachine::_get_property_list(List<PropertyInfo> *p_list) c
p_list->push_back(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
}
+void AnimationNodeStateMachine::reset_state() {
+ states.clear();
+ transitions.clear();
+ playback = "playback";
+ start_node = StringName();
+ end_node = StringName();
+ graph_offset = Vector2();
+
+ emit_changed();
+ emit_signal("tree_changed");
+}
+
void AnimationNodeStateMachine::set_node_position(const StringName &p_name, const Vector2 &p_position) {
ERR_FAIL_COND(!states.has(p_name));
states[p_name].position = p_position;
@@ -975,5 +972,4 @@ void AnimationNodeStateMachine::_bind_methods() {
}
AnimationNodeStateMachine::AnimationNodeStateMachine() {
- playback = "playback";
}
diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h
index daeb2fabaa..9c1bca63c3 100644
--- a/scene/animation/animation_node_state_machine.h
+++ b/scene/animation/animation_node_state_machine.h
@@ -44,13 +44,13 @@ public:
};
private:
- SwitchMode switch_mode;
- bool auto_advance;
+ SwitchMode switch_mode = SWITCH_MODE_IMMEDIATE;
+ bool auto_advance = false;
StringName advance_condition;
StringName advance_condition_name;
- float xfade;
- bool disabled;
- int priority;
+ float xfade = 0.0;
+ bool disabled = false;
+ int priority = 1;
protected:
static void _bind_methods();
@@ -89,28 +89,28 @@ class AnimationNodeStateMachinePlayback : public Resource {
friend class AnimationNodeStateMachine;
struct AStarCost {
- float distance;
+ float distance = 0.0;
StringName prev;
};
- float len_total;
+ float len_total = 0.0;
- float len_current;
- float pos_current;
- int loops_current;
+ float len_current = 0.0;
+ float pos_current = 0.0;
+ int loops_current = 0;
StringName current;
StringName fading_from;
- float fading_time;
- float fading_pos;
+ float fading_time = 0.0;
+ float fading_pos = 0.0;
Vector<StringName> path;
- bool playing;
+ bool playing = false;
StringName start_request;
- bool start_request_travel;
- bool stop_request;
+ bool start_request_travel = false;
+ bool stop_request = false;
bool _travel(AnimationNodeStateMachine *p_state_machine, const StringName &p_travel);
@@ -154,7 +154,7 @@ private:
Vector<Transition> transitions;
- StringName playback;
+ StringName playback = "playback";
StringName start_node;
StringName end_node;
@@ -171,6 +171,8 @@ protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ virtual void reset_state() override;
+
public:
virtual void get_parameter_list(List<PropertyInfo> *r_list) const override;
virtual Variant get_parameter_default_value(const StringName &p_parameter) const override;
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 8e50c733ae..0c1798a876 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -206,7 +206,7 @@ void AnimationPlayer::_notification(int p_what) {
}
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
- if (animation_process_mode == ANIMATION_PROCESS_PHYSICS) {
+ if (process_callback == ANIMATION_PROCESS_PHYSICS) {
break;
}
@@ -215,7 +215,7 @@ void AnimationPlayer::_notification(int p_what) {
}
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
- if (animation_process_mode == ANIMATION_PROCESS_IDLE) {
+ if (process_callback == ANIMATION_PROCESS_IDLE) {
break;
}
@@ -229,13 +229,13 @@ void AnimationPlayer::_notification(int p_what) {
}
}
-void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) {
+void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_override) {
// Already cached?
if (p_anim->node_cache.size() == p_anim->animation->get_track_count()) {
return;
}
- Node *parent = get_node(root);
+ Node *parent = p_root_override ? p_root_override : get_node(root);
ERR_FAIL_COND(!parent);
@@ -605,7 +605,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
}
if (p_seeked) {
- //find whathever should be playing
+ //find whatever should be playing
int idx = a->track_find_key(i, p_time);
if (idx < 0) {
continue;
@@ -634,7 +634,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
nc->audio_playing = true;
playing_caches.insert(nc);
- if (len && end_ofs > 0) { //force a end at a time
+ if (len && end_ofs > 0) { //force an end at a time
nc->audio_len = len - start_ofs - end_ofs;
} else {
nc->audio_len = 0;
@@ -665,7 +665,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
nc->audio_playing = true;
playing_caches.insert(nc);
- if (len && end_ofs > 0) { //force a end at a time
+ if (len && end_ofs > 0) { //force an end at a time
nc->audio_len = len - start_ofs - end_ofs;
} else {
nc->audio_len = 0;
@@ -969,7 +969,7 @@ Error AnimationPlayer::add_animation(const StringName &p_name, const Ref<Animati
}
_ref_anim(p_animation);
- _change_notify();
+ notify_property_list_changed();
return OK;
}
@@ -981,7 +981,7 @@ void AnimationPlayer::remove_animation(const StringName &p_name) {
animation_set.erase(p_name);
clear_caches();
- _change_notify();
+ notify_property_list_changed();
}
void AnimationPlayer::_ref_anim(const Ref<Animation> &p_anim) {
@@ -1039,7 +1039,7 @@ void AnimationPlayer::rename_animation(const StringName &p_name, const StringNam
}
clear_caches();
- _change_notify();
+ notify_property_list_changed();
}
bool AnimationPlayer::has_animation(const StringName &p_name) const {
@@ -1132,7 +1132,7 @@ void AnimationPlayer::play(const StringName &p_name, float p_custom_blend, float
Playback &c = playback;
if (c.current.from) {
- float blend_time = 0;
+ float blend_time = 0.0;
// find if it can blend
BlendKey bk;
bk.from = c.current.from->name;
@@ -1343,7 +1343,7 @@ void AnimationPlayer::_stop_playing_caches() {
}
void AnimationPlayer::_node_removed(Node *p_node) {
- clear_caches(); // nodes contained here ar being removed, clear the caches
+ clear_caches(); // nodes contained here are being removed, clear the caches
}
void AnimationPlayer::clear_caches() {
@@ -1403,8 +1403,8 @@ bool AnimationPlayer::is_reset_on_save_enabled() const {
return reset_on_save;
}
-void AnimationPlayer::set_animation_process_mode(AnimationProcessMode p_mode) {
- if (animation_process_mode == p_mode) {
+void AnimationPlayer::set_process_callback(AnimationProcessCallback p_mode) {
+ if (process_callback == p_mode) {
return;
}
@@ -1412,14 +1412,14 @@ void AnimationPlayer::set_animation_process_mode(AnimationProcessMode p_mode) {
if (pr) {
_set_process(false);
}
- animation_process_mode = p_mode;
+ process_callback = p_mode;
if (pr) {
_set_process(true);
}
}
-AnimationPlayer::AnimationProcessMode AnimationPlayer::get_animation_process_mode() const {
- return animation_process_mode;
+AnimationPlayer::AnimationProcessCallback AnimationPlayer::get_process_callback() const {
+ return process_callback;
}
void AnimationPlayer::set_method_call_mode(AnimationMethodCallMode p_mode) {
@@ -1435,7 +1435,7 @@ void AnimationPlayer::_set_process(bool p_process, bool p_force) {
return;
}
- switch (animation_process_mode) {
+ switch (process_callback) {
case ANIMATION_PROCESS_PHYSICS:
set_physics_process_internal(p_process && active);
break;
@@ -1497,13 +1497,13 @@ void AnimationPlayer::get_argument_options(const StringName &p_function, int p_i
}
#ifdef TOOLS_ENABLED
-Ref<AnimatedValuesBackup> AnimationPlayer::backup_animated_values() {
+Ref<AnimatedValuesBackup> AnimationPlayer::backup_animated_values(Node *p_root_override) {
Ref<AnimatedValuesBackup> backup;
if (!playback.current.from) {
return backup;
}
- _ensure_node_caches(playback.current.from);
+ _ensure_node_caches(playback.current.from, p_root_override);
backup.instance();
for (int i = 0; i < playback.current.from->node_cache.size(); i++) {
@@ -1560,10 +1560,11 @@ Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) {
AnimationPlayer *aux_player = memnew(AnimationPlayer);
EditorNode::get_singleton()->add_child(aux_player);
- aux_player->set_root(aux_player->get_path_to(root_node));
aux_player->add_animation("RESET", reset_anim);
aux_player->set_assigned_animation("RESET");
- Ref<AnimatedValuesBackup> old_values = aux_player->backup_animated_values();
+ // Forcing the use of the original root because the scene where original player belongs may be not the active one
+ Node *root = get_node(get_root());
+ Ref<AnimatedValuesBackup> old_values = aux_player->backup_animated_values(root);
aux_player->seek(0.0f, true);
aux_player->queue_delete();
@@ -1636,8 +1637,8 @@ void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_caches"), &AnimationPlayer::clear_caches);
- ClassDB::bind_method(D_METHOD("set_animation_process_mode", "mode"), &AnimationPlayer::set_animation_process_mode);
- ClassDB::bind_method(D_METHOD("get_animation_process_mode"), &AnimationPlayer::get_animation_process_mode);
+ ClassDB::bind_method(D_METHOD("set_process_callback", "mode"), &AnimationPlayer::set_process_callback);
+ ClassDB::bind_method(D_METHOD("get_process_callback"), &AnimationPlayer::get_process_callback);
ClassDB::bind_method(D_METHOD("set_method_call_mode", "mode"), &AnimationPlayer::set_method_call_mode);
ClassDB::bind_method(D_METHOD("get_method_call_mode"), &AnimationPlayer::get_method_call_mode);
@@ -1657,7 +1658,7 @@ void AnimationPlayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "current_animation_position", PROPERTY_HINT_NONE, "", 0), "", "get_current_animation_position");
ADD_GROUP("Playback Options", "playback_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_animation_process_mode", "get_animation_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_process_callback", "get_process_callback");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_default_blend_time", "get_default_blend_time");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playback_active", PROPERTY_HINT_NONE, "", 0), "set_active", "is_active");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_speed", PROPERTY_HINT_RANGE, "-64,64,0.01"), "set_speed_scale", "get_speed_scale");
@@ -1677,23 +1678,7 @@ void AnimationPlayer::_bind_methods() {
}
AnimationPlayer::AnimationPlayer() {
- accum_pass = 1;
- cache_update_size = 0;
- cache_update_prop_size = 0;
- cache_update_bezier_size = 0;
- speed_scale = 1;
- end_reached = false;
- end_notify = false;
- reset_on_save = true;
- animation_process_mode = ANIMATION_PROCESS_IDLE;
- method_call_mode = ANIMATION_METHOD_CALL_DEFERRED;
- processing = false;
- default_blend_time = 0;
root = SceneStringNames::get_singleton()->path_pp;
- playing = false;
- active = true;
- playback.seeked = false;
- playback.started = false;
}
AnimationPlayer::~AnimationPlayer() {
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index 4532825f5a..2a1821c215 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -41,9 +41,9 @@ class AnimatedValuesBackup : public Reference {
GDCLASS(AnimatedValuesBackup, Reference);
struct Entry {
- Object *object;
+ Object *object = nullptr;
Vector<StringName> subpath; // Unused if bone
- int bone_idx; // -1 if not a bone
+ int bone_idx = -1; // -1 if not a bone
Variant value;
};
Vector<Entry> entries;
@@ -64,7 +64,7 @@ class AnimationPlayer : public Node {
OBJ_CATEGORY("Animation Nodes");
public:
- enum AnimationProcessMode {
+ enum AnimationProcessCallback {
ANIMATION_PROCESS_PHYSICS,
ANIMATION_PROCESS_IDLE,
ANIMATION_PROCESS_MANUAL,
@@ -118,8 +118,6 @@ private:
Variant value_accum;
uint64_t accum_pass = 0;
Variant capture;
-
- PropertyAnim() {}
};
Map<StringName, PropertyAnim> property_anim;
@@ -130,8 +128,6 @@ private:
float bezier_accum = 0.0;
Object *object = nullptr;
uint64_t accum_pass = 0;
-
- BezierAnim() {}
};
Map<StringName, BezierAnim> bezier_anim;
@@ -141,7 +137,7 @@ private:
struct TrackNodeCacheKey {
ObjectID id;
- int bone_idx;
+ int bone_idx = -1;
inline bool operator<(const TrackNodeCacheKey &p_right) const {
if (id == p_right.id) {
@@ -155,16 +151,16 @@ private:
Map<TrackNodeCacheKey, TrackNodeCache> node_cache_map;
TrackNodeCache *cache_update[NODE_CACHE_UPDATE_MAX];
- int cache_update_size;
+ int cache_update_size = 0;
TrackNodeCache::PropertyAnim *cache_update_prop[NODE_CACHE_UPDATE_MAX];
- int cache_update_prop_size;
+ int cache_update_prop_size = 0;
TrackNodeCache::BezierAnim *cache_update_bezier[NODE_CACHE_UPDATE_MAX];
- int cache_update_bezier_size;
+ int cache_update_bezier_size = 0;
Set<TrackNodeCache *> playing_caches;
- uint64_t accum_pass;
- float speed_scale;
- float default_blend_time;
+ uint64_t accum_pass = 1;
+ float speed_scale = 1.0;
+ float default_blend_time = 0.0;
struct AnimationData {
String name;
@@ -183,54 +179,43 @@ private:
Map<BlendKey, float> blend_times;
struct PlaybackData {
- AnimationData *from;
- float pos;
- float speed_scale;
-
- PlaybackData() {
- pos = 0;
- speed_scale = 1.0;
- from = nullptr;
- }
+ AnimationData *from = nullptr;
+ float pos = 0.0;
+ float speed_scale = 1.0;
};
struct Blend {
PlaybackData data;
- float blend_time;
- float blend_left;
-
- Blend() {
- blend_left = 0;
- blend_time = 0;
- }
+ float blend_time = 0.0;
+ float blend_left = 0.0;
};
struct Playback {
List<Blend> blend;
PlaybackData current;
StringName assigned;
- bool seeked;
- bool started;
+ bool seeked = false;
+ bool started = false;
} playback;
List<StringName> queued;
- bool end_reached;
- bool end_notify;
+ bool end_reached = false;
+ bool end_notify = false;
String autoplay;
- bool reset_on_save;
- AnimationProcessMode animation_process_mode;
- AnimationMethodCallMode method_call_mode;
- bool processing;
- bool active;
+ bool reset_on_save = true;
+ AnimationProcessCallback process_callback = ANIMATION_PROCESS_IDLE;
+ AnimationMethodCallMode method_call_mode = ANIMATION_METHOD_CALL_DEFERRED;
+ bool processing = false;
+ bool active = true;
NodePath root;
void _animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false);
- void _ensure_node_caches(AnimationData *p_anim);
+ void _ensure_node_caches(AnimationData *p_anim, Node *p_root_override = nullptr);
void _animation_process_data(PlaybackData &cd, float p_delta, float p_blend, bool p_seeked, bool p_started);
void _animation_process2(float p_delta, bool p_started);
void _animation_update_transforms();
@@ -257,7 +242,7 @@ private:
void _set_process(bool p_process, bool p_force = false);
- bool playing;
+ bool playing = false;
protected:
bool _set(const StringName &p_name, const Variant &p_value);
@@ -313,8 +298,8 @@ public:
void set_reset_on_save_enabled(bool p_enabled);
bool is_reset_on_save_enabled() const;
- void set_animation_process_mode(AnimationProcessMode p_mode);
- AnimationProcessMode get_animation_process_mode() const;
+ void set_process_callback(AnimationProcessCallback p_mode);
+ AnimationProcessCallback get_process_callback() const;
void set_method_call_mode(AnimationMethodCallMode p_mode);
AnimationMethodCallMode get_method_call_mode() const;
@@ -334,7 +319,7 @@ public:
void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override;
#ifdef TOOLS_ENABLED
- Ref<AnimatedValuesBackup> backup_animated_values();
+ Ref<AnimatedValuesBackup> backup_animated_values(Node *p_root_override = nullptr);
Ref<AnimatedValuesBackup> apply_reset(bool p_user_initiated = false);
bool can_apply_reset() const;
#endif
@@ -343,7 +328,7 @@ public:
~AnimationPlayer();
};
-VARIANT_ENUM_CAST(AnimationPlayer::AnimationProcessMode);
+VARIANT_ENUM_CAST(AnimationPlayer::AnimationProcessCallback);
VARIANT_ENUM_CAST(AnimationPlayer::AnimationMethodCallMode);
#endif
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index e6abbc0c7a..4b4d3943c9 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -158,7 +158,7 @@ float AnimationNode::blend_input(int p_input, float p_time, bool p_seek, float p
Ref<AnimationNode> node = blend_tree->get_node(node_name);
//inputs.write[p_input].last_pass = state->last_pass;
- float activity = 0;
+ float activity = 0.0;
float ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), nullptr, node, p_time, p_seek, p_blend, p_filter, p_optimize, &activity);
Vector<AnimationTree::Activity> *activity_ptr = state->tree->input_activity_map.getptr(base_path);
@@ -441,9 +441,6 @@ void AnimationNode::_bind_methods() {
}
AnimationNode::AnimationNode() {
- state = nullptr;
- parent = nullptr;
- filter_enabled = false;
}
////////////////////
@@ -476,7 +473,7 @@ void AnimationTree::set_active(bool p_active) {
active = p_active;
started = active;
- if (process_mode == ANIMATION_PROCESS_IDLE) {
+ if (process_callback == ANIMATION_PROCESS_IDLE) {
set_process_internal(active);
} else {
set_physics_process_internal(active);
@@ -497,8 +494,8 @@ bool AnimationTree::is_active() const {
return active;
}
-void AnimationTree::set_process_mode(AnimationProcessMode p_mode) {
- if (process_mode == p_mode) {
+void AnimationTree::set_process_callback(AnimationProcessCallback p_mode) {
+ if (process_callback == p_mode) {
return;
}
@@ -507,15 +504,15 @@ void AnimationTree::set_process_mode(AnimationProcessMode p_mode) {
set_active(false);
}
- process_mode = p_mode;
+ process_callback = p_mode;
if (was_active) {
set_active(true);
}
}
-AnimationTree::AnimationProcessMode AnimationTree::get_process_mode() const {
- return process_mode;
+AnimationTree::AnimationProcessCallback AnimationTree::get_process_callback() const {
+ return process_callback;
}
void AnimationTree::_node_removed(Node *p_node) {
@@ -820,6 +817,7 @@ void AnimationTree::_process_graph(float p_delta) {
Ref<Animation> a = as.animation;
float time = as.time;
float delta = as.delta;
+ float weight = as.blend;
bool seeked = as.seeked;
for (int i = 0; i < a->get_track_count(); i++) {
@@ -839,7 +837,7 @@ void AnimationTree::_process_graph(float p_delta) {
ERR_CONTINUE(blend_idx < 0 || blend_idx >= state.track_count);
- float blend = (*as.track_blends)[blend_idx];
+ float blend = (*as.track_blends)[blend_idx] * weight;
if (blend < CMP_EPSILON) {
continue; //nothing to blend
@@ -1011,7 +1009,7 @@ void AnimationTree::_process_graph(float p_delta) {
TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track);
if (seeked) {
- //find whathever should be playing
+ //find whatever should be playing
int idx = a->track_find_key(i, time);
if (idx < 0) {
continue;
@@ -1040,7 +1038,7 @@ void AnimationTree::_process_graph(float p_delta) {
t->playing = true;
playing_caches.insert(t);
- if (len && end_ofs > 0) { //force a end at a time
+ if (len && end_ofs > 0) { //force an end at a time
t->len = len - start_ofs - end_ofs;
} else {
t->len = 0;
@@ -1071,7 +1069,7 @@ void AnimationTree::_process_graph(float p_delta) {
t->playing = true;
playing_caches.insert(t);
- if (len && end_ofs > 0) { //force a end at a time
+ if (len && end_ofs > 0) { //force an end at a time
t->len = len - start_ofs - end_ofs;
} else {
t->len = 0;
@@ -1236,11 +1234,11 @@ void AnimationTree::advance(float p_time) {
}
void AnimationTree::_notification(int p_what) {
- if (active && p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS && process_mode == ANIMATION_PROCESS_PHYSICS) {
+ if (active && p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS && process_callback == ANIMATION_PROCESS_PHYSICS) {
_process_graph(get_physics_process_delta_time());
}
- if (active && p_what == NOTIFICATION_INTERNAL_PROCESS && process_mode == ANIMATION_PROCESS_IDLE) {
+ if (active && p_what == NOTIFICATION_INTERNAL_PROCESS && process_callback == ANIMATION_PROCESS_IDLE) {
_process_graph(get_process_delta_time());
}
@@ -1339,6 +1337,7 @@ void AnimationTree::_tree_changed() {
}
void AnimationTree::_update_properties_for_node(const String &p_base_path, Ref<AnimationNode> node) {
+ ERR_FAIL_COND(node.is_null());
if (!property_parent_map.has(p_base_path)) {
property_parent_map[p_base_path] = HashMap<StringName, StringName>();
}
@@ -1396,7 +1395,7 @@ void AnimationTree::_update_properties() {
properties_dirty = false;
- _change_notify();
+ notify_property_list_changed();
}
bool AnimationTree::_set(const StringName &p_name, const Variant &p_value) {
@@ -1406,9 +1405,6 @@ bool AnimationTree::_set(const StringName &p_name, const Variant &p_value) {
if (property_map.has(p_name)) {
property_map[p_name] = p_value;
-#ifdef TOOLS_ENABLED
- _change_notify(p_name.operator String().utf8().get_data());
-#endif
return true;
}
@@ -1476,8 +1472,8 @@ void AnimationTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tree_root", "root"), &AnimationTree::set_tree_root);
ClassDB::bind_method(D_METHOD("get_tree_root"), &AnimationTree::get_tree_root);
- ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &AnimationTree::set_process_mode);
- ClassDB::bind_method(D_METHOD("get_process_mode"), &AnimationTree::get_process_mode);
+ ClassDB::bind_method(D_METHOD("set_process_callback", "mode"), &AnimationTree::set_process_callback);
+ ClassDB::bind_method(D_METHOD("get_process_callback"), &AnimationTree::get_process_callback);
ClassDB::bind_method(D_METHOD("set_animation_player", "root"), &AnimationTree::set_animation_player);
ClassDB::bind_method(D_METHOD("get_animation_player"), &AnimationTree::get_animation_player);
@@ -1496,7 +1492,7 @@ void AnimationTree::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tree_root", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode"), "set_tree_root", "get_tree_root");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "anim_player", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "AnimationPlayer"), "set_animation_player", "get_animation_player");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_process_mode", "get_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_process_callback", "get_process_callback");
ADD_GROUP("Root Motion", "root_motion_");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_motion_track"), "set_root_motion_track", "get_root_motion_track");
@@ -1506,13 +1502,6 @@ void AnimationTree::_bind_methods() {
}
AnimationTree::AnimationTree() {
- process_mode = ANIMATION_PROCESS_IDLE;
- active = false;
- cache_valid = false;
- setup_pass = 1;
- process_pass = 1;
- started = true;
- properties_dirty = true;
}
AnimationTree::~AnimationTree() {
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index a0171e617b..1c5aec26ab 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -63,26 +63,26 @@ public:
struct AnimationState {
Ref<Animation> animation;
- float time;
- float delta;
- const Vector<float> *track_blends;
- float blend;
- bool seeked;
+ float time = 0.0;
+ float delta = 0.0;
+ const Vector<float> *track_blends = nullptr;
+ float blend = 0.0;
+ bool seeked = false;
};
struct State {
- int track_count;
+ int track_count = 0;
HashMap<NodePath, int> track_map;
List<AnimationState> animation_states;
- bool valid;
- AnimationPlayer *player;
- AnimationTree *tree;
+ bool valid = false;
+ AnimationPlayer *player = nullptr;
+ AnimationTree *tree = nullptr;
String invalid_reasons;
- uint64_t last_pass;
+ uint64_t last_pass = 0;
};
Vector<float> blends;
- State *state;
+ State *state = nullptr;
float _pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, float p_time, bool p_seek, const Vector<StringName> &p_connections);
void _pre_update_animations(HashMap<NodePath, int> *track_map);
@@ -90,10 +90,10 @@ public:
//all this is temporary
StringName base_path;
Vector<StringName> connections;
- AnimationNode *parent;
+ AnimationNode *parent = nullptr;
HashMap<NodePath, bool> filter;
- bool filter_enabled;
+ bool filter_enabled = false;
Array _get_filters() const;
void _set_filters(const Array &p_filters);
@@ -163,7 +163,7 @@ class AnimationTree : public Node {
GDCLASS(AnimationTree, Node);
public:
- enum AnimationProcessMode {
+ enum AnimationProcessCallback {
ANIMATION_PROCESS_PHYSICS,
ANIMATION_PROCESS_IDLE,
ANIMATION_PROCESS_MANUAL,
@@ -171,36 +171,29 @@ public:
private:
struct TrackCache {
- bool root_motion;
- uint64_t setup_pass;
- uint64_t process_pass;
- Animation::TrackType type;
- Object *object;
+ 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;
TrackCache() {
- root_motion = false;
- setup_pass = 0;
- process_pass = 0;
- object = nullptr;
}
virtual ~TrackCache() {}
};
struct TrackCacheTransform : public TrackCache {
- Node3D *spatial;
- Skeleton3D *skeleton;
- int bone_idx;
+ Node3D *spatial = nullptr;
+ Skeleton3D *skeleton = nullptr;
+ int bone_idx = -1;
Vector3 loc;
Quat rot;
- float rot_blend_accum;
+ float rot_blend_accum = 0.0;
Vector3 scale;
TrackCacheTransform() {
type = Animation::TYPE_TRANSFORM;
- spatial = nullptr;
- bone_idx = -1;
- skeleton = nullptr;
}
};
@@ -215,33 +208,28 @@ private:
};
struct TrackCacheBezier : public TrackCache {
- float value;
+ float value = 0.0;
Vector<StringName> subpath;
TrackCacheBezier() {
type = Animation::TYPE_BEZIER;
- value = 0;
}
};
struct TrackCacheAudio : public TrackCache {
- bool playing;
- float start;
- float len;
+ bool playing = false;
+ float start = 0.0;
+ float len = 0.0;
TrackCacheAudio() {
type = Animation::TYPE_AUDIO;
- playing = false;
- start = 0;
- len = 0;
}
};
struct TrackCacheAnimation : public TrackCache {
- bool playing;
+ bool playing = false;
TrackCacheAnimation() {
type = Animation::TYPE_ANIMATION;
- playing = false;
}
};
@@ -250,12 +238,12 @@ private:
Ref<AnimationNode> root;
- AnimationProcessMode process_mode;
- bool active;
+ AnimationProcessCallback process_callback = ANIMATION_PROCESS_IDLE;
+ bool active = false;
NodePath animation_player;
AnimationNode::State state;
- bool cache_valid;
+ bool cache_valid = false;
void _node_removed(Node *p_node);
void _caches_cleared();
@@ -263,16 +251,16 @@ private:
bool _update_caches(AnimationPlayer *player);
void _process_graph(float p_delta);
- uint64_t setup_pass;
- uint64_t process_pass;
+ uint64_t setup_pass = 1;
+ uint64_t process_pass = 1;
- bool started;
+ bool started = true;
NodePath root_motion_track;
Transform root_motion_transform;
friend class AnimationNode;
- bool properties_dirty;
+ bool properties_dirty = true;
void _tree_changed();
void _update_properties();
List<PropertyInfo> properties;
@@ -280,8 +268,8 @@ private:
HashMap<StringName, Variant> property_map;
struct Activity {
- uint64_t last_pass;
- float activity;
+ uint64_t last_pass = 0;
+ float activity = 0.0;
};
HashMap<StringName, Vector<Activity>> input_activity_map;
@@ -306,8 +294,8 @@ public:
void set_active(bool p_active);
bool is_active() const;
- void set_process_mode(AnimationProcessMode p_mode);
- AnimationProcessMode get_process_mode() const;
+ void set_process_callback(AnimationProcessCallback p_mode);
+ AnimationProcessCallback get_process_callback() const;
void set_animation_player(const NodePath &p_player);
NodePath get_animation_player() const;
@@ -332,6 +320,6 @@ public:
~AnimationTree();
};
-VARIANT_ENUM_CAST(AnimationTree::AnimationProcessMode)
+VARIANT_ENUM_CAST(AnimationTree::AnimationProcessCallback)
#endif // ANIMATION_GRAPH_PLAYER_H
diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp
index 5fd936df8e..9ee1f32581 100644
--- a/scene/animation/root_motion_view.cpp
+++ b/scene/animation/root_motion_view.cpp
@@ -89,12 +89,12 @@ void RootMotionView::_notification(int p_what) {
AnimationTree *tree = Object::cast_to<AnimationTree>(node);
if (tree && tree->is_active() && tree->get_root_motion_track() != NodePath()) {
- if (is_processing_internal() && tree->get_process_mode() == AnimationTree::ANIMATION_PROCESS_PHYSICS) {
+ if (is_processing_internal() && tree->get_process_callback() == AnimationTree::ANIMATION_PROCESS_PHYSICS) {
set_process_internal(false);
set_physics_process_internal(true);
}
- if (is_physics_processing_internal() && tree->get_process_mode() == AnimationTree::ANIMATION_PROCESS_IDLE) {
+ if (is_physics_processing_internal() && tree->get_process_callback() == AnimationTree::ANIMATION_PROCESS_IDLE) {
set_process_internal(true);
set_physics_process_internal(false);
}
@@ -188,13 +188,9 @@ void RootMotionView::_bind_methods() {
}
RootMotionView::RootMotionView() {
- zero_y = true;
- radius = 10;
- cell_size = 1;
set_process_internal(true);
immediate = RenderingServer::get_singleton()->immediate_create();
set_base(immediate);
- color = Color(0.5, 0.5, 1.0);
}
RootMotionView::~RootMotionView() {
diff --git a/scene/animation/root_motion_view.h b/scene/animation/root_motion_view.h
index 063fb8feda..afcff6137f 100644
--- a/scene/animation/root_motion_view.h
+++ b/scene/animation/root_motion_view.h
@@ -39,12 +39,12 @@ class RootMotionView : public VisualInstance3D {
public:
RID immediate;
NodePath path;
- float cell_size;
- float radius;
- bool use_in_game;
- Color color;
- bool first;
- bool zero_y;
+ float cell_size = 1.0;
+ float radius = 10.0;
+ bool use_in_game = false;
+ Color color = Color(0.5, 0.5, 1.0);
+ bool first = true;
+ bool zero_y = true;
Transform accumulated;
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 8bdb5c7447..2030808724 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -869,8 +869,21 @@ void Tween::start() {
return;
}
+ pending_update++;
+ for (List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) {
+ InterpolateData &data = E->get();
+ data.active = true;
+ }
+ pending_update--;
+
// We want to be activated
set_active(true);
+
+ // Don't resume from current position if stop_all() function has been used
+ if (was_stopped) {
+ seek(0);
+ }
+ was_stopped = false;
}
void Tween::reset(Object *p_object, StringName p_key) {
@@ -939,7 +952,7 @@ void Tween::stop(Object *p_object, StringName p_key) {
void Tween::stop_all() {
// We no longer need to be active since all tweens have been stopped
set_active(false);
-
+ was_stopped = true;
// For each interpolation...
pending_update++;
for (List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) {
@@ -1098,11 +1111,11 @@ void Tween::seek(real_t p_time) {
real_t Tween::tell() const {
// We want to grab the position of the furthest along tween
pending_update++;
- real_t pos = 0;
+ real_t pos = 0.0;
// For each interpolation...
for (const List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) {
- // Get the data and figure out if it's position is further along than the previous ones
+ // Get the data and figure out if its position is further along than the previous ones
const InterpolateData &data = E->get();
if (data.elapsed > pos) {
// Save it if so
@@ -1122,7 +1135,7 @@ real_t Tween::get_runtime() const {
pending_update++;
// For each interpolation...
- real_t runtime = 0;
+ real_t runtime = 0.0;
for (const List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) {
// Get the tween data and see if it's runtime is greater than the previous tweens
const InterpolateData &data = E->get();
@@ -1350,6 +1363,9 @@ void Tween::interpolate_property(Object *p_object, NodePath p_property, Variant
return;
}
+ // Check that the target object is valid
+ ERR_FAIL_COND_MSG(p_object == nullptr, vformat("The Tween \"%s\"'s target node is `null`. Is the node reference correct?", get_name()));
+
// Get the property from the node path
p_property = p_property.get_as_property_path();
@@ -1378,6 +1394,9 @@ void Tween::interpolate_method(Object *p_object, StringName p_method, Variant p_
return;
}
+ // Check that the target object is valid
+ ERR_FAIL_COND_MSG(p_object == nullptr, vformat("The Tween \"%s\"'s target node is `null`. Is the node reference correct?", get_name()));
+
// Convert any integers into REALs as they are better for interpolation
if (p_initial_val.get_type() == Variant::INT) {
p_initial_val = p_initial_val.operator real_t();
@@ -1789,12 +1808,6 @@ void Tween::targeting_method(Object *p_object, StringName p_method, Object *p_in
}
Tween::Tween() {
- // Initialize tween attributes
- tween_process_mode = TWEEN_PROCESS_IDLE;
- repeat = false;
- speed_scale = 1;
- pending_update = 0;
- uid = 0;
}
Tween::~Tween() {
diff --git a/scene/animation/tween.h b/scene/animation/tween.h
index c65a6f850f..142c0c65e0 100644
--- a/scene/animation/tween.h
+++ b/scene/animation/tween.h
@@ -79,11 +79,11 @@ private:
};
struct InterpolateData {
- bool active;
- InterpolateType type;
- bool finish;
- bool call_deferred;
- real_t elapsed;
+ bool active = false;
+ InterpolateType type = INTER_CALLBACK;
+ bool finish = false;
+ bool call_deferred = false;
+ real_t elapsed = 0.0;
ObjectID id;
Vector<StringName> key;
StringName concatenated_key;
@@ -92,33 +92,28 @@ private:
Variant final_val;
ObjectID target_id;
Vector<StringName> target_key;
- real_t duration;
- TransitionType trans_type;
- EaseType ease_type;
- real_t delay;
- int args;
+ real_t duration = 0.0;
+ TransitionType trans_type = TransitionType::TRANS_BACK;
+ EaseType ease_type = EaseType::EASE_COUNT;
+ real_t delay = 0.0;
+ int args = 0;
Variant arg[5];
- int uid;
- InterpolateData() {
- active = false;
- finish = false;
- call_deferred = false;
- uid = 0;
- }
+ int uid = 0;
};
String autoplay;
- TweenProcessMode tween_process_mode;
- bool repeat;
- float speed_scale;
- mutable int pending_update;
- int uid;
+ TweenProcessMode tween_process_mode = TWEEN_PROCESS_IDLE;
+ bool repeat = false;
+ float speed_scale = 1.0;
+ mutable int pending_update = 0;
+ int uid = 0;
+ bool was_stopped = false;
List<InterpolateData> interpolates;
struct PendingCommand {
StringName key;
- int args;
+ int args = 0;
Variant arg[10];
};
List<PendingCommand> pending_commands;
diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp
index 4a9e146696..1478cbf69e 100644
--- a/scene/audio/audio_stream_player.cpp
+++ b/scene/audio/audio_stream_player.cpp
@@ -99,37 +99,37 @@ void AudioStreamPlayer::_mix_audio() {
use_fadeout = false;
}
- if (!stream_playback.is_valid() || !active ||
+ if (!stream_playback.is_valid() || !active.is_set() ||
(stream_paused && !stream_paused_fade)) {
return;
}
if (stream_paused) {
- if (stream_paused_fade) {
+ if (stream_paused_fade && stream_playback->is_playing()) {
_mix_internal(true);
stream_paused_fade = false;
}
return;
}
- if (setstop) {
+ if (setstop.is_set()) {
_mix_internal(true);
stream_playback->stop();
- setstop = false;
+ setstop.clear();
}
- if (setseek >= 0.0 && !stop_has_priority) {
+ if (setseek.get() >= 0.0 && !stop_has_priority.is_set()) {
if (stream_playback->is_playing()) {
//fade out to avoid pops
_mix_internal(true);
}
- stream_playback->start(setseek);
- setseek = -1.0; //reset seek
+ stream_playback->start(setseek.get());
+ setseek.set(-1.0); //reset seek
mix_volume_db = volume_db; //reset ramp
}
- stop_has_priority = false;
+ stop_has_priority.clear();
_mix_internal(false);
}
@@ -143,8 +143,8 @@ void AudioStreamPlayer::_notification(int p_what) {
}
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
- if (!active || (setseek < 0 && !stream_playback->is_playing())) {
- active = false;
+ if (!active.is_set() || (setseek.get() < 0 && !stream_playback->is_playing())) {
+ active.clear();
set_process_internal(false);
emit_signal("finished");
}
@@ -169,9 +169,9 @@ void AudioStreamPlayer::_notification(int p_what) {
void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) {
AudioServer::get_singleton()->lock();
- if (active && stream_playback.is_valid() && !stream_paused) {
+ if (active.is_set() && stream_playback.is_valid() && !stream_paused) {
//changing streams out of the blue is not a great idea, but at least
- //lets try to somehow avoid a click
+ //let's try to somehow avoid a click
AudioFrame *buffer = fadeout_buffer.ptrw();
int buffer_size = fadeout_buffer.size();
@@ -196,9 +196,9 @@ void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) {
if (stream_playback.is_valid()) {
stream_playback.unref();
stream.unref();
- active = false;
- setseek = -1;
- setstop = false;
+ active.clear();
+ setseek.set(-1);
+ setstop.clear();
}
if (p_stream.is_valid()) {
@@ -237,29 +237,29 @@ float AudioStreamPlayer::get_pitch_scale() const {
void AudioStreamPlayer::play(float p_from_pos) {
if (stream_playback.is_valid()) {
//mix_volume_db = volume_db; do not reset volume ramp here, can cause clicks
- setseek = p_from_pos;
- stop_has_priority = false;
- active = true;
+ setseek.set(p_from_pos);
+ stop_has_priority.clear();
+ active.set();
set_process_internal(true);
}
}
void AudioStreamPlayer::seek(float p_seconds) {
if (stream_playback.is_valid()) {
- setseek = p_seconds;
+ setseek.set(p_seconds);
}
}
void AudioStreamPlayer::stop() {
- if (stream_playback.is_valid() && active) {
- setstop = true;
- stop_has_priority = true;
+ if (stream_playback.is_valid() && active.is_set()) {
+ setstop.set();
+ stop_has_priority.set();
}
}
bool AudioStreamPlayer::is_playing() const {
if (stream_playback.is_valid()) {
- return active && !setstop; //&& stream_playback->is_playing();
+ return active.is_set() && !setstop.is_set(); //&& stream_playback->is_playing();
}
return false;
@@ -267,6 +267,10 @@ bool AudioStreamPlayer::is_playing() const {
float AudioStreamPlayer::get_playback_position() {
if (stream_playback.is_valid()) {
+ float ss = setseek.get();
+ if (ss >= 0.0) {
+ return ss;
+ }
return stream_playback->get_playback_position();
}
@@ -314,7 +318,7 @@ void AudioStreamPlayer::_set_playing(bool p_enable) {
}
bool AudioStreamPlayer::_is_active() const {
- return active;
+ return active.is_set();
}
void AudioStreamPlayer::set_stream_paused(bool p_pause) {
@@ -344,7 +348,7 @@ void AudioStreamPlayer::_validate_property(PropertyInfo &property) const {
}
void AudioStreamPlayer::_bus_layout_changed() {
- _change_notify();
+ notify_property_list_changed();
}
Ref<AudioStreamPlayback> AudioStreamPlayer::get_stream_playback() {
@@ -402,18 +406,7 @@ void AudioStreamPlayer::_bind_methods() {
}
AudioStreamPlayer::AudioStreamPlayer() {
- mix_volume_db = 0;
- pitch_scale = 1.0;
- volume_db = 0;
- autoplay = false;
- setseek = -1;
- active = false;
- stream_paused = false;
- stream_paused_fade = false;
- mix_target = MIX_TARGET_STEREO;
fadeout_buffer.resize(512);
- setstop = false;
- use_fadeout = false;
AudioServer::get_singleton()->connect("bus_layout_changed", callable_mp(this, &AudioStreamPlayer::_bus_layout_changed));
}
diff --git a/scene/audio/audio_stream_player.h b/scene/audio/audio_stream_player.h
index fa45a39682..aa8d088be5 100644
--- a/scene/audio/audio_stream_player.h
+++ b/scene/audio/audio_stream_player.h
@@ -31,6 +31,7 @@
#ifndef AUDIO_STREAM_PLAYER_H
#define AUDIO_STREAM_PLAYER_H
+#include "core/templates/safe_refcount.h"
#include "scene/main/node.h"
#include "servers/audio/audio_stream.h"
@@ -49,22 +50,22 @@ private:
Ref<AudioStream> stream;
Vector<AudioFrame> mix_buffer;
Vector<AudioFrame> fadeout_buffer;
- bool use_fadeout;
-
- volatile float setseek;
- volatile bool active;
- volatile bool setstop;
- volatile bool stop_has_priority;
-
- float mix_volume_db;
- float pitch_scale;
- float volume_db;
- bool autoplay;
- bool stream_paused;
- bool stream_paused_fade;
+ bool use_fadeout = false;
+
+ SafeNumeric<float> setseek{ -1.0 };
+ SafeFlag active;
+ SafeFlag setstop;
+ SafeFlag stop_has_priority;
+
+ float mix_volume_db = 0.0;
+ float pitch_scale = 1.0;
+ float volume_db = 0.0;
+ bool autoplay = false;
+ bool stream_paused = false;
+ bool stream_paused_fade = false;
StringName bus;
- MixTarget mix_target;
+ MixTarget mix_target = MIX_TARGET_STEREO;
void _mix_internal(bool p_fadeout);
void _mix_audio();
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index 4dbe3cc1c4..a1d4adcd41 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -487,7 +487,7 @@ void LiveEditor::_send_tree() {
}
Array arr;
- // Encoded as a flat list depth fist.
+ // Encoded as a flat list depth first.
SceneDebuggerTree tree(scene_tree->root);
tree.serialize(arr);
EngineDebugger::get_singleton()->send_message("scene:scene_tree", arr);
diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h
index 51632446f8..9d54556187 100644
--- a/scene/debugger/scene_debugger.h
+++ b/scene/debugger/scene_debugger.h
@@ -77,7 +77,7 @@ public:
class SceneDebuggerTree {
public:
struct RemoteNode {
- int child_count;
+ int child_count = 0;
String name;
String type_name;
ObjectID id;
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 27e33be9d7..db13b9b11f 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -199,7 +199,6 @@ void BaseButton::set_disabled(bool p_disabled) {
status.pressing_inside = false;
}
update();
- _change_notify("disabled");
}
bool BaseButton::is_disabled() const {
@@ -213,7 +212,6 @@ void BaseButton::set_pressed(bool p_pressed) {
if (status.pressed == p_pressed) {
return;
}
- _change_notify("pressed");
status.pressed = p_pressed;
if (p_pressed) {
@@ -448,18 +446,7 @@ void BaseButton::_bind_methods() {
}
BaseButton::BaseButton() {
- toggle_mode = false;
- shortcut_in_tooltip = true;
- keep_pressed_outside = false;
- status.pressed = false;
- status.press_attempt = false;
- status.hovering = false;
- status.pressing_inside = false;
- status.disabled = false;
set_focus_mode(FOCUS_ALL);
- action_mode = ACTION_MODE_BUTTON_RELEASE;
- button_mask = BUTTON_MASK_LEFT;
- shortcut_context = ObjectID();
}
BaseButton::~BaseButton() {
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index b349b75761..6c7a8f3433 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -45,21 +45,21 @@ public:
};
private:
- int button_mask;
- bool toggle_mode;
- bool shortcut_in_tooltip;
- bool keep_pressed_outside;
+ int button_mask = MOUSE_BUTTON_MASK_LEFT;
+ bool toggle_mode = false;
+ bool shortcut_in_tooltip = true;
+ bool keep_pressed_outside = false;
Ref<Shortcut> shortcut;
ObjectID shortcut_context;
- ActionMode action_mode;
+ ActionMode action_mode = ACTION_MODE_BUTTON_RELEASE;
struct Status {
- bool pressed;
- bool hovering;
- bool press_attempt;
- bool pressing_inside;
+ bool pressed = false;
+ bool hovering = false;
+ bool press_attempt = false;
+ bool pressing_inside = false;
- bool disabled;
+ bool disabled = false;
} status;
diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp
index a00d755c9c..7407ad5b8f 100644
--- a/scene/gui/box_container.cpp
+++ b/scene/gui/box_container.cpp
@@ -33,9 +33,9 @@
#include "margin_container.h"
struct _MinSizeCache {
- int min_size;
- bool will_stretch;
- int final_size;
+ int min_size = 0;
+ bool will_stretch = false;
+ int final_size = 0;
};
void BoxContainer::_resort() {
@@ -50,7 +50,7 @@ void BoxContainer::_resort() {
int children_count = 0;
int stretch_min = 0;
int stretch_avail = 0;
- float stretch_ratio_total = 0;
+ float stretch_ratio_total = 0.0;
Map<Control *, _MinSizeCache> min_size_cache;
for (int i = 0; i < get_child_count(); i++) {
@@ -105,7 +105,7 @@ void BoxContainer::_resort() {
has_stretched = true;
bool refit_successful = true; //assume refit-test will go well
- float error = 0; // Keep track of accumulated error in pixels
+ float error = 0.0; // Keep track of accumulated error in pixels
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@@ -313,7 +313,7 @@ BoxContainer::AlignMode BoxContainer::get_alignment() const {
return align;
}
-void BoxContainer::add_spacer(bool p_begin) {
+Control *BoxContainer::add_spacer(bool p_begin) {
Control *c = memnew(Control);
c->set_mouse_filter(MOUSE_FILTER_PASS); //allow spacer to pass mouse events
@@ -327,11 +327,12 @@ void BoxContainer::add_spacer(bool p_begin) {
if (p_begin) {
move_child(c, 0);
}
+
+ return c;
}
BoxContainer::BoxContainer(bool p_vertical) {
vertical = p_vertical;
- align = ALIGN_BEGIN;
}
void BoxContainer::_bind_methods() {
diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h
index 8285c2b9a2..23feea565c 100644
--- a/scene/gui/box_container.h
+++ b/scene/gui/box_container.h
@@ -44,8 +44,8 @@ public:
};
private:
- bool vertical;
- AlignMode align;
+ bool vertical = false;
+ AlignMode align = ALIGN_BEGIN;
void _resort();
@@ -55,7 +55,7 @@ protected:
static void _bind_methods();
public:
- void add_spacer(bool p_begin = false);
+ Control *add_spacer(bool p_begin = false);
void set_alignment(AlignMode p_align);
AlignMode get_alignment() const;
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 8b3daf79a8..b0bcde8865 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -56,6 +56,11 @@ Size2 Button::get_minimum_size() const {
}
}
+ Ref<Font> font = get_theme_font("font");
+ float font_height = font->get_height(get_theme_font_size("font_size"));
+
+ minsize.height = MAX(font_height, minsize.height);
+
return get_theme_stylebox("normal")->get_minimum_size() + minsize;
}
@@ -203,7 +208,7 @@ void Button::_notification(int p_what) {
color_icon.a = 0.4;
}
- float icon_ofs_region = 0;
+ float icon_ofs_region = 0.0;
if (rtl) {
if (_internal_margin[SIDE_RIGHT] > 0) {
icon_ofs_region = _internal_margin[SIDE_RIGHT] + get_theme_constant("hseparation");
@@ -338,7 +343,6 @@ void Button::set_text(const String &p_text) {
_shape();
update();
- _change_notify("text");
minimum_size_changed();
}
}
@@ -399,7 +403,6 @@ void Button::set_icon(const Ref<Texture2D> &p_icon) {
if (icon != p_icon) {
icon = p_icon;
update();
- _change_notify("icon");
minimum_size_changed();
}
}
@@ -424,7 +427,6 @@ void Button::set_flat(bool p_flat) {
if (flat != p_flat) {
flat = p_flat;
update();
- _change_notify("flat");
}
}
@@ -474,7 +476,7 @@ bool Button::_set(const StringName &p_name, const Variant &p_value) {
update();
}
}
- _change_notify();
+ notify_property_list_changed();
return true;
}
@@ -544,16 +546,8 @@ Button::Button(const String &p_text) {
text_buf.instance();
text_buf->set_flags(TextServer::BREAK_MANDATORY);
- flat = false;
- clip_text = false;
- expand_icon = false;
set_mouse_filter(MOUSE_FILTER_STOP);
set_text(p_text);
- align = ALIGN_CENTER;
-
- for (int i = 0; i < 4; i++) {
- _internal_margin[i] = 0;
- }
}
Button::~Button() {
diff --git a/scene/gui/button.h b/scene/gui/button.h
index d633fddc8a..d968f63f51 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -45,7 +45,7 @@ public:
};
private:
- bool flat;
+ bool flat = false;
String text;
String xl_text;
Ref<TextParagraph> text_buf;
@@ -55,10 +55,10 @@ private:
TextDirection text_direction = TEXT_DIRECTION_AUTO;
Ref<Texture2D> icon;
- bool expand_icon;
- bool clip_text;
- TextAlign align;
- float _internal_margin[4];
+ bool expand_icon = false;
+ bool clip_text = false;
+ TextAlign align = ALIGN_CENTER;
+ float _internal_margin[4] = {};
void _shape();
diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp
index f2d1dee0fc..909516e7ef 100644
--- a/scene/gui/center_container.cpp
+++ b/scene/gui/center_container.cpp
@@ -95,6 +95,4 @@ void CenterContainer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_top_left"), "set_use_top_left", "is_using_top_left");
}
-CenterContainer::CenterContainer() {
- use_top_left = false;
-}
+CenterContainer::CenterContainer() {}
diff --git a/scene/gui/center_container.h b/scene/gui/center_container.h
index ee8b2e0e48..0944f200fc 100644
--- a/scene/gui/center_container.h
+++ b/scene/gui/center_container.h
@@ -36,7 +36,7 @@
class CenterContainer : public Container {
GDCLASS(CenterContainer, Container);
- bool use_top_left;
+ bool use_top_left = false;
protected:
void _notification(int p_what);
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index 9df328dd11..c0650a8f3f 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -34,7 +34,9 @@
Size2 CheckBox::get_icon_size() const {
Ref<Texture2D> checked = Control::get_theme_icon("checked");
+ Ref<Texture2D> checked_disabled = Control::get_theme_icon("checked_disabled");
Ref<Texture2D> unchecked = Control::get_theme_icon("unchecked");
+ Ref<Texture2D> unchecked_disabled = Control::get_theme_icon("unchecked_disabled");
Ref<Texture2D> radio_checked = Control::get_theme_icon("radio_checked");
Ref<Texture2D> radio_unchecked = Control::get_theme_icon("radio_unchecked");
@@ -79,8 +81,8 @@ void CheckBox::_notification(int p_what) {
} else if (p_what == NOTIFICATION_DRAW) {
RID ci = get_canvas_item();
- Ref<Texture2D> on = Control::get_theme_icon(is_radio() ? "radio_checked" : "checked");
- Ref<Texture2D> off = Control::get_theme_icon(is_radio() ? "radio_unchecked" : "unchecked");
+ Ref<Texture2D> on = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_checked" : "checked", is_disabled() ? "_disabled" : ""));
+ Ref<Texture2D> off = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_unchecked" : "unchecked", is_disabled() ? "_disabled" : ""));
Ref<StyleBox> sb = get_theme_stylebox("normal");
Vector2 ofs;
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 6c81ef0998..5822119b46 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -52,6 +52,7 @@ void ColorPicker::_notification(int p_what) {
btn_pick->set_icon(get_theme_icon("screen_picker", "ColorPicker"));
bt_add_preset->set_icon(get_theme_icon("add_preset"));
+ _update_controls();
_update_color();
#ifdef TOOLS_ENABLED
@@ -112,6 +113,24 @@ void ColorPicker::_update_controls() {
btn_hsv->set_disabled(false);
}
+ if (raw_mode_enabled) {
+ for (int i = 0; i < 3; i++) {
+ scroll[i]->add_theme_icon_override("grabber", Ref<Texture2D>());
+ scroll[i]->add_theme_icon_override("grabber_highlight", Ref<Texture2D>());
+ scroll[i]->add_theme_style_override("slider", Ref<StyleBox>());
+ scroll[i]->add_theme_style_override("grabber_area", Ref<StyleBox>());
+ scroll[i]->add_theme_style_override("grabber_area_highlight", Ref<StyleBox>());
+ }
+ } else {
+ for (int i = 0; i < 3; i++) {
+ scroll[i]->add_theme_icon_override("grabber", get_theme_icon("bar_arrow"));
+ scroll[i]->add_theme_icon_override("grabber_highlight", get_theme_icon("bar_arrow"));
+ scroll[i]->add_theme_style_override("slider", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
+ scroll[i]->add_theme_style_override("grabber_area", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
+ scroll[i]->add_theme_style_override("grabber_area_highlight", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
+ }
+ }
+
if (edit_alpha) {
values[3]->show();
scroll[3]->show();
@@ -165,10 +184,13 @@ void ColorPicker::_value_changed(double) {
}
if (hsv_mode_enabled) {
- color.set_hsv(scroll[0]->get_value() / 360.0,
- scroll[1]->get_value() / 100.0,
- scroll[2]->get_value() / 100.0,
- scroll[3]->get_value() / 255.0);
+ h = scroll[0]->get_value() / 360.0;
+ s = scroll[1]->get_value() / 100.0;
+ v = scroll[2]->get_value() / 100.0;
+ color.set_hsv(h, s, v, scroll[3]->get_value() / 255.0);
+
+ last_hsv = color;
+
} else {
for (int i = 0; i < 4; i++) {
color.components[i] = scroll[i]->get_value() / (raw_mode_enabled ? 1.0 : 255.0);
@@ -239,6 +261,9 @@ void ColorPicker::_update_color(bool p_update_sliders) {
sample->update();
uv_edit->update();
w_edit->update();
+ for (int i = 0; i < 4; i++) {
+ scroll[i]->update();
+ }
updating = false;
}
@@ -452,11 +477,74 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
}
}
+void ColorPicker::_slider_draw(int p_which) {
+ Vector<Vector2> pos;
+ pos.resize(4);
+ Vector<Color> col;
+ col.resize(4);
+ Size2 size = scroll[p_which]->get_size();
+ Color left_color;
+ Color right_color;
+#ifdef TOOLS_ENABLED
+ const real_t margin = 4 * EDSCALE;
+#else
+ const real_t margin = 4;
+#endif
+
+ if (p_which == 3) {
+ scroll[p_which]->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), Rect2(Point2(0, margin), Size2(size.x, margin)), true);
+
+ left_color = color;
+ left_color.a = 0;
+ right_color = color;
+ right_color.a = 1;
+ } else {
+ if (raw_mode_enabled) {
+ return;
+ }
+ if (hsv_mode_enabled) {
+ if (p_which == 0) {
+ Ref<Texture2D> hue = get_theme_icon("color_hue", "ColorPicker");
+ scroll[p_which]->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0));
+ scroll[p_which]->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(scroll[p_which]->get_size().x, margin)), false, Color(1, 1, 1), true);
+ return;
+ }
+ Color s_col;
+ Color v_col;
+ s_col.set_hsv(h, 0, v);
+ left_color = (p_which == 1) ? s_col : Color(0, 0, 0);
+ s_col.set_hsv(h, 1, v);
+ v_col.set_hsv(h, s, 1);
+ right_color = (p_which == 1) ? s_col : v_col;
+ } else {
+ left_color = Color(
+ p_which == 0 ? 0 : color.r,
+ p_which == 1 ? 0 : color.g,
+ p_which == 2 ? 0 : color.b);
+ right_color = Color(
+ p_which == 0 ? 1 : color.r,
+ p_which == 1 ? 1 : color.g,
+ p_which == 2 ? 1 : color.b);
+ }
+ }
+
+ col.set(0, left_color);
+ col.set(1, right_color);
+ col.set(2, right_color);
+ col.set(3, left_color);
+ pos.set(0, Vector2(0, margin));
+ pos.set(1, Vector2(size.x, margin));
+ pos.set(2, Vector2(size.x, margin * 2));
+ pos.set(3, Vector2(0, margin * 2));
+
+ scroll[p_which]->draw_polygon(pos, col);
+}
+
void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> bev = p_event;
if (bev.is_valid()) {
- if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) {
+ if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
changing_color = true;
float x = CLAMP((float)bev->get_position().x, 0, uv_edit->get_size().width);
float y = CLAMP((float)bev->get_position().y, 0, uv_edit->get_size().height);
@@ -469,7 +557,7 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) {
if (!deferred_mode_enabled) {
emit_signal("color_changed", color);
}
- } else if (deferred_mode_enabled && !bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) {
+ } else if (deferred_mode_enabled && !bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
emit_signal("color_changed", color);
changing_color = false;
} else {
@@ -501,7 +589,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> bev = p_event;
if (bev.is_valid()) {
- if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) {
+ if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
changing_color = true;
float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height);
h = y / w_edit->get_size().height;
@@ -514,7 +602,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
_update_color();
if (!deferred_mode_enabled) {
emit_signal("color_changed", color);
- } else if (!bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) {
+ } else if (!bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
emit_signal("color_changed", color);
}
}
@@ -542,7 +630,7 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) {
if (bev.is_valid()) {
int index = 0;
- if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) {
+ if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
for (int i = 0; i < presets.size(); i++) {
int x = (i % presets_per_row) * bt_add_preset->get_size().x;
int y = (Math::floor((float)i / presets_per_row)) * bt_add_preset->get_size().y;
@@ -553,7 +641,7 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) {
set_pick_color(presets[index]);
_update_color();
emit_signal("color_changed", color);
- } else if (bev->is_pressed() && bev->get_button_index() == BUTTON_RIGHT && presets_enabled) {
+ } else if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_RIGHT && presets_enabled) {
index = bev->get_position().x / (preset->get_size().x / presets.size());
Color clicked_preset = presets[index];
erase_preset(clicked_preset);
@@ -577,8 +665,12 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) {
}
void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) {
+ if (!is_inside_tree()) {
+ return;
+ }
+
Ref<InputEventMouseButton> bev = p_event;
- if (bev.is_valid() && bev->get_button_index() == BUTTON_LEFT && !bev->is_pressed()) {
+ if (bev.is_valid() && bev->get_button_index() == MOUSE_BUTTON_LEFT && !bev->is_pressed()) {
emit_signal("color_changed", color);
screen->hide();
}
@@ -606,6 +698,10 @@ void ColorPicker::_add_preset_pressed() {
}
void ColorPicker::_screen_pick_pressed() {
+ if (!is_inside_tree()) {
+ return;
+ }
+
Viewport *r = get_tree()->get_root();
if (!screen) {
screen = memnew(Control);
@@ -718,17 +814,6 @@ void ColorPicker::_bind_methods() {
ColorPicker::ColorPicker() :
BoxContainer(true) {
- updating = true;
- edit_alpha = true;
- text_is_constructor = false;
- hsv_mode_enabled = false;
- raw_mode_enabled = false;
- deferred_mode_enabled = false;
- changing_color = false;
- presets_enabled = true;
- presets_visible = true;
- screen = nullptr;
-
HBoxContainer *hb_edit = memnew(HBoxContainer);
add_child(hb_edit);
hb_edit->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -798,10 +883,16 @@ ColorPicker::ColorPicker() :
scroll[i]->set_h_size_flags(SIZE_EXPAND_FILL);
scroll[i]->connect("value_changed", callable_mp(this, &ColorPicker::_value_changed));
+ scroll[i]->connect("draw", callable_mp(this, &ColorPicker::_slider_draw), make_binds(i));
vbr->add_child(hbc);
}
labels[3]->set_text("A");
+ scroll[3]->add_theme_icon_override("grabber", get_theme_icon("bar_arrow"));
+ scroll[3]->add_theme_icon_override("grabber_highlight", get_theme_icon("bar_arrow"));
+ scroll[3]->add_theme_style_override("slider", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
+ scroll[3]->add_theme_style_override("grabber_area", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
+ scroll[3]->add_theme_style_override("grabber_area_highlight", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
HBoxContainer *hhb = memnew(HBoxContainer);
vbr->add_child(hhb);
@@ -1001,12 +1092,5 @@ void ColorPickerButton::_bind_methods() {
}
ColorPickerButton::ColorPickerButton() {
- // Initialization is now done deferred,
- // this improves performance in the inspector as the color picker
- // can be expensive to initialize.
- picker = nullptr;
- popup = nullptr;
- edit_alpha = true;
-
set_toggle_mode(true);
}
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 3695820a79..24e1746c41 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -46,7 +46,7 @@ class ColorPicker : public BoxContainer {
GDCLASS(ColorPicker, BoxContainer);
private:
- Control *screen;
+ Control *screen = nullptr;
Control *uv_edit;
Control *w_edit;
TextureRect *sample;
@@ -64,20 +64,22 @@ private:
Label *labels[4];
Button *text_type;
LineEdit *c_text;
- bool edit_alpha;
+ bool edit_alpha = true;
Size2i ms;
- bool text_is_constructor;
- int presets_per_row;
+ bool text_is_constructor = false;
+ int presets_per_row = 0;
Color color;
- bool raw_mode_enabled;
- bool hsv_mode_enabled;
- bool deferred_mode_enabled;
- bool updating;
- bool changing_color;
- bool presets_enabled;
- bool presets_visible;
- float h, s, v;
+ bool raw_mode_enabled = false;
+ bool hsv_mode_enabled = false;
+ bool deferred_mode_enabled = false;
+ bool updating = true;
+ bool changing_color = false;
+ bool presets_enabled = true;
+ bool presets_visible = true;
+ float h = 0.0;
+ float s = 0.0;
+ float v = 0.0;
Color last_hsv;
void _html_entered(const String &p_html);
@@ -89,6 +91,7 @@ private:
void _text_type_toggled();
void _sample_draw();
void _hsv_draw(int p_which, Control *c);
+ void _slider_draw(int p_which);
void _uv_input(const Ref<InputEvent> &p_event);
void _w_input(const Ref<InputEvent> &p_event);
@@ -139,10 +142,14 @@ public:
class ColorPickerButton : public Button {
GDCLASS(ColorPickerButton, Button);
- PopupPanel *popup;
- ColorPicker *picker;
+ // Initialization is now done deferred,
+ // this improves performance in the inspector as the color picker
+ // can be expensive to initialize.
+
+ PopupPanel *popup = nullptr;
+ ColorPicker *picker = nullptr;
Color color;
- bool edit_alpha;
+ bool edit_alpha = true;
void _color_changed(const Color &p_color);
void _modal_closed();
diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp
index 03bade6702..2e6b798eea 100644
--- a/scene/gui/container.cpp
+++ b/scene/gui/container.cpp
@@ -180,7 +180,6 @@ void Container::_bind_methods() {
}
Container::Container() {
- pending_sort = false;
// All containers should let mouse events pass by default.
set_mouse_filter(MOUSE_FILTER_PASS);
}
diff --git a/scene/gui/container.h b/scene/gui/container.h
index 5e60ca04dc..a4f392a3ae 100644
--- a/scene/gui/container.h
+++ b/scene/gui/container.h
@@ -36,7 +36,7 @@
class Container : public Control {
GDCLASS(Container, Control);
- bool pending_sort;
+ bool pending_sort = false;
void _sort_children();
void _child_minsize_changed();
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 6b5d8cb658..2e391adf2c 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -73,6 +73,9 @@ Dictionary Control::_edit_get_state() const {
}
void Control::_edit_set_state(const Dictionary &p_state) {
+ ERR_FAIL_COND((p_state.size() <= 0) ||
+ !p_state.has("rotation") || !p_state.has("scale") ||
+ !p_state.has("pivot") || !p_state.has("anchors") || !p_state.has("offsets"));
Dictionary state = p_state;
set_rotation(state["rotation"]);
@@ -93,7 +96,8 @@ void Control::_edit_set_state(const Dictionary &p_state) {
void Control::_edit_set_position(const Point2 &p_position) {
#ifdef TOOLS_ENABLED
- set_position(p_position, CanvasItemEditor::get_singleton()->is_anchors_mode_enabled());
+ ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins.");
+ set_position(p_position, CanvasItemEditor::get_singleton()->is_anchors_mode_enabled() && Object::cast_to<Control>(data.parent));
#else
// Unlikely to happen. TODO: enclose all _edit_ functions into TOOLS_ENABLED
set_position(p_position);
@@ -114,6 +118,7 @@ Size2 Control::_edit_get_scale() const {
void Control::_edit_set_rect(const Rect2 &p_edit_rect) {
#ifdef TOOLS_ENABLED
+ ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins.");
set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1)), CanvasItemEditor::get_singleton()->is_anchors_mode_enabled());
set_size(p_edit_rect.size.snapped(Vector2(1, 1)), CanvasItemEditor::get_singleton()->is_anchors_mode_enabled());
#else
@@ -131,11 +136,11 @@ bool Control::_edit_use_rect() const {
return true;
}
-void Control::_edit_set_rotation(float p_rotation) {
+void Control::_edit_set_rotation(real_t p_rotation) {
set_rotation(p_rotation);
}
-float Control::_edit_get_rotation() const {
+real_t Control::_edit_get_rotation() const {
return get_rotation();
}
@@ -439,14 +444,14 @@ bool Control::is_layout_rtl() const {
} else if (parent_window) {
return parent_window->is_layout_rtl();
} else {
- if (GLOBAL_GET("display/window/force_right_to_left_layout_direction")) {
+ if (GLOBAL_GET("internationalization/rendering/force_right_to_left_layout_direction")) {
return true;
}
String locale = TranslationServer::get_singleton()->get_tool_locale();
return TS->is_locale_right_to_left(locale);
}
} else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) {
- if (GLOBAL_GET("display/window/force_right_to_left_layout_direction")) {
+ if (GLOBAL_GET("internationalization/rendering/force_right_to_left_layout_direction")) {
return true;
}
String locale = TranslationServer::get_singleton()->get_tool_locale();
@@ -456,6 +461,10 @@ bool Control::is_layout_rtl() const {
}
}
+void Control::_clear_size_warning() {
+ data.size_warning = false;
+}
+
//moved theme configuration here, so controls can set up even if still not inside active scene
void Control::add_child_notify(Node *p_child) {
@@ -503,7 +512,9 @@ void Control::_notification(int p_notification) {
} break;
case NOTIFICATION_EXIT_TREE: {
get_viewport()->_gui_remove_control(this);
-
+ } break;
+ case NOTIFICATION_READY: {
+ connect("ready", callable_mp(this, &Control::_clear_size_warning), varray(), CONNECT_DEFERRED | CONNECT_ONESHOT);
} break;
case NOTIFICATION_ENTER_CANVAS: {
@@ -575,7 +586,7 @@ void Control::_notification(int p_notification) {
} break;
case NOTIFICATION_MOVED_IN_PARENT: {
- // some parents need to know the order of the childrens to draw (like TabContainer)
+ // some parents need to know the order of the children to draw (like TabContainer)
// update if necessary
if (data.parent) {
data.parent->update();
@@ -1227,10 +1238,10 @@ Size2 Control::get_parent_area_size() const {
void Control::_size_changed() {
Rect2 parent_rect = get_parent_anchorable_rect();
- float edge_pos[4];
+ real_t edge_pos[4];
for (int i = 0; i < 4; i++) {
- float area = parent_rect.size[i & 1];
+ real_t area = parent_rect.size[i & 1];
edge_pos[i] = data.offset[i] + (data.anchor[i] * area);
}
@@ -1275,7 +1286,6 @@ void Control::_size_changed() {
}
if (pos_changed || size_changed) {
item_rect_changed(size_changed);
- _change_notify_offsets();
_notify_transform();
}
@@ -1285,13 +1295,13 @@ void Control::_size_changed() {
}
}
-void Control::set_anchor(Side p_side, float p_anchor, bool p_keep_offset, bool p_push_opposite_anchor) {
+void Control::set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset, bool p_push_opposite_anchor) {
ERR_FAIL_INDEX((int)p_side, 4);
Rect2 parent_rect = get_parent_anchorable_rect();
- float parent_range = (p_side == SIDE_LEFT || p_side == SIDE_RIGHT) ? parent_rect.size.x : parent_rect.size.y;
- float previous_pos = data.offset[p_side] + data.anchor[p_side] * parent_range;
- float previous_opposite_pos = data.offset[(p_side + 2) % 4] + data.anchor[(p_side + 2) % 4] * parent_range;
+ real_t parent_range = (p_side == SIDE_LEFT || p_side == SIDE_RIGHT) ? parent_rect.size.x : parent_rect.size.y;
+ real_t previous_pos = data.offset[p_side] + data.anchor[p_side] * parent_range;
+ real_t previous_opposite_pos = data.offset[(p_side + 2) % 4] + data.anchor[(p_side + 2) % 4] * parent_range;
data.anchor[p_side] = p_anchor;
@@ -1315,17 +1325,13 @@ void Control::set_anchor(Side p_side, float p_anchor, bool p_keep_offset, bool p
}
update();
- _change_notify("anchor_left");
- _change_notify("anchor_right");
- _change_notify("anchor_top");
- _change_notify("anchor_bottom");
}
-void Control::_set_anchor(Side p_side, float p_anchor) {
+void Control::_set_anchor(Side p_side, real_t p_anchor) {
set_anchor(p_side, p_anchor);
}
-void Control::set_anchor_and_offset(Side p_side, float p_anchor, float p_pos, bool p_push_opposite_anchor) {
+void Control::set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos, bool p_push_opposite_anchor) {
set_anchor(p_side, p_anchor, false, p_push_opposite_anchor);
set_offset(p_side, p_pos);
}
@@ -1462,7 +1468,7 @@ void Control::set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz
Rect2 parent_rect = get_parent_anchorable_rect();
- float x = parent_rect.size.x;
+ real_t x = parent_rect.size.x;
if (is_layout_rtl()) {
x = parent_rect.size.x - x - new_size.x;
}
@@ -1586,23 +1592,13 @@ void Control::set_anchors_and_offsets_preset(LayoutPreset p_preset, LayoutPreset
set_offsets_preset(p_preset, p_resize_mode, p_margin);
}
-float Control::get_anchor(Side p_side) const {
+real_t Control::get_anchor(Side p_side) const {
ERR_FAIL_INDEX_V(int(p_side), 4, 0.0);
return data.anchor[p_side];
}
-void Control::_change_notify_offsets() {
- // this avoids sending the whole object data again on a change
- _change_notify("offset_left");
- _change_notify("offset_top");
- _change_notify("offset_right");
- _change_notify("offset_bottom");
- _change_notify("rect_position");
- _change_notify("rect_size");
-}
-
-void Control::set_offset(Side p_side, float p_value) {
+void Control::set_offset(Side p_side, real_t p_value) {
ERR_FAIL_INDEX((int)p_side, 4);
data.offset[p_side] = p_value;
@@ -1621,7 +1617,7 @@ void Control::set_end(const Size2 &p_point) {
_size_changed();
}
-float Control::get_offset(Side p_side) const {
+real_t Control::get_offset(Side p_side) const {
ERR_FAIL_INDEX_V((int)p_side, 4, 0);
return data.offset[p_side];
@@ -1664,12 +1660,12 @@ void Control::set_global_position(const Point2 &p_point, bool p_keep_offsets) {
set_position(inv.xform(p_point), p_keep_offsets);
}
-void Control::_compute_anchors(Rect2 p_rect, const float p_offsets[4], float (&r_anchors)[4]) {
+void Control::_compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]) {
Size2 parent_rect_size = get_parent_anchorable_rect().size;
ERR_FAIL_COND(parent_rect_size.x == 0.0);
ERR_FAIL_COND(parent_rect_size.y == 0.0);
- float x = p_rect.position.x;
+ real_t x = p_rect.position.x;
if (is_layout_rtl()) {
x = parent_rect_size.x - x - p_rect.size.x;
}
@@ -1679,10 +1675,10 @@ void Control::_compute_anchors(Rect2 p_rect, const float p_offsets[4], float (&r
r_anchors[3] = (p_rect.position.y + p_rect.size.y - p_offsets[3]) / parent_rect_size.y;
}
-void Control::_compute_offsets(Rect2 p_rect, const float p_anchors[4], float (&r_offsets)[4]) {
+void Control::_compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]) {
Size2 parent_rect_size = get_parent_anchorable_rect().size;
- float x = p_rect.position.x;
+ real_t x = p_rect.position.x;
if (is_layout_rtl()) {
x = parent_rect_size.x - x - p_rect.size.x;
}
@@ -1699,10 +1695,6 @@ void Control::_set_position(const Size2 &p_point) {
void Control::set_position(const Size2 &p_point, bool p_keep_offsets) {
if (p_keep_offsets) {
_compute_anchors(Rect2(p_point, data.size_cache), data.offset, data.anchor);
- _change_notify("anchor_left");
- _change_notify("anchor_right");
- _change_notify("anchor_top");
- _change_notify("anchor_bottom");
} else {
_compute_offsets(Rect2(p_point, data.size_cache), data.anchor, data.offset);
}
@@ -1721,6 +1713,11 @@ void Control::set_rect(const Rect2 &p_rect) {
}
void Control::_set_size(const Size2 &p_size) {
+#ifdef DEBUG_ENABLED
+ if (data.size_warning) {
+ WARN_PRINT("Adjusting the size of Control nodes before they are fully initialized is unreliable. Consider deferring it with set_deferred().");
+ }
+#endif
set_size(p_size);
}
@@ -1736,10 +1733,6 @@ void Control::set_size(const Size2 &p_size, bool p_keep_offsets) {
if (p_keep_offsets) {
_compute_anchors(Rect2(data.pos_cache, new_size), data.offset, data.anchor);
- _change_notify("anchor_left");
- _change_notify("anchor_right");
- _change_notify("anchor_top");
- _change_notify("anchor_bottom");
} else {
_compute_offsets(Rect2(data.pos_cache, new_size), data.anchor, data.offset);
}
@@ -1791,7 +1784,7 @@ void Control::add_theme_icon_override(const StringName &p_name, const Ref<Textur
data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed));
}
- // clear if "null" is passed instead of a icon
+ // clear if "null" is passed instead of an icon
if (p_icon.is_null()) {
data.icon_override.erase(p_name);
} else {
@@ -2264,7 +2257,7 @@ Control *Control::_get_focus_neighbor(Side p_side, int p_count) {
return c;
}
- float dist = 1e7;
+ real_t dist = 1e7;
Control *result = nullptr;
Point2 points[4];
@@ -2285,10 +2278,10 @@ Control *Control::_get_focus_neighbor(Side p_side, int p_count) {
Vector2 vdir = dir[p_side];
- float maxd = -1e7;
+ real_t maxd = -1e7;
for (int i = 0; i < 4; i++) {
- float d = vdir.dot(points[i]);
+ real_t d = vdir.dot(points[i]);
if (d > maxd) {
maxd = d;
}
@@ -2315,7 +2308,7 @@ Control *Control::_get_focus_neighbor(Side p_side, int p_count) {
return result;
}
-void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, float p_min, float &r_closest_dist, Control **r_closest) {
+void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, real_t p_min, real_t &r_closest_dist, Control **r_closest) {
if (Object::cast_to<Viewport>(p_at)) {
return; //bye
}
@@ -2332,10 +2325,10 @@ void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, cons
points[2] = xform.xform(c->get_size());
points[3] = xform.xform(Point2(0, c->get_size().y));
- float min = 1e7;
+ real_t min = 1e7;
for (int i = 0; i < 4; i++) {
- float d = p_dir.dot(points[i]);
+ real_t d = p_dir.dot(points[i]);
if (d < min) {
min = d;
}
@@ -2351,8 +2344,8 @@ void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, cons
Vector2 fb = points[(j + 1) % 4];
Vector2 pa, pb;
- float d = Geometry2D::get_closest_points_between_segments(la, lb, fa, fb, pa, pb);
- //float d = Geometry2D::get_closest_distance_between_segments(Vector3(la.x,la.y,0),Vector3(lb.x,lb.y,0),Vector3(fa.x,fa.y,0),Vector3(fb.x,fb.y,0));
+ real_t d = Geometry2D::get_closest_points_between_segments(la, lb, fa, fb, pa, pb);
+ //real_t d = Geometry2D::get_closest_distance_between_segments(Vector3(la.x,la.y,0),Vector3(lb.x,lb.y,0),Vector3(fa.x,fa.y,0),Vector3(fb.x,fb.y,0));
if (d < r_closest_dist) {
r_closest_dist = d;
*r_closest = c;
@@ -2392,7 +2385,7 @@ void Control::set_v_size_flags(int p_flags) {
emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
}
-void Control::set_stretch_ratio(float p_ratio) {
+void Control::set_stretch_ratio(real_t p_ratio) {
if (data.expand == p_ratio) {
return;
}
@@ -2401,7 +2394,7 @@ void Control::set_stretch_ratio(float p_ratio) {
emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
}
-float Control::get_stretch_ratio() const {
+real_t Control::get_stretch_ratio() const {
return data.expand;
}
@@ -2573,22 +2566,21 @@ Vector<Vector2i> Control::structured_text_parser(StructuredTextParser p_node_typ
return ret;
}
-void Control::set_rotation(float p_radians) {
+void Control::set_rotation(real_t p_radians) {
data.rotation = p_radians;
update();
_notify_transform();
- _change_notify("rect_rotation");
}
-float Control::get_rotation() const {
+real_t Control::get_rotation() const {
return data.rotation;
}
-void Control::set_rotation_degrees(float p_degrees) {
+void Control::set_rotation_degrees(real_t p_degrees) {
set_rotation(Math::deg2rad(p_degrees));
}
-float Control::get_rotation_degrees() const {
+real_t Control::get_rotation_degrees() const {
return Math::rad2deg(get_rotation());
}
@@ -2602,7 +2594,6 @@ void Control::set_pivot_offset(const Vector2 &p_pivot) {
data.pivot_offset = p_pivot;
update();
_notify_transform();
- _change_notify("rect_pivot_offset");
}
Vector2 Control::get_pivot_offset() const {
diff --git a/scene/gui/control.h b/scene/gui/control.h
index ac2a1b35de..a911d69c3f 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -171,21 +171,22 @@ private:
Size2 last_minimum_size;
bool updating_last_minimum_size = false;
- float offset[4] = { 0.0, 0.0, 0.0, 0.0 };
- float anchor[4] = { ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN };
+ real_t offset[4] = { 0.0, 0.0, 0.0, 0.0 };
+ real_t anchor[4] = { ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN };
FocusMode focus_mode = FOCUS_NONE;
GrowDirection h_grow = GROW_DIRECTION_END;
GrowDirection v_grow = GROW_DIRECTION_END;
LayoutDirection layout_dir = LAYOUT_DIRECTION_INHERITED;
- float rotation = 0;
+ real_t rotation = 0.0;
Vector2 scale = Vector2(1, 1);
Vector2 pivot_offset;
+ bool size_warning = true;
int h_size_flags = SIZE_FILL;
int v_size_flags = SIZE_FILL;
- float expand = 1;
+ real_t expand = 1.0;
Point2 custom_minimum_size;
MouseFilter mouse_filter = MOUSE_FILTER_STOP;
@@ -223,23 +224,23 @@ private:
// used internally
Control *_find_control_at_pos(CanvasItem *p_node, const Point2 &p_pos, const Transform2D &p_xform, Transform2D &r_inv_xform);
- void _window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, float p_min, float &r_closest_dist, Control **r_closest);
+ void _window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, real_t p_min, real_t &r_closest_dist, Control **r_closest);
Control *_get_focus_neighbor(Side p_side, int p_count = 0);
- void _set_anchor(Side p_side, float p_anchor);
+ void _set_anchor(Side p_side, real_t p_anchor);
void _set_position(const Point2 &p_point);
void _set_global_position(const Point2 &p_point);
void _set_size(const Size2 &p_size);
void _theme_changed();
- void _change_notify_offsets();
void _update_minimum_size();
+ void _clear_size_warning();
void _update_scroll();
- void _compute_offsets(Rect2 p_rect, const float p_anchors[4], float (&r_offsets)[4]);
- void _compute_anchors(Rect2 p_rect, const float p_offsets[4], float (&r_anchors)[4]);
+ void _compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]);
+ void _compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]);
void _size_changed();
String _get_tooltip() const;
@@ -324,8 +325,8 @@ public:
virtual Rect2 _edit_get_rect() const override;
virtual bool _edit_use_rect() const override;
- virtual void _edit_set_rotation(float p_rotation) override;
- virtual float _edit_get_rotation() const override;
+ virtual void _edit_set_rotation(real_t p_rotation) override;
+ virtual real_t _edit_get_rotation() const override;
virtual bool _edit_use_rotation() const override;
virtual void _edit_set_pivot(const Point2 &p_pivot) override;
@@ -363,13 +364,13 @@ public:
void set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
void set_anchors_and_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
- void set_anchor(Side p_side, float p_anchor, bool p_keep_offset = true, bool p_push_opposite_anchor = true);
- float get_anchor(Side p_side) const;
+ void set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset = true, bool p_push_opposite_anchor = true);
+ real_t get_anchor(Side p_side) const;
- void set_offset(Side p_side, float p_value);
- float get_offset(Side p_side) const;
+ void set_offset(Side p_side, real_t p_value);
+ real_t get_offset(Side p_side) const;
- void set_anchor_and_offset(Side p_side, float p_anchor, float p_pos, bool p_push_opposite_anchor = true);
+ void set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos, bool p_push_opposite_anchor = true);
void set_begin(const Point2 &p_point); // helper
void set_end(const Point2 &p_point); // helper
@@ -394,10 +395,10 @@ public:
void set_rect(const Rect2 &p_rect); // Reset anchors to begin and set rect, for faster container children sorting.
- void set_rotation(float p_radians);
- void set_rotation_degrees(float p_degrees);
- float get_rotation() const;
- float get_rotation_degrees() 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_h_grow_direction(GrowDirection p_direction);
GrowDirection get_h_grow_direction() const;
@@ -420,8 +421,8 @@ public:
void set_v_size_flags(int p_flags);
int get_v_size_flags() const;
- void set_stretch_ratio(float p_ratio);
- float get_stretch_ratio() const;
+ void set_stretch_ratio(real_t p_ratio);
+ real_t get_stretch_ratio() const;
void minimum_size_changed();
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index 773c609a70..b6884bd37d 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -256,7 +256,7 @@ Button *AcceptDialog::add_button(const String &p_text, bool p_right, const Strin
Button *AcceptDialog::add_cancel_button(const String &p_cancel) {
String c = p_cancel;
if (p_cancel == "") {
- c = RTR("Cancel");
+ c = TTRC("Cancel");
}
Button *b = swap_cancel_ok ? add_button(c, true) : add_button(c);
b->connect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed));
@@ -292,8 +292,6 @@ void AcceptDialog::set_swap_cancel_ok(bool p_swap) {
}
AcceptDialog::AcceptDialog() {
- parent_visible = nullptr;
-
set_wrap_controls(true);
set_visible(false);
set_transient(true);
@@ -319,14 +317,13 @@ AcceptDialog::AcceptDialog() {
hbc->add_spacer();
ok = memnew(Button);
- ok->set_text(RTR("OK"));
+ ok->set_text(TTRC("OK"));
hbc->add_child(ok);
hbc->add_spacer();
ok->connect("pressed", callable_mp(this, &AcceptDialog::_ok_pressed));
- hide_on_ok = true;
- set_title(RTR("Alert!"));
+ set_title(TTRC("Alert!"));
connect("window_input", callable_mp(this, &AcceptDialog::_input_from_window));
}
@@ -345,7 +342,7 @@ Button *ConfirmationDialog::get_cancel_button() {
}
ConfirmationDialog::ConfirmationDialog() {
- set_title(RTR("Please Confirm..."));
+ set_title(TTRC("Please Confirm..."));
#ifdef TOOLS_ENABLED
set_min_size(Size2(200, 70) * EDSCALE);
#endif
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index e450a3c30a..b072055d49 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -44,12 +44,12 @@ class LineEdit;
class AcceptDialog : public Window {
GDCLASS(AcceptDialog, Window);
- Window *parent_visible;
+ Window *parent_visible = nullptr;
Panel *bg;
HBoxContainer *hbc;
Label *label;
Button *ok;
- bool hide_on_ok;
+ bool hide_on_ok = true;
void _custom_action(const String &p_action);
void _update_child_rects();
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 3a0350b9fb..7ad4ac80c9 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -272,7 +272,7 @@ void FileDialog::_action_pressed() {
}
if (dir_access->file_exists(f)) {
- confirm_save->set_text(RTR("File exists, overwrite?"));
+ confirm_save->set_text(TTRC("File exists, overwrite?"));
confirm_save->popup_centered(Size2(200, 80));
} else {
emit_signal("file_selected", f);
@@ -329,10 +329,10 @@ void FileDialog::deselect_all() {
switch (mode) {
case FILE_MODE_OPEN_FILE:
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(RTR("Open"));
+ get_ok_button()->set_text(TTRC("Open"));
break;
case FILE_MODE_OPEN_DIR:
- get_ok_button()->set_text(RTR("Select Current Folder"));
+ get_ok_button()->set_text(TTRC("Select Current Folder"));
break;
case FILE_MODE_OPEN_ANY:
case FILE_MODE_SAVE_FILE:
@@ -356,7 +356,7 @@ void FileDialog::_tree_selected() {
if (!d["dir"]) {
file->set_text(d["name"]);
} else if (mode == FILE_MODE_OPEN_DIR) {
- get_ok_button()->set_text(RTR("Select This Folder"));
+ get_ok_button()->set_text(TTRC("Select This Folder"));
}
get_ok_button()->set_disabled(_is_open_should_be_disabled());
@@ -549,7 +549,7 @@ void FileDialog::update_filters() {
all_filters += ", ...";
}
- filter->add_item(RTR("All Recognized") + " (" + all_filters + ")");
+ filter->add_item(String(TTRC("All Recognized")) + " (" + all_filters + ")");
}
for (int i = 0; i < filters.size(); i++) {
String flt = filters[i].get_slice(";", 0).strip_edges();
@@ -561,7 +561,7 @@ void FileDialog::update_filters() {
}
}
- filter->add_item(RTR("All Files (*)"));
+ filter->add_item(TTRC("All Files (*)"));
}
void FileDialog::clear_filters() {
@@ -646,37 +646,37 @@ void FileDialog::set_file_mode(FileMode p_mode) {
mode = p_mode;
switch (mode) {
case FILE_MODE_OPEN_FILE:
- get_ok_button()->set_text(RTR("Open"));
+ get_ok_button()->set_text(TTRC("Open"));
if (mode_overrides_title) {
- set_title(RTR("Open a File"));
+ set_title(TTRC("Open a File"));
}
makedir->hide();
break;
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(RTR("Open"));
+ get_ok_button()->set_text(TTRC("Open"));
if (mode_overrides_title) {
- set_title(RTR("Open File(s)"));
+ set_title(TTRC("Open File(s)"));
}
makedir->hide();
break;
case FILE_MODE_OPEN_DIR:
- get_ok_button()->set_text(RTR("Select Current Folder"));
+ get_ok_button()->set_text(TTRC("Select Current Folder"));
if (mode_overrides_title) {
- set_title(RTR("Open a Directory"));
+ set_title(TTRC("Open a Directory"));
}
makedir->show();
break;
case FILE_MODE_OPEN_ANY:
- get_ok_button()->set_text(RTR("Open"));
+ get_ok_button()->set_text(TTRC("Open"));
if (mode_overrides_title) {
- set_title(RTR("Open a File or Directory"));
+ set_title(TTRC("Open a File or Directory"));
}
makedir->show();
break;
case FILE_MODE_SAVE_FILE:
- get_ok_button()->set_text(RTR("Save"));
+ get_ok_button()->set_text(TTRC("Save"));
if (mode_overrides_title) {
- set_title(RTR("Save a File"));
+ set_title(TTRC("Save a File"));
}
makedir->show();
break;
@@ -731,9 +731,9 @@ FileDialog::Access FileDialog::get_access() const {
}
void FileDialog::_make_dir_confirm() {
- Error err = dir_access->make_dir(makedirname->get_text());
+ Error err = dir_access->make_dir(makedirname->get_text().strip_edges());
if (err == OK) {
- dir_access->change_dir(makedirname->get_text());
+ dir_access->change_dir(makedirname->get_text().strip_edges());
invalidate();
update_filters();
update_dir();
@@ -852,24 +852,22 @@ void FileDialog::set_default_show_hidden_files(bool p_show) {
FileDialog::FileDialog() {
show_hidden_files = default_show_hidden_files;
- mode_overrides_title = true;
-
vbox = memnew(VBoxContainer);
add_child(vbox);
vbox->connect("theme_changed", callable_mp(this, &FileDialog::_theme_changed));
mode = FILE_MODE_SAVE_FILE;
- set_title(RTR("Save a File"));
+ set_title(TTRC("Save a File"));
HBoxContainer *hbc = memnew(HBoxContainer);
dir_up = memnew(Button);
dir_up->set_flat(true);
- dir_up->set_tooltip(RTR("Go to parent folder."));
+ dir_up->set_tooltip(TTRC("Go to parent folder."));
hbc->add_child(dir_up);
dir_up->connect("pressed", callable_mp(this, &FileDialog::_go_up));
- hbc->add_child(memnew(Label(RTR("Path:"))));
+ hbc->add_child(memnew(Label(TTRC("Path:"))));
drives_container = memnew(HBoxContainer);
hbc->add_child(drives_container);
@@ -885,7 +883,7 @@ FileDialog::FileDialog() {
refresh = memnew(Button);
refresh->set_flat(true);
- refresh->set_tooltip(RTR("Refresh files."));
+ refresh->set_tooltip(TTRC("Refresh files."));
refresh->connect("pressed", callable_mp(this, &FileDialog::update_file_list));
hbc->add_child(refresh);
@@ -893,7 +891,7 @@ FileDialog::FileDialog() {
show_hidden->set_flat(true);
show_hidden->set_toggle_mode(true);
show_hidden->set_pressed(is_showing_hidden_files());
- show_hidden->set_tooltip(RTR("Toggle the visibility of hidden files."));
+ show_hidden->set_tooltip(TTRC("Toggle the visibility of hidden files."));
show_hidden->connect("toggled", callable_mp(this, &FileDialog::set_show_hidden_files));
hbc->add_child(show_hidden);
@@ -901,17 +899,17 @@ FileDialog::FileDialog() {
hbc->add_child(shortcuts_container);
makedir = memnew(Button);
- makedir->set_text(RTR("Create Folder"));
+ makedir->set_text(TTRC("Create Folder"));
makedir->connect("pressed", callable_mp(this, &FileDialog::_make_dir));
hbc->add_child(makedir);
vbox->add_child(hbc);
tree = memnew(Tree);
tree->set_hide_root(true);
- vbox->add_margin_child(RTR("Directories & Files:"), tree, true);
+ vbox->add_margin_child(TTRC("Directories & Files:"), tree, true);
file_box = memnew(HBoxContainer);
- file_box->add_child(memnew(Label(RTR("File:"))));
+ file_box->add_child(memnew(Label(TTRC("File:"))));
file = memnew(LineEdit);
file->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
file->set_stretch_ratio(4);
@@ -925,7 +923,6 @@ FileDialog::FileDialog() {
vbox->add_child(file_box);
dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- access = ACCESS_RESOURCES;
_update_drives();
connect("confirmed", callable_mp(this, &FileDialog::_action_pressed));
@@ -944,22 +941,22 @@ FileDialog::FileDialog() {
confirm_save->connect("confirmed", callable_mp(this, &FileDialog::_save_confirm_pressed));
makedialog = memnew(ConfirmationDialog);
- makedialog->set_title(RTR("Create Folder"));
+ makedialog->set_title(TTRC("Create Folder"));
VBoxContainer *makevb = memnew(VBoxContainer);
makedialog->add_child(makevb);
makedirname = memnew(LineEdit);
makedirname->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
- makevb->add_margin_child(RTR("Name:"), makedirname);
+ makevb->add_margin_child(TTRC("Name:"), makedirname);
add_child(makedialog);
makedialog->register_text_enter(makedirname);
makedialog->connect("confirmed", callable_mp(this, &FileDialog::_make_dir_confirm));
mkdirerr = memnew(AcceptDialog);
- mkdirerr->set_text(RTR("Could not create folder."));
+ mkdirerr->set_text(TTRC("Could not create folder."));
add_child(mkdirerr);
exterr = memnew(AcceptDialog);
- exterr->set_text(RTR("Must use a valid extension."));
+ exterr->set_text(TTRC("Must use a valid extension."));
add_child(exterr);
update_filters();
@@ -967,7 +964,6 @@ FileDialog::FileDialog() {
set_hide_on_ok(false);
- invalidated = true;
if (register_func) {
register_func(this);
}
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 626bb78d42..25b742c234 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -69,7 +69,7 @@ private:
LineEdit *makedirname;
Button *makedir;
- Access access;
+ Access access = ACCESS_RESOURCES;
//Button *action;
VBoxContainer *vbox;
FileMode mode;
@@ -93,12 +93,12 @@ private:
Vector<String> filters;
- bool mode_overrides_title;
+ bool mode_overrides_title = true;
static bool default_show_hidden_files;
- bool show_hidden_files;
+ bool show_hidden_files = false;
- bool invalidated;
+ bool invalidated = true;
void update_dir();
void update_file_name();
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
index d18fff887d..36b383f16c 100644
--- a/scene/gui/gradient_edit.cpp
+++ b/scene/gui/gradient_edit.cpp
@@ -42,8 +42,6 @@
#endif
GradientEdit::GradientEdit() {
- grabbed = -1;
- grabbing = false;
set_focus_mode(FOCUS_ALL);
popup = memnew(PopupPanel);
diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h
index 189b33f563..eb7367d598 100644
--- a/scene/gui/gradient_edit.h
+++ b/scene/gui/gradient_edit.h
@@ -44,8 +44,8 @@ class GradientEdit : public Control {
Ref<ImageTexture> checker;
- bool grabbing;
- int grabbed;
+ bool grabbing = false;
+ int grabbed = -1;
Vector<Gradient::Point> points;
void _draw_checker(int x, int y, int w, int h);
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index bc87aabb2c..315bef38e8 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -161,7 +161,7 @@ void GraphEditMinimap::_gui_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventMouseButton> mb = p_ev;
Ref<InputEventMouseMotion> mm = p_ev;
- if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
is_pressing = true;
@@ -180,7 +180,12 @@ void GraphEditMinimap::_gui_input(const Ref<InputEvent> &p_ev) {
accept_event();
} else if (mm.is_valid() && is_pressing) {
if (is_resizing) {
- ge->set_minimap_size(ge->get_minimap_size() - mm->get_relative());
+ // Prevent setting minimap wider than GraphEdit
+ Vector2 new_minimap_size;
+ new_minimap_size.x = MIN(get_size().x - mm->get_relative().x, ge->get_size().x - 2.0 * minimap_padding.x);
+ new_minimap_size.y = MIN(get_size().y - mm->get_relative().y, ge->get_size().y - 2.0 * minimap_padding.y);
+ ge->set_minimap_size(new_minimap_size);
+
update();
} else {
Vector2 click_position = _convert_to_graph_position(mm->get_position() - minimap_padding) - graph_padding;
@@ -385,6 +390,15 @@ void GraphEdit::_graph_node_moved(Node *p_gn) {
connections_layer->update();
}
+void GraphEdit::_graph_node_slot_updated(int p_index, Node *p_gn) {
+ GraphNode *gn = Object::cast_to<GraphNode>(p_gn);
+ ERR_FAIL_COND(!gn);
+ top_layer->update();
+ minimap->update();
+ update();
+ connections_layer->update();
+}
+
void GraphEdit::add_child_notify(Node *p_child) {
Control::add_child_notify(p_child);
@@ -394,6 +408,7 @@ void GraphEdit::add_child_notify(Node *p_child) {
if (gn) {
gn->set_scale(Vector2(zoom, zoom));
gn->connect("position_offset_changed", callable_mp(this, &GraphEdit::_graph_node_moved), varray(gn));
+ gn->connect("slot_updated", callable_mp(this, &GraphEdit::_graph_node_slot_updated), varray(gn));
gn->connect("raise_request", callable_mp(this, &GraphEdit::_graph_node_raised), varray(gn));
gn->connect("item_rect_changed", callable_mp((CanvasItem *)connections_layer, &CanvasItem::update));
gn->connect("item_rect_changed", callable_mp((CanvasItem *)minimap, &GraphEditMinimap::update));
@@ -419,6 +434,7 @@ void GraphEdit::remove_child_notify(Node *p_child) {
GraphNode *gn = Object::cast_to<GraphNode>(p_child);
if (gn) {
gn->disconnect("position_offset_changed", callable_mp(this, &GraphEdit::_graph_node_moved));
+ gn->disconnect("slot_updated", callable_mp(this, &GraphEdit::_graph_node_slot_updated));
gn->disconnect("raise_request", callable_mp(this, &GraphEdit::_graph_node_raised));
// In case of the whole GraphEdit being destroyed these references can already be freed.
@@ -519,14 +535,14 @@ bool GraphEdit::_filter_input(const Point2 &p_point) {
for (int j = 0; j < gn->get_connection_output_count(); j++) {
Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
- if (is_in_hot_zone(pos, p_point)) {
+ if (is_in_hot_zone(pos / zoom, p_point / zoom)) {
return true;
}
}
for (int j = 0; j < gn->get_connection_input_count(); j++) {
Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
- if (is_in_hot_zone(pos, p_point)) {
+ if (is_in_hot_zone(pos / zoom, p_point / zoom)) {
return true;
}
}
@@ -537,10 +553,10 @@ bool GraphEdit::_filter_input(const Point2 &p_point) {
void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventMouseButton> mb = p_ev;
- if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) {
connecting_valid = false;
Ref<Texture2D> port = get_theme_icon("port", "GraphNode");
- click_pos = mb->get_position();
+ click_pos = mb->get_position() / zoom;
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
if (!gn) {
@@ -549,7 +565,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_output_count(); j++) {
Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
- if (is_in_hot_zone(pos, click_pos)) {
+ if (is_in_hot_zone(pos / zoom, click_pos)) {
if (valid_left_disconnect_types.has(gn->get_connection_output_type(j))) {
//check disconnect
for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
@@ -591,7 +607,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_input_count(); j++) {
Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
- if (is_in_hot_zone(pos, click_pos)) {
+ if (is_in_hot_zone(pos / zoom, click_pos)) {
if (right_disconnects || valid_right_disconnect_types.has(gn->get_connection_input_type(j))) {
//check disconnect
for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
@@ -640,11 +656,11 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
connecting_target = false;
top_layer->update();
minimap->update();
- connecting_valid = just_disconnected || click_pos.distance_to(connecting_to) > 20.0 * zoom;
+ connecting_valid = just_disconnected || click_pos.distance_to(connecting_to / zoom) > 20.0 * zoom;
if (connecting_valid) {
Ref<Texture2D> port = get_theme_icon("port", "GraphNode");
- Vector2 mpos = mm->get_position();
+ Vector2 mpos = mm->get_position() / zoom;
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
if (!gn) {
@@ -655,7 +671,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_output_count(); j++) {
Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
int type = gn->get_connection_output_type(j);
- if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_hot_zone(pos, mpos)) {
+ if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_hot_zone(pos / zoom, mpos)) {
connecting_target = true;
connecting_to = pos;
connecting_target_to = gn->get_name();
@@ -667,7 +683,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_input_count(); j++) {
Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
int type = gn->get_connection_input_type(j);
- if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_hot_zone(pos, mpos)) {
+ if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_hot_zone(pos / zoom, mpos)) {
connecting_target = true;
connecting_to = pos;
connecting_target_to = gn->get_name();
@@ -680,7 +696,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
}
}
- if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) {
if (connecting_valid) {
if (connecting && connecting_target) {
String from = connecting_from;
@@ -749,6 +765,11 @@ bool GraphEdit::is_in_hot_zone(const Vector2 &pos, const Vector2 &p_mouse_pos) {
continue;
}
Rect2 rect = child->get_rect();
+
+ // To prevent intersections with other nodes.
+ rect.position *= zoom;
+ rect.size *= zoom;
+
if (rect.has_point(p_mouse_pos)) {
//check sub-controls
Vector2 subpos = p_mouse_pos - rect.position;
@@ -1046,7 +1067,7 @@ void GraphEdit::set_selected(Node *p_child) {
void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventMouseMotion> mm = p_ev;
- if (mm.is_valid() && (mm->get_button_mask() & BUTTON_MASK_MIDDLE || (mm->get_button_mask() & BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) {
+ if (mm.is_valid() && (mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE || (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) {
h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x);
v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y);
}
@@ -1118,7 +1139,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventMouseButton> b = p_ev;
if (b.is_valid()) {
- if (b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
+ if (b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) {
if (box_selecting) {
box_selecting = false;
for (int i = get_child_count() - 1; i >= 0; i--) {
@@ -1148,7 +1169,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
}
}
- if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed() && dragging) {
+ if (b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed() && dragging) {
if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
//deselect current node
for (int i = get_child_count() - 1; i >= 0; i--) {
@@ -1187,7 +1208,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
connections_layer->update();
}
- if (b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
+ if (b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) {
GraphNode *gn = nullptr;
for (int i = get_child_count() - 1; i >= 0; i--) {
@@ -1198,7 +1219,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
continue;
}
- if (gn_selected->has_point(b->get_position() - gn_selected->get_position())) {
+ if (gn_selected->has_point((b->get_position() - gn_selected->get_position()) / zoom)) {
gn = gn_selected;
break;
}
@@ -1289,55 +1310,39 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
}
}
- if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed() && box_selecting) {
+ if (b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed() && box_selecting) {
box_selecting = false;
previus_selected.clear();
top_layer->update();
minimap->update();
}
- if (b->get_button_index() == BUTTON_WHEEL_UP && b->is_pressed()) {
- //too difficult to get right
- //set_zoom(zoom*ZOOM_SCALE);
- }
-
- if (b->get_button_index() == BUTTON_WHEEL_DOWN && b->is_pressed()) {
- //too difficult to get right
- //set_zoom(zoom/ZOOM_SCALE);
- }
- if (b->get_button_index() == BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ set_zoom(zoom * ZOOM_SCALE);
+ } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ set_zoom(zoom / ZOOM_SCALE);
+ } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8);
- }
- if (b->get_button_index() == BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8);
- }
- if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
+ } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT || (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b->get_factor() / 8);
- }
- if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
+ } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT || (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b->get_factor() / 8);
}
}
- Ref<InputEventKey> k = p_ev;
-
- if (k.is_valid()) {
- if (k->get_keycode() == KEY_D && k->is_pressed() && k->get_command()) {
+ if (p_ev->is_pressed()) {
+ if (p_ev->is_action("ui_graph_duplicate")) {
emit_signal("duplicate_nodes_request");
accept_event();
- }
-
- if (k->get_keycode() == KEY_C && k->is_pressed() && k->get_command()) {
+ } else if (p_ev->is_action("ui_copy")) {
emit_signal("copy_nodes_request");
accept_event();
- }
-
- if (k->get_keycode() == KEY_V && k->is_pressed() && k->get_command()) {
+ } else if (p_ev->is_action("ui_paste")) {
emit_signal("paste_nodes_request");
accept_event();
- }
-
- if (k->get_keycode() == KEY_DELETE && k->is_pressed()) {
+ } else if (p_ev->is_action("ui_graph_delete")) {
emit_signal("delete_nodes_request");
accept_event();
}
@@ -1550,7 +1555,12 @@ bool GraphEdit::is_minimap_enabled() const {
}
void GraphEdit::_minimap_toggled() {
- minimap->update();
+ if (is_minimap_enabled()) {
+ minimap->set_visible(true);
+ minimap->update();
+ } else {
+ minimap->set_visible(false);
+ }
}
void GraphEdit::set_connection_lines_thickness(float p_thickness) {
@@ -1593,7 +1603,7 @@ void GraphEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_valid_connection_type", "from_type", "to_type"), &GraphEdit::remove_valid_connection_type);
ClassDB::bind_method(D_METHOD("is_valid_connection_type", "from_type", "to_type"), &GraphEdit::is_valid_connection_type);
- ClassDB::bind_method(D_METHOD("set_zoom", "p_zoom"), &GraphEdit::set_zoom);
+ ClassDB::bind_method(D_METHOD("set_zoom", "zoom"), &GraphEdit::set_zoom);
ClassDB::bind_method(D_METHOD("get_zoom"), &GraphEdit::get_zoom);
ClassDB::bind_method(D_METHOD("set_snap", "pixels"), &GraphEdit::set_snap);
@@ -1608,9 +1618,9 @@ void GraphEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_connection_lines_antialiased", "pixels"), &GraphEdit::set_connection_lines_antialiased);
ClassDB::bind_method(D_METHOD("is_connection_lines_antialiased"), &GraphEdit::is_connection_lines_antialiased);
- ClassDB::bind_method(D_METHOD("set_minimap_size", "p_size"), &GraphEdit::set_minimap_size);
+ ClassDB::bind_method(D_METHOD("set_minimap_size", "size"), &GraphEdit::set_minimap_size);
ClassDB::bind_method(D_METHOD("get_minimap_size"), &GraphEdit::get_minimap_size);
- ClassDB::bind_method(D_METHOD("set_minimap_opacity", "p_opacity"), &GraphEdit::set_minimap_opacity);
+ ClassDB::bind_method(D_METHOD("set_minimap_opacity", "opacity"), &GraphEdit::set_minimap_opacity);
ClassDB::bind_method(D_METHOD("get_minimap_opacity"), &GraphEdit::get_minimap_opacity);
ClassDB::bind_method(D_METHOD("set_minimap_enabled", "enable"), &GraphEdit::set_minimap_enabled);
@@ -1657,8 +1667,6 @@ void GraphEdit::_bind_methods() {
GraphEdit::GraphEdit() {
set_focus_mode(FOCUS_ALL);
- awaiting_scroll_offset_update = false;
- top_layer = nullptr;
top_layer = memnew(GraphEditFilter(this));
add_child(top_layer);
top_layer->set_mouse_filter(MOUSE_FILTER_PASS);
@@ -1681,13 +1689,6 @@ GraphEdit::GraphEdit() {
v_scroll->set_name("_v_scroll");
top_layer->add_child(v_scroll);
- updating = false;
- connecting = false;
- right_disconnects = false;
-
- box_selecting = false;
- dragging = false;
-
//set large minmax so it can scroll even if not resized yet
h_scroll->set_min(-10000);
h_scroll->set_max(10000);
@@ -1698,8 +1699,6 @@ GraphEdit::GraphEdit() {
h_scroll->connect("value_changed", callable_mp(this, &GraphEdit::_scroll_moved));
v_scroll->connect("value_changed", callable_mp(this, &GraphEdit::_scroll_moved));
- zoom = 1;
-
zoom_hb = memnew(HBoxContainer);
top_layer->add_child(zoom_hb);
zoom_hb->set_position(Vector2(10, 10));
@@ -1768,7 +1767,5 @@ GraphEdit::GraphEdit() {
minimap->set_offset(Side::SIDE_BOTTOM, -MINIMAP_OFFSET);
minimap->connect("draw", callable_mp(this, &GraphEdit::_minimap_draw));
- setting_scroll_ofs = false;
- just_disconnected = false;
set_clip_contents(true);
}
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 4525152bd5..8fdf975319 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -99,9 +99,9 @@ public:
struct Connection {
StringName from;
StringName to;
- int from_port;
- int to_port;
- float activity;
+ int from_port = 0;
+ int to_port = 0;
+ float activity = 0.0;
};
private:
@@ -121,41 +121,41 @@ private:
HScrollBar *h_scroll;
VScrollBar *v_scroll;
- float port_grab_distance_horizontal;
+ float port_grab_distance_horizontal = 0.0;
float port_grab_distance_vertical;
- bool connecting;
+ bool connecting = false;
String connecting_from;
- bool connecting_out;
- int connecting_index;
- int connecting_type;
+ bool connecting_out = false;
+ int connecting_index = 0;
+ int connecting_type = 0;
Color connecting_color;
- bool connecting_target;
+ bool connecting_target = false;
Vector2 connecting_to;
String connecting_target_to;
int connecting_target_index;
- bool just_disconnected;
- bool connecting_valid;
+ bool just_disconnected = false;
+ bool connecting_valid = false;
Vector2 click_pos;
- bool dragging;
- bool just_selected;
- bool moving_selection;
+ bool dragging = false;
+ bool just_selected = false;
+ bool moving_selection = false;
Vector2 drag_accum;
- float zoom;
+ float zoom = 1.0;
- bool box_selecting;
- bool box_selection_mode_additive;
+ bool box_selecting = false;
+ bool box_selection_mode_additive = false;
Point2 box_selecting_from;
Point2 box_selecting_to;
Rect2 box_selecting_rect;
List<GraphNode *> previus_selected;
- bool setting_scroll_ofs;
- bool right_disconnects;
- bool updating;
- bool awaiting_scroll_offset_update;
+ bool setting_scroll_ofs = false;
+ bool right_disconnects = false;
+ bool updating = false;
+ bool awaiting_scroll_offset_update = false;
List<Connection> connections;
float lines_thickness = 2.0f;
@@ -167,6 +167,7 @@ private:
void _graph_node_raised(Node *p_gn);
void _graph_node_moved(Node *p_gn);
+ void _graph_node_slot_updated(int p_index, Node *p_gn);
void _update_scroll();
void _scroll_moved(double);
@@ -194,7 +195,7 @@ private:
uint32_t type_a;
uint32_t type_b;
};
- uint64_t key;
+ uint64_t key = 0;
};
bool operator<(const ConnType &p_type) const {
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 6a83042b00..8eba473d57 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -32,6 +32,12 @@
#include "core/string/translation.h"
+struct _MinSizeCache {
+ int min_size;
+ bool will_stretch;
+ int final_size;
+};
+
bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
@@ -51,7 +57,7 @@ bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
update();
}
}
- _change_notify();
+ notify_property_list_changed();
return true;
}
@@ -171,15 +177,23 @@ void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const {
}
void GraphNode::_resort() {
- int sep = get_theme_constant("separation");
+ /** First pass, determine minimum size AND amount of stretchable elements */
+
+ Size2i new_size = get_size();
Ref<StyleBox> sb = get_theme_stylebox("frame");
- bool first = true;
- Size2 minsize;
+ int sep = get_theme_constant("separation");
+
+ bool first = true;
+ int children_count = 0;
+ int stretch_min = 0;
+ int stretch_avail = 0;
+ float stretch_ratio_total = 0;
+ Map<Control *, _MinSizeCache> min_size_cache;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
- if (!c) {
+ if (!c || !c->is_visible_in_tree()) {
continue;
}
if (c->is_set_as_top_level()) {
@@ -187,38 +201,120 @@ void GraphNode::_resort() {
}
Size2i size = c->get_combined_minimum_size();
+ _MinSizeCache msc;
- minsize.y += size.y;
- minsize.x = MAX(minsize.x, size.x);
+ stretch_min += size.height;
+ msc.min_size = size.height;
+ msc.will_stretch = c->get_v_size_flags() & SIZE_EXPAND;
- if (first) {
- first = false;
- } else {
- minsize.y += sep;
+ if (msc.will_stretch) {
+ stretch_avail += msc.min_size;
+ stretch_ratio_total += c->get_stretch_ratio();
}
+ msc.final_size = msc.min_size;
+ min_size_cache[c] = msc;
+ children_count++;
}
- int vofs = 0;
- int w = get_size().x - sb->get_minimum_size().x;
+ if (children_count == 0) {
+ return;
+ }
+
+ int stretch_max = new_size.height - (children_count - 1) * sep;
+ int stretch_diff = stretch_max - stretch_min;
+ if (stretch_diff < 0) {
+ //avoid negative stretch space
+ stretch_diff = 0;
+ }
+ stretch_avail += stretch_diff - sb->get_margin(SIDE_BOTTOM) - sb->get_margin(SIDE_TOP); //available stretch space.
+ /** Second, pass sucessively to discard elements that can't be stretched, this will run while stretchable
+ elements exist */
+
+ while (stretch_ratio_total > 0) { // first of all, don't even be here if no stretchable objects exist
+ bool refit_successful = true; //assume refit-test will go well
+
+ for (int i = 0; i < get_child_count(); i++) {
+ Control *c = Object::cast_to<Control>(get_child(i));
+ if (!c || !c->is_visible_in_tree()) {
+ continue;
+ }
+ if (c->is_set_as_top_level()) {
+ continue;
+ }
+
+ ERR_FAIL_COND(!min_size_cache.has(c));
+ _MinSizeCache &msc = min_size_cache[c];
+
+ if (msc.will_stretch) { //wants to stretch
+ //let's see if it can really stretch
+
+ int final_pixel_size = stretch_avail * c->get_stretch_ratio() / stretch_ratio_total;
+ if (final_pixel_size < msc.min_size) {
+ //if available stretching area is too small for widget,
+ //then remove it from stretching area
+ msc.will_stretch = false;
+ stretch_ratio_total -= c->get_stretch_ratio();
+ refit_successful = false;
+ stretch_avail -= msc.min_size;
+ msc.final_size = msc.min_size;
+ break;
+ } else {
+ msc.final_size = final_pixel_size;
+ }
+ }
+ }
+
+ if (refit_successful) { //uf refit went well, break
+ break;
+ }
+ }
+
+ /** Final pass, draw and stretch elements **/
+
+ int ofs = sb->get_margin(SIDE_TOP);
+
+ first = true;
+ int idx = 0;
cache_y.clear();
+ int w = new_size.width - sb->get_minimum_size().x;
+
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
- if (!c) {
+ if (!c || !c->is_visible_in_tree()) {
continue;
}
if (c->is_set_as_top_level()) {
continue;
}
- Size2i size = c->get_combined_minimum_size();
+ _MinSizeCache &msc = min_size_cache[c];
- Rect2 r(sb->get_margin(SIDE_LEFT), sb->get_margin(SIDE_TOP) + vofs, w, size.y);
+ if (first) {
+ first = false;
+ } else {
+ ofs += sep;
+ }
+
+ int from = ofs;
+ int to = ofs + msc.final_size;
+
+ if (msc.will_stretch && idx == children_count - 1) {
+ //adjust so the last one always fits perfect
+ //compensating for numerical imprecision
+
+ to = new_size.height - sb->get_margin(SIDE_BOTTOM);
+ }
+
+ int size = to - from;
+
+ Rect2 rect(sb->get_margin(SIDE_LEFT), from, w, size);
- fit_child_in_rect(c, r);
- cache_y.push_back(vofs + size.y * 0.5);
+ fit_child_in_rect(c, rect);
+ cache_y.push_back(from - sb->get_margin(SIDE_TOP) + size * 0.5);
- vofs += size.y + sep;
+ ofs = to;
+ idx++;
}
update();
@@ -384,6 +480,8 @@ void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const C
slot_info[p_idx] = s;
update();
connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
}
void GraphNode::clear_slot(int p_idx) {
@@ -484,7 +582,6 @@ void GraphNode::set_title(const String &p_title) {
_shape();
update();
- _change_notify("title");
minimum_size_changed();
}
@@ -711,7 +808,7 @@ void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) {
if (mb.is_valid()) {
ERR_FAIL_COND_MSG(get_parent_control() == nullptr, "GraphNode must be the child of a GraphEdit node.");
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
Vector2 mpos = Vector2(mb->get_position().x, mb->get_position().y);
if (close_rect.size != Size2() && close_rect.has_point(mpos)) {
//send focus to parent
@@ -734,7 +831,7 @@ void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) {
emit_signal("raise_request");
}
- if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
resizing = false;
}
}
@@ -838,6 +935,7 @@ void GraphNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "overlay", PROPERTY_HINT_ENUM, "Disabled,Breakpoint,Position"), "set_overlay", "get_overlay");
ADD_SIGNAL(MethodInfo("position_offset_changed"));
+ ADD_SIGNAL(MethodInfo("slot_updated", PropertyInfo(Variant::INT, "idx")));
ADD_SIGNAL(MethodInfo("dragged", PropertyInfo(Variant::VECTOR2, "from"), PropertyInfo(Variant::VECTOR2, "to")));
ADD_SIGNAL(MethodInfo("raise_request"));
ADD_SIGNAL(MethodInfo("close_request"));
@@ -850,12 +948,5 @@ void GraphNode::_bind_methods() {
GraphNode::GraphNode() {
title_buf.instance();
- overlay = OVERLAY_DISABLED;
- show_close = false;
- connpos_dirty = true;
set_mouse_filter(MOUSE_FILTER_STOP);
- comment = false;
- resizable = false;
- resizing = false;
- selected = false;
}
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index cf66586e6b..1bc54dddb7 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -46,23 +46,14 @@ public:
private:
struct Slot {
- bool enable_left;
- int type_left;
- Color color_left;
- bool enable_right;
- int type_right;
- Color color_right;
+ bool enable_left = false;
+ int type_left = 0;
+ Color color_left = Color(1, 1, 1, 1);
+ bool enable_right = false;
+ int type_right = 0;
+ Color color_right = Color(1, 1, 1, 1);
Ref<Texture2D> custom_slot_left;
Ref<Texture2D> custom_slot_right;
-
- Slot() {
- enable_left = false;
- type_left = 0;
- color_left = Color(1, 1, 1, 1);
- enable_right = false;
- type_right = 0;
- color_right = Color(1, 1, 1, 1);
- }
};
String title;
@@ -72,12 +63,12 @@ private:
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
- bool show_close;
+ bool show_close = false;
Vector2 position_offset;
- bool comment;
- bool resizable;
+ bool comment = false;
+ bool resizable = false;
- bool resizing;
+ bool resizing = false;
Vector2 resizing_from;
Vector2 resizing_from_size;
@@ -87,7 +78,7 @@ private:
struct ConnCache {
Vector2 pos;
- int type;
+ int type = 0;
Color color;
};
@@ -96,16 +87,16 @@ private:
Map<int, Slot> slot_info;
- bool connpos_dirty;
+ bool connpos_dirty = true;
void _connpos_update();
void _resort();
void _shape();
Vector2 drag_from;
- bool selected;
+ bool selected = false;
- Overlay overlay;
+ Overlay overlay = OVERLAY_DISABLED;
protected:
void _gui_input(const Ref<InputEvent> &p_ev);
diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp
index 11335db54a..541925a802 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -261,6 +261,4 @@ Size2 GridContainer::get_minimum_size() const {
return ms;
}
-GridContainer::GridContainer() {
- columns = 1;
-}
+GridContainer::GridContainer() {}
diff --git a/scene/gui/grid_container.h b/scene/gui/grid_container.h
index 8045c94b9a..9b43a5bc7e 100644
--- a/scene/gui/grid_container.h
+++ b/scene/gui/grid_container.h
@@ -36,7 +36,7 @@
class GridContainer : public Container {
GDCLASS(GridContainer, Container);
- int columns;
+ int columns = 1;
protected:
void _notification(int p_what);
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index bd57817bd3..482560d29d 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -540,7 +540,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (defer_select_single >= 0 && mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) {
+ if (defer_select_single >= 0 && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) {
select(defer_select_single, true);
emit_signal("multi_selected", defer_select_single, true);
@@ -548,7 +548,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
- if (mb.is_valid() && (mb->get_button_index() == BUTTON_LEFT || (allow_rmb_select && mb->get_button_index() == BUTTON_RIGHT)) && mb->is_pressed()) {
+ if (mb.is_valid() && (mb->get_button_index() == MOUSE_BUTTON_LEFT || (allow_rmb_select && mb->get_button_index() == MOUSE_BUTTON_RIGHT)) && mb->is_pressed()) {
search_string = ""; //any mousepress cancels
Vector2 pos = mb->get_position();
Ref<StyleBox> bg = get_theme_stylebox("bg");
@@ -594,16 +594,16 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb->get_button_index() == BUTTON_RIGHT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
emit_signal("item_rmb_selected", i, get_local_mouse_position());
}
} else {
- if (!mb->is_doubleclick() && !mb->get_command() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == BUTTON_LEFT) {
+ if (!mb->is_doubleclick() && !mb->get_command() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
defer_select_single = i;
return;
}
- if (items[i].selected && mb->get_button_index() == BUTTON_RIGHT) {
+ if (items[i].selected && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
emit_signal("item_rmb_selected", i, get_local_mouse_position());
} else {
bool selected = items[i].selected;
@@ -618,7 +618,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb->get_button_index() == BUTTON_RIGHT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
emit_signal("item_rmb_selected", i, get_local_mouse_position());
} else if (/*select_mode==SELECT_SINGLE &&*/ mb->is_doubleclick()) {
emit_signal("item_activated", i);
@@ -628,7 +628,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
- if (mb->get_button_index() == BUTTON_RIGHT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
emit_signal("rmb_clicked", mb->get_position());
return;
@@ -637,10 +637,10 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
// Since closest is null, more likely we clicked on empty space, so send signal to interested controls. Allows, for example, implement items deselecting.
emit_signal("nothing_selected");
}
- if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) {
scroll_bar->set_value(scroll_bar->get_value() - scroll_bar->get_page() * mb->get_factor() / 8);
}
- if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) {
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) {
scroll_bar->set_value(scroll_bar->get_value() + scroll_bar->get_page() * mb->get_factor() / 8);
}
@@ -768,7 +768,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
}
}
} else if (p_event->is_action("ui_accept")) {
- search_string = ""; //any mousepress cance
+ search_string = ""; //any mousepress cancels
if (current >= 0 && current < items.size()) {
emit_signal("item_activated", current);
@@ -883,6 +883,8 @@ void ItemList::_notification(int p_what) {
int vseparation = get_theme_constant("vseparation");
int icon_margin = get_theme_constant("icon_margin");
int line_separation = get_theme_constant("line_separation");
+ Color font_outline_color = get_theme_color("font_outline_color");
+ int outline_size = get_theme_constant("outline_size");
Ref<StyleBox> sbsel = has_focus() ? get_theme_stylebox("selected_focus") : get_theme_stylebox("selected");
Ref<StyleBox> cursor = has_focus() ? get_theme_stylebox("cursor") : get_theme_stylebox("cursor_unfocused");
@@ -899,7 +901,7 @@ void ItemList::_notification(int p_what) {
}
if (shape_changed) {
- float max_column_width = 0;
+ float max_column_width = 0.0;
//1- compute item minimum sizes
for (int i = 0; i < items.size(); i++) {
@@ -1204,6 +1206,10 @@ void ItemList::_notification(int p_what) {
items.write[i].text_buf->set_width(max_len);
items.write[i].text_buf->set_align(HALIGN_CENTER);
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, outline_size, font_outline_color);
+ }
+
items[i].text_buf->draw(get_canvas_item(), text_ofs, modulate);
} else {
if (fixed_column_width > 0) {
@@ -1230,6 +1236,11 @@ void ItemList::_notification(int p_what) {
} else {
items.write[i].text_buf->set_align(HALIGN_LEFT);
}
+
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, outline_size, font_outline_color);
+ }
+
items[i].text_buf->draw(get_canvas_item(), text_ofs, modulate);
}
}
@@ -1615,34 +1626,12 @@ void ItemList::_bind_methods() {
}
ItemList::ItemList() {
- current = -1;
-
- select_mode = SELECT_SINGLE;
- icon_mode = ICON_MODE_LEFT;
-
- fixed_column_width = 0;
- same_column_width = false;
- max_text_lines = 1;
- max_columns = 1;
- auto_height = false;
- auto_height_value = 0.0f;
-
scroll_bar = memnew(VScrollBar);
add_child(scroll_bar);
- shape_changed = true;
scroll_bar->connect("value_changed", callable_mp(this, &ItemList::_scroll_changed));
set_focus_mode(FOCUS_ALL);
- current_columns = 1;
- search_time_msec = 0;
- ensure_selected_visible = false;
- defer_select_single = -1;
- allow_rmb_select = false;
- allow_reselect = false;
- do_autoscroll_to_bottom = false;
-
- icon_scale = 1.0f;
set_clip_contents(true);
}
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 4982a68071..86a0174a20 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -52,7 +52,7 @@ public:
private:
struct Item {
Ref<Texture2D> icon;
- bool icon_transposed;
+ bool icon_transposed = false;
Rect2i icon_region;
Color icon_modulate;
Ref<Texture2D> tag_icon;
@@ -62,10 +62,10 @@ private:
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
- bool selectable;
- bool selected;
- bool disabled;
- bool tooltip_enabled;
+ bool selectable = false;
+ bool selected = false;
+ bool disabled = false;
+ bool tooltip_enabled = false;
Variant metadata;
String tooltip;
Color custom_fg;
@@ -79,44 +79,44 @@ private:
bool operator<(const Item &p_another) const { return text < p_another.text; }
};
- int current;
+ int current = -1;
- bool shape_changed;
+ bool shape_changed = true;
- bool ensure_selected_visible;
- bool same_column_width;
+ bool ensure_selected_visible = false;
+ bool same_column_width = false;
- bool auto_height;
- float auto_height_value;
+ bool auto_height = false;
+ float auto_height_value = 0.0;
Vector<Item> items;
Vector<int> separators;
- SelectMode select_mode;
- IconMode icon_mode;
+ SelectMode select_mode = SELECT_SINGLE;
+ IconMode icon_mode = ICON_MODE_LEFT;
VScrollBar *scroll_bar;
- uint64_t search_time_msec;
+ uint64_t search_time_msec = 0;
String search_string;
- int current_columns;
- int fixed_column_width;
- int max_text_lines;
- int max_columns;
+ int current_columns = 1;
+ int fixed_column_width = 0;
+ int max_text_lines = 1;
+ int max_columns = 1;
Size2 fixed_icon_size;
Size2 max_item_size_cache;
- int defer_select_single;
+ int defer_select_single = -1;
- bool allow_rmb_select;
+ bool allow_rmb_select = false;
- bool allow_reselect;
+ bool allow_reselect = false;
- real_t icon_scale;
+ real_t icon_scale = 1.0;
- bool do_autoscroll_to_bottom;
+ bool do_autoscroll_to_bottom = false;
Array _get_items() const;
void _set_items(const Array &p_items);
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index 8fc40955f0..be73fd8f51 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -194,7 +194,7 @@ void Label::_notification(int p_what) {
style->draw(ci, Rect2(Point2(0, 0), get_size()));
- float total_h = 0;
+ float total_h = 0.0;
int lines_visible = 0;
// Get number of lines to fit to the height.
@@ -260,7 +260,8 @@ void Label::_notification(int p_what) {
}
}
}
- visible_glyphs = total_glyphs * percent_visible;
+
+ visible_glyphs = MIN(total_glyphs, visible_chars);
}
Vector2 ofs;
@@ -357,21 +358,25 @@ void Label::_notification(int p_what) {
}
Size2 Label::get_minimum_size() const {
- Size2 min_style = get_theme_stylebox("normal")->get_minimum_size();
-
// don't want to mutable everything
if (dirty || lines_dirty) {
const_cast<Label *>(this)->_shape();
}
+ Size2 min_size = minsize;
+
+ Ref<Font> font = get_theme_font("font");
+ min_size.height = MAX(min_size.height, font->get_height(get_theme_font_size("font_size")) + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM));
+
+ Size2 min_style = get_theme_stylebox("normal")->get_minimum_size();
if (autowrap) {
- return Size2(1, clip ? 1 : minsize.height) + min_style;
+ return Size2(1, clip ? 1 : min_size.height) + min_style;
} else {
- Size2 ms = minsize;
if (clip) {
- ms.width = 1;
+ min_size.width = 1;
}
- return ms + min_style;
+
+ return min_size + min_style;
}
}
@@ -391,7 +396,7 @@ int Label::get_visible_line_count() const {
Ref<StyleBox> style = get_theme_stylebox("normal");
int line_spacing = get_theme_constant("line_spacing");
int lines_visible = 0;
- float total_h = 0;
+ float total_h = 0.0;
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM) + line_spacing;
if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) {
@@ -537,8 +542,9 @@ void Label::set_visible_characters(int p_amount) {
visible_chars = p_amount;
if (get_total_character_count() > 0) {
percent_visible = (float)p_amount / (float)get_total_character_count();
+ } else {
+ percent_visible = 1.0;
}
- _change_notify("percent_visible");
update();
}
@@ -555,7 +561,6 @@ void Label::set_percent_visible(float p_percent) {
visible_chars = get_total_character_count() * p_percent;
percent_visible = p_percent;
}
- _change_notify("visible_chars");
update();
}
@@ -564,6 +569,7 @@ float Label::get_percent_visible() const {
}
void Label::set_lines_skipped(int p_lines) {
+ ERR_FAIL_COND(p_lines < 0);
lines_skipped = p_lines;
_update_visible();
update();
@@ -610,7 +616,7 @@ bool Label::_set(const StringName &p_name, const Variant &p_value) {
update();
}
}
- _change_notify();
+ notify_property_list_changed();
return true;
}
diff --git a/scene/gui/label.h b/scene/gui/label.h
index 219c6af39e..032b4112e1 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -72,7 +72,7 @@ private:
Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT;
Array st_args;
- float percent_visible = 1;
+ float percent_visible = 1.0;
int visible_chars = -1;
int lines_skipped = 0;
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 51f780462f..d1cd73c803 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -30,6 +30,7 @@
#include "line_edit.h"
+#include "core/input/input_map.h"
#include "core/object/message_queue.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
@@ -44,6 +45,175 @@
#endif
#include "scene/main/window.h"
+void LineEdit::_swap_current_input_direction() {
+ if (input_direction == TEXT_DIRECTION_LTR) {
+ input_direction = TEXT_DIRECTION_RTL;
+ } else {
+ input_direction = TEXT_DIRECTION_LTR;
+ }
+ set_cursor_position(get_cursor_position());
+ update();
+}
+
+void LineEdit::_move_cursor_left(bool p_select, bool p_move_by_word) {
+ if (selection.enabled && !p_select) {
+ set_cursor_position(selection.begin);
+ deselect();
+ return;
+ }
+
+ shift_selection_check_pre(p_select);
+
+ if (p_move_by_word) {
+ int cc = cursor_pos;
+
+ Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
+ for (int i = words.size() - 1; i >= 0; i--) {
+ if (words[i].x < cc) {
+ cc = words[i].x;
+ break;
+ }
+ }
+
+ set_cursor_position(cc);
+ } else {
+ if (mid_grapheme_caret_enabled) {
+ set_cursor_position(get_cursor_position() - 1);
+ } else {
+ set_cursor_position(TS->shaped_text_prev_grapheme_pos(text_rid, get_cursor_position()));
+ }
+ }
+
+ shift_selection_check_post(p_select);
+}
+
+void LineEdit::_move_cursor_right(bool p_select, bool p_move_by_word) {
+ if (selection.enabled && !p_select) {
+ set_cursor_position(selection.end);
+ deselect();
+ return;
+ }
+
+ shift_selection_check_pre(p_select);
+
+ if (p_move_by_word) {
+ int cc = cursor_pos;
+
+ Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
+ for (int i = 0; i < words.size(); i++) {
+ if (words[i].y > cc) {
+ cc = words[i].y;
+ break;
+ }
+ }
+
+ set_cursor_position(cc);
+ } else {
+ if (mid_grapheme_caret_enabled) {
+ set_cursor_position(get_cursor_position() + 1);
+ } else {
+ set_cursor_position(TS->shaped_text_next_grapheme_pos(text_rid, get_cursor_position()));
+ }
+ }
+
+ shift_selection_check_post(p_select);
+}
+
+void LineEdit::_move_cursor_start(bool p_select) {
+ shift_selection_check_pre(p_select);
+ set_cursor_position(0);
+ shift_selection_check_post(p_select);
+}
+
+void LineEdit::_move_cursor_end(bool p_select) {
+ shift_selection_check_pre(p_select);
+ set_cursor_position(text.length());
+ shift_selection_check_post(p_select);
+}
+
+void LineEdit::_backspace(bool p_word, bool p_all_to_left) {
+ if (!editable) {
+ return;
+ }
+
+ if (p_all_to_left) {
+ deselect();
+ text = text.substr(0, cursor_pos);
+ _text_changed();
+ return;
+ }
+
+ if (selection.enabled) {
+ selection_delete();
+ return;
+ }
+
+ if (p_word) {
+ int cc = cursor_pos;
+
+ Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
+ for (int i = words.size() - 1; i >= 0; i--) {
+ if (words[i].x < cc) {
+ cc = words[i].x;
+ }
+ }
+
+ delete_text(cc, cursor_pos);
+
+ set_cursor_position(cc);
+ } else {
+ delete_char();
+ }
+}
+
+void LineEdit::_delete(bool p_word, bool p_all_to_right) {
+ if (!editable) {
+ return;
+ }
+
+ if (p_all_to_right) {
+ deselect();
+ text = text.substr(cursor_pos, text.length() - cursor_pos);
+ _shape();
+ set_cursor_position(0);
+ _text_changed();
+ return;
+ }
+
+ if (selection.enabled) {
+ selection_delete();
+ return;
+ }
+
+ int text_len = text.length();
+
+ if (cursor_pos == text_len) {
+ return; // Nothing to do.
+ }
+
+ if (p_word) {
+ int cc = cursor_pos;
+ Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
+ for (int i = 0; i < words.size(); i++) {
+ if (words[i].y > cc) {
+ cc = words[i].y;
+ break;
+ }
+ }
+
+ delete_text(cursor_pos, cc);
+ } else {
+ if (mid_grapheme_caret_enabled) {
+ set_cursor_position(cursor_pos + 1);
+ delete_char();
+ } else {
+ int cc = cursor_pos;
+ set_cursor_position(TS->shaped_text_next_grapheme_pos(text_rid, cursor_pos));
+ delete_text(cc, cursor_pos);
+ }
+ }
+}
+
void LineEdit::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventMouseButton> b = p_event;
@@ -52,17 +222,17 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
// Ignore mouse clicks in IME input mode.
return;
}
- if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT && context_menu_enabled) {
+ if (b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT && context_menu_enabled) {
menu->set_position(get_screen_transform().xform(get_local_mouse_position()));
menu->set_size(Vector2(1, 1));
- //menu->set_scale(get_global_transform().get_scale());
+ _generate_context_menu();
menu->popup();
grab_focus();
accept_event();
return;
}
- if (b->get_button_index() != BUTTON_LEFT) {
+ if (b->get_button_index() != MOUSE_BUTTON_LEFT) {
return;
}
@@ -85,11 +255,30 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
selection.creating = true;
} else {
- if (b->is_doubleclick() && selecting_enabled) {
- selection.enabled = true;
- selection.begin = 0;
- selection.end = text.length();
- selection.doubleclick = true;
+ if (selecting_enabled) {
+ if (!b->is_doubleclick() && (OS::get_singleton()->get_ticks_msec() - selection.last_dblclk) < 600) {
+ // Triple-click select all.
+ selection.enabled = true;
+ selection.begin = 0;
+ selection.end = text.length();
+ selection.doubleclick = true;
+ selection.last_dblclk = 0;
+ cursor_pos = selection.begin;
+ } else if (b->is_doubleclick()) {
+ // Double-click select word.
+ Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
+ for (int i = 0; i < words.size(); i++) {
+ if (words[i].x < cursor_pos && words[i].y > cursor_pos) {
+ selection.enabled = true;
+ selection.begin = words[i].x;
+ selection.end = words[i].y;
+ selection.doubleclick = true;
+ selection.last_dblclk = OS::get_singleton()->get_ticks_msec();
+ cursor_pos = selection.end;
+ break;
+ }
+ }
+ }
}
selection.drag_attempt = false;
@@ -138,7 +327,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
}
}
- if (m->get_button_mask() & BUTTON_LEFT) {
+ if (m->get_button_mask() & MOUSE_BUTTON_LEFT) {
if (selection.creating) {
set_cursor_at_pixel_pos(m->get_position().x);
selection_fill_at_cursor();
@@ -153,453 +342,163 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
return;
}
-#ifdef APPLE_STYLE_KEYS
- if (k->get_control() && !k->get_shift() && !k->get_alt() && !k->get_command()) {
- uint32_t remap_key = KEY_UNKNOWN;
- switch (k->get_keycode()) {
- case KEY_F: {
- remap_key = KEY_RIGHT;
- } break;
- case KEY_B: {
- remap_key = KEY_LEFT;
- } break;
- case KEY_P: {
- remap_key = KEY_UP;
- } break;
- case KEY_N: {
- remap_key = KEY_DOWN;
- } break;
- case KEY_D: {
- remap_key = KEY_DELETE;
- } break;
- case KEY_H: {
- remap_key = KEY_BACKSPACE;
- } break;
- case KEY_A: {
- remap_key = KEY_HOME;
- } break;
- case KEY_E: {
- remap_key = KEY_END;
- } break;
+ if (context_menu_enabled) {
+ if (k->is_action("ui_menu", true)) {
+ Point2 pos = Point2(get_cursor_pixel_pos().x, (get_size().y + get_theme_font("font")->get_height(get_theme_font_size("font_size"))) / 2);
+ menu->set_position(get_global_transform().xform(pos));
+ menu->set_size(Vector2(1, 1));
+ _generate_context_menu();
+ menu->popup();
+ menu->grab_focus();
}
+ }
- if (remap_key != KEY_UNKNOWN) {
- k->set_keycode(remap_key);
- k->set_control(false);
+ // Default is ENTER, KP_ENTER. Cannot use ui_accept as default includes SPACE
+ if (k->is_action("ui_text_newline", true)) {
+ emit_signal("text_entered", text);
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD) && virtual_keyboard_enabled) {
+ DisplayServer::get_singleton()->virtual_keyboard_hide();
}
}
-#endif
-
- unsigned int code = k->get_keycode();
-
- if (k->get_command() && is_shortcut_keys_enabled()) {
- bool handled = true;
-
- switch (code) {
- case (KEY_QUOTELEFT): { // Swap current input direction (primary cursor)
-
- if (input_direction == TEXT_DIRECTION_LTR) {
- input_direction = TEXT_DIRECTION_RTL;
- } else {
- input_direction = TEXT_DIRECTION_LTR;
- }
- set_cursor_position(get_cursor_position());
- update();
-
- } break;
-
- case (KEY_X): { // CUT.
-
- if (editable) {
- cut_text();
- }
- } break;
-
- case (KEY_C): { // COPY.
-
- copy_text();
-
- } break;
-
- case (KEY_Y): // PASTE (Yank for unix users).
- case (KEY_V): { // PASTE.
-
- if (editable) {
- paste_text();
- }
-
- } break;
-
- case (KEY_Z): { // Undo/redo.
- if (editable) {
- if (k->get_shift()) {
- redo();
- } else {
- undo();
- }
- }
- } break;
-
- case (KEY_U): { // Delete from start to cursor.
-
- if (editable) {
- deselect();
- text = text.substr(cursor_pos, text.length() - cursor_pos);
- _shape();
- set_cursor_position(0);
- _text_changed();
- }
-
- } break;
-
- case (KEY_K): { // Delete from cursor_pos to end.
-
- if (editable) {
- deselect();
- text = text.substr(0, cursor_pos);
- _text_changed();
- }
+ if (is_shortcut_keys_enabled()) {
+ if (k->is_action("ui_copy", true)) {
+ copy_text();
+ accept_event();
+ return;
+ }
- } break;
- case (KEY_A): { // Select all.
- select();
+ if (k->is_action("ui_text_select_all", true)) {
+ select();
+ accept_event();
+ return;
+ }
- } break;
-#ifdef APPLE_STYLE_KEYS
- case (KEY_LEFT): { // Go to start of text - like HOME key.
- shift_selection_check_pre(k->get_shift());
- set_cursor_position(0);
- shift_selection_check_post(k->get_shift());
- } break;
- case (KEY_RIGHT): { // Go to end of text - like END key.
- shift_selection_check_pre(k->get_shift());
- set_cursor_position(text.length());
- shift_selection_check_post(k->get_shift());
- } break;
- case (KEY_BACKSPACE): {
- if (!editable)
- break;
+ // Cut / Paste
+ if (k->is_action("ui_cut", true)) {
+ cut_text();
+ accept_event();
+ return;
+ }
- // If selected, delete the selection
- if (selection.enabled) {
- selection_delete();
- break;
- }
+ if (k->is_action("ui_paste", true)) {
+ paste_text();
+ accept_event();
+ return;
+ }
- // Otherwise delete from cursor to beginning of text edit
- int current_pos = get_cursor_position();
- if (current_pos != 0) {
- delete_text(0, current_pos);
- }
- } break;
-#endif
- default: {
- handled = false;
- }
+ // Undo / Redo
+ if (k->is_action("ui_undo", true)) {
+ undo();
+ accept_event();
+ return;
}
- if (handled) {
+ if (k->is_action("ui_redo", true)) {
+ redo();
accept_event();
return;
}
}
- _reset_caret_blink_timer();
- if (!k->get_metakey()) {
- bool handled = true;
- switch (code) {
- case KEY_KP_ENTER:
- case KEY_ENTER: {
- emit_signal("text_entered", text);
- if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD) && virtual_keyboard_enabled) {
- DisplayServer::get_singleton()->virtual_keyboard_hide();
- }
-
- } break;
-
- case KEY_BACKSPACE: {
- if (!editable) {
- break;
- }
-
- if (selection.enabled) {
- selection_delete();
- break;
- }
-
-#ifdef APPLE_STYLE_KEYS
- if (k->get_alt()) {
-#else
- if (k->get_alt()) {
- handled = false;
- break;
- } else if (k->get_command()) {
-#endif
- int cc = cursor_pos;
-
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
- for (int i = words.size() - 1; i >= 0; i--) {
- if (words[i].x < cc) {
- cc = words[i].x;
- break;
- }
- }
-
- delete_text(cc, cursor_pos);
-
- set_cursor_position(cc);
-
- } else {
- delete_char();
- }
-
- } break;
- case KEY_KP_4: {
- if (k->get_unicode() != 0) {
- handled = false;
- break;
- }
- [[fallthrough]];
- }
- case KEY_LEFT: {
-#ifndef APPLE_STYLE_KEYS
- if (!k->get_alt()) {
-#endif
- if (selection.enabled && !k->get_shift()) {
- set_cursor_position(selection.begin);
- deselect();
- handled = true;
- break;
- }
-
- shift_selection_check_pre(k->get_shift());
-#ifndef APPLE_STYLE_KEYS
- }
-#endif
-
-#ifdef APPLE_STYLE_KEYS
- if (k->get_command()) {
- set_cursor_position(0);
- } else if (k->get_alt()) {
-#else
- if (k->get_alt()) {
- handled = false;
- break;
- } else if (k->get_command()) {
-#endif
- int cc = cursor_pos;
-
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
- for (int i = words.size() - 1; i >= 0; i--) {
- if (words[i].x < cc) {
- cc = words[i].x;
- break;
- }
- }
-
- set_cursor_position(cc);
-
- } else {
- if (mid_grapheme_caret_enabled) {
- set_cursor_position(get_cursor_position() - 1);
- } else {
- set_cursor_position(TS->shaped_text_prev_grapheme_pos(text_rid, get_cursor_position()));
- }
- }
-
- shift_selection_check_post(k->get_shift());
-
- } break;
- case KEY_KP_6: {
- if (k->get_unicode() != 0) {
- handled = false;
- break;
- }
- [[fallthrough]];
- }
- case KEY_RIGHT: {
-#ifndef APPLE_STYLE_KEYS
- if (!k->get_alt()) {
-#endif
- if (selection.enabled && !k->get_shift()) {
- set_cursor_position(selection.end);
- deselect();
- handled = true;
- break;
- }
-
- shift_selection_check_pre(k->get_shift());
-#ifndef APPLE_STYLE_KEYS
- }
-#endif
-
-#ifdef APPLE_STYLE_KEYS
- if (k->get_command()) {
- set_cursor_position(text.length());
- } else if (k->get_alt()) {
-#else
- if (k->get_alt()) {
- handled = false;
- break;
- } else if (k->get_command()) {
-#endif
- int cc = cursor_pos;
-
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
- for (int i = 0; i < words.size(); i++) {
- if (words[i].y > cc) {
- cc = words[i].y;
- break;
- }
- }
-
- set_cursor_position(cc);
-
- } else {
- if (mid_grapheme_caret_enabled) {
- set_cursor_position(get_cursor_position() + 1);
- } else {
- set_cursor_position(TS->shaped_text_next_grapheme_pos(text_rid, get_cursor_position()));
- }
- }
-
- shift_selection_check_post(k->get_shift());
-
- } break;
- case KEY_UP: {
- shift_selection_check_pre(k->get_shift());
- if (get_cursor_position() == 0) {
- handled = false;
- }
- set_cursor_position(0);
- shift_selection_check_post(k->get_shift());
- } break;
- case KEY_DOWN: {
- shift_selection_check_pre(k->get_shift());
- if (get_cursor_position() == text.length()) {
- handled = false;
- }
- set_cursor_position(text.length());
- shift_selection_check_post(k->get_shift());
- } break;
- case KEY_DELETE: {
- if (!editable) {
- break;
- }
-
- if (k->get_shift() && !k->get_command() && !k->get_alt()) {
- cut_text();
- break;
- }
-
- if (selection.enabled) {
- selection_delete();
- break;
- }
-
- int text_len = text.length();
+ // BACKSPACE
+ if (k->is_action("ui_text_backspace_all_to_left", true)) {
+ _backspace(false, true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_backspace_word", true)) {
+ _backspace(true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_backspace", true)) {
+ _backspace();
+ accept_event();
+ return;
+ }
- if (cursor_pos == text_len) {
- break; // Nothing to do.
- }
+ // DELETE
+ if (k->is_action("ui_text_delete_all_to_right", true)) {
+ _delete(false, true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_delete_word", true)) {
+ _delete(true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_delete", true)) {
+ _delete();
+ accept_event();
+ return;
+ }
-#ifdef APPLE_STYLE_KEYS
- if (k->get_alt()) {
-#else
- if (k->get_alt()) {
- handled = false;
- break;
- } else if (k->get_command()) {
-#endif
- int cc = cursor_pos;
+ // Cursor Movement
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
- for (int i = 0; i < words.size(); i++) {
- if (words[i].y > cc) {
- cc = words[i].y;
- break;
- }
- }
+ k = k->duplicate();
+ bool shift_pressed = k->get_shift();
+ // Remove shift or else actions will not match. Use above variable for selection.
+ k->set_shift(false);
- delete_text(cursor_pos, cc);
+ if (k->is_action("ui_text_caret_word_left", true)) {
+ _move_cursor_left(shift_pressed, true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_caret_left", true)) {
+ _move_cursor_left(shift_pressed);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_caret_word_right", true)) {
+ _move_cursor_right(shift_pressed, true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_caret_right", true)) {
+ _move_cursor_right(shift_pressed, false);
+ accept_event();
+ return;
+ }
- } else {
- if (mid_grapheme_caret_enabled) {
- set_cursor_position(cursor_pos + 1);
- delete_char();
- } else {
- int cc = cursor_pos;
- set_cursor_position(TS->shaped_text_next_grapheme_pos(text_rid, cursor_pos));
- delete_text(cc, cursor_pos);
- }
- }
+ // Up = Home, Down = End
+ if (k->is_action("ui_text_caret_up", true) || k->is_action("ui_text_caret_line_start", true) || k->is_action("ui_text_caret_page_up", true)) {
+ _move_cursor_start(shift_pressed);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_caret_down", true) || k->is_action("ui_text_caret_line_end", true) || k->is_action("ui_text_caret_page_down", true)) {
+ _move_cursor_end(shift_pressed);
+ accept_event();
+ return;
+ }
- } break;
- case KEY_KP_7: {
- if (k->get_unicode() != 0) {
- handled = false;
- break;
- }
- [[fallthrough]];
- }
- case KEY_HOME: {
- shift_selection_check_pre(k->get_shift());
- set_cursor_position(0);
- shift_selection_check_post(k->get_shift());
- } break;
- case KEY_KP_1: {
- if (k->get_unicode() != 0) {
- handled = false;
- break;
- }
- [[fallthrough]];
- }
- case KEY_END: {
- shift_selection_check_pre(k->get_shift());
- set_cursor_position(text.length());
- shift_selection_check_post(k->get_shift());
- } break;
- case KEY_MENU: {
- if (context_menu_enabled) {
- Point2 pos = Point2(get_cursor_pixel_pos().x, (get_size().y + get_theme_font("font")->get_height(get_theme_font_size("font_size"))) / 2);
- menu->set_position(get_global_transform().xform(pos));
- menu->set_size(Vector2(1, 1));
- //menu->set_scale(get_global_transform().get_scale());
- menu->popup();
- menu->grab_focus();
- }
- } break;
+ // Misc
+ if (k->is_action("ui_swap_input_direction", true)) {
+ _swap_current_input_direction();
+ accept_event();
+ return;
+ }
- default: {
- handled = false;
- } break;
- }
+ _reset_caret_blink_timer();
- if (handled) {
- accept_event();
- } else if (!k->get_command()) {
- if (k->get_unicode() >= 32 && k->get_keycode() != KEY_DELETE) {
- if (editable) {
- selection_delete();
- char32_t ucodestr[2] = { (char32_t)k->get_unicode(), 0 };
- int prev_len = text.length();
- append_at_cursor(ucodestr);
- if (text.length() != prev_len) {
- _text_changed();
- }
- accept_event();
- }
+ // Allow unicode handling if:
+ // * No Modifiers are pressed (except shift)
+ bool allow_unicode_handling = !(k->get_command() || k->get_control() || k->get_alt() || k->get_metakey());
- } else {
- return;
- }
+ if (allow_unicode_handling && editable && k->get_unicode() >= 32) {
+ // Handle Unicode (if no modifiers active)
+ selection_delete();
+ char32_t ucodestr[2] = { (char32_t)k->get_unicode(), 0 };
+ int prev_len = text.length();
+ append_at_cursor(ucodestr);
+ if (text.length() != prev_len) {
+ _text_changed();
}
-
- update();
+ accept_event();
}
-
- return;
}
}
@@ -835,6 +734,24 @@ void LineEdit::_notification(int p_what) {
// Draw text.
ofs.y += TS->shaped_text_get_ascent(text_rid);
+ Color font_outline_color = get_theme_color("font_outline_color");
+ int outline_size = get_theme_constant("outline_size");
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ Vector2 oofs = ofs;
+ for (int i = 0; i < gl_size; i++) {
+ for (int j = 0; j < glyphs[i].repeat; j++) {
+ if (ceil(oofs.x) >= x_ofs && (oofs.x + glyphs[i].advance) <= ofs_max) {
+ if (glyphs[i].font_rid != RID()) {
+ TS->font_draw_glyph_outline(glyphs[i].font_rid, ci, glyphs[i].font_size, outline_size, oofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, font_outline_color);
+ }
+ }
+ oofs.x += glyphs[i].advance;
+ }
+ if (oofs.x >= ofs_max) {
+ break;
+ }
+ }
+ }
for (int i = 0; i < gl_size; i++) {
bool selected = selection.enabled && glyphs[i].start >= selection.begin && glyphs[i].end <= selection.end;
for (int j = 0; j < glyphs[i].repeat; j++) {
@@ -892,7 +809,7 @@ void LineEdit::_notification(int p_what) {
}
} else {
{
- // IME intermidiet text range.
+ // IME intermediate text range.
Vector<Vector2> sel = TS->shaped_text_get_selection(text_rid, cursor_pos, cursor_pos + ime_text.length());
for (int i = 0; i < sel.size(); i++) {
Rect2 rect = Rect2(sel[i].x + ofs.x, ofs.y, sel[i].y - sel[i].x, text_height);
@@ -931,7 +848,7 @@ void LineEdit::_notification(int p_what) {
}
if (has_focus()) {
- if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) {
DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + Point2(using_placeholder ? 0 : x_ofs, y_ofs + TS->shaped_text_get_size(text_rid).y), get_viewport()->get_window_id());
}
@@ -948,7 +865,7 @@ void LineEdit::_notification(int p_what) {
}
}
- if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) {
DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height;
DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos, get_viewport()->get_window_id());
@@ -961,7 +878,7 @@ void LineEdit::_notification(int p_what) {
caret_blink_timer->stop();
}
- if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ 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());
DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id());
}
@@ -995,13 +912,17 @@ void LineEdit::copy_text() {
}
void LineEdit::cut_text() {
- if (selection.enabled && !pass) {
+ if (editable && selection.enabled && !pass) {
DisplayServer::get_singleton()->clipboard_set(text.substr(selection.begin, selection.end - selection.begin));
selection_delete();
}
}
void LineEdit::paste_text() {
+ if (!editable) {
+ return;
+ }
+
// Strip escape characters like \n and \t as they can't be displayed on LineEdit.
String paste_buffer = DisplayServer::get_singleton()->clipboard_get().strip_escapes();
@@ -1022,6 +943,10 @@ void LineEdit::paste_text() {
}
void LineEdit::undo() {
+ if (!editable) {
+ return;
+ }
+
if (undo_stack_pos == nullptr) {
if (undo_stack.size() <= 1) {
return;
@@ -1041,6 +966,10 @@ void LineEdit::undo() {
}
void LineEdit::redo() {
+ if (!editable) {
+ return;
+ }
+
if (undo_stack_pos == nullptr) {
return;
}
@@ -1225,6 +1154,8 @@ void LineEdit::cursor_set_blink_enabled(const bool p_enabled) {
}
draw_caret = true;
+
+ notify_property_list_changed();
}
bool LineEdit::cursor_get_force_displayed() const {
@@ -1505,7 +1436,7 @@ void LineEdit::set_cursor_position(int p_pos) {
ofs_max -= r_icon->get_width();
}
- // Note: Use too coordinates to fit IME input range.
+ // Note: Use two coordinates to fit IME input range.
Vector2i primary_catret_offset = get_cursor_pixel_pos();
if (MIN(primary_catret_offset.x, primary_catret_offset.y) <= x_ofs) {
@@ -1568,12 +1499,12 @@ Size2 LineEdit::get_minimum_size() const {
Size2 min_size;
// Minimum size of text.
- int space_size = font->get_char_size('m', 0, font_size).x;
- min_size.width = get_theme_constant("minimum_spaces") * space_size;
+ int em_space_size = font->get_char_size('M', 0, font_size).x;
+ min_size.width = get_theme_constant("minimum_character_width") * em_space_size;
if (expand_to_text_length) {
// Add a space because some fonts are too exact, and because cursor needs a bit more when at the end.
- min_size.width = MAX(min_size.width, full_width + space_size);
+ min_size.width = MAX(min_size.width, full_width + em_space_size);
}
min_size.height = MAX(TS->shaped_text_get_size(text_rid).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM), font->get_height(font_size));
@@ -1958,7 +1889,6 @@ void LineEdit::_text_changed() {
void LineEdit::_emit_text_change() {
emit_signal("text_changed", text);
- _change_notify("text");
text_changed_dirty = false;
}
@@ -2043,25 +1973,50 @@ void LineEdit::_create_undo_state() {
undo_stack.push_back(op);
}
+int LineEdit::_get_menu_action_accelerator(const String &p_action) {
+ const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(p_action);
+ if (!events) {
+ return 0;
+ }
+
+ // Use first event in the list for the accelerator.
+ const List<Ref<InputEvent>>::Element *first_event = events->front();
+ if (!first_event) {
+ return 0;
+ }
+
+ const Ref<InputEventKey> event = first_event->get();
+ if (event.is_null()) {
+ return 0;
+ }
+
+ // Use physical keycode if non-zero
+ if (event->get_physical_keycode() != 0) {
+ return event->get_physical_keycode_with_modifiers();
+ } else {
+ return event->get_keycode_with_modifiers();
+ }
+}
+
void LineEdit::_generate_context_menu() {
// Reorganize context menu.
menu->clear();
if (editable) {
- menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_X : 0);
+ menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : 0);
}
- menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_C : 0);
+ menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : 0);
if (editable) {
- menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_V : 0);
+ menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : 0);
}
menu->add_separator();
if (is_selecting_enabled()) {
- menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_A : 0);
+ menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : 0);
}
if (editable) {
menu->add_item(RTR("Clear"), MENU_CLEAR);
menu->add_separator();
- menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_Z : 0);
- menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z : 0);
+ menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : 0);
+ menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0);
}
menu->add_separator();
menu->add_submenu_item(RTR("Text writing direction"), "DirMenu");
@@ -2091,7 +2046,7 @@ bool LineEdit::_set(const StringName &p_name, const Variant &p_value) {
update();
}
}
- _change_notify();
+ notify_property_list_changed();
return true;
}
@@ -2122,6 +2077,12 @@ void LineEdit::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
}
+void LineEdit::_validate_property(PropertyInfo &property) const {
+ if (!caret_blink_enabled && property.name == "caret_blink_speed") {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+}
+
void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("_text_changed"), &LineEdit::_text_changed);
@@ -2264,9 +2225,6 @@ LineEdit::LineEdit() {
text_rid = TS->create_shaped_text();
_create_undo_state();
- clear_button_status.press_attempt = false;
- clear_button_status.pressing_inside = false;
-
deselect();
set_focus_mode(FOCUS_ALL);
set_default_cursor_shape(CURSOR_IBEAM);
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 6db7a78f61..ef36377f2e 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -94,7 +94,7 @@ private:
Point2 ime_selection;
RID text_rid;
- float full_width = 0;
+ float full_width = 0.0;
bool selecting_enabled = true;
@@ -129,19 +129,20 @@ private:
Ref<Texture2D> right_icon;
struct Selection {
- int begin;
- int end;
- int cursor_start;
- bool enabled;
- bool creating;
- bool doubleclick;
- bool drag_attempt;
+ int begin = 0;
+ int end = 0;
+ int cursor_start = 0;
+ bool enabled = false;
+ bool creating = false;
+ bool doubleclick = false;
+ bool drag_attempt = false;
+ uint64_t last_dblclk = 0;
} selection;
struct TextOperation {
- int cursor_pos;
- int scroll_offset;
- int cached_width;
+ int cursor_pos = 0;
+ int scroll_offset = 0;
+ int cached_width = 0;
String text;
};
List<TextOperation> undo_stack;
@@ -163,6 +164,7 @@ private:
void _clear_redo();
void _create_undo_state();
+ int _get_menu_action_accelerator(const String &p_action);
void _generate_context_menu();
void _shape();
@@ -188,15 +190,23 @@ private:
void _editor_settings_changed();
- void _gui_input(Ref<InputEvent> p_event);
- void _notification(int p_what);
+ void _swap_current_input_direction();
+ void _move_cursor_left(bool p_select, bool p_move_by_word = false);
+ void _move_cursor_right(bool p_select, bool p_move_by_word = false);
+ void _move_cursor_start(bool p_select);
+ void _move_cursor_end(bool p_select);
+ void _backspace(bool p_word = false, bool p_all_to_left = false);
+ void _delete(bool p_word = false, bool p_all_to_right = false);
protected:
+ void _notification(int p_what);
static void _bind_methods();
+ void _gui_input(Ref<InputEvent> p_event);
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ void _validate_property(PropertyInfo &property) const override;
public:
void set_align(Align p_align);
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index 8e972438a5..1f7b61e3d1 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -191,9 +191,17 @@ void LinkButton::_notification(int p_what) {
int width = text_buf->get_line_width();
+ Color font_outline_color = get_theme_color("font_outline_color");
+ int outline_size = get_theme_constant("outline_size");
if (is_layout_rtl()) {
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ text_buf->draw_outline(get_canvas_item(), Vector2(size.width - width, 0), outline_size, font_outline_color);
+ }
text_buf->draw(get_canvas_item(), Vector2(size.width - width, 0), color);
} else {
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ text_buf->draw_outline(get_canvas_item(), Vector2(0, 0), outline_size, font_outline_color);
+ }
text_buf->draw(get_canvas_item(), Vector2(0, 0), color);
}
@@ -231,7 +239,7 @@ bool LinkButton::_set(const StringName &p_name, const Variant &p_value) {
update();
}
}
- _change_notify();
+ notify_property_list_changed();
return true;
}
@@ -294,7 +302,6 @@ void LinkButton::_bind_methods() {
LinkButton::LinkButton() {
text_buf.instance();
- underline_mode = UNDERLINE_MODE_ALWAYS;
set_focus_mode(FOCUS_NONE);
set_default_cursor_shape(CURSOR_POINTING_HAND);
}
diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h
index 5ab6aba122..7eaa9f88b6 100644
--- a/scene/gui/link_button.h
+++ b/scene/gui/link_button.h
@@ -48,7 +48,7 @@ public:
private:
String text;
Ref<TextLine> text_buf;
- UnderlineMode underline_mode;
+ UnderlineMode underline_mode = UNDERLINE_MODE_ALWAYS;
Dictionary opentype_features;
String language;
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 94cb5ef0f4..5acc7e808a 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -118,7 +118,6 @@ void MenuButton::set_disable_shortcuts(bool p_disabled) {
}
MenuButton::MenuButton() {
- switch_on_hover = false;
set_flat(true);
set_toggle_mode(true);
set_disable_shortcuts(false);
diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h
index cd4ed5bcb2..fd9ae6021e 100644
--- a/scene/gui/menu_button.h
+++ b/scene/gui/menu_button.h
@@ -37,9 +37,9 @@
class MenuButton : public Button {
GDCLASS(MenuButton, Button);
- bool clicked;
- bool switch_on_hover;
- bool disable_shortcuts;
+ bool clicked = false;
+ bool switch_on_hover = false;
+ bool disable_shortcuts = false;
PopupMenu *popup;
Array _get_items() const;
diff --git a/scene/gui/nine_patch_rect.cpp b/scene/gui/nine_patch_rect.cpp
index c274eb5c10..29a38ad5e3 100644
--- a/scene/gui/nine_patch_rect.cpp
+++ b/scene/gui/nine_patch_rect.cpp
@@ -98,7 +98,6 @@ void NinePatchRect::set_texture(const Ref<Texture2D> &p_tex) {
*/
minimum_size_changed();
emit_signal("texture_changed");
- _change_notify("texture");
}
Ref<Texture2D> NinePatchRect::get_texture() const {
@@ -110,20 +109,6 @@ void NinePatchRect::set_patch_margin(Side p_side, int p_size) {
margin[p_side] = p_size;
update();
minimum_size_changed();
- switch (p_side) {
- case SIDE_LEFT:
- _change_notify("patch_margin_left");
- break;
- case SIDE_TOP:
- _change_notify("patch_margin_top");
- break;
- case SIDE_RIGHT:
- _change_notify("patch_margin_right");
- break;
- case SIDE_BOTTOM:
- _change_notify("patch_margin_bottom");
- break;
- }
}
int NinePatchRect::get_patch_margin(Side p_side) const {
@@ -139,7 +124,6 @@ void NinePatchRect::set_region_rect(const Rect2 &p_region_rect) {
region_rect = p_region_rect;
item_rect_changed();
- _change_notify("region_rect");
}
Rect2 NinePatchRect::get_region_rect() const {
@@ -174,16 +158,7 @@ NinePatchRect::AxisStretchMode NinePatchRect::get_v_axis_stretch_mode() const {
}
NinePatchRect::NinePatchRect() {
- margin[SIDE_LEFT] = 0;
- margin[SIDE_RIGHT] = 0;
- margin[SIDE_BOTTOM] = 0;
- margin[SIDE_TOP] = 0;
-
set_mouse_filter(MOUSE_FILTER_IGNORE);
- draw_center = true;
-
- axis_h = AXIS_STRETCH_MODE_STRETCH;
- axis_v = AXIS_STRETCH_MODE_STRETCH;
}
NinePatchRect::~NinePatchRect() {
diff --git a/scene/gui/nine_patch_rect.h b/scene/gui/nine_patch_rect.h
index fcf25018aa..f9a3f31fe5 100644
--- a/scene/gui/nine_patch_rect.h
+++ b/scene/gui/nine_patch_rect.h
@@ -43,12 +43,13 @@ public:
AXIS_STRETCH_MODE_TILE_FIT,
};
- bool draw_center;
- int margin[4];
+ bool draw_center = true;
+ int margin[4] = {};
Rect2 region_rect;
Ref<Texture2D> texture;
- AxisStretchMode axis_h, axis_v;
+ AxisStretchMode axis_h = AXIS_STRETCH_MODE_STRETCH;
+ AxisStretchMode axis_v = AXIS_STRETCH_MODE_STRETCH;
protected:
void _notification(int p_what);
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index e4c1f94b31..e52b6917be 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -336,7 +336,6 @@ void OptionButton::_bind_methods() {
}
OptionButton::OptionButton() {
- current = -1;
set_toggle_mode(true);
set_text_align(ALIGN_LEFT);
if (is_layout_rtl()) {
diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h
index 9cb296baa9..d846e395ad 100644
--- a/scene/gui/option_button.h
+++ b/scene/gui/option_button.h
@@ -38,7 +38,7 @@ class OptionButton : public Button {
GDCLASS(OptionButton, Button);
PopupMenu *popup;
- int current;
+ int current = -1;
void _focused(int p_which);
void _selected(int p_which);
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index b2ebb91500..bfbd46a9f0 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -52,8 +52,8 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
Size2 minsize = get_theme_stylebox("panel")->get_minimum_size(); // Accounts for margin in the margin container
minsize.x += scroll_container->get_v_scrollbar()->get_size().width * 2; // Adds a buffer so that the scrollbar does not render over the top of content
- float max_w = 0;
- float icon_w = 0;
+ float max_w = 0.0;
+ float icon_w = 0.0;
int check_w = MAX(get_theme_icon("checked")->get_width(), get_theme_icon("radio_checked")->get_width()) + hseparation;
int accel_max_w = 0;
bool has_check = false;
@@ -62,7 +62,7 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
Size2 size;
Size2 icon_size = items[i].get_icon_size();
- size.height = MAX(icon_size.height, items[i].text_buf->get_size().y);
+ size.height = _get_item_height(i);
icon_w = MAX(icon_size.width, icon_w);
size.width += items[i].h_ofs;
@@ -89,7 +89,9 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
minsize.height += size.height;
}
- minsize.width += max_w + icon_w + accel_max_w;
+ int item_side_padding = get_theme_constant("item_start_padding") + get_theme_constant("item_end_padding");
+ minsize.width += max_w + icon_w + accel_max_w + item_side_padding;
+
if (has_check) {
minsize.width += check_w;
}
@@ -104,13 +106,35 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
return minsize;
}
+int PopupMenu::_get_item_height(int p_item) const {
+ ERR_FAIL_INDEX_V(p_item, items.size(), 0);
+ ERR_FAIL_COND_V(p_item < 0, 0);
+
+ int icon_height = items[p_item].get_icon_size().height;
+ if (items[p_item].checkable_type) {
+ icon_height = MAX(icon_height, MAX(get_theme_icon("checked")->get_height(), get_theme_icon("radio_checked")->get_height()));
+ }
+
+ int text_height = items[p_item].text_buf->get_size().height;
+ if (text_height == 0 && !items[p_item].separator) {
+ text_height = get_theme_font("font")->get_height(get_theme_font_size("font_size"));
+ }
+
+ int separator_height = 0;
+ if (items[p_item].separator) {
+ separator_height = MAX(get_theme_stylebox("separator")->get_minimum_size().height, MAX(get_theme_stylebox("labeled_separator_left")->get_minimum_size().height, get_theme_stylebox("labeled_separator_right")->get_minimum_size().height));
+ }
+
+ return MAX(separator_height, MAX(text_height, icon_height));
+}
+
int PopupMenu::_get_items_total_height() const {
int vsep = get_theme_constant("vseparation");
// Get total height of all items by taking max of icon height and font height
int items_total_height = 0;
for (int i = 0; i < items.size(); i++) {
- items_total_height += MAX(items[i].get_icon_size().height, items[i].text_buf->get_size().y) + vsep;
+ items_total_height += _get_item_height(i) + vsep;
}
// Subtract a separator which is not needed for the last item.
@@ -152,7 +176,7 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const {
for (int i = 0; i < items.size(); i++) {
ofs.y += i > 0 ? vseparation : (float)vseparation / 2;
- ofs.y += MAX(items[i].get_icon_size().height, items[i].text_buf->get_size().y);
+ ofs.y += _get_item_height(i);
if (p_over.y - control->get_position().y < ofs.y) {
return i;
@@ -198,7 +222,7 @@ void PopupMenu::_activate_submenu(int p_over) {
submenu_popup->set_close_on_parent_focus(false);
submenu_popup->set_position(submenu_pos);
- submenu_popup->set_as_minsize(); // Shrink the popup size to it's contents.
+ submenu_popup->set_as_minsize(); // Shrink the popup size to its contents.
submenu_popup->popup();
// Set autohide areas
@@ -335,7 +359,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
if (b->is_pressed() || (!b->is_pressed() && during_grabbed_click)) {
// Allow activating item by releasing the LMB or any that was down when the popup appeared.
// However, if button was not held when opening menu, do not allow release to activate item.
- if (button_idx == BUTTON_LEFT || (initial_button_mask & (1 << (button_idx - 1)))) {
+ if (button_idx == MOUSE_BUTTON_LEFT || (initial_button_mask & (1 << (button_idx - 1)))) {
bool was_during_grabbed_click = during_grabbed_click;
during_grabbed_click = false;
initial_button_mask = 0;
@@ -451,6 +475,10 @@ void PopupMenu::_draw_items() {
margin_size.width = margin_container->get_theme_constant("margin_right") + margin_container->get_theme_constant("margin_left");
margin_size.height = margin_container->get_theme_constant("margin_top") + margin_container->get_theme_constant("margin_bottom");
+ // Space between the item content and the sides of popup menu.
+ int item_start_padding = get_theme_constant("item_start_padding");
+ int item_end_padding = get_theme_constant("item_end_padding");
+
bool rtl = control->is_layout_rtl();
Ref<StyleBox> style = get_theme_stylebox("panel");
Ref<StyleBox> hover = get_theme_stylebox("hover");
@@ -509,7 +537,7 @@ void PopupMenu::_draw_items() {
Point2 item_ofs = ofs;
Size2 icon_size = items[i].get_icon_size();
- float h = MAX(icon_size.height, items[i].text_buf->get_size().y);
+ float h = _get_item_height(i);
if (i == mouse_over) {
if (rtl) {
@@ -525,24 +553,28 @@ void PopupMenu::_draw_items() {
item_ofs.x += items[i].h_ofs;
if (items[i].separator) {
int sep_h = separator->get_center_size().height + separator->get_minimum_size().height;
+ int sep_ofs = Math::floor((h - sep_h) / 2.0);
if (text != String()) {
int text_size = items[i].text_buf->get_size().width;
int text_center = display_width / 2;
int text_left = text_center - text_size / 2;
int text_right = text_center + text_size / 2;
if (text_left > item_ofs.x) {
- labeled_separator_left->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(MAX(0, text_left - item_ofs.x), sep_h)));
+ labeled_separator_left->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(MAX(0, text_left - item_ofs.x), sep_h)));
}
if (text_right < display_width) {
- labeled_separator_right->draw(ci, Rect2(Point2(text_right, item_ofs.y + Math::floor((h - sep_h) / 2.0)), Size2(MAX(0, display_width - text_right), sep_h)));
+ labeled_separator_right->draw(ci, Rect2(Point2(text_right, item_ofs.y + sep_ofs), Size2(MAX(0, display_width - text_right), sep_h)));
}
} else {
- separator->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(display_width, sep_h)));
+ separator->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(display_width, sep_h)));
}
}
Color icon_color(1, 1, 1, items[i].disabled ? 0.5 : 1);
+ // For non-separator items, add some padding for the content.
+ item_ofs.x += item_start_padding;
+
// Checkboxes
if (items[i].checkable_type) {
Texture2D *icon = (items[i].checked ? check[items[i].checkable_type - 1] : uncheck[items[i].checkable_type - 1]).ptr();
@@ -565,35 +597,53 @@ void PopupMenu::_draw_items() {
// Submenu arrow on right hand side
if (items[i].submenu != "") {
if (rtl) {
- submenu->draw(ci, Point2(scroll_width + style->get_margin(SIDE_LEFT), item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
+ submenu->draw(ci, Point2(scroll_width + style->get_margin(SIDE_LEFT) + item_end_padding, item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
} else {
- submenu->draw(ci, Point2(display_width - style->get_margin(SIDE_RIGHT) - submenu->get_width(), item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
+ submenu->draw(ci, Point2(display_width - style->get_margin(SIDE_RIGHT) - submenu->get_width() - item_end_padding, item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
}
}
// Text
+ Color font_outline_color = get_theme_color("font_outline_color");
+ int outline_size = get_theme_constant("outline_size");
if (items[i].separator) {
if (text != String()) {
int center = (display_width - items[i].text_buf->get_size().width) / 2;
- items[i].text_buf->draw(ci, Point2(center, item_ofs.y + Math::floor((h - items[i].text_buf->get_size().y) / 2.0)), font_separator_color);
+ Vector2 text_pos = Point2(center, item_ofs.y + Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ }
+ items[i].text_buf->draw(ci, text_pos, font_separator_color);
}
} else {
item_ofs.x += icon_ofs + check_ofs;
if (rtl) {
- items[i].text_buf->draw(ci, Size2(control->get_size().width - items[i].text_buf->get_size().width - item_ofs.x, item_ofs.y) + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0)), items[i].disabled ? font_disabled_color : (i == mouse_over ? font_hover_color : font_color));
+ Vector2 text_pos = Size2(control->get_size().width - items[i].text_buf->get_size().width - item_ofs.x, item_ofs.y) + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ }
+ items[i].text_buf->draw(ci, text_pos, items[i].disabled ? font_disabled_color : (i == mouse_over ? font_hover_color : font_color));
} else {
- items[i].text_buf->draw(ci, item_ofs + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0)), items[i].disabled ? font_disabled_color : (i == mouse_over ? font_hover_color : font_color));
+ Vector2 text_pos = item_ofs + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ }
+ items[i].text_buf->draw(ci, text_pos, items[i].disabled ? font_disabled_color : (i == mouse_over ? font_hover_color : font_color));
}
}
// Accelerator / Shortcut
if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) {
if (rtl) {
- item_ofs.x = scroll_width + style->get_margin(SIDE_LEFT);
+ item_ofs.x = scroll_width + style->get_margin(SIDE_LEFT) + item_end_padding;
} else {
- item_ofs.x = display_width - style->get_margin(SIDE_RIGHT) - items[i].accel_text_buf->get_size().x;
+ item_ofs.x = display_width - style->get_margin(SIDE_RIGHT) - items[i].accel_text_buf->get_size().x - item_end_padding;
+ }
+ Vector2 text_pos = item_ofs + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ items[i].accel_text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
}
- items[i].accel_text_buf->draw(ci, item_ofs + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0)), i == mouse_over ? font_hover_color : font_accelerator_color);
+ items[i].accel_text_buf->draw(ci, text_pos, i == mouse_over ? font_hover_color : font_accelerator_color);
}
// Cache the item vertical offset from the first item and the height
@@ -672,6 +722,7 @@ void PopupMenu::_notification(int p_what) {
for (int i = 0; i < items.size(); i++) {
items.write[i].xl_text = tr(items[i].text);
items.write[i].dirty = true;
+ _shape_item(i);
}
child_controls_changed();
@@ -1656,19 +1707,6 @@ PopupMenu::PopupMenu() {
connect("window_input", callable_mp(this, &PopupMenu::_gui_input));
- mouse_over = -1;
- submenu_over = -1;
- initial_button_mask = 0;
- during_grabbed_click = false;
-
- allow_search = true;
- search_time_msec = 0;
- search_string = "";
-
- set_hide_on_item_selection(true);
- set_hide_on_checkable_item_selection(true);
- set_hide_on_multistate_item_selection(false);
-
submenu_timer = memnew(Timer);
submenu_timer->set_wait_time(0.3);
submenu_timer->set_one_shot(true);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index c050e61d50..e4cbe984c9 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -51,28 +51,28 @@ class PopupMenu : public Popup {
String language;
Control::TextDirection text_direction = Control::TEXT_DIRECTION_AUTO;
- bool checked;
+ bool checked = false;
enum {
CHECKABLE_TYPE_NONE,
CHECKABLE_TYPE_CHECK_BOX,
CHECKABLE_TYPE_RADIO_BUTTON,
} checkable_type;
- int max_states;
- int state;
- bool separator;
- bool disabled;
- bool dirty;
- int id;
+ int max_states = 0;
+ int state = 0;
+ bool separator = false;
+ bool disabled = false;
+ bool dirty = true;
+ int id = 0;
Variant metadata;
String submenu;
String tooltip;
- uint32_t accel;
- int _ofs_cache;
- int _height_cache;
- int h_ofs;
+ uint32_t accel = 0;
+ int _ofs_cache = 0;
+ int _height_cache = 0;
+ int h_ofs = 0;
Ref<Shortcut> shortcut;
- bool shortcut_is_global;
- bool shortcut_is_disabled;
+ bool shortcut_is_global = false;
+ bool shortcut_is_disabled = false;
// Returns (0,0) if icon is null.
Size2 get_icon_size() const {
@@ -82,19 +82,7 @@ class PopupMenu : public Popup {
Item() {
text_buf.instance();
accel_text_buf.instance();
- dirty = true;
- checked = false;
checkable_type = CHECKABLE_TYPE_NONE;
- separator = false;
- max_states = 0;
- state = 0;
- accel = 0;
- disabled = false;
- _ofs_cache = 0;
- _height_cache = 0;
- h_ofs = 0;
- shortcut_is_global = false;
- shortcut_is_disabled = false;
}
};
@@ -104,15 +92,16 @@ class PopupMenu : public Popup {
Timer *submenu_timer;
List<Rect2> autohide_areas;
Vector<Item> items;
- int initial_button_mask;
- bool during_grabbed_click;
- int mouse_over;
- int submenu_over;
+ int initial_button_mask = 0;
+ bool during_grabbed_click = false;
+ int mouse_over = -1;
+ int submenu_over = -1;
Rect2 parent_rect;
String _get_accel_text(const Item &p_item) const;
int _get_mouse_over(const Point2 &p_over) const;
virtual Size2 _get_contents_minimum_size() const override;
+ int _get_item_height(int p_item) const;
int _get_items_total_height() const;
void _scroll_to_item(int p_item);
@@ -123,9 +112,9 @@ class PopupMenu : public Popup {
void _submenu_timeout();
uint64_t popup_time_msec = 0;
- bool hide_on_item_selection;
- bool hide_on_checkable_item_selection;
- bool hide_on_multistate_item_selection;
+ bool hide_on_item_selection = true;
+ bool hide_on_checkable_item_selection = true;
+ bool hide_on_multistate_item_selection = false;
Vector2 moved;
Array _get_items() const;
@@ -136,9 +125,9 @@ class PopupMenu : public Popup {
void _ref_shortcut(Ref<Shortcut> p_sc);
void _unref_shortcut(Ref<Shortcut> p_sc);
- bool allow_search;
- uint64_t search_time_msec;
- String search_string;
+ bool allow_search = true;
+ uint64_t search_time_msec = 0;
+ String search_string = "";
MarginContainer *margin_container;
ScrollContainer *scroll_container;
diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp
index 1b33cc6ffb..6e8dfd5994 100644
--- a/scene/gui/progress_bar.cpp
+++ b/scene/gui/progress_bar.cpp
@@ -74,7 +74,13 @@ void ProgressBar::_notification(int p_what) {
if (percent_visible) {
String txt = TS->format_number(itos(int(get_as_ratio() * 100))) + TS->percent_sign();
TextLine tl = TextLine(txt, font, font_size);
- tl.draw(get_canvas_item(), (Point2(get_size().width - tl.get_size().x, get_size().height - tl.get_size().y) / 2).round(), font_color);
+ Vector2 text_pos = (Point2(get_size().width - tl.get_size().x, get_size().height - tl.get_size().y) / 2).round();
+ Color font_outline_color = get_theme_color("font_outline_color");
+ int outline_size = get_theme_constant("outline_size");
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ tl.draw_outline(get_canvas_item(), text_pos, outline_size, font_outline_color);
+ }
+ tl.draw(get_canvas_item(), text_pos, font_color);
}
}
}
@@ -98,5 +104,4 @@ void ProgressBar::_bind_methods() {
ProgressBar::ProgressBar() {
set_v_size_flags(0);
set_step(0.01);
- percent_visible = true;
}
diff --git a/scene/gui/progress_bar.h b/scene/gui/progress_bar.h
index 3317846108..fb6060d932 100644
--- a/scene/gui/progress_bar.h
+++ b/scene/gui/progress_bar.h
@@ -36,7 +36,7 @@
class ProgressBar : public Range {
GDCLASS(ProgressBar, Range);
- bool percent_visible;
+ bool percent_visible = true;
protected:
void _notification(int p_what);
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 1e33ab0758..86b775e795 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -47,7 +47,6 @@ void Range::_value_changed_notify() {
_value_changed(shared->val);
emit_signal("value_changed", shared->val);
update();
- _change_notify("value");
}
void Range::Shared::emit_value_changed() {
@@ -63,7 +62,6 @@ void Range::Shared::emit_value_changed() {
void Range::_changed_notify(const char *p_what) {
emit_signal("changed");
update();
- _change_notify(p_what);
}
void Range::Shared::emit_changed(const char *p_what) {
@@ -314,17 +312,7 @@ bool Range::is_lesser_allowed() const {
Range::Range() {
shared = memnew(Shared);
- shared->min = 0;
- shared->max = 100;
- shared->val = 0;
- shared->step = 1;
- shared->page = 0;
shared->owners.insert(this);
- shared->exp_ratio = false;
- shared->allow_greater = false;
- shared->allow_lesser = false;
-
- _rounded_values = false;
}
Range::~Range() {
diff --git a/scene/gui/range.h b/scene/gui/range.h
index 68ff46bd74..1072a109c6 100644
--- a/scene/gui/range.h
+++ b/scene/gui/range.h
@@ -37,11 +37,14 @@ class Range : public Control {
GDCLASS(Range, Control);
struct Shared {
- double val, min, max;
- double step, page;
- bool exp_ratio;
- bool allow_greater;
- bool allow_lesser;
+ double val = 0.0;
+ double min = 0.0;
+ double max = 100.0;
+ double step = 1.0;
+ double page = 0.0;
+ bool exp_ratio = false;
+ bool allow_greater = false;
+ bool allow_lesser = false;
Set<Range *> owners;
void emit_value_changed();
void emit_changed(const char *p_what = "");
@@ -62,7 +65,7 @@ protected:
static void _bind_methods();
- bool _rounded_values;
+ bool _rounded_values = false;
public:
void set_value(double p_val);
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 6d5905aedc..13b57ece6c 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -45,7 +45,7 @@
#include "editor/editor_scale.h"
#endif
-RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) {
+RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) const {
if (p_free) {
if (p_item->subitems.size()) {
return p_item->subitems.front()->get();
@@ -90,7 +90,7 @@ RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) {
return nullptr;
}
-RichTextLabel::Item *RichTextLabel::_get_prev_item(Item *p_item, bool p_free) {
+RichTextLabel::Item *RichTextLabel::_get_prev_item(Item *p_item, bool p_free) const {
if (p_free) {
if (p_item->subitems.size()) {
return p_item->subitems.back()->get();
@@ -220,7 +220,7 @@ void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font>
if (tab_size > 0) { // Align inline tabs.
Vector<float> tabs;
- tabs.push_back(tab_size * p_base_font->get_char_size('m', 0, p_base_font_size).width);
+ tabs.push_back(tab_size * p_base_font->get_char_size(' ', 0, p_base_font_size).width);
l.text_buf->tab_align(tabs);
}
@@ -314,7 +314,7 @@ void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font>
table->rows.clear();
Vector2 offset;
- float row_height = 0;
+ float row_height = 0.0;
for (List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) {
ERR_CONTINUE(E->get()->type != ITEM_FRAME); // Children should all be frames.
@@ -392,7 +392,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
if (tab_size > 0) { // Align inline tabs.
Vector<float> tabs;
- tabs.push_back(tab_size * p_base_font->get_char_size('m', 0, p_base_font_size).width);
+ tabs.push_back(tab_size * p_base_font->get_char_size(' ', 0, p_base_font_size).width);
l.text_buf->tab_align(tabs);
}
@@ -454,6 +454,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
ItemImage *img = (ItemImage *)it;
l.text_buf->add_object((uint64_t)it, img->image->get_size(), img->inline_align, 1);
text += String::chr(0xfffc);
+ l.char_count += 1;
} break;
case ITEM_TABLE: {
ItemTable *table = static_cast<ItemTable *>(it);
@@ -553,7 +554,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
table->rows.clear();
Vector2 offset;
- float row_height = 0;
+ float row_height = 0.0;
for (List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) {
ERR_CONTINUE(E->get()->type != ITEM_FRAME); // Children should all be frames.
@@ -587,7 +588,8 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
offset.x += table->columns[column].width + hseparation + frame->padding.size.x;
row_height = MAX(yofs, row_height);
- if (column == col_count - 1) {
+ // Add row height after last column of the row or last cell of the table.
+ if (column == col_count - 1 || E->next() == nullptr) {
offset.x = 0;
row_height += vseparation;
table->total_height += row_height;
@@ -776,6 +778,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
Color odd_row_bg = get_theme_color("table_odd_row_bg");
Color even_row_bg = get_theme_color("table_even_row_bg");
Color border = get_theme_color("table_border");
+ int hseparation = get_theme_constant("table_hseparation");
int col_count = table->columns.size();
int row_count = table->rows.size();
@@ -792,11 +795,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, 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 + 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);
} else {
- draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width, 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->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, 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 + hseparation + 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 < frame->lines.size(); j++) {
@@ -819,8 +822,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
// Draw oulines and shadow.
for (int i = 0; i < gl_size; i++) {
Item *it = _get_item_at_pos(it_from, it_to, glyphs[i].start);
- int size = _find_outline_size(it);
- Color font_color = _find_outline_color(it, Color(0, 0, 0, 0));
+ int size = _find_outline_size(it, p_outline_size);
+ Color font_color = _find_outline_color(it, p_outline_color);
if (size <= 0) {
gloff.x += glyphs[i].advance;
continue;
@@ -1115,7 +1118,8 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
Point2 ofs = text_rect.get_position() + Vector2(0, main->lines[from_line].offset.y - vofs);
while (ofs.y < size.height && from_line < main->lines.size()) {
- ofs.y += _find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, p_click, r_click_frame, r_click_line, r_click_item, r_click_char);
+ _find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, p_click, r_click_frame, r_click_line, r_click_item, r_click_char);
+ ofs.y += main->lines[from_line].text_buf->get_size().y;
if (((r_click_item != nullptr) && ((*r_click_item) != nullptr)) || ((r_click_frame != nullptr) && ((*r_click_frame) != nullptr))) {
if (r_outside != nullptr) {
*r_outside = false;
@@ -1242,8 +1246,19 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
if (r_click_item != nullptr) {
Item *it = p_frame->lines[p_line].from;
Item *it_to = (p_line + 1 < p_frame->lines.size()) ? p_frame->lines[p_line + 1].from : nullptr;
- it = _get_item_at_pos(it, it_to, char_pos);
- *r_click_item = it;
+ if (char_pos == p_frame->lines[p_line].char_count) {
+ // Selection after the end of line, select last item.
+ if (it_to != nullptr) {
+ *r_click_item = _get_prev_item(it_to);
+ } else {
+ for (Item *i = it; i && i != it_to; i = _get_next_item(i)) {
+ *r_click_item = i;
+ }
+ }
+ } else {
+ // Selection in the line.
+ *r_click_item = _get_item_at_pos(it, it_to, char_pos);
+ }
}
if (r_click_frame != nullptr) {
@@ -1398,7 +1413,7 @@ void RichTextLabel::_notification(int p_what) {
}
Ref<Font> base_font = get_theme_font("normal_font");
Color base_color = get_theme_color("default_color");
- Color outline_color = get_theme_color("outline_color");
+ Color outline_color = get_theme_color("font_outline_color");
int outline_size = get_theme_constant("outline_size");
Color font_shadow_color = get_theme_color("font_shadow_color");
bool use_outline = get_theme_constant("shadow_as_outline");
@@ -1464,7 +1479,7 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
return;
}
- if (b->get_button_index() == BUTTON_LEFT) {
+ if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
if (b->is_pressed() && !b->is_doubleclick()) {
scroll_updated = false;
ItemFrame *c_frame = nullptr;
@@ -1549,12 +1564,12 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
}
}
- if (b->get_button_index() == BUTTON_WHEEL_UP) {
+ if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
if (scroll_active) {
vscroll->set_value(vscroll->get_value() - vscroll->get_page() * b->get_factor() * 0.5 / 8);
}
}
- if (b->get_button_index() == BUTTON_WHEEL_DOWN) {
+ if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
if (scroll_active) {
vscroll->set_value(vscroll->get_value() + vscroll->get_page() * b->get_factor() * 0.5 / 8);
}
@@ -1573,53 +1588,36 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
- if (k->is_pressed() && !k->get_alt() && !k->get_shift()) {
+ if (k->is_pressed()) {
bool handled = false;
- switch (k->get_keycode()) {
- case KEY_PAGEUP: {
- if (vscroll->is_visible_in_tree()) {
- vscroll->set_value(vscroll->get_value() - vscroll->get_page());
- handled = true;
- }
- } break;
- case KEY_PAGEDOWN: {
- if (vscroll->is_visible_in_tree()) {
- vscroll->set_value(vscroll->get_value() + vscroll->get_page());
- handled = true;
- }
- } break;
- case KEY_UP: {
- if (vscroll->is_visible_in_tree()) {
- vscroll->set_value(vscroll->get_value() - get_theme_font("normal_font")->get_height(get_theme_font_size("normal_font_size")));
- handled = true;
- }
- } break;
- case KEY_DOWN: {
- if (vscroll->is_visible_in_tree()) {
- vscroll->set_value(vscroll->get_value() + get_theme_font("normal_font")->get_height(get_theme_font_size("normal_font_size")));
- handled = true;
- }
- } break;
- case KEY_HOME: {
- if (vscroll->is_visible_in_tree()) {
- vscroll->set_value(0);
- handled = true;
- }
- } break;
- case KEY_END: {
- if (vscroll->is_visible_in_tree()) {
- vscroll->set_value(vscroll->get_max());
- handled = true;
- }
- } break;
- case KEY_INSERT:
- case KEY_C: {
- if (k->get_command()) {
- selection_copy();
- handled = true;
- }
- } break;
+ if (k->is_action("ui_page_up") && vscroll->is_visible_in_tree()) {
+ vscroll->set_value(vscroll->get_value() - vscroll->get_page());
+ handled = true;
+ }
+ if (k->is_action("ui_page_down") && vscroll->is_visible_in_tree()) {
+ vscroll->set_value(vscroll->get_value() + vscroll->get_page());
+ handled = true;
+ }
+ if (k->is_action("ui_up") && vscroll->is_visible_in_tree()) {
+ vscroll->set_value(vscroll->get_value() - get_theme_font("normal_font")->get_height(get_theme_font_size("normal_font_size")));
+ handled = true;
+ }
+ if (k->is_action("ui_down") && vscroll->is_visible_in_tree()) {
+ vscroll->set_value(vscroll->get_value() + get_theme_font("normal_font")->get_height(get_theme_font_size("normal_font_size")));
+ handled = true;
+ }
+ if (k->is_action("ui_home") && vscroll->is_visible_in_tree()) {
+ vscroll->set_value(0);
+ handled = true;
+ }
+ if (k->is_action("ui_end") && vscroll->is_visible_in_tree()) {
+ vscroll->set_value(vscroll->get_max());
+ handled = true;
+ }
+ if (k->is_action("ui_copy")) {
+ selection_copy();
+ handled = true;
}
if (handled) {
@@ -1753,7 +1751,7 @@ int RichTextLabel::_find_font_size(Item *p_item) {
return -1;
}
-int RichTextLabel::_find_outline_size(Item *p_item) {
+int RichTextLabel::_find_outline_size(Item *p_item, int p_default) {
Item *sizeitem = p_item;
while (sizeitem) {
@@ -1765,7 +1763,7 @@ int RichTextLabel::_find_outline_size(Item *p_item) {
sizeitem = sizeitem->parent;
}
- return 0;
+ return p_default;
}
Dictionary RichTextLabel::_find_font_features(Item *p_item) {
@@ -1847,7 +1845,7 @@ int RichTextLabel::_find_list(Item *p_item, Vector<int> &r_index, Vector<ItemLis
int RichTextLabel::_find_margin(Item *p_item, const Ref<Font> &p_base_font, int p_base_font_size) {
Item *item = p_item;
- float margin = 0;
+ float margin = 0.0;
while (item) {
if (item->type == ITEM_INDENT) {
@@ -1859,7 +1857,7 @@ int RichTextLabel::_find_margin(Item *p_item, const Ref<Font> &p_base_font, int
if (font_size == -1) {
font_size = p_base_font_size;
}
- margin += tab_size * font->get_char_size('m', 0, font_size).width;
+ margin += tab_size * font->get_char_size(' ', 0, font_size).width;
} else if (item->type == ITEM_LIST) {
Ref<Font> font = _find_font(item);
@@ -1870,7 +1868,7 @@ int RichTextLabel::_find_margin(Item *p_item, const Ref<Font> &p_base_font, int
if (font_size == -1) {
font_size = p_base_font_size;
}
- margin += tab_size * font->get_char_size('m', 0, font_size).width;
+ margin += tab_size * font->get_char_size(' ', 0, font_size).width;
}
item = item->parent;
@@ -2252,6 +2250,8 @@ void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width,
}
ERR_FAIL_COND(p_image.is_null());
+ ERR_FAIL_COND(p_image->get_width() == 0);
+ ERR_FAIL_COND(p_image->get_height() == 0);
ItemImage *item = memnew(ItemImage);
item->image = p_image;
@@ -3520,7 +3520,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p
return false;
}
-String RichTextLabel::_get_line_text(ItemFrame *p_frame, int p_line, Selection p_selection) {
+String RichTextLabel::_get_line_text(ItemFrame *p_frame, int p_line, Selection p_selection) const {
String text;
ERR_FAIL_COND_V(p_frame == nullptr, text);
ERR_FAIL_COND_V(p_line < 0 || p_line >= p_frame->lines.size(), text);
@@ -3587,7 +3587,7 @@ String RichTextLabel::_get_line_text(ItemFrame *p_frame, int p_line, Selection p
return text;
}
-String RichTextLabel::get_selected_text() {
+String RichTextLabel::get_selected_text() const {
if (!selection.active || !selection.enabled) {
return "";
}
@@ -3611,6 +3611,22 @@ bool RichTextLabel::is_selection_enabled() const {
return selection.enabled;
}
+int RichTextLabel::get_selection_from() const {
+ if (!selection.active || !selection.enabled) {
+ return -1;
+ }
+
+ return selection.from_frame->lines[selection.from_line].char_offset + selection.from_char;
+}
+
+int RichTextLabel::get_selection_to() const {
+ if (!selection.active || !selection.enabled) {
+ return -1;
+ }
+
+ return selection.to_frame->lines[selection.to_line].char_offset + selection.to_char - 1;
+}
+
void RichTextLabel::set_bbcode(const String &p_bbcode) {
bbcode = p_bbcode;
if (is_inside_tree() && use_bbcode) {
@@ -3631,6 +3647,7 @@ void RichTextLabel::set_use_bbcode(bool p_enable) {
}
use_bbcode = p_enable;
set_bbcode(bbcode);
+ notify_property_list_changed();
}
bool RichTextLabel::is_using_bbcode() const {
@@ -3646,6 +3663,8 @@ String RichTextLabel::get_text() {
text += t->text;
} else if (it->type == ITEM_NEWLINE) {
text += "\n";
+ } else if (it->type == ITEM_IMAGE) {
+ text += " ";
} else if (it->type == ITEM_INDENT || it->type == ITEM_LIST) {
text += "\t";
}
@@ -3722,7 +3741,6 @@ void RichTextLabel::set_percent_visible(float p_percent) {
}
main->first_invalid_line = 0; //invalidate ALL
_validate_line_caches(main);
- _change_notify("visible_characters");
update();
}
}
@@ -3767,6 +3785,12 @@ int RichTextLabel::get_content_height() const {
return total_height;
}
+void RichTextLabel::_validate_property(PropertyInfo &property) const {
+ if (!use_bbcode && property.name == "bbcode_text") {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+}
+
void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &RichTextLabel::_gui_input);
ClassDB::bind_method(D_METHOD("get_text"), &RichTextLabel::get_text);
@@ -3839,6 +3863,11 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_selection_enabled", "enabled"), &RichTextLabel::set_selection_enabled);
ClassDB::bind_method(D_METHOD("is_selection_enabled"), &RichTextLabel::is_selection_enabled);
+ ClassDB::bind_method(D_METHOD("get_selection_from"), &RichTextLabel::get_selection_from);
+ ClassDB::bind_method(D_METHOD("get_selection_to"), &RichTextLabel::get_selection_to);
+
+ ClassDB::bind_method(D_METHOD("get_selected_text"), &RichTextLabel::get_selected_text);
+
ClassDB::bind_method(D_METHOD("parse_bbcode", "bbcode"), &RichTextLabel::parse_bbcode);
ClassDB::bind_method(D_METHOD("append_bbcode", "bbcode"), &RichTextLabel::append_bbcode);
@@ -3948,7 +3977,6 @@ void RichTextLabel::set_visible_characters(int p_visible) {
percent_visible = (float)p_visible / (float)total_char_count;
}
}
- _change_notify("percent_visible");
update();
}
@@ -4066,19 +4094,6 @@ RichTextLabel::RichTextLabel() {
main->first_invalid_line = 0;
main->first_resized_line = 0;
current_frame = main;
- tab_size = 4;
- default_align = ALIGN_LEFT;
- underline_meta = true;
- meta_hovering = nullptr;
- override_selected_font_color = false;
-
- scroll_visible = false;
- scroll_follow = false;
- scroll_following = false;
- updating_scroll = false;
- scroll_active = true;
- scroll_w = 0;
- scroll_updated = false;
vscroll = memnew(VScrollBar);
add_child(vscroll);
@@ -4090,19 +4105,6 @@ RichTextLabel::RichTextLabel() {
vscroll->connect("value_changed", callable_mp(this, &RichTextLabel::_scroll_changed));
vscroll->set_step(1);
vscroll->hide();
- use_bbcode = false;
-
- selection.click_frame = nullptr;
- selection.click_item = nullptr;
- selection.active = false;
- selection.enabled = false;
-
- visible_characters = -1;
- percent_visible = 1;
- visible_line_count = 0;
-
- fixed_width = -1;
- fit_content_height = false;
set_clip_contents(true);
}
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 037839dac7..e3e457d1f2 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -81,7 +81,9 @@ public:
};
protected:
+ void _notification(int p_what);
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const override;
private:
struct Item;
@@ -147,9 +149,9 @@ private:
struct ItemDropcap : public Item {
String text;
Ref<Font> font;
- int font_size;
+ int font_size = 0;
Color color;
- int ol_size;
+ int ol_size = 0;
Color ol_color;
Rect2 dropcap_margins;
ItemDropcap() { type = ITEM_DROPCAP; }
@@ -232,11 +234,11 @@ private:
struct ItemTable : public Item {
struct Column {
- bool expand;
- int expand_ratio;
- int min_width;
- int max_width;
- int width;
+ bool expand = false;
+ int expand_ratio = 0;
+ int min_width = 0;
+ int max_width = 0;
+ int width = 0;
};
Vector<Column> columns;
@@ -322,31 +324,31 @@ private:
}
};
- ItemFrame *main;
- Item *current;
- ItemFrame *current_frame;
+ ItemFrame *main = nullptr;
+ Item *current = nullptr;
+ ItemFrame *current_frame = nullptr;
- VScrollBar *vscroll;
+ VScrollBar *vscroll = nullptr;
- bool scroll_visible;
- bool scroll_follow;
- bool scroll_following;
- bool scroll_active;
- int scroll_w;
- bool scroll_updated;
- bool updating_scroll;
+ bool scroll_visible = false;
+ bool scroll_follow = false;
+ bool scroll_following = false;
+ bool scroll_active = true;
+ int scroll_w = 0;
+ bool scroll_updated = false;
+ bool updating_scroll = false;
int current_idx = 1;
int current_char_ofs = 0;
- int visible_paragraph_count;
- int visible_line_count;
+ int visible_paragraph_count = 0;
+ int visible_line_count = 0;
- int tab_size;
- bool underline_meta;
- bool override_selected_font_color;
+ int tab_size = 4;
+ bool underline_meta = true;
+ bool override_selected_font_color = false;
- Align default_align;
+ Align default_align = ALIGN_LEFT;
- ItemMeta *meta_hovering;
+ ItemMeta *meta_hovering = nullptr;
Variant current_meta;
Vector<Ref<RichTextEffect>> custom_effects;
@@ -363,33 +365,33 @@ private:
Array st_args;
struct Selection {
- ItemFrame *click_frame;
- int click_line;
- Item *click_item;
- int click_char;
-
- ItemFrame *from_frame;
- int from_line;
- Item *from_item;
- int from_char;
-
- ItemFrame *to_frame;
- int to_line;
- Item *to_item;
- int to_char;
-
- bool active; // anything selected? i.e. from, to, etc. valid?
- bool enabled; // allow selections?
+ ItemFrame *click_frame = nullptr;
+ int click_line = 0;
+ Item *click_item = nullptr;
+ int click_char = 0;
+
+ ItemFrame *from_frame = nullptr;
+ int from_line = 0;
+ Item *from_item = nullptr;
+ int from_char = 0;
+
+ ItemFrame *to_frame = nullptr;
+ int to_line = 0;
+ Item *to_item = nullptr;
+ int to_char = 0;
+
+ bool active = false; // anything selected? i.e. from, to, etc. valid?
+ bool enabled = false; // allow selections?
};
Selection selection;
- int visible_characters;
- float percent_visible;
+ int visible_characters = -1;
+ float percent_visible = 1.0;
void _find_click(ItemFrame *p_frame, const Point2i &p_click, ItemFrame **r_click_frame = nullptr, int *r_click_line = nullptr, Item **r_click_item = nullptr, int *r_click_char = nullptr, bool *r_outside = nullptr);
- String _get_line_text(ItemFrame *p_frame, int p_line, Selection p_sel);
+ String _get_line_text(ItemFrame *p_frame, int p_line, Selection p_sel) const;
bool _search_line(ItemFrame *p_frame, int p_line, const String &p_string, Item *p_from, Item *p_to);
void _shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width, int *r_char_offset);
@@ -405,7 +407,7 @@ private:
Ref<Font> _find_font(Item *p_item);
int _find_font_size(Item *p_item);
Dictionary _find_font_features(Item *p_item);
- int _find_outline_size(Item *p_item);
+ int _find_outline_size(Item *p_item, int p_default);
ItemList *_find_list_item(Item *p_item);
ItemDropcap *_find_dc_item(Item *p_item);
int _find_list(Item *p_item, Vector<int> &r_index, Vector<ItemList *> &r_list);
@@ -427,22 +429,19 @@ private:
void _scroll_changed(double);
void _gui_input(Ref<InputEvent> p_event);
- Item *_get_next_item(Item *p_item, bool p_free = false);
- Item *_get_prev_item(Item *p_item, bool p_free = false);
+ Item *_get_next_item(Item *p_item, bool p_free = false) const;
+ Item *_get_prev_item(Item *p_item, bool p_free = false) const;
Rect2 _get_text_rect();
Ref<RichTextEffect> _get_custom_effect_by_code(String p_bbcode_identifier);
virtual Dictionary parse_expressions_for_values(Vector<String> p_expressions);
- bool use_bbcode;
+ bool use_bbcode = false;
String bbcode;
- int fixed_width;
-
- bool fit_content_height;
+ int fixed_width = -1;
-protected:
- void _notification(int p_what);
+ bool fit_content_height = false;
public:
String get_text();
@@ -524,7 +523,9 @@ public:
void set_selection_enabled(bool p_enabled);
bool is_selection_enabled() const;
- String get_selected_text();
+ int get_selection_from() const;
+ int get_selection_to() const;
+ String get_selected_text() const;
void selection_copy();
Error parse_bbcode(const String &p_bbcode);
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index 79a0de35fc..a56bf15507 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -52,17 +52,17 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
if (b.is_valid()) {
accept_event();
- if (b->get_button_index() == BUTTON_WHEEL_DOWN && b->is_pressed()) {
+ if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && b->is_pressed()) {
set_value(get_value() + get_page() / 4.0);
accept_event();
}
- if (b->get_button_index() == BUTTON_WHEEL_UP && b->is_pressed()) {
+ if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && b->is_pressed()) {
set_value(get_value() - get_page() / 4.0);
accept_event();
}
- if (b->get_button_index() != BUTTON_LEFT) {
+ if (b->get_button_index() != MOUSE_BUTTON_LEFT) {
return;
}
@@ -434,7 +434,7 @@ double ScrollBar::get_area_size() const {
}
double ScrollBar::get_area_offset() const {
- double ofs = 0;
+ double ofs = 0.0;
if (orientation == VERTICAL) {
ofs += get_theme_stylebox("hscroll")->get_margin(SIDE_TOP);
diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h
index 7dd71cc269..24b3b33e82 100644
--- a/scene/gui/scroll_bar.h
+++ b/scene/gui/scroll_bar.h
@@ -47,14 +47,14 @@ class ScrollBar : public Range {
Orientation orientation;
Size2 size;
- float custom_step = -1;
+ float custom_step = -1.0;
HighlightStatus highlight = HIGHLIGHT_NONE;
struct Drag {
bool active = false;
- float pos_at_click = 0;
- float value_at_click = 0;
+ float pos_at_click = 0.0;
+ float value_at_click = 0.0;
} drag;
double get_grabber_size() const;
@@ -73,14 +73,14 @@ class ScrollBar : public Range {
Vector2 drag_node_accum;
Vector2 drag_node_from;
Vector2 last_drag_node_accum;
- float last_drag_node_time;
- float time_since_motion;
+ float last_drag_node_time = 0.0;
+ float time_since_motion = 0.0;
bool drag_node_touching = false;
bool drag_node_touching_deaccel = false;
- bool click_handled;
+ bool click_handled = false;
bool scrolling = false;
- double target_scroll = 0;
+ double target_scroll = 0.0;
bool smooth_scroll_enabled = false;
void _drag_node_exit();
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 52feb2ab23..90a528482f 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -94,7 +94,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
Ref<InputEventMouseButton> mb = p_gui_input;
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) {
// only horizontal is enabled, scroll horizontally
if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->get_shift())) {
h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8 * mb->get_factor());
@@ -103,7 +103,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
- if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) {
// only horizontal is enabled, scroll horizontally
if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->get_shift())) {
h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8 * mb->get_factor());
@@ -112,13 +112,13 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
- if (mb->get_button_index() == BUTTON_WHEEL_LEFT && mb->is_pressed()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT && mb->is_pressed()) {
if (h_scroll->is_visible_in_tree()) {
h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * mb->get_factor() / 8);
}
}
- if (mb->get_button_index() == BUTTON_WHEEL_RIGHT && mb->is_pressed()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT && mb->is_pressed()) {
if (h_scroll->is_visible_in_tree()) {
h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * mb->get_factor() / 8);
}
@@ -132,7 +132,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
return;
}
- if (mb->get_button_index() != BUTTON_LEFT) {
+ if (mb->get_button_index() != MOUSE_BUTTON_LEFT) {
return;
}
@@ -244,11 +244,11 @@ void ScrollContainer::_ensure_focused_visible(Control *p_control) {
if (is_a_parent_of(p_control)) {
Rect2 global_rect = get_global_rect();
Rect2 other_rect = p_control->get_global_rect();
- float right_margin = 0;
+ float right_margin = 0.0;
if (v_scroll->is_visible()) {
right_margin += v_scroll->get_size().x;
}
- float bottom_margin = 0;
+ float bottom_margin = 0.0;
if (h_scroll->is_visible()) {
bottom_margin += h_scroll->get_size().y;
}
@@ -624,15 +624,7 @@ ScrollContainer::ScrollContainer() {
add_child(v_scroll);
v_scroll->connect("value_changed", callable_mp(this, &ScrollContainer::_scroll_moved));
- drag_speed = Vector2();
- drag_touching = false;
- drag_touching_deaccel = false;
- beyond_deadzone = false;
- scroll_h = true;
- scroll_v = true;
-
deadzone = GLOBAL_GET("gui/common/default_scroll_deadzone");
- follow_focus = false;
set_clip_contents(true);
};
diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h
index 7e32cbed1c..9d3ce39345 100644
--- a/scene/gui/scroll_container.h
+++ b/scene/gui/scroll_container.h
@@ -50,18 +50,18 @@ class ScrollContainer : public Container {
Vector2 drag_accum;
Vector2 drag_from;
Vector2 last_drag_accum;
- float last_drag_time;
- float time_since_motion;
- bool drag_touching;
- bool drag_touching_deaccel;
- bool click_handled;
- bool beyond_deadzone;
-
- bool scroll_h;
- bool scroll_v;
-
- int deadzone;
- bool follow_focus;
+ float last_drag_time = 0.0;
+ float time_since_motion = 0.0;
+ bool drag_touching = false;
+ bool drag_touching_deaccel = false;
+ bool click_handled = false;
+ bool beyond_deadzone = false;
+
+ bool scroll_h = true;
+ bool scroll_v = true;
+
+ int deadzone = 0;
+ bool follow_focus = false;
void _cancel_drag();
diff --git a/scene/gui/separator.h b/scene/gui/separator.h
index 1ac0f2c503..77162c68fa 100644
--- a/scene/gui/separator.h
+++ b/scene/gui/separator.h
@@ -36,7 +36,7 @@ class Separator : public Control {
GDCLASS(Separator, Control);
protected:
- Orientation orientation;
+ Orientation orientation = Orientation::HORIZONTAL;
void _notification(int p_what);
public:
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 0edf1856de..7f1d19a87a 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -53,7 +53,7 @@ void Slider::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
Ref<Texture2D> grabber = get_theme_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber");
grab.pos = orientation == VERTICAL ? mb->get_position().y : mb->get_position().x;
@@ -72,9 +72,11 @@ void Slider::_gui_input(Ref<InputEvent> p_event) {
grab.active = false;
}
} else if (scrollable) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
+ grab_focus();
set_value(get_value() + get_step());
- } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
+ } else if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
+ grab_focus();
set_value(get_value() - get_step());
}
}
@@ -269,12 +271,5 @@ void Slider::_bind_methods() {
Slider::Slider(Orientation p_orientation) {
orientation = p_orientation;
- mouse_inside = false;
- grab.active = false;
- ticks = 0;
- ticks_on_borders = false;
- custom_step = -1;
- editable = true;
- scrollable = true;
set_focus_mode(FOCUS_ALL);
}
diff --git a/scene/gui/slider.h b/scene/gui/slider.h
index 292931b7b5..65a4036cd1 100644
--- a/scene/gui/slider.h
+++ b/scene/gui/slider.h
@@ -37,23 +37,23 @@ class Slider : public Range {
GDCLASS(Slider, Range);
struct Grab {
- int pos;
- float uvalue;
- bool active;
+ int pos = 0;
+ float uvalue = 0.0;
+ bool active = false;
} grab;
- int ticks;
- bool mouse_inside;
+ int ticks = 0;
+ bool mouse_inside = false;
Orientation orientation;
- float custom_step;
- bool editable;
- bool scrollable;
+ float custom_step = -1.0;
+ bool editable = true;
+ bool scrollable = true;
protected:
void _gui_input(Ref<InputEvent> p_event);
void _notification(int p_what);
static void _bind_methods();
- bool ticks_on_borders;
+ bool ticks_on_borders = false;
public:
virtual Size2 get_minimum_size() const override;
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 32c878205e..50b25fa7b4 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -76,7 +76,7 @@ void SpinBox::_line_edit_input(const Ref<InputEvent> &p_event) {
}
void SpinBox::_range_click_timeout() {
- if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+ if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) {
bool up = get_local_mouse_position().y < (get_size().height / 2);
set_value(get_value() + (up ? get_step() : -get_step()));
@@ -91,6 +91,14 @@ void SpinBox::_range_click_timeout() {
}
}
+void SpinBox::_release_mouse() {
+ if (drag.enabled) {
+ drag.enabled = false;
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+ warp_mouse(drag.capture_pos);
+ }
+}
+
void SpinBox::_gui_input(const Ref<InputEvent> &p_event) {
if (!is_editable()) {
return;
@@ -102,7 +110,7 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) {
bool up = mb->get_position().y < (get_size().height / 2);
switch (mb->get_button_index()) {
- case BUTTON_LEFT: {
+ case MOUSE_BUTTON_LEFT: {
line_edit->grab_focus();
set_value(get_value() + (up ? get_step() : -get_step()));
@@ -114,17 +122,17 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) {
drag.allowed = true;
drag.capture_pos = mb->get_position();
} break;
- case BUTTON_RIGHT: {
+ case MOUSE_BUTTON_RIGHT: {
line_edit->grab_focus();
set_value((up ? get_max() : get_min()));
} break;
- case BUTTON_WHEEL_UP: {
+ case MOUSE_BUTTON_WHEEL_UP: {
if (line_edit->has_focus()) {
set_value(get_value() + get_step() * mb->get_factor());
accept_event();
}
} break;
- case BUTTON_WHEEL_DOWN: {
+ case MOUSE_BUTTON_WHEEL_DOWN: {
if (line_edit->has_focus()) {
set_value(get_value() - get_step() * mb->get_factor());
accept_event();
@@ -133,21 +141,16 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
//set_default_cursor_shape(CURSOR_ARROW);
range_click_timer->stop();
-
- if (drag.enabled) {
- drag.enabled = false;
- Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
- warp_mouse(drag.capture_pos);
- }
+ _release_mouse();
drag.allowed = false;
}
Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
if (drag.enabled) {
drag.diff_y += mm->get_relative().y;
float diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8f) * SGN(drag.diff_y);
@@ -199,6 +202,8 @@ void SpinBox::_notification(int p_what) {
} else if (p_what == NOTIFICATION_ENTER_TREE) {
_adjust_width_for_icon(get_theme_icon("updown"));
_value_changed(0);
+ } else if (p_what == NOTIFICATION_EXIT_TREE) {
+ _release_mouse();
} else if (p_what == NOTIFICATION_TRANSLATION_CHANGED) {
_value_changed(0);
} else if (p_what == NOTIFICATION_THEME_CHANGED) {
@@ -268,7 +273,6 @@ void SpinBox::_bind_methods() {
}
SpinBox::SpinBox() {
- last_w = 0;
line_edit = memnew(LineEdit);
add_child(line_edit);
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index a4e3d644e2..e116adb64c 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -39,10 +39,11 @@ class SpinBox : public Range {
GDCLASS(SpinBox, Range);
LineEdit *line_edit;
- int last_w;
+ int last_w = 0;
Timer *range_click_timer;
void _range_click_timeout();
+ void _release_mouse();
void _text_entered(const String &p_string);
virtual void _value_changed(double) override;
@@ -52,11 +53,11 @@ class SpinBox : public Range {
void _line_edit_input(const Ref<InputEvent> &p_event);
struct Drag {
- float base_val = 0;
+ float base_val = 0.0;
bool allowed = false;
bool enabled = false;
Vector2 capture_pos;
- float diff_y = 0;
+ float diff_y = 0.0;
} drag;
void _line_edit_focus_exit();
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index d6f2df1d8c..c80120f87d 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -102,7 +102,7 @@ void SplitContainer::_resort() {
middle_sep += clamped_split_offset;
if (should_clamp_split_offset) {
split_offset = clamped_split_offset;
- _change_notify("split_offset");
+
should_clamp_split_offset = false;
}
}
@@ -214,7 +214,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
int sep = get_theme_constant("separation");
@@ -359,12 +359,5 @@ void SplitContainer::_bind_methods() {
}
SplitContainer::SplitContainer(bool p_vertical) {
- mouse_inside = false;
- split_offset = 0;
- should_clamp_split_offset = false;
- middle_sep = 0;
vertical = p_vertical;
- dragging = false;
- collapsed = false;
- dragger_visibility = DRAGGER_VISIBLE;
}
diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h
index 46a6792206..6cb94d6ecf 100644
--- a/scene/gui/split_container.h
+++ b/scene/gui/split_container.h
@@ -44,16 +44,16 @@ public:
};
private:
- bool should_clamp_split_offset;
- int split_offset;
- int middle_sep;
- bool vertical;
- bool dragging;
- int drag_from;
- int drag_ofs;
- bool collapsed;
- DraggerVisibility dragger_visibility;
- bool mouse_inside;
+ bool should_clamp_split_offset = false;
+ int split_offset = 0;
+ int middle_sep = 0;
+ bool vertical = false;
+ bool dragging = false;
+ int drag_from = 0;
+ int drag_ofs = 0;
+ bool collapsed = false;
+ DraggerVisibility dragger_visibility = DRAGGER_VISIBLE;
+ bool mouse_inside = false;
Control *_getch(int p_idx) const;
diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp
index 68eef0f96b..8ffdd269a4 100644
--- a/scene/gui/subviewport_container.cpp
+++ b/scene/gui/subviewport_container.cpp
@@ -203,8 +203,6 @@ void SubViewportContainer::_bind_methods() {
}
SubViewportContainer::SubViewportContainer() {
- stretch = false;
- shrink = 1;
set_process_input(true);
set_process_unhandled_input(true);
}
diff --git a/scene/gui/subviewport_container.h b/scene/gui/subviewport_container.h
index 91fc29d377..77cf4c16b3 100644
--- a/scene/gui/subviewport_container.h
+++ b/scene/gui/subviewport_container.h
@@ -36,8 +36,8 @@
class SubViewportContainer : public Container {
GDCLASS(SubViewportContainer, Container);
- bool stretch;
- int shrink;
+ bool stretch = false;
+ int shrink = 1;
protected:
void _notification(int p_what);
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 5acc789fbb..1e31f9e206 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -76,7 +76,7 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
Popup *popup = get_popup();
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
Point2 pos(mb->get_position().x, mb->get_position().y);
Size2 size = get_size();
@@ -535,6 +535,8 @@ void TabContainer::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, in
Vector<Control *> tabs = _get_tabs();
RID canvas = get_canvas_item();
Ref<Font> font = get_theme_font("font");
+ Color font_outline_color = get_theme_color("font_outline_color");
+ int outline_size = get_theme_constant("outline_size");
int icon_text_distance = get_theme_constant("icon_separation");
int tab_width = _get_tab_width(p_index);
int header_height = _get_top_margin();
@@ -565,6 +567,9 @@ void TabContainer::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, in
// Draw the tab text.
Point2i text_pos(x_content, y_center - text_buf[p_index]->get_size().y / 2);
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ text_buf[p_index]->draw_outline(canvas, text_pos, outline_size, font_outline_color);
+ }
text_buf[p_index]->draw(canvas, text_pos, p_font_color);
}
@@ -640,7 +645,7 @@ int TabContainer::_get_tab_width(int p_index) const {
// Get the width of the text displayed on the tab.
Ref<Font> font = get_theme_font("font");
int font_size = get_theme_font_size("font_size");
- String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(control->get_name());
+ String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(tr(control->get_name()));
int width = font->get_string_size(text, font_size).width;
// Add space for a tab icon.
@@ -747,8 +752,6 @@ void TabContainer::set_current_tab(int p_current) {
_repaint();
- _change_notify("current_tab");
-
if (pending_previous == current) {
emit_signal("tab_selected", current);
} else {
@@ -967,8 +970,6 @@ void TabContainer::set_tab_align(TabAlign p_align) {
ERR_FAIL_INDEX(p_align, 3);
align = p_align;
update();
-
- _change_notify("tab_align");
}
TabContainer::TabAlign TabContainer::get_tab_align() const {
@@ -1022,6 +1023,7 @@ void TabContainer::set_tab_title(int p_tab, const String &p_title) {
Control *child = _get_tab(p_tab);
ERR_FAIL_COND(!child);
child->set_meta("_tab_name", p_title);
+ _refresh_texts();
update();
}
@@ -1243,20 +1245,5 @@ void TabContainer::_bind_methods() {
}
TabContainer::TabContainer() {
- first_tab_cache = 0;
- last_tab_cache = 0;
- buttons_visible_cache = false;
- menu_hovered = false;
- highlight_arrow = -1;
- tabs_ofs_cache = 0;
- current = 0;
- previous = 0;
- align = ALIGN_CENTER;
- tabs_visible = true;
- all_tabs_in_front = false;
- drag_to_rearrange_enabled = false;
- tabs_rearrange_group = -1;
- use_hidden_tabs_for_min_size = false;
-
connect("mouse_exited", callable_mp(this, &TabContainer::_on_mouse_exited));
}
diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h
index 58742c5be8..4ed5255729 100644
--- a/scene/gui/tab_container.h
+++ b/scene/gui/tab_container.h
@@ -46,23 +46,23 @@ public:
};
private:
- int first_tab_cache;
- int tabs_ofs_cache;
- int last_tab_cache;
- int current;
- int previous;
- bool tabs_visible;
- bool all_tabs_in_front;
- bool buttons_visible_cache;
- bool menu_hovered;
- int highlight_arrow;
- TabAlign align;
+ int first_tab_cache = 0;
+ int tabs_ofs_cache = 0;
+ int last_tab_cache = 0;
+ int current = 0;
+ int previous = 0;
+ bool tabs_visible = true;
+ bool all_tabs_in_front = false;
+ bool buttons_visible_cache = false;
+ bool menu_hovered = false;
+ int highlight_arrow = -1;
+ TabAlign align = ALIGN_CENTER;
Control *_get_tab(int p_idx) const;
int _get_top_margin() const;
mutable ObjectID popup_obj_id;
- bool drag_to_rearrange_enabled;
- bool use_hidden_tabs_for_min_size;
- int tabs_rearrange_group;
+ bool drag_to_rearrange_enabled = false;
+ bool use_hidden_tabs_for_min_size = false;
+ int tabs_rearrange_group = -1;
Vector<Ref<TextLine>> text_buf;
Vector<Control *> _get_tabs() const;
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index c156b1e6f8..4a7285a154 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -122,7 +122,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->get_command()) {
if (scrolling_enabled && buttons_visible) {
if (offset > 0) {
offset--;
@@ -131,7 +131,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->get_command()) {
if (scrolling_enabled && buttons_visible) {
if (missing_right) {
offset++;
@@ -140,7 +140,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (rb_hover != -1) {
//pressed
emit_signal("right_button_pressed", rb_hover);
@@ -150,7 +150,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
update();
}
- if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (cb_hover != -1) {
//pressed
emit_signal("tab_closed", cb_hover);
@@ -160,7 +160,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
update();
}
- if (mb->is_pressed() && (mb->get_button_index() == BUTTON_LEFT || (select_with_rmb && mb->get_button_index() == BUTTON_RIGHT))) {
+ if (mb->is_pressed() && (mb->get_button_index() == MOUSE_BUTTON_LEFT || (select_with_rmb && mb->get_button_index() == MOUSE_BUTTON_RIGHT))) {
// clicks
Point2 pos(mb->get_position().x, mb->get_position().y);
@@ -275,6 +275,9 @@ void Tabs::_notification(int p_what) {
Color font_unselected_color = get_theme_color("font_unselected_color");
Color font_disabled_color = get_theme_color("font_disabled_color");
Ref<Texture2D> close = get_theme_icon("close");
+ Color font_outline_color = get_theme_color("font_outline_color");
+ int outline_size = get_theme_constant("outline_size");
+
Vector2 size = get_size();
bool rtl = is_layout_rtl();
@@ -357,9 +360,17 @@ void Tabs::_notification(int p_what) {
}
if (rtl) {
- tabs[i].text_buf->draw(ci, Point2i(size.width - w - tabs[i].text_buf->get_size().x, sb->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - tabs[i].text_buf->get_size().y) / 2), col);
+ Vector2 text_pos = Point2i(size.width - w - tabs[i].text_buf->get_size().x, sb->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - tabs[i].text_buf->get_size().y) / 2);
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ tabs[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ }
+ tabs[i].text_buf->draw(ci, text_pos, col);
} else {
- tabs[i].text_buf->draw(ci, Point2i(w, sb->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - tabs[i].text_buf->get_size().y) / 2), col);
+ Vector2 text_pos = Point2i(w, sb->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - tabs[i].text_buf->get_size().y) / 2);
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ tabs[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ }
+ tabs[i].text_buf->draw(ci, text_pos, col);
}
w += tabs[i].size_text;
@@ -481,7 +492,6 @@ void Tabs::set_current_tab(int p_current) {
previous = current;
current = p_current;
- _change_notify("current_tab");
_update_cache();
update();
@@ -1137,27 +1147,5 @@ void Tabs::_bind_methods() {
}
Tabs::Tabs() {
- current = 0;
- previous = 0;
- tab_align = ALIGN_CENTER;
- rb_hover = -1;
- rb_pressing = false;
- highlight_arrow = -1;
-
- cb_hover = -1;
- cb_pressing = false;
- cb_displaypolicy = CLOSE_BUTTON_SHOW_NEVER;
- offset = 0;
- max_drawn_tab = 0;
-
- select_with_rmb = false;
-
- min_width = 0;
- scrolling_enabled = true;
- buttons_visible = false;
- hover = -1;
- drag_to_rearrange_enabled = false;
- tabs_rearrange_group = -1;
-
connect("mouse_exited", callable_mp(this, &Tabs::_on_mouse_exited));
}
diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h
index 4396981004..86877f4d80 100644
--- a/scene/gui/tabs.h
+++ b/scene/gui/tabs.h
@@ -63,42 +63,42 @@ private:
Ref<TextLine> text_buf;
Ref<Texture2D> icon;
- int ofs_cache;
- bool disabled;
- int size_cache;
- int size_text;
- int x_cache;
- int x_size_cache;
+ int ofs_cache = 0;
+ bool disabled = false;
+ int size_cache = 0;
+ int size_text = 0;
+ int x_cache = 0;
+ int x_size_cache = 0;
Ref<Texture2D> right_button;
Rect2 rb_rect;
Rect2 cb_rect;
};
- int offset;
- int max_drawn_tab;
- int highlight_arrow;
- bool buttons_visible;
- bool missing_right;
+ int offset = 0;
+ int max_drawn_tab = 0;
+ int highlight_arrow = -1;
+ bool buttons_visible = false;
+ bool missing_right = false;
Vector<Tab> tabs;
- int current;
- int previous;
+ int current = 0;
+ int previous = 0;
int _get_top_margin() const;
- TabAlign tab_align;
- int rb_hover;
- bool rb_pressing;
+ TabAlign tab_align = ALIGN_CENTER;
+ int rb_hover = -1;
+ bool rb_pressing = false;
- bool select_with_rmb;
+ bool select_with_rmb = false;
- int cb_hover;
- bool cb_pressing;
- CloseButtonDisplayPolicy cb_displaypolicy;
+ int cb_hover = -1;
+ bool cb_pressing = false;
+ CloseButtonDisplayPolicy cb_displaypolicy = CLOSE_BUTTON_SHOW_NEVER;
- int hover; // Hovered tab.
- int min_width;
- bool scrolling_enabled;
- bool drag_to_rearrange_enabled;
- int tabs_rearrange_group;
+ int hover = -1; // Hovered tab.
+ int min_width = 0;
+ bool scrolling_enabled = true;
+ bool drag_to_rearrange_enabled = false;
+ int tabs_rearrange_group = -1;
int get_tab_width(int p_idx) const;
void _ensure_no_over_offset();
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 81c53708ab..74c530f1b0 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
+#include "core/input/input_map.h"
#include "core/object/message_queue.h"
#include "core/object/script_language.h"
#include "core/os/keyboard.h"
@@ -202,7 +203,7 @@ void TextEdit::Text::invalidate_cache(int p_line, int p_column, const String &p_
// Apply tab align.
if (indent_size > 0) {
Vector<float> tabs;
- tabs.push_back(font->get_char_size('m', 0, font_size).width * indent_size);
+ tabs.push_back(font->get_char_size(' ', 0, font_size).width * indent_size);
text.write[p_line].data_buf->tab_align(tabs);
}
}
@@ -212,7 +213,7 @@ void TextEdit::Text::invalidate_all_lines() {
text.write[i].data_buf->set_width(width);
if (indent_size > 0) {
Vector<float> tabs;
- tabs.push_back(font->get_char_size('m', 0, font_size).width * indent_size);
+ tabs.push_back(font->get_char_size(' ', 0, font_size).width * indent_size);
text.write[i].data_buf->tab_align(tabs);
}
}
@@ -356,10 +357,10 @@ void TextEdit::_update_scrollbars() {
}
void TextEdit::_click_selection_held() {
- // Warning: is_mouse_button_pressed(BUTTON_LEFT) returns false for double+ clicks, so this doesn't work for MODE_WORD
+ // Warning: is_mouse_button_pressed(MOUSE_BUTTON_LEFT) returns false for double+ clicks, so this doesn't work for MODE_WORD
// and MODE_LINE. However, moving the mouse triggers _gui_input, which calls these functions too, so that's not a huge problem.
// I'm unsure if there's an actual fix that doesn't have a ton of side effects.
- if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode != SelectionMode::SELECTION_MODE_NONE) {
+ if (Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && selection.selecting_mode != SelectionMode::SELECTION_MODE_NONE) {
switch (selection.selecting_mode) {
case SelectionMode::SELECTION_MODE_POINTER: {
_update_selection_mode_pointer();
@@ -411,25 +412,16 @@ void TextEdit::_update_selection_mode_word() {
_get_mouse_pos(Point2i(mp.x, mp.y), row, col);
String line = text[row];
- int beg = CLAMP(col, 0, line.length());
- // If its the first selection and on whitespace make sure we grab the word instead.
- if (!selection.active) {
- while (beg > 0 && line[beg] <= 32) {
- beg--;
- }
- }
+ int cursor_pos = CLAMP(col, 0, line.length());
+ int beg = cursor_pos;
int end = beg;
- bool symbol = beg < line.length() && _is_symbol(line[beg]);
-
- // Get the word end and begin points.
- while (beg > 0 && line[beg - 1] > 32 && (symbol == _is_symbol(line[beg - 1]))) {
- beg--;
- }
- while (end < line.length() && line[end + 1] > 32 && (symbol == _is_symbol(line[end + 1]))) {
- end++;
- }
- if (end < line.length()) {
- end += 1;
+ Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(row)->get_rid());
+ for (int i = 0; i < words.size(); i++) {
+ if (words[i].x < cursor_pos && words[i].y > cursor_pos) {
+ beg = words[i].x;
+ end = words[i].y;
+ break;
+ }
}
// Initial selection.
@@ -500,7 +492,7 @@ void TextEdit::_update_minimap_click() {
int row;
_get_minimap_mouse_row(Point2i(mp.x, mp.y), row);
- if (row >= get_first_visible_line() && (row < get_last_visible_line() || row >= (text.size() - 1))) {
+ if (row >= get_first_visible_line() && (row < get_last_full_visible_line() || row >= (text.size() - 1))) {
minimap_scroll_ratio = v_scroll->get_as_ratio();
minimap_scroll_click_pos = mp.y;
can_drag_minimap = true;
@@ -816,7 +808,7 @@ void TextEdit::_notification(int p_what) {
// Get the highlighted words.
String highlighted_text = get_selection_text();
- // Check if highlighted words contains only whitespaces (tabs or spaces).
+ // Check if highlighted words contain only whitespaces (tabs or spaces).
bool only_whitespaces_highlighted = highlighted_text.strip_edges() == String();
int cursor_wrap_index = get_cursor_wrap_index();
@@ -977,6 +969,16 @@ void TextEdit::_notification(int p_what) {
}
}
+ int top_limit_y = 0;
+ int bottom_limit_y = get_size().height;
+ if (readonly) {
+ top_limit_y += cache.style_readonly->get_margin(SIDE_TOP);
+ bottom_limit_y -= cache.style_readonly->get_margin(SIDE_BOTTOM);
+ } else {
+ top_limit_y += cache.style_normal->get_margin(SIDE_TOP);
+ bottom_limit_y -= cache.style_normal->get_margin(SIDE_BOTTOM);
+ }
+
// draw main text
int row_height = get_row_height();
int line = first_visible_line;
@@ -1019,17 +1021,33 @@ void TextEdit::_notification(int p_what) {
const String &str = wrap_rows[line_wrap_index];
int char_margin = xmargin_beg - cursor.x_ofs;
- int ofs_readonly = 0;
int ofs_x = 0;
+ int ofs_y = 0;
if (readonly) {
- ofs_readonly = cache.style_readonly->get_offset().y / 2;
ofs_x = cache.style_readonly->get_offset().x / 2;
+ ofs_x -= cache.style_normal->get_offset().x / 2;
+ ofs_y = cache.style_readonly->get_offset().y / 2;
+ } else {
+ ofs_y = cache.style_normal->get_offset().y / 2;
}
- int ofs_y = (i * row_height + cache.line_spacing / 2) + ofs_readonly;
+ ofs_y += i * row_height + cache.line_spacing / 2;
ofs_y -= cursor.wrap_ofs * row_height;
ofs_y -= get_v_scroll_offset() * row_height;
+ bool clipped = false;
+ if (ofs_y + row_height < top_limit_y) {
+ // Line is outside the top margin, clip current line.
+ // Still need to go through the process to prepare color changes for next lines.
+ clipped = true;
+ }
+
+ if (ofs_y > bottom_limit_y) {
+ // Line is outside the bottom margin, clip any remaining text.
+ i = draw_amount;
+ break;
+ }
+
if (text.is_marked(line)) {
if (rtl) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end - xmargin_beg, row_height), cache.mark_color);
@@ -1039,7 +1057,7 @@ void TextEdit::_notification(int p_what) {
}
if (str.length() == 0) {
- // Draw line background if empty as we won't loop at at all.
+ // Draw line background if empty as we won't loop at all.
if (line == cursor.line && cursor_wrap_index == line_wrap_index && highlight_current_line) {
if (rtl) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), cache.current_line_color);
@@ -1050,7 +1068,7 @@ void TextEdit::_notification(int p_what) {
// Give visual indication of empty selected line.
if (selection.active && line >= selection.from_line && line <= selection.to_line && char_margin >= xmargin_beg) {
- int char_w = cache.font->get_char_size('m', 0, cache.font_size).width;
+ int char_w = cache.font->get_char_size(' ', 0, cache.font_size).width;
if (rtl) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_beg - ofs_x - char_w, ofs_y, char_w, row_height), cache.selection_color);
} else {
@@ -1091,6 +1109,9 @@ void TextEdit::_notification(int p_what) {
tl->add_string(text, cache.font, cache.font_size);
int yofs = ofs_y + (row_height - tl->get_size().y) / 2;
+ if (cache.outline_size > 0 && cache.outline_color.a > 0) {
+ tl->draw_outline(ci, Point2(gutter_offset + ofs_x, yofs), cache.outline_size, cache.outline_color);
+ }
tl->draw(ci, Point2(gutter_offset + ofs_x, yofs), get_line_gutter_item_color(line, g));
} break;
case GUTTER_TPYE_ICON: {
@@ -1147,7 +1168,7 @@ void TextEdit::_notification(int p_what) {
char_margin = size.width - char_margin - TS->shaped_text_get_size(rid).x;
}
- if (selection.active && line >= selection.from_line && line <= selection.to_line) { // Selection
+ if (!clipped && selection.active && line >= selection.from_line && line <= selection.to_line) { // Selection
int sel_from = (line > selection.from_line) ? TS->shaped_text_get_range(rid).x : selection.from_column;
int sel_to = (line < selection.to_line) ? TS->shaped_text_get_range(rid).y : selection.to_column;
Vector<Vector2> sel = TS->shaped_text_get_selection(rid, sel_from, sel_to);
@@ -1167,7 +1188,7 @@ void TextEdit::_notification(int p_what) {
}
int start = TS->shaped_text_get_range(rid).x;
- if (!search_text.is_empty()) { // Search highhlight
+ if (!clipped && !search_text.is_empty()) { // Search highhlight
int search_text_col = _get_column_pos_of_word(search_text, str, search_flags, 0);
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);
@@ -1190,7 +1211,7 @@ void TextEdit::_notification(int p_what) {
}
}
- if (highlight_all_occurrences && !only_whitespaces_highlighted && !highlighted_text.is_empty()) { // Highlight
+ 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);
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);
@@ -1212,7 +1233,7 @@ void TextEdit::_notification(int p_what) {
}
}
- if (select_identifiers_enabled && highlighted_word.length() != 0) { // Highlight word
+ if (!clipped && select_identifiers_enabled && highlighted_word.length() != 0) { // Highlight word
if (_is_char(highlighted_word[0]) || highlighted_word[0] == '.') {
int highlighted_word_col = _get_column_pos_of_word(highlighted_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
while (highlighted_word_col != -1) {
@@ -1247,6 +1268,22 @@ void TextEdit::_notification(int p_what) {
ofs_y += ldata->get_line_ascent(line_wrap_index);
int char_ofs = 0;
+ if (cache.outline_size > 0 && cache.outline_color.a > 0) {
+ for (int j = 0; j < gl_size; j++) {
+ for (int k = 0; k < glyphs[j].repeat; k++) {
+ if ((char_ofs + char_margin) >= xmargin_beg && (char_ofs + glyphs[j].advance + char_margin) <= xmargin_end) {
+ if (glyphs[j].font_rid != RID()) {
+ TS->font_draw_glyph_outline(glyphs[j].font_rid, ci, glyphs[j].font_size, cache.outline_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, cache.outline_color);
+ }
+ }
+ char_ofs += glyphs[j].advance;
+ }
+ if ((char_ofs + char_margin) >= xmargin_end) {
+ break;
+ }
+ }
+ char_ofs = 0;
+ }
for (int j = 0; j < gl_size; j++) {
if (color_map.has(glyphs[j].start)) {
current_color = color_map[glyphs[j].start].get("color");
@@ -1297,7 +1334,7 @@ void TextEdit::_notification(int p_what) {
}
for (int k = 0; k < glyphs[j].repeat; k++) {
- if ((char_ofs + char_margin) >= xmargin_beg && (char_ofs + glyphs[j].advance + char_margin) <= xmargin_end) {
+ if (!clipped && (char_ofs + char_margin) >= xmargin_beg && (char_ofs + glyphs[j].advance + char_margin) <= xmargin_end) {
if (glyphs[j].font_rid != RID()) {
TS->font_draw_glyph(glyphs[j].font_rid, ci, glyphs[j].font_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, current_color);
} else if ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
@@ -1327,7 +1364,7 @@ void TextEdit::_notification(int p_what) {
#else
int caret_width = 1;
#endif
- if (cursor.line == line && ((line_wrap_index == line_wrap_amount) || (cursor.column != TS->shaped_text_get_range(rid).y))) {
+ if (!clipped && cursor.line == line && ((line_wrap_index == line_wrap_amount) || (cursor.column != TS->shaped_text_get_range(rid).y))) {
is_cursor_line_visible = true;
cursor_pos.y = line_top_offset_y;
@@ -1380,7 +1417,7 @@ void TextEdit::_notification(int p_what) {
l_caret.size.y = h;
}
l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
- l_caret.size.x = cache.font->get_char_size('m', 0, cache.font_size).x;
+ l_caret.size.x = cache.font->get_char_size('M', 0, cache.font_size).x;
draw_rect(l_caret, cache.caret_color, false);
}
@@ -1405,7 +1442,7 @@ void TextEdit::_notification(int p_what) {
}
} else {
{
- // IME intermidiet text range.
+ // IME Intermediate text range.
Vector<Vector2> sel = TS->shaped_text_get_selection(rid, cursor.column, cursor.column + ime_text.length());
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, text_height);
@@ -1444,7 +1481,6 @@ void TextEdit::_notification(int p_what) {
}
}
}
- ofs_y += ldata->get_line_descent(line_wrap_index);
}
}
@@ -1521,7 +1557,7 @@ void TextEdit::_notification(int p_what) {
completion_rect.position.x = rect_left_border_x;
}
- if (cursor_pos.y + row_height + total_height > get_size().height) {
+ if (cursor_pos.y + row_height + total_height > get_size().height && cursor_pos.y > total_height) {
// Completion panel above the cursor line
completion_rect.position.y = cursor_pos.y - total_height;
} else {
@@ -1576,6 +1612,9 @@ void TextEdit::_notification(int p_what) {
}
tl->set_align(HALIGN_LEFT);
}
+ if (cache.outline_size > 0 && cache.outline_color.a > 0) {
+ tl->draw_outline(ci, title_pos, cache.outline_size, cache.outline_color);
+ }
tl->draw(ci, title_pos, completion_options[l].font_color);
}
@@ -1663,7 +1702,7 @@ void TextEdit::_notification(int p_what) {
}
if (has_focus()) {
- if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) {
DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos, get_viewport()->get_window_id());
}
@@ -1676,7 +1715,7 @@ void TextEdit::_notification(int p_what) {
draw_caret = true;
}
- if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) {
DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + _get_cursor_pixel_pos(false), get_viewport()->get_window_id());
}
@@ -1705,7 +1744,7 @@ void TextEdit::_notification(int p_what) {
caret_blink_timer->stop();
}
- if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ 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());
DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id());
}
@@ -1938,7 +1977,7 @@ void TextEdit::backspace_at_cursor() {
cursor_set_column(prev_column);
}
-void TextEdit::indent_right() {
+void TextEdit::indent_selected_lines_right() {
int start_line;
int end_line;
@@ -1970,7 +2009,7 @@ void TextEdit::indent_right() {
// We don't really care where selection is - we just need to know indentation level at the beginning of the line.
int left = _find_first_non_whitespace_column_of_line(line_text);
int spaces_to_add = _calculate_spaces_till_next_right_indent(left);
- // Since we will add this much spaces we want move whole selection and cursor by this much.
+ // Since we will add these many spaces, we want to move the whole selection and cursor by this much.
selection_offset = spaces_to_add;
for (int j = 0; j < spaces_to_add; j++) {
line_text = ' ' + line_text;
@@ -1990,12 +2029,12 @@ void TextEdit::indent_right() {
update();
}
-void TextEdit::indent_left() {
+void TextEdit::indent_selected_lines_left() {
int start_line;
int end_line;
// Moving cursor and selection after unindenting can get tricky because
- // changing content of line can move cursor and selection on it's own (if new line ends before previous position of either),
+ // changing content of line can move cursor and selection on its own (if new line ends before previous position of either),
// therefore we just remember initial values and at the end of the operation offset them by number of removed characters.
int removed_characters = 0;
int initial_selection_end_column = selection.to_column;
@@ -2061,6 +2100,623 @@ int TextEdit::_calculate_spaces_till_next_right_indent(int column) {
return indent_size - column % indent_size;
}
+void TextEdit::_swap_current_input_direction() {
+ if (input_direction == TEXT_DIRECTION_LTR) {
+ input_direction = TEXT_DIRECTION_RTL;
+ } else {
+ input_direction = TEXT_DIRECTION_LTR;
+ }
+ cursor_set_column(cursor.column);
+ update();
+}
+
+void TextEdit::_new_line(bool p_split_current_line, bool p_above) {
+ if (readonly) {
+ return;
+ }
+
+ String ins = "\n";
+
+ // Keep indentation.
+ int space_count = 0;
+ for (int i = 0; i < cursor.column; i++) {
+ if (text[cursor.line][i] == '\t') {
+ if (indent_using_spaces) {
+ ins += space_indent;
+ } else {
+ ins += "\t";
+ }
+ space_count = 0;
+ } else if (text[cursor.line][i] == ' ') {
+ space_count++;
+
+ if (space_count == indent_size) {
+ if (indent_using_spaces) {
+ ins += space_indent;
+ } else {
+ ins += "\t";
+ }
+ space_count = 0;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (is_folded(cursor.line)) {
+ unfold_line(cursor.line);
+ }
+
+ bool brace_indent = false;
+
+ // No need to indent if we are going upwards.
+ if (auto_indent && !p_above) {
+ // Indent once again if previous line will end with ':','{','[','(' and the line is not a comment
+ // (i.e. colon/brace precedes current cursor position).
+ if (cursor.column > 0) {
+ bool indent_char_found = false;
+ bool should_indent = false;
+ char indent_char = ':';
+ char c = text[cursor.line][cursor.column];
+
+ for (int i = 0; i < cursor.column; i++) {
+ c = text[cursor.line][i];
+ switch (c) {
+ case ':':
+ case '{':
+ case '[':
+ case '(':
+ indent_char_found = true;
+ should_indent = true;
+ indent_char = c;
+ continue;
+ }
+
+ if (indent_char_found && is_line_comment(cursor.line)) {
+ should_indent = true;
+ break;
+ } else if (indent_char_found && !_is_whitespace(c)) {
+ should_indent = false;
+ indent_char_found = false;
+ }
+ }
+
+ if (!is_line_comment(cursor.line) && should_indent) {
+ if (indent_using_spaces) {
+ ins += space_indent;
+ } else {
+ ins += "\t";
+ }
+
+ // No need to move the brace below if we are not taking the text with us.
+ char32_t closing_char = _get_right_pair_symbol(indent_char);
+ if ((closing_char != 0) && (closing_char == text[cursor.line][cursor.column])) {
+ if (p_split_current_line) {
+ brace_indent = true;
+ ins += "\n" + ins.substr(1, ins.length() - 2);
+ } else {
+ brace_indent = false;
+ ins = "\n" + ins.substr(1, ins.length() - 2);
+ }
+ }
+ }
+ }
+ }
+ begin_complex_operation();
+ bool first_line = false;
+ if (!p_split_current_line) {
+ if (p_above) {
+ if (cursor.line > 0) {
+ cursor_set_line(cursor.line - 1);
+ cursor_set_column(text[cursor.line].length());
+ } else {
+ cursor_set_column(0);
+ first_line = true;
+ }
+ } else {
+ cursor_set_column(text[cursor.line].length());
+ }
+ }
+
+ insert_text_at_cursor(ins);
+
+ if (first_line) {
+ cursor_set_line(0);
+ } else if (brace_indent) {
+ cursor_set_line(cursor.line - 1);
+ cursor_set_column(text[cursor.line].length());
+ }
+ end_complex_operation();
+}
+
+void TextEdit::_indent_right() {
+ if (readonly) {
+ return;
+ }
+
+ if (is_selection_active()) {
+ indent_selected_lines_right();
+ } else {
+ // Simple indent.
+ if (indent_using_spaces) {
+ // Insert only as much spaces as needed till next indentation level.
+ int spaces_to_add = _calculate_spaces_till_next_right_indent(cursor.column);
+ String indent_to_insert = String();
+ for (int i = 0; i < spaces_to_add; i++) {
+ indent_to_insert = ' ' + indent_to_insert;
+ }
+ _insert_text_at_cursor(indent_to_insert);
+ } else {
+ _insert_text_at_cursor("\t");
+ }
+ }
+}
+
+void TextEdit::_indent_left() {
+ if (readonly) {
+ return;
+ }
+
+ if (is_selection_active()) {
+ indent_selected_lines_left();
+ } else {
+ // Simple unindent.
+ int cc = cursor.column;
+ const String &line = text[cursor.line];
+
+ int left = _find_first_non_whitespace_column_of_line(line);
+ cc = MIN(cc, left);
+
+ while (cc < indent_size && cc < left && line[cc] == ' ') {
+ cc++;
+ }
+
+ if (cc > 0 && cc <= text[cursor.line].length()) {
+ if (text[cursor.line][cc - 1] == '\t') {
+ // Tabs unindentation.
+ _remove_text(cursor.line, cc - 1, cursor.line, cc);
+ if (cursor.column >= left) {
+ cursor_set_column(MAX(0, cursor.column - 1));
+ }
+ update();
+ } else {
+ // Spaces unindentation.
+ int spaces_to_remove = _calculate_spaces_till_next_left_indent(cc);
+ if (spaces_to_remove > 0) {
+ _remove_text(cursor.line, cc - spaces_to_remove, cursor.line, cc);
+ if (cursor.column > left - spaces_to_remove) { // Inside text?
+ cursor_set_column(MAX(0, cursor.column - spaces_to_remove));
+ }
+ update();
+ }
+ }
+ } else if (cc == 0 && line.length() > 0 && line[0] == '\t') {
+ _remove_text(cursor.line, 0, cursor.line, 1);
+ update();
+ }
+ }
+}
+
+void TextEdit::_move_cursor_left(bool p_select, bool p_move_by_word) {
+ // Handle selection
+ if (p_select) {
+ _pre_shift_selection();
+ } else {
+ deselect();
+ }
+
+ if (p_move_by_word) {
+ int cc = cursor.column;
+
+ if (cc == 0 && cursor.line > 0) {
+ cursor_set_line(cursor.line - 1);
+ cursor_set_column(text[cursor.line].length());
+ } else {
+ Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(cursor.line)->get_rid());
+ for (int i = words.size() - 1; i >= 0; i--) {
+ if (words[i].x < cc) {
+ cc = words[i].x;
+ break;
+ }
+ }
+ cursor_set_column(cc);
+ }
+ } else {
+ // If the cursor is at the start of the line, and not on the first line, move it up to the end of the previous line.
+ if (cursor.column == 0) {
+ if (cursor.line > 0) {
+ cursor_set_line(cursor.line - num_lines_from(CLAMP(cursor.line - 1, 0, text.size() - 1), -1));
+ cursor_set_column(text[cursor.line].length());
+ }
+ } else {
+ if (mid_grapheme_caret_enabled) {
+ cursor_set_column(cursor_get_column() - 1);
+ } else {
+ cursor_set_column(TS->shaped_text_prev_grapheme_pos(text.get_line_data(cursor.line)->get_rid(), cursor_get_column()));
+ }
+ }
+ }
+
+ if (p_select) {
+ _post_shift_selection();
+ }
+}
+
+void TextEdit::_move_cursor_right(bool p_select, bool p_move_by_word) {
+ // Handle selection
+ if (p_select) {
+ _pre_shift_selection();
+ } else {
+ deselect();
+ }
+
+ if (p_move_by_word) {
+ int cc = cursor.column;
+
+ if (cc == text[cursor.line].length() && cursor.line < text.size() - 1) {
+ cursor_set_line(cursor.line + 1);
+ cursor_set_column(0);
+ } else {
+ Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(cursor.line)->get_rid());
+ for (int i = 0; i < words.size(); i++) {
+ if (words[i].y > cc) {
+ cc = words[i].y;
+ break;
+ }
+ }
+ cursor_set_column(cc);
+ }
+ } else {
+ // If we are at the end of the line, move the caret to the next line down.
+ if (cursor.column == text[cursor.line].length()) {
+ if (cursor.line < text.size() - 1) {
+ cursor_set_line(cursor_get_line() + num_lines_from(CLAMP(cursor.line + 1, 0, text.size() - 1), 1), true, false);
+ cursor_set_column(0);
+ }
+ } else {
+ if (mid_grapheme_caret_enabled) {
+ cursor_set_column(cursor_get_column() + 1);
+ } else {
+ cursor_set_column(TS->shaped_text_next_grapheme_pos(text.get_line_data(cursor.line)->get_rid(), cursor_get_column()));
+ }
+ }
+ }
+
+ if (p_select) {
+ _post_shift_selection();
+ }
+}
+
+void TextEdit::_move_cursor_up(bool p_select) {
+ if (p_select) {
+ _pre_shift_selection();
+ } else {
+ deselect();
+ }
+
+ int cur_wrap_index = get_cursor_wrap_index();
+ if (cur_wrap_index > 0) {
+ cursor_set_line(cursor.line, true, false, cur_wrap_index - 1);
+ } else if (cursor.line == 0) {
+ cursor_set_column(0);
+ } else {
+ int new_line = cursor.line - num_lines_from(cursor.line - 1, -1);
+ if (line_wraps(new_line)) {
+ cursor_set_line(new_line, true, false, times_line_wraps(new_line));
+ } else {
+ cursor_set_line(new_line, true, false);
+ }
+ }
+
+ if (p_select) {
+ _post_shift_selection();
+ }
+
+ _cancel_code_hint();
+}
+
+void TextEdit::_move_cursor_down(bool p_select) {
+ if (p_select) {
+ _pre_shift_selection();
+ } else {
+ deselect();
+ }
+
+ int cur_wrap_index = get_cursor_wrap_index();
+ if (cur_wrap_index < times_line_wraps(cursor.line)) {
+ cursor_set_line(cursor.line, true, false, cur_wrap_index + 1);
+ } else if (cursor.line == get_last_unhidden_line()) {
+ cursor_set_column(text[cursor.line].length());
+ } else {
+ int new_line = cursor.line + num_lines_from(CLAMP(cursor.line + 1, 0, text.size() - 1), 1);
+ cursor_set_line(new_line, true, false, 0);
+ }
+
+ if (p_select) {
+ _post_shift_selection();
+ }
+
+ _cancel_code_hint();
+}
+
+void TextEdit::_move_cursor_to_line_start(bool p_select) {
+ if (p_select) {
+ _pre_shift_selection();
+ } else {
+ deselect();
+ }
+
+ // Move cursor column to start of wrapped row and then to start of text.
+ Vector<String> rows = get_wrap_rows_text(cursor.line);
+ int wi = get_cursor_wrap_index();
+ int row_start_col = 0;
+ for (int i = 0; i < wi; i++) {
+ row_start_col += rows[i].length();
+ }
+ if (cursor.column == row_start_col || wi == 0) {
+ // Compute whitespace symbols sequence length.
+ int current_line_whitespace_len = 0;
+ while (current_line_whitespace_len < text[cursor.line].length()) {
+ char32_t c = text[cursor.line][current_line_whitespace_len];
+ if (c != '\t' && c != ' ') {
+ break;
+ }
+ current_line_whitespace_len++;
+ }
+
+ if (cursor_get_column() == current_line_whitespace_len) {
+ cursor_set_column(0);
+ } else {
+ cursor_set_column(current_line_whitespace_len);
+ }
+ } else {
+ cursor_set_column(row_start_col);
+ }
+
+ if (p_select) {
+ _post_shift_selection();
+ }
+
+ _cancel_completion();
+ completion_hint = "";
+}
+
+void TextEdit::_move_cursor_to_line_end(bool p_select) {
+ if (p_select) {
+ _pre_shift_selection();
+ } else {
+ deselect();
+ }
+
+ // Move cursor column to end of wrapped row and then to end of text.
+ Vector<String> rows = get_wrap_rows_text(cursor.line);
+ int wi = get_cursor_wrap_index();
+ int row_end_col = -1;
+ for (int i = 0; i < wi + 1; i++) {
+ row_end_col += rows[i].length();
+ }
+ if (wi == rows.size() - 1 || cursor.column == row_end_col) {
+ cursor_set_column(text[cursor.line].length());
+ } else {
+ cursor_set_column(row_end_col);
+ }
+
+ if (p_select) {
+ _post_shift_selection();
+ }
+ _cancel_completion();
+ completion_hint = "";
+}
+
+void TextEdit::_move_cursor_page_up(bool p_select) {
+ if (p_select) {
+ _pre_shift_selection();
+ } else {
+ deselect();
+ }
+
+ int wi;
+ int n_line = cursor.line - num_lines_from_rows(cursor.line, get_cursor_wrap_index(), -get_visible_rows(), wi) + 1;
+ cursor_set_line(n_line, true, false, wi);
+
+ if (p_select) {
+ _post_shift_selection();
+ }
+
+ _cancel_completion();
+ completion_hint = "";
+}
+
+void TextEdit::_move_cursor_page_down(bool p_select) {
+ if (p_select) {
+ _pre_shift_selection();
+ } else {
+ deselect();
+ }
+
+ int wi;
+ int n_line = cursor.line + num_lines_from_rows(cursor.line, get_cursor_wrap_index(), get_visible_rows(), wi) - 1;
+ cursor_set_line(n_line, true, false, wi);
+
+ if (p_select) {
+ _post_shift_selection();
+ }
+
+ _cancel_completion();
+ completion_hint = "";
+}
+
+void TextEdit::_backspace(bool p_word, bool p_all_to_left) {
+ if (readonly) {
+ return;
+ }
+
+ if (is_selection_active()) {
+ _delete_selection();
+ return;
+ }
+ if (p_all_to_left) {
+ int cursor_current_column = cursor.column;
+ cursor.column = 0;
+ _remove_text(cursor.line, 0, cursor.line, cursor_current_column);
+ } else if (p_word) {
+ int line = cursor.line;
+ int column = cursor.column;
+
+ Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
+ for (int i = words.size() - 1; i >= 0; i--) {
+ if (words[i].x < column) {
+ column = words[i].x;
+ break;
+ }
+ }
+
+ _remove_text(line, column, cursor.line, cursor.column);
+
+ cursor_set_line(line);
+ cursor_set_column(column);
+ } else {
+ // One character.
+ if (cursor.line > 0 && is_line_hidden(cursor.line - 1)) {
+ unfold_line(cursor.line - 1);
+ }
+ backspace_at_cursor();
+ }
+}
+
+void TextEdit::_delete(bool p_word, bool p_all_to_right) {
+ if (readonly) {
+ return;
+ }
+
+ if (is_selection_active()) {
+ _delete_selection();
+ return;
+ }
+ int curline_len = text[cursor.line].length();
+
+ if (cursor.line == text.size() - 1 && cursor.column == curline_len) {
+ return; // Last line, last column: Nothing to do.
+ }
+
+ int next_line = cursor.column < curline_len ? cursor.line : cursor.line + 1;
+ int next_column;
+
+ if (p_all_to_right) {
+ // Delete everything to right of cursor
+ next_column = curline_len;
+ next_line = cursor.line;
+ } else if (p_word && cursor.column < curline_len - 1) {
+ // Delete next word to right of cursor
+ int line = cursor.line;
+ int column = cursor.column;
+
+ Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
+ for (int i = 0; i < words.size(); i++) {
+ if (words[i].y > column) {
+ column = words[i].y;
+ break;
+ }
+ }
+
+ next_line = line;
+ next_column = column;
+ } else {
+ // Delete one character
+ next_column = cursor.column < curline_len ? (cursor.column + 1) : 0;
+ if (mid_grapheme_caret_enabled) {
+ next_column = cursor.column < curline_len ? (cursor.column + 1) : 0;
+ } else {
+ next_column = cursor.column < curline_len ? TS->shaped_text_next_grapheme_pos(text.get_line_data(cursor.line)->get_rid(), (cursor.column)) : 0;
+ }
+ }
+
+ _remove_text(cursor.line, cursor.column, next_line, next_column);
+ update();
+}
+
+void TextEdit::_delete_selection() {
+ if (is_selection_active()) {
+ selection.active = false;
+ update();
+ _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
+ cursor_set_line(selection.from_line, true, false);
+ cursor_set_column(selection.from_column);
+ update();
+ }
+}
+
+void TextEdit::_move_cursor_document_start(bool p_select) {
+ if (p_select) {
+ _pre_shift_selection();
+ } else {
+ deselect();
+ }
+
+ cursor_set_line(0);
+ cursor_set_column(0);
+
+ if (p_select) {
+ _post_shift_selection();
+ }
+}
+
+void TextEdit::_move_cursor_document_end(bool p_select) {
+ if (p_select) {
+ _pre_shift_selection();
+ } else {
+ deselect();
+ }
+
+ cursor_set_line(get_last_unhidden_line(), true, false, 9999);
+ cursor_set_column(text[cursor.line].length());
+
+ if (p_select) {
+ _post_shift_selection();
+ }
+}
+
+void TextEdit::_handle_unicode_character(uint32_t unicode, bool p_had_selection, bool p_update_auto_complete) {
+ if (p_update_auto_complete) {
+ _reset_caret_blink_timer();
+ }
+
+ if (p_had_selection) {
+ _delete_selection();
+ }
+
+ // Remove the old character if in insert mode and no selection.
+ if (insert_mode && !p_had_selection) {
+ begin_complex_operation();
+
+ // Make sure we don't try and remove empty space.
+ if (cursor.column < get_line(cursor.line).length()) {
+ _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1);
+ }
+ }
+
+ const char32_t chr[2] = { (char32_t)unicode, 0 };
+
+ // Clear completion hint when function closed
+ if (completion_hint != "" && unicode == ')') {
+ completion_hint = "";
+ }
+
+ if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) {
+ _consume_pair_symbol(chr[0]);
+ } else {
+ _insert_text_at_cursor(chr);
+ }
+
+ if ((insert_mode && !p_had_selection) || (selection.active != p_had_selection)) {
+ end_complex_operation();
+ }
+
+ if (p_update_auto_complete) {
+ _update_completion_candidates();
+ }
+}
+
void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) const {
float rows = p_mouse.y;
rows -= cache.style_normal->get_margin(SIDE_TOP);
@@ -2091,6 +2747,18 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co
} else {
int colx = p_mouse.x - (cache.style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding);
colx += cursor.x_ofs;
+ col = get_char_pos_for_line(colx, row, wrap_index);
+ if (is_wrap_enabled() && wrap_index < times_line_wraps(row)) {
+ // Move back one if we are at the end of the row.
+ Vector<String> rows2 = get_wrap_rows_text(row);
+ int row_end_col = 0;
+ for (int i = 0; i < wrap_index + 1; i++) {
+ row_end_col += rows2[i].length();
+ }
+ if (col >= row_end_col) {
+ col -= 1;
+ }
+ }
RID text_rid = text.get_line_data(row)->get_line_rid(wrap_index);
if (is_layout_rtl()) {
@@ -2205,14 +2873,14 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
return;
}
- if (mb->get_button_index() == BUTTON_WHEEL_UP) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
if (completion_index > 0) {
completion_index--;
completion_current = completion_options[completion_index];
update();
}
}
- if (mb->get_button_index() == BUTTON_WHEEL_DOWN) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
if (completion_index < completion_options.size() - 1) {
completion_index++;
completion_current = completion_options[completion_index];
@@ -2220,7 +2888,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
completion_index = CLAMP(completion_line_ofs + (mpos.y - completion_rect.position.y) / get_row_height(), 0, completion_options.size() - 1);
completion_current = completion_options[completion_index];
@@ -2236,27 +2904,27 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
if (mb->is_pressed()) {
- if (mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->get_command()) {
if (mb->get_shift()) {
h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor()));
} else if (v_scroll->is_visible()) {
_scroll_up(3 * mb->get_factor());
}
}
- if (mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->get_command()) {
if (mb->get_shift()) {
h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor()));
} else if (v_scroll->is_visible()) {
_scroll_down(3 * mb->get_factor());
}
}
- if (mb->get_button_index() == BUTTON_WHEEL_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT) {
h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor()));
}
- if (mb->get_button_index() == BUTTON_WHEEL_RIGHT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT) {
h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor()));
}
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
_reset_caret_blink_timer();
int row, col;
@@ -2296,7 +2964,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
int prev_col = cursor.column;
int prev_line = cursor.line;
- cursor_set_line(row, true, false);
+ cursor_set_line(row, false, false);
cursor_set_column(col);
if (mb->get_shift() && (cursor.column != prev_col || cursor.line != prev_line)) {
@@ -2321,8 +2989,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
} else {
if (cursor.line < selection.selecting_line || (cursor.line == selection.selecting_line && cursor.column < selection.selecting_column)) {
if (selection.shiftclick_left) {
- SWAP(selection.from_column, selection.to_column);
- SWAP(selection.from_line, selection.to_line);
selection.shiftclick_left = !selection.shiftclick_left;
}
selection.from_column = cursor.column;
@@ -2343,7 +3009,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
update();
}
-
} else {
selection.active = false;
selection.selecting_mode = SelectionMode::SELECTION_MODE_POINTER;
@@ -2366,7 +3031,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
update();
}
- if (mb->get_button_index() == BUTTON_RIGHT && context_menu_enabled) {
+ if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && context_menu_enabled) {
_reset_caret_blink_timer();
int row, col;
@@ -2392,12 +3057,12 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
menu->set_position(get_screen_transform().xform(mpos));
menu->set_size(Vector2(1, 1));
- // menu->set_scale(get_global_transform().get_scale());
+ _generate_context_menu();
menu->popup();
grab_focus();
}
} else {
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->get_command() && highlighted_word != String()) {
int row, col;
_get_mouse_pos(Point2i(mpos.x, mpos.y), row, col);
@@ -2453,7 +3118,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
- if (mm->get_button_mask() & BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data() == Variant()) { // Ignore if dragging.
+ if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data() == Variant()) { // Ignore if dragging.
_reset_caret_blink_timer();
if (draw_minimap && !dragging_selection) {
@@ -2486,13 +3151,11 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
Ref<InputEventKey> k = p_gui_input;
if (k.is_valid()) {
- k = k->duplicate(); // It will be modified later on.
-
+ // Ctrl + Hover symbols
#ifdef OSX_ENABLED
if (k->get_keycode() == KEY_META) {
#else
if (k->get_keycode() == KEY_CONTROL) {
-
#endif
if (select_identifiers_enabled) {
if (k->is_pressed() && !dragging_minimap && !dragging_selection) {
@@ -2502,1191 +3165,347 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
set_highlighted_word(String());
}
}
+ return;
}
if (!k->is_pressed()) {
return;
}
- if (completion_active) {
- if (readonly) {
- return;
- }
-
- bool valid = true;
- if (k->get_command() || k->get_metakey()) {
- valid = false;
- }
-
- if (valid) {
- if (!k->get_alt()) {
- if (k->get_keycode() == KEY_UP) {
- if (completion_index > 0) {
- completion_index--;
- } else {
- completion_index = completion_options.size() - 1;
- }
- completion_current = completion_options[completion_index];
- update();
-
- accept_event();
- return;
- }
-
- if (k->get_keycode() == KEY_DOWN) {
- if (completion_index < completion_options.size() - 1) {
- completion_index++;
- } else {
- completion_index = 0;
- }
- completion_current = completion_options[completion_index];
- update();
-
- accept_event();
- return;
- }
-
- if (k->get_keycode() == KEY_PAGEUP) {
- completion_index -= get_theme_constant("completion_lines");
- if (completion_index < 0) {
- completion_index = 0;
- }
- completion_current = completion_options[completion_index];
- update();
- accept_event();
- return;
- }
-
- if (k->get_keycode() == KEY_PAGEDOWN) {
- completion_index += get_theme_constant("completion_lines");
- if (completion_index >= completion_options.size()) {
- completion_index = completion_options.size() - 1;
- }
- completion_current = completion_options[completion_index];
- update();
- accept_event();
- return;
- }
-
- if (k->get_keycode() == KEY_HOME && completion_index > 0) {
- completion_index = 0;
- completion_current = completion_options[completion_index];
- update();
- accept_event();
- return;
- }
-
- if (k->get_keycode() == KEY_END && completion_index < completion_options.size() - 1) {
- completion_index = completion_options.size() - 1;
- completion_current = completion_options[completion_index];
- update();
- accept_event();
- return;
- }
-
- if (k->get_keycode() == KEY_KP_ENTER || k->get_keycode() == KEY_ENTER || k->get_keycode() == KEY_TAB) {
- _confirm_completion();
- accept_event();
- return;
- }
-
- if (k->get_keycode() == KEY_BACKSPACE) {
- _reset_caret_blink_timer();
-
- backspace_at_cursor();
- _update_completion_candidates();
- accept_event();
- return;
- }
-
- if (k->get_keycode() == KEY_SHIFT) {
- accept_event();
- return;
- }
- }
-
- if (k->get_unicode() > 32) {
- _reset_caret_blink_timer();
-
- const char32_t chr[2] = { (char32_t)k->get_unicode(), 0 };
- if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) {
- _consume_pair_symbol(chr[0]);
- } else {
- // Remove the old character if in insert mode.
- if (insert_mode) {
- begin_complex_operation();
-
- // Make sure we don't try and remove empty space.
- if (cursor.column < get_line(cursor.line).length()) {
- _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1);
- }
- }
-
- _insert_text_at_cursor(chr);
-
- if (insert_mode) {
- end_complex_operation();
- }
- }
- _update_completion_candidates();
- accept_event();
-
- return;
- }
- }
-
- _cancel_completion();
- }
-
- /* TEST CONTROL FIRST! */
-
- // Some remaps for duplicate functions.
- if (k->get_command() && !k->get_shift() && !k->get_alt() && !k->get_metakey() && k->get_keycode() == KEY_INSERT) {
- k->set_keycode(KEY_C);
- }
- if (!k->get_command() && k->get_shift() && !k->get_alt() && !k->get_metakey() && k->get_keycode() == KEY_INSERT) {
- k->set_keycode(KEY_V);
- k->set_command(true);
- k->set_shift(false);
- }
-#ifdef APPLE_STYLE_KEYS
- if (k->get_control() && !k->get_shift() && !k->get_alt() && !k->get_command()) {
- uint32_t remap_key = KEY_UNKNOWN;
- switch (k->get_keycode()) {
- case KEY_F: {
- remap_key = KEY_RIGHT;
- } break;
- case KEY_B: {
- remap_key = KEY_LEFT;
- } break;
- case KEY_P: {
- remap_key = KEY_UP;
- } break;
- case KEY_N: {
- remap_key = KEY_DOWN;
- } break;
- case KEY_D: {
- remap_key = KEY_DELETE;
- } break;
- case KEY_H: {
- remap_key = KEY_BACKSPACE;
- } break;
- }
-
- if (remap_key != KEY_UNKNOWN) {
- k->set_keycode(remap_key);
- k->set_control(false);
- }
+ // If a modifier has been pressed, and nothing else, return.
+ if (k->get_keycode() == KEY_CONTROL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) {
+ return;
}
-#endif
_reset_caret_blink_timer();
+ // Allow unicode handling if:
+ // * No Modifiers are pressed (except shift)
+ bool allow_unicode_handling = !(k->get_command() || k->get_control() || k->get_alt() || k->get_metakey());
+
// Save here for insert mode, just in case it is cleared in the following section.
bool had_selection = selection.active;
- // Stuff to do when selection is active.
- if (!readonly && selection.active) {
- bool clear = false;
- bool unselect = false;
- bool dobreak = false;
-
- switch (k->get_keycode()) {
- case KEY_TAB: {
- if (k->get_shift()) {
- indent_left();
- } else {
- indent_right();
- }
- dobreak = true;
- accept_event();
- } break;
- case KEY_X:
- case KEY_C:
- // Special keys often used with control, wait.
- clear = (!k->get_command() || k->get_shift() || k->get_alt());
- break;
- case KEY_DELETE:
- if (!k->get_shift()) {
- accept_event();
- clear = true;
- dobreak = true;
- } else if (k->get_command() || k->get_alt()) {
- dobreak = true;
- }
- break;
- case KEY_BACKSPACE:
- accept_event();
- clear = true;
- dobreak = true;
- break;
- case KEY_LEFT:
- case KEY_RIGHT:
- case KEY_UP:
- case KEY_DOWN:
- case KEY_PAGEUP:
- case KEY_PAGEDOWN:
- case KEY_HOME:
- case KEY_END:
- // Ignore arrows if any modifiers are held (shift = selecting, others may be used for editor hotkeys).
- if (k->get_command() || k->get_shift() || k->get_alt()) {
- break;
- }
- unselect = true;
- break;
-
- default:
- if (k->get_unicode() >= 32 && !k->get_command() && !k->get_alt() && !k->get_metakey()) {
- clear = true;
- }
- if (auto_brace_completion_enabled && _is_pair_left_symbol(k->get_unicode())) {
- clear = false;
- }
- }
-
- if (unselect) {
- selection.active = false;
- selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE;
- update();
- }
- if (clear) {
- if (!dobreak) {
- begin_complex_operation();
- }
- selection.active = false;
- update();
- _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
- cursor_set_line(selection.from_line, true, false);
- cursor_set_column(selection.from_column);
- update();
- }
- if (dobreak) {
- return;
- }
- }
-
selection.selecting_text = false;
- bool keycode_handled = true;
-
- // Special keycode test.
-
- switch (k->get_keycode()) {
- case KEY_KP_ENTER:
- case KEY_ENTER: {
- if (readonly) {
- break;
- }
-
- String ins = "\n";
-
- // Keep indentation.
- int space_count = 0;
- for (int i = 0; i < cursor.column; i++) {
- if (text[cursor.line][i] == '\t') {
- if (indent_using_spaces) {
- ins += space_indent;
- } else {
- ins += "\t";
- }
- space_count = 0;
- } else if (text[cursor.line][i] == ' ') {
- space_count++;
-
- if (space_count == indent_size) {
- if (indent_using_spaces) {
- ins += space_indent;
- } else {
- ins += "\t";
- }
- space_count = 0;
- }
- } else {
- break;
- }
- }
-
- if (is_folded(cursor.line)) {
- unfold_line(cursor.line);
- }
-
- bool brace_indent = false;
-
- // No need to indent if we are going upwards.
- if (auto_indent && !(k->get_command() && k->get_shift())) {
- // Indent once again if previous line will end with ':','{','[','(' and the line is not a comment
- // (i.e. colon/brace precedes current cursor position).
- if (cursor.column > 0) {
- bool indent_char_found = false;
- bool should_indent = false;
- char indent_char = ':';
- char c = text[cursor.line][cursor.column];
-
- for (int i = 0; i < cursor.column; i++) {
- c = text[cursor.line][i];
- switch (c) {
- case ':':
- case '{':
- case '[':
- case '(':
- indent_char_found = true;
- should_indent = true;
- indent_char = c;
- continue;
- }
-
- if (indent_char_found && is_line_comment(cursor.line)) {
- should_indent = true;
- break;
- } else if (indent_char_found && !_is_whitespace(c)) {
- should_indent = false;
- indent_char_found = false;
- }
- }
-
- if (!is_line_comment(cursor.line) && should_indent) {
- if (indent_using_spaces) {
- ins += space_indent;
- } else {
- ins += "\t";
- }
-
- // No need to move the brace below if we are not taking the text with us.
- char32_t closing_char = _get_right_pair_symbol(indent_char);
- if ((closing_char != 0) && (closing_char == text[cursor.line][cursor.column]) && !k->get_command()) {
- brace_indent = true;
- ins += "\n" + ins.substr(1, ins.length() - 2);
- }
- }
- }
- }
- begin_complex_operation();
- bool first_line = false;
- if (k->get_command()) {
- if (k->get_shift()) {
- if (cursor.line > 0) {
- cursor_set_line(cursor.line - 1);
- cursor_set_column(text[cursor.line].length());
- } else {
- cursor_set_column(0);
- first_line = true;
- }
- } else {
- cursor_set_column(text[cursor.line].length());
- }
- }
-
- insert_text_at_cursor(ins);
-
- if (first_line) {
- cursor_set_line(0);
- } else if (brace_indent) {
- cursor_set_line(cursor.line - 1);
- cursor_set_column(text[cursor.line].length());
- }
- end_complex_operation();
- } break;
- case KEY_ESCAPE: {
- if (completion_hint != "") {
- completion_hint = "";
- update();
- } else {
- keycode_handled = false;
- }
- } break;
- case KEY_TAB: {
- if (k->get_command()) {
- break; // Avoid tab when command.
- }
-
- if (readonly) {
- break;
- }
-
- if (is_selection_active()) {
- if (k->get_shift()) {
- indent_left();
- } else {
- indent_right();
- }
- } else {
- if (k->get_shift()) {
- // Simple unindent.
- int cc = cursor.column;
- const String &line = text[cursor.line];
-
- int left = _find_first_non_whitespace_column_of_line(line);
- cc = MIN(cc, left);
-
- while (cc < indent_size && cc < left && line[cc] == ' ') {
- cc++;
- }
-
- if (cc > 0 && cc <= text[cursor.line].length()) {
- if (text[cursor.line][cc - 1] == '\t') {
- // Tabs unindentation.
- _remove_text(cursor.line, cc - 1, cursor.line, cc);
- if (cursor.column >= left) {
- cursor_set_column(MAX(0, cursor.column - 1));
- }
- update();
- } else {
- // Spaces unindentation.
- int spaces_to_remove = _calculate_spaces_till_next_left_indent(cc);
- if (spaces_to_remove > 0) {
- _remove_text(cursor.line, cc - spaces_to_remove, cursor.line, cc);
- if (cursor.column > left - spaces_to_remove) { // Inside text?
- cursor_set_column(MAX(0, cursor.column - spaces_to_remove));
- }
- update();
- }
- }
- } else if (cc == 0 && line.length() > 0 && line[0] == '\t') {
- _remove_text(cursor.line, 0, cursor.line, 1);
- update();
- }
- } else {
- // Simple indent.
- if (indent_using_spaces) {
- // Insert only as much spaces as needed till next indentation level.
- int spaces_to_add = _calculate_spaces_till_next_right_indent(cursor.column);
- String indent_to_insert = String();
- for (int i = 0; i < spaces_to_add; i++) {
- indent_to_insert = ' ' + indent_to_insert;
- }
- _insert_text_at_cursor(indent_to_insert);
- } else {
- _insert_text_at_cursor("\t");
- }
- }
- }
-
- } break;
- case KEY_BACKSPACE: {
- if (readonly) {
- break;
- }
-
-#ifdef APPLE_STYLE_KEYS
- if (k->get_alt() && cursor.column > 1) {
-#else
- if (k->get_alt()) {
- keycode_handled = false;
- break;
- } else if (k->get_command() && cursor.column > 1) {
-#endif
- int line = cursor.line;
- int column = cursor.column;
-
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
- for (int i = words.size() - 1; i >= 0; i--) {
- if (words[i].x < column) {
- column = words[i].x;
- break;
- }
- }
-
- _remove_text(line, column, cursor.line, cursor.column);
+ // Check and handle all built in shortcuts.
- cursor_set_line(line);
- cursor_set_column(column);
+ // AUTO-COMPLETE
-#ifdef APPLE_STYLE_KEYS
- } else if (k->get_command()) {
- int cursor_current_column = cursor.column;
- cursor.column = 0;
- _remove_text(cursor.line, 0, cursor.line, cursor_current_column);
-#endif
- } else {
- if (cursor.line > 0 && is_line_hidden(cursor.line - 1)) {
- unfold_line(cursor.line - 1);
- }
- backspace_at_cursor();
- }
-
- } break;
- case KEY_KP_4: {
- if (k->get_unicode() != 0) {
- keycode_handled = false;
- break;
- }
- [[fallthrough]];
- }
- case KEY_LEFT: {
- if (k->get_shift()) {
- _pre_shift_selection();
-#ifdef APPLE_STYLE_KEYS
- } else {
-#else
- } else if (!k->get_alt()) {
-#endif
- deselect();
- }
-
-#ifdef APPLE_STYLE_KEYS
- if (k->get_command()) {
- // Start at first column (it's slightly faster that way) and look for the first non-whitespace character.
- int new_cursor_pos = 0;
- for (int i = 0; i < text[cursor.line].length(); ++i) {
- if (!_is_whitespace(text[cursor.line][i])) {
- new_cursor_pos = i;
- break;
- }
- }
- if (new_cursor_pos == cursor.column) {
- // We're already at the first text character, so move to the very beginning of the line.
- cursor_set_column(0);
- } else {
- // We're somewhere to the right of the first text character; move to the first one.
- cursor_set_column(new_cursor_pos);
- }
- } else if (k->get_alt()) {
-#else
- if (k->get_alt()) {
- keycode_handled = false;
- break;
- } else if (k->get_command()) {
-#endif
- int cc = cursor.column;
-
- if (cc == 0 && cursor.line > 0) {
- cursor_set_line(cursor.line - 1);
- cursor_set_column(text[cursor.line].length());
- } else {
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(cursor.line)->get_rid());
- for (int i = words.size() - 1; i >= 0; i--) {
- if (words[i].x < cc) {
- cc = words[i].x;
- break;
- }
- }
- cursor_set_column(cc);
- }
+ if (k->is_action("ui_text_completion_query", true)) {
+ query_code_comple();
+ accept_event();
+ return;
+ }
- } else if (cursor.column == 0) {
- if (cursor.line > 0) {
- cursor_set_line(cursor.line - num_lines_from(CLAMP(cursor.line - 1, 0, text.size() - 1), -1));
- cursor_set_column(text[cursor.line].length());
- }
+ if (completion_active) {
+ if (k->is_action("ui_up", true)) {
+ if (completion_index > 0) {
+ completion_index--;
} else {
- if (mid_grapheme_caret_enabled) {
- cursor_set_column(cursor_get_column() - 1);
- } else {
- cursor_set_column(TS->shaped_text_prev_grapheme_pos(text.get_line_data(cursor.line)->get_rid(), cursor_get_column()));
- }
- }
-
- if (k->get_shift()) {
- _post_shift_selection();
+ completion_index = completion_options.size() - 1;
}
-
- } break;
- case KEY_KP_6: {
- if (k->get_unicode() != 0) {
- keycode_handled = false;
- break;
- }
- [[fallthrough]];
+ completion_current = completion_options[completion_index];
+ update();
+ accept_event();
+ return;
}
- case KEY_RIGHT: {
- if (k->get_shift()) {
- _pre_shift_selection();
-#ifdef APPLE_STYLE_KEYS
- } else {
-#else
- } else if (!k->get_alt()) {
-#endif
- deselect();
- }
-
-#ifdef APPLE_STYLE_KEYS
- if (k->get_command()) {
- cursor_set_column(text[cursor.line].length());
- } else if (k->get_alt()) {
-#else
- if (k->get_alt()) {
- keycode_handled = false;
- break;
- } else if (k->get_command()) {
-#endif
- int cc = cursor.column;
-
- if (cc == text[cursor.line].length() && cursor.line < text.size() - 1) {
- cursor_set_line(cursor.line + 1);
- cursor_set_column(0);
- } else {
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(cursor.line)->get_rid());
- for (int i = 0; i < words.size(); i++) {
- if (words[i].y > cc) {
- cc = words[i].y;
- break;
- }
- }
- cursor_set_column(cc);
- }
-
- } else if (cursor.column == text[cursor.line].length()) {
- if (cursor.line < text.size() - 1) {
- cursor_set_line(cursor_get_line() + num_lines_from(CLAMP(cursor.line + 1, 0, text.size() - 1), 1), true, false);
- cursor_set_column(0);
- }
+ if (k->is_action("ui_down", true)) {
+ if (completion_index < completion_options.size() - 1) {
+ completion_index++;
} else {
- if (mid_grapheme_caret_enabled) {
- cursor_set_column(cursor_get_column() + 1);
- } else {
- cursor_set_column(TS->shaped_text_next_grapheme_pos(text.get_line_data(cursor.line)->get_rid(), cursor_get_column()));
- }
- }
-
- if (k->get_shift()) {
- _post_shift_selection();
- }
-
- } break;
- case KEY_KP_8: {
- if (k->get_unicode() != 0) {
- keycode_handled = false;
- break;
+ completion_index = 0;
}
- [[fallthrough]];
+ completion_current = completion_options[completion_index];
+ update();
+ accept_event();
+ return;
}
- case KEY_UP: {
- if (k->get_alt()) {
- keycode_handled = false;
- break;
+ if (k->is_action("ui_page_up", true)) {
+ completion_index -= get_theme_constant("completion_lines");
+ if (completion_index < 0) {
+ completion_index = 0;
}
-#ifndef APPLE_STYLE_KEYS
- if (k->get_command()) {
-#else
- if (k->get_command() && k->get_alt()) {
-#endif
- _scroll_lines_up();
- break;
- }
-
- if (k->get_shift()) {
- _pre_shift_selection();
- }
-
-#ifdef APPLE_STYLE_KEYS
- if (k->get_command()) {
- cursor_set_line(0);
- } else
-#endif
- {
- int cur_wrap_index = get_cursor_wrap_index();
- if (cur_wrap_index > 0) {
- cursor_set_line(cursor.line, true, false, cur_wrap_index - 1);
- } else if (cursor.line == 0) {
- cursor_set_column(0);
- } else {
- int new_line = cursor.line - num_lines_from(cursor.line - 1, -1);
- if (line_wraps(new_line)) {
- cursor_set_line(new_line, true, false, times_line_wraps(new_line));
- } else {
- cursor_set_line(new_line, true, false);
- }
- }
- }
-
- if (k->get_shift()) {
- _post_shift_selection();
- }
- _cancel_code_hint();
-
- } break;
- case KEY_KP_2: {
- if (k->get_unicode() != 0) {
- keycode_handled = false;
- break;
- }
- [[fallthrough]];
+ completion_current = completion_options[completion_index];
+ update();
+ accept_event();
+ return;
}
- case KEY_DOWN: {
- if (k->get_alt()) {
- keycode_handled = false;
- break;
- }
-#ifndef APPLE_STYLE_KEYS
- if (k->get_command()) {
-#else
- if (k->get_command() && k->get_alt()) {
-#endif
- _scroll_lines_down();
- break;
- }
-
- if (k->get_shift()) {
- _pre_shift_selection();
- }
-
-#ifdef APPLE_STYLE_KEYS
- if (k->get_command()) {
- cursor_set_line(get_last_unhidden_line(), true, false, 9999);
- } else
-#endif
- {
- int cur_wrap_index = get_cursor_wrap_index();
- if (cur_wrap_index < times_line_wraps(cursor.line)) {
- cursor_set_line(cursor.line, true, false, cur_wrap_index + 1);
- } else if (cursor.line == get_last_unhidden_line()) {
- cursor_set_column(text[cursor.line].length());
- } else {
- int new_line = cursor.line + num_lines_from(CLAMP(cursor.line + 1, 0, text.size() - 1), 1);
- cursor_set_line(new_line, true, false, 0);
- }
- }
-
- if (k->get_shift()) {
- _post_shift_selection();
- }
- _cancel_code_hint();
-
- } break;
- case KEY_DELETE: {
- if (readonly) {
- break;
- }
-
- if (k->get_shift() && !k->get_command() && !k->get_alt() && is_shortcut_keys_enabled()) {
- cut();
- break;
- }
-
- int curline_len = text[cursor.line].length();
-
- if (cursor.line == text.size() - 1 && cursor.column == curline_len) {
- break; // Nothing to do.
+ if (k->is_action("ui_page_down", true)) {
+ completion_index += get_theme_constant("completion_lines");
+ if (completion_index >= completion_options.size()) {
+ completion_index = completion_options.size() - 1;
}
-
- int next_line = cursor.column < curline_len ? cursor.line : cursor.line + 1;
- int next_column;
-
-#ifdef APPLE_STYLE_KEYS
- if (k->get_alt() && cursor.column < curline_len - 1) {
-#else
- if (k->get_alt()) {
- keycode_handled = false;
- break;
- } else if (k->get_command() && cursor.column < curline_len - 1) {
-#endif
-
- int line = cursor.line;
- int column = cursor.column;
-
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
- for (int i = 0; i < words.size(); i++) {
- if (words[i].y > column) {
- column = words[i].y;
- break;
- }
- }
-
- next_line = line;
- next_column = column;
-#ifdef APPLE_STYLE_KEYS
- } else if (k->get_command()) {
- next_column = curline_len;
- next_line = cursor.line;
-#endif
- } else {
- if (mid_grapheme_caret_enabled) {
- next_column = cursor.column < curline_len ? (cursor.column + 1) : 0;
- } else {
- next_column = cursor.column < curline_len ? TS->shaped_text_next_grapheme_pos(text.get_line_data(cursor.line)->get_rid(), (cursor.column)) : 0;
- }
- }
-
- _remove_text(cursor.line, cursor.column, next_line, next_column);
+ completion_current = completion_options[completion_index];
update();
-
- } break;
- case KEY_KP_7: {
- if (k->get_unicode() != 0) {
- keycode_handled = false;
- break;
- }
- [[fallthrough]];
+ accept_event();
+ return;
}
- case KEY_HOME: {
-#ifdef APPLE_STYLE_KEYS
- if (k->get_shift())
- _pre_shift_selection();
-
- cursor_set_line(0);
-
- if (k->get_shift())
- _post_shift_selection();
- else if (k->get_command() || k->get_control())
- deselect();
-#else
- if (k->get_shift()) {
- _pre_shift_selection();
- }
-
- if (k->get_command()) {
- cursor_set_line(0);
- cursor_set_column(0);
- } else {
- // Move cursor column to start of wrapped row and then to start of text.
- Vector<String> rows = get_wrap_rows_text(cursor.line);
- int wi = get_cursor_wrap_index();
- int row_start_col = 0;
- for (int i = 0; i < wi; i++) {
- row_start_col += rows[i].length();
- }
- if (cursor.column == row_start_col || wi == 0) {
- // Compute whitespace symbols seq length.
- int current_line_whitespace_len = 0;
- while (current_line_whitespace_len < text[cursor.line].length()) {
- char32_t c = text[cursor.line][current_line_whitespace_len];
- if (c != '\t' && c != ' ') {
- break;
- }
- current_line_whitespace_len++;
- }
-
- if (cursor_get_column() == current_line_whitespace_len) {
- cursor_set_column(0);
- } else {
- cursor_set_column(current_line_whitespace_len);
- }
- } else {
- cursor_set_column(row_start_col);
- }
- }
-
- if (k->get_shift()) {
- _post_shift_selection();
- } else if (k->get_command() || k->get_control()) {
- deselect();
- }
- _cancel_completion();
- completion_hint = "";
-#endif
- } break;
- case KEY_KP_1: {
- if (k->get_unicode() != 0) {
- keycode_handled = false;
- break;
+ if (k->is_action("ui_home", true)) {
+ if (completion_index > 0) {
+ completion_index = 0;
+ completion_current = completion_options[completion_index];
+ update();
}
- [[fallthrough]];
+ accept_event();
+ return;
}
- case KEY_END: {
-#ifdef APPLE_STYLE_KEYS
- if (k->get_shift())
- _pre_shift_selection();
-
- cursor_set_line(get_last_unhidden_line(), true, false, 9999);
-
- if (k->get_shift())
- _post_shift_selection();
- else if (k->get_command() || k->get_control())
- deselect();
-#else
- if (k->get_shift()) {
- _pre_shift_selection();
- }
-
- if (k->get_command()) {
- cursor_set_line(get_last_unhidden_line(), true, false, 9999);
- }
-
- // Move cursor column to end of wrapped row and then to end of text.
- Vector<String> rows = get_wrap_rows_text(cursor.line);
- int wi = get_cursor_wrap_index();
- int row_end_col = -1;
- for (int i = 0; i < wi + 1; i++) {
- row_end_col += rows[i].length();
- }
- if (wi == rows.size() - 1 || cursor.column == row_end_col) {
- cursor_set_column(text[cursor.line].length());
- } else {
- cursor_set_column(row_end_col);
- }
-
- if (k->get_shift()) {
- _post_shift_selection();
- } else if (k->get_command() || k->get_control()) {
- deselect();
- }
-
- _cancel_completion();
- completion_hint = "";
-#endif
- } break;
- case KEY_KP_9: {
- if (k->get_unicode() != 0) {
- keycode_handled = false;
- break;
+ if (k->is_action("ui_end", true)) {
+ if (completion_index < completion_options.size() - 1) {
+ completion_index = completion_options.size() - 1;
+ completion_current = completion_options[completion_index];
+ update();
}
- [[fallthrough]];
+ accept_event();
+ return;
}
- case KEY_PAGEUP: {
- if (k->get_shift()) {
- _pre_shift_selection();
- }
-
- int wi;
- int n_line = cursor.line - num_lines_from_rows(cursor.line, get_cursor_wrap_index(), -get_visible_rows(), wi) + 1;
- cursor_set_line(n_line, true, false, wi);
-
- if (k->get_shift()) {
- _post_shift_selection();
- }
-
+ if (k->is_action("ui_accept", true) || k->is_action("ui_text_completion_accept", true)) {
+ _confirm_completion();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_cancel", true)) {
_cancel_completion();
- completion_hint = "";
+ accept_event();
+ return;
+ }
- } break;
- case KEY_KP_3: {
- if (k->get_unicode() != 0) {
- keycode_handled = false;
- break;
+ // Handle Unicode here (if no modifiers active) and update autocomplete.
+ if (k->get_unicode() >= 32) {
+ if (allow_unicode_handling && !readonly) {
+ _handle_unicode_character(k->get_unicode(), had_selection, true);
+ accept_event();
+ return;
}
- [[fallthrough]];
}
- case KEY_PAGEDOWN: {
- if (k->get_shift()) {
- _pre_shift_selection();
- }
-
- int wi;
- int n_line = cursor.line + num_lines_from_rows(cursor.line, get_cursor_wrap_index(), get_visible_rows(), wi) - 1;
- cursor_set_line(n_line, true, false, wi);
+ }
- if (k->get_shift()) {
- _post_shift_selection();
- }
+ // NEWLINES.
+ if (k->is_action("ui_text_newline_above", true)) {
+ _new_line(false, true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_newline_blank", true)) {
+ _new_line(false);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_newline", true)) {
+ _new_line();
+ accept_event();
+ return;
+ }
- _cancel_completion();
- completion_hint = "";
+ // INDENTATION.
+ if (k->is_action("ui_text_dedent", true)) {
+ _indent_left();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_indent", true)) {
+ _indent_right();
+ accept_event();
+ return;
+ }
- } break;
- case KEY_A: {
-#ifndef APPLE_STYLE_KEYS
- if (!k->get_control() || k->get_shift() || k->get_alt()) {
- keycode_handled = false;
- break;
- }
- if (is_shortcut_keys_enabled()) {
- select_all();
- }
-#else
- if ((!k->get_command() && !k->get_control())) {
- keycode_handled = false;
- break;
- }
- if (!k->get_shift() && k->get_command() && is_shortcut_keys_enabled())
- select_all();
- else if (k->get_control()) {
- if (k->get_shift())
- _pre_shift_selection();
-
- int current_line_whitespace_len = 0;
- while (current_line_whitespace_len < text[cursor.line].length()) {
- char32_t c = text[cursor.line][current_line_whitespace_len];
- if (c != '\t' && c != ' ')
- break;
- current_line_whitespace_len++;
- }
+ // BACKSPACE AND DELETE.
+ if (k->is_action("ui_text_backspace_all_to_left", true)) {
+ _backspace(false, true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_backspace_word", true)) {
+ _backspace(true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_backspace", true)) {
+ _backspace();
+ if (completion_active) {
+ _update_completion_candidates();
+ }
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_delete_all_to_right", true)) {
+ _delete(false, true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_delete_word", true)) {
+ _delete(true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_delete", true)) {
+ _delete();
+ accept_event();
+ return;
+ }
- if (cursor_get_column() == current_line_whitespace_len)
- cursor_set_column(0);
- else
- cursor_set_column(current_line_whitespace_len);
+ // SCROLLING.
+ if (k->is_action("ui_text_scroll_up", true)) {
+ _scroll_lines_up();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_scroll_down", true)) {
+ _scroll_lines_down();
+ accept_event();
+ return;
+ }
- if (k->get_shift())
- _post_shift_selection();
- else if (k->get_command() || k->get_control())
- deselect();
- }
- } break;
- case KEY_E: {
- if (!k->get_control() || k->get_command() || k->get_alt()) {
- keycode_handled = false;
- break;
- }
+ // SELECT ALL, CUT, COPY, PASTE.
- if (k->get_shift())
- _pre_shift_selection();
+ if (k->is_action("ui_text_select_all", true)) {
+ select_all();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_cut", true)) {
+ cut();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_copy", true)) {
+ copy();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_paste", true)) {
+ paste();
+ accept_event();
+ return;
+ }
- if (k->get_command())
- cursor_set_line(text.size() - 1, true, false);
- cursor_set_column(text[cursor.line].length());
+ // UNDO/REDO.
+ if (k->is_action("ui_undo", true)) {
+ undo();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_redo", true)) {
+ redo();
+ accept_event();
+ return;
+ }
- if (k->get_shift())
- _post_shift_selection();
- else if (k->get_command() || k->get_control())
- deselect();
+ // MISC.
- _cancel_completion();
+ if (k->is_action("ui_menu", true)) {
+ if (context_menu_enabled) {
+ menu->set_position(get_screen_transform().xform(_get_cursor_pixel_pos()));
+ menu->set_size(Vector2(1, 1));
+ _generate_context_menu();
+ menu->popup();
+ menu->grab_focus();
+ }
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_toggle_insert_mode", true)) {
+ set_insert_mode(!insert_mode);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_cancel", true)) {
+ if (completion_hint != "") {
completion_hint = "";
-#endif
- } break;
- case (KEY_QUOTELEFT): { // Swap current input direction (primary cursor)
- if (!k->get_command()) {
- keycode_handled = false;
- break;
- }
-
- if (input_direction == TEXT_DIRECTION_LTR) {
- input_direction = TEXT_DIRECTION_RTL;
- } else {
- input_direction = TEXT_DIRECTION_LTR;
- }
- cursor_set_column(cursor.column);
update();
- } break;
- case KEY_X: {
- if (readonly) {
- break;
- }
- if (!k->get_command() || k->get_shift() || k->get_alt()) {
- keycode_handled = false;
- break;
- }
- if (is_shortcut_keys_enabled()) {
- cut();
- }
-
- } break;
- case KEY_C: {
- if (!k->get_command() || k->get_shift() || k->get_alt()) {
- keycode_handled = false;
- break;
- }
-
- if (is_shortcut_keys_enabled()) {
- copy();
- }
-
- } break;
- case KEY_Z: {
- if (readonly) {
- break;
- }
-
- if (!k->get_command()) {
- keycode_handled = false;
- break;
- }
-
- if (is_shortcut_keys_enabled()) {
- if (k->get_shift()) {
- redo();
- } else {
- undo();
- }
- }
- } break;
- case KEY_Y: {
- if (readonly) {
- break;
- }
-
- if (!k->get_command()) {
- keycode_handled = false;
- break;
- }
-
- if (is_shortcut_keys_enabled()) {
- redo();
- }
- } break;
- case KEY_V: {
- if (readonly) {
- break;
- }
- if (!k->get_command() || k->get_shift() || k->get_alt()) {
- keycode_handled = false;
- break;
- }
-
- if (is_shortcut_keys_enabled()) {
- paste();
- }
-
- } break;
- case KEY_SPACE: {
-#ifdef OSX_ENABLED
- if (completion_enabled && k->get_metakey()) { // cmd-space is spotlight shortcut in OSX
-#else
- if (completion_enabled && k->get_command()) {
-#endif
-
- query_code_comple();
- keycode_handled = true;
- } else {
- keycode_handled = false;
- }
+ }
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_swap_input_direction", true)) {
+ _swap_current_input_direction();
+ accept_event();
+ return;
+ }
- } break;
+ // CURSOR MOVEMENT
- case KEY_MENU: {
- if (context_menu_enabled) {
- menu->set_position(get_screen_transform().xform(_get_cursor_pixel_pos()));
- menu->set_size(Vector2(1, 1));
- menu->popup();
- menu->grab_focus();
- }
- } break;
+ k = k->duplicate();
+ bool shift_pressed = k->get_shift();
+ // Remove shift or else actions will not match. Use above variable for selection.
+ k->set_shift(false);
- default: {
- keycode_handled = false;
- } break;
+ // CURSOR MOVEMENT - LEFT, RIGHT.
+ if (k->is_action("ui_text_caret_word_left", true)) {
+ _move_cursor_left(shift_pressed, true);
+ accept_event();
+ return;
}
-
- if (keycode_handled) {
+ if (k->is_action("ui_text_caret_left", true)) {
+ _move_cursor_left(shift_pressed, false);
accept_event();
+ return;
}
-
- if (k->get_keycode() == KEY_INSERT) {
- set_insert_mode(!insert_mode);
+ if (k->is_action("ui_text_caret_word_right", true)) {
+ _move_cursor_right(shift_pressed, true);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_caret_right", true)) {
+ _move_cursor_right(shift_pressed, false);
accept_event();
return;
}
- if (!keycode_handled && !k->get_command()) { // For German keyboards.
-
- if (k->get_unicode() >= 32) {
- if (readonly) {
- return;
- }
-
- // Remove the old character if in insert mode and no selection.
- if (insert_mode && !had_selection) {
- begin_complex_operation();
-
- // Make sure we don't try and remove empty space.
- if (cursor.column < get_line(cursor.line).length()) {
- _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1);
- }
- }
-
- const char32_t chr[2] = { (char32_t)k->get_unicode(), 0 };
+ // CURSOR MOVEMENT - UP, DOWN.
+ if (k->is_action("ui_text_caret_up", true)) {
+ _move_cursor_up(shift_pressed);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_caret_down", true)) {
+ _move_cursor_down(shift_pressed);
+ accept_event();
+ return;
+ }
- if (completion_hint != "" && k->get_unicode() == ')') {
- completion_hint = "";
- }
- if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) {
- _consume_pair_symbol(chr[0]);
- } else {
- _insert_text_at_cursor(chr);
- }
+ // CURSOR MOVEMENT - DOCUMENT START/END.
+ if (k->is_action("ui_text_caret_document_start", true)) { // && shift_pressed) {
+ _move_cursor_document_start(shift_pressed);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_caret_document_end", true)) { // && shift_pressed) {
+ _move_cursor_document_end(shift_pressed);
+ accept_event();
+ return;
+ }
- if (insert_mode && !had_selection) {
- end_complex_operation();
- }
+ // CURSOR MOVEMENT - LINE START/END.
+ if (k->is_action("ui_text_caret_line_start", true)) {
+ _move_cursor_to_line_start(shift_pressed);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_caret_line_end", true)) {
+ _move_cursor_to_line_end(shift_pressed);
+ accept_event();
+ return;
+ }
- if (selection.active != had_selection) {
- end_complex_operation();
- }
- accept_event();
- }
+ // CURSOR MOVEMENT - PAGE UP/DOWN.
+ if (k->is_action("ui_text_caret_page_up", true)) {
+ _move_cursor_page_up(shift_pressed);
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_caret_page_down", true)) {
+ _move_cursor_page_down(shift_pressed);
+ accept_event();
+ return;
}
- return;
+ if (allow_unicode_handling && !readonly && k->get_unicode() >= 32) {
+ // Handle Unicode (if no modifiers active).
+ _handle_unicode_character(k->get_unicode(), had_selection, false);
+ accept_event();
+ return;
+ }
}
}
@@ -3775,8 +3594,8 @@ void TextEdit::_scroll_lines_up() {
if (!selection.active) {
int cur_line = cursor.line;
int cur_wrap = get_cursor_wrap_index();
- int last_vis_line = get_last_visible_line();
- int last_vis_wrap = get_last_visible_line_wrap_index();
+ int last_vis_line = get_last_full_visible_line();
+ int last_vis_wrap = get_last_full_visible_line_wrap_index();
if (cur_line > last_vis_line || (cur_line == last_vis_line && cur_wrap > last_vis_wrap)) {
cursor_set_line(last_vis_line, false, false, last_vis_wrap);
@@ -4062,25 +3881,50 @@ int TextEdit::_get_control_height() const {
return control_height;
}
+int TextEdit::_get_menu_action_accelerator(const String &p_action) {
+ const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(p_action);
+ if (!events) {
+ return 0;
+ }
+
+ // Use first event in the list for the accelerator.
+ const List<Ref<InputEvent>>::Element *first_event = events->front();
+ if (!first_event) {
+ return 0;
+ }
+
+ const Ref<InputEventKey> event = first_event->get();
+ if (event.is_null()) {
+ return 0;
+ }
+
+ // Use physical keycode if non-zero
+ if (event->get_physical_keycode() != 0) {
+ return event->get_physical_keycode_with_modifiers();
+ } else {
+ return event->get_keycode_with_modifiers();
+ }
+}
+
void TextEdit::_generate_context_menu() {
// Reorganize context menu.
menu->clear();
if (!readonly) {
- menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_X : 0);
+ menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : 0);
}
- menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_C : 0);
+ menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : 0);
if (!readonly) {
- menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_V : 0);
+ menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : 0);
}
menu->add_separator();
if (is_selecting_enabled()) {
- menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_A : 0);
+ menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : 0);
}
if (!readonly) {
menu->add_item(RTR("Clear"), MENU_CLEAR);
menu->add_separator();
- menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_Z : 0);
- menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z : 0);
+ menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : 0);
+ menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0);
}
menu->add_separator();
menu->add_submenu_item(RTR("Text writing direction"), "DirMenu");
@@ -4149,8 +3993,8 @@ void TextEdit::adjust_viewport_to_cursor() {
int first_vis_line = get_first_visible_line();
int first_vis_wrap = cursor.wrap_ofs;
- int last_vis_line = get_last_visible_line();
- int last_vis_wrap = get_last_visible_line_wrap_index();
+ int last_vis_line = get_last_full_visible_line();
+ int last_vis_wrap = get_last_full_visible_line_wrap_index();
if (cur_line < first_vis_line || (cur_line == first_vis_line && cur_wrap < first_vis_wrap)) {
// Cursor is above screen.
@@ -4919,6 +4763,8 @@ void TextEdit::_update_caches() {
cache.completion_font_color = get_theme_color("completion_font_color");
cache.font = get_theme_font("font");
cache.font_size = get_theme_font_size("font_size");
+ cache.outline_color = get_theme_color("font_outline_color");
+ cache.outline_size = get_theme_constant("outline_size");
cache.caret_color = get_theme_color("caret_color");
cache.caret_background_color = get_theme_color("caret_background_color");
cache.font_color = get_theme_color("font_color");
@@ -5168,6 +5014,10 @@ void TextEdit::set_auto_indent(bool p_auto_indent) {
}
void TextEdit::cut() {
+ if (readonly) {
+ return;
+ }
+
if (!selection.active) {
String clipboard = text[cursor.line];
DisplayServer::get_singleton()->clipboard_set(clipboard);
@@ -5215,6 +5065,10 @@ void TextEdit::copy() {
}
void TextEdit::paste() {
+ if (readonly) {
+ return;
+ }
+
String clipboard = DisplayServer::get_singleton()->clipboard_get();
begin_complex_operation();
@@ -5918,6 +5772,10 @@ void TextEdit::_clear_redo() {
}
void TextEdit::undo() {
+ if (readonly) {
+ return;
+ }
+
_push_current_op();
if (undo_stack_pos == nullptr) {
@@ -5968,6 +5826,9 @@ void TextEdit::undo() {
}
void TextEdit::redo() {
+ if (readonly) {
+ return;
+ }
_push_current_op();
if (undo_stack_pos == nullptr) {
@@ -6128,7 +5989,7 @@ double TextEdit::get_scroll_pos_for_line(int p_line, int p_wrap_index) const {
}
// Count the number of visible lines up to this line.
- double new_line_scroll_pos = 0;
+ double new_line_scroll_pos = 0.0;
int to = CLAMP(p_line, 0, text.size() - 1);
for (int i = 0; i < to; i++) {
if (!text.is_hidden(i)) {
@@ -6163,19 +6024,19 @@ int TextEdit::get_first_visible_line() const {
return CLAMP(cursor.line_ofs, 0, text.size() - 1);
}
-int TextEdit::get_last_visible_line() const {
+int TextEdit::get_last_full_visible_line() const {
int first_vis_line = get_first_visible_line();
int last_vis_line = 0;
int wi;
- last_vis_line = first_vis_line + num_lines_from_rows(first_vis_line, cursor.wrap_ofs, get_visible_rows() + 1, wi) - 1;
+ last_vis_line = first_vis_line + num_lines_from_rows(first_vis_line, cursor.wrap_ofs, get_visible_rows(), wi) - 1;
last_vis_line = CLAMP(last_vis_line, 0, text.size() - 1);
return last_vis_line;
}
-int TextEdit::get_last_visible_line_wrap_index() const {
+int TextEdit::get_last_full_visible_line_wrap_index() const {
int first_vis_line = get_first_visible_line();
int wi;
- num_lines_from_rows(first_vis_line, cursor.wrap_ofs, get_visible_rows() + 1, wi);
+ num_lines_from_rows(first_vis_line, cursor.wrap_ofs, get_visible_rows(), wi);
return wi;
}
@@ -6906,7 +6767,7 @@ bool TextEdit::_set(const StringName &p_name, const Variant &p_value) {
update();
}
}
- _change_notify();
+ notify_property_list_changed();
return true;
}
@@ -7205,23 +7066,11 @@ void TextEdit::_bind_methods() {
}
TextEdit::TextEdit() {
- setting_row = false;
- draw_tabs = false;
- draw_spaces = false;
- override_selected_font_color = false;
- draw_caret = true;
- max_chars = 0;
clear();
- wrap_enabled = false;
- wrap_at = 0;
- wrap_right_offset = 10;
set_focus_mode(FOCUS_ALL);
_update_caches();
- cache.line_spacing = 1;
- cache.font_size = 16;
set_default_cursor_shape(CURSOR_IBEAM);
- indent_size = 4;
text.set_indent_size(indent_size);
text.clear();
@@ -7231,31 +7080,16 @@ TextEdit::TextEdit() {
add_child(h_scroll);
add_child(v_scroll);
- updating_scrolls = false;
- selection.active = false;
-
h_scroll->connect("value_changed", callable_mp(this, &TextEdit::_scroll_moved));
v_scroll->connect("value_changed", callable_mp(this, &TextEdit::_scroll_moved));
v_scroll->connect("scrolling", callable_mp(this, &TextEdit::_v_scroll_input));
- cursor_changed_dirty = false;
- text_changed_dirty = false;
-
- selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE;
- selection.selecting_line = 0;
- selection.selecting_column = 0;
- selection.selecting_text = false;
- selection.active = false;
-
- block_caret = false;
- caret_blink_enabled = false;
caret_blink_timer = memnew(Timer);
add_child(caret_blink_timer);
caret_blink_timer->set_wait_time(0.65);
caret_blink_timer->connect("timeout", callable_mp(this, &TextEdit::_toggle_draw_caret));
cursor_set_blink_enabled(false);
- right_click_moves_caret = true;
idle_detect = memnew(Timer);
add_child(idle_detect);
@@ -7268,54 +7102,8 @@ TextEdit::TextEdit() {
click_select_held->set_wait_time(0.05);
click_select_held->connect("timeout", callable_mp(this, &TextEdit::_click_selection_held));
- current_op.type = TextOperation::TYPE_NONE;
- undo_enabled = true;
undo_stack_max_size = GLOBAL_GET("gui/common/text_edit_undo_stack_max_size");
- undo_stack_pos = nullptr;
- setting_text = false;
- last_dblclk = 0;
- current_op.version = 0;
- version = 0;
- saved_version = 0;
- completion_enabled = false;
- completion_active = false;
- completion_line_ofs = 0;
- tooltip_obj = nullptr;
- line_length_guidelines = false;
- line_length_guideline_soft_col = 80;
- line_length_guideline_hard_col = 100;
- hiding_enabled = false;
- next_operation_is_complex = false;
- scroll_past_end_of_file_enabled = false;
- auto_brace_completion_enabled = false;
- brace_matching_enabled = false;
- highlight_all_occurrences = false;
- highlight_current_line = false;
- indent_using_spaces = false;
- space_indent = " ";
- auto_indent = false;
- insert_mode = false;
- window_has_focus = true;
- select_identifiers_enabled = false;
- smooth_scroll_enabled = false;
- scrolling = false;
- minimap_clicked = false;
- dragging_minimap = false;
- can_drag_minimap = false;
- minimap_scroll_ratio = 0;
- minimap_scroll_click_pos = 0;
- dragging_selection = false;
- target_v_scroll = 0;
- v_scroll_speed = 80;
- draw_minimap = false;
- minimap_width = 80;
- minimap_char_size = Point2(1, 2);
- minimap_line_spacing = 1;
-
- selecting_enabled = true;
- context_menu_enabled = true;
- shortcut_keys_enabled = true;
menu = memnew(PopupMenu);
add_child(menu);
@@ -7350,12 +7138,10 @@ TextEdit::TextEdit() {
menu_ctl->add_item(RTR("Soft hyphen (SHY)"), MENU_INSERT_SHY);
menu->add_child(menu_ctl);
- readonly = true; // Initialise to opposite first, so we get past the early-out in set_readonly.
set_readonly(false);
menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
menu_dir->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
menu_ctl->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
- first_draw = true;
}
TextEdit::~TextEdit() {
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index dc811059c8..b0c7314c65 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -92,14 +92,11 @@ private:
Vector<Vector2i> bidi_override;
Ref<TextParagraph> data_buf;
- bool marked;
- bool hidden;
+ bool marked = false;
+ bool hidden = false;
Line() {
data_buf.instance();
-
- marked = false;
- hidden = false;
}
};
@@ -173,46 +170,31 @@ private:
};
struct Cursor {
- int last_fit_x;
- int line, column; ///< cursor
- int x_ofs, line_ofs, wrap_ofs;
- Cursor() {
- last_fit_x = 0;
- line = 0;
- column = 0; ///< cursor
- x_ofs = 0;
- line_ofs = 0;
- wrap_ofs = 0;
- }
+ int last_fit_x = 0;
+ int line = 0;
+ int column = 0; ///< cursor
+ int x_ofs = 0;
+ int line_ofs = 0;
+ int wrap_ofs = 0;
} cursor;
struct Selection {
- SelectionMode selecting_mode;
- int selecting_line, selecting_column;
- int selected_word_beg, selected_word_end, selected_word_origin;
- bool selecting_text;
-
- bool active;
-
- int from_line, from_column;
- int to_line, to_column;
-
- bool shiftclick_left;
- Selection() {
- selecting_mode = SelectionMode::SELECTION_MODE_NONE;
- selecting_line = 0;
- selecting_column = 0;
- selected_word_beg = 0;
- selected_word_end = 0;
- selected_word_origin = 0;
- selecting_text = false;
- active = false;
- from_line = 0;
- from_column = 0;
- to_line = 0;
- to_column = 0;
- shiftclick_left = false;
- }
+ SelectionMode selecting_mode = SelectionMode::SELECTION_MODE_NONE;
+ int selecting_line = 0;
+ int selecting_column = 0;
+ int selected_word_beg = 0;
+ int selected_word_end = 0;
+ int selected_word_origin = 0;
+ bool selecting_text = false;
+
+ bool active = false;
+
+ int from_line = 0;
+ int from_column = 0;
+ int to_line = 0;
+ int to_column = 0;
+
+ bool shiftclick_left = false;
} selection;
Map<int, Dictionary> syntax_highlighting_cache;
@@ -224,25 +206,16 @@ private:
TYPE_REMOVE
};
- Type type;
- int from_line, from_column;
- int to_line, to_column;
+ Type type = TYPE_NONE;
+ int from_line = 0;
+ int from_column = 0;
+ int to_line = 0;
+ int to_column = 0;
String text;
- uint32_t prev_version;
- uint32_t version;
- bool chain_forward;
- bool chain_backward;
- TextOperation() {
- type = TYPE_NONE;
- from_line = 0;
- from_column = 0;
- to_line = 0;
- to_column = 0;
- prev_version = 0;
- version = 0;
- chain_forward = false;
- chain_backward = false;
- }
+ uint32_t prev_version = 0;
+ uint32_t version = 0;
+ bool chain_forward = false;
+ bool chain_backward = false;
};
String ime_text;
@@ -251,7 +224,7 @@ private:
TextOperation current_op;
List<TextOperation> undo_stack;
- List<TextOperation>::Element *undo_stack_pos;
+ List<TextOperation>::Element *undo_stack_pos = nullptr;
int undo_stack_max_size;
void _clear_redo();
@@ -264,20 +237,20 @@ private:
Dictionary _get_line_syntax_highlighting(int p_line);
Set<String> completion_prefixes;
- bool completion_enabled;
+ bool completion_enabled = false;
List<ScriptCodeCompletionOption> completion_sources;
Vector<ScriptCodeCompletionOption> completion_options;
- bool completion_active;
- bool completion_forced;
+ bool completion_active = false;
+ bool completion_forced = false;
ScriptCodeCompletionOption completion_current;
String completion_base;
- int completion_index;
+ int completion_index = 0;
Rect2i completion_rect;
- int completion_line_ofs;
+ int completion_line_ofs = 0;
String completion_hint;
- int completion_hint_offset;
+ int completion_hint_offset = 0;
- bool setting_text;
+ bool setting_text = false;
// data
Text text;
@@ -290,93 +263,93 @@ private:
Array st_args;
bool draw_control_chars = false;
- uint32_t version;
- uint32_t saved_version;
+ uint32_t version = 0;
+ uint32_t saved_version = 0;
- int max_chars;
- bool readonly;
- bool indent_using_spaces;
- int indent_size;
- String space_indent;
+ int max_chars = 0;
+ bool readonly = true; // Initialise to opposite first, so we get past the early-out in set_readonly.
+ bool indent_using_spaces = false;
+ int indent_size = 4;
+ String space_indent = " ";
Timer *caret_blink_timer;
- bool caret_blink_enabled;
- bool draw_caret;
- bool window_has_focus;
- bool block_caret;
- bool right_click_moves_caret;
+ bool caret_blink_enabled = false;
+ bool draw_caret = true;
+ bool window_has_focus = true;
+ bool block_caret = false;
+ bool right_click_moves_caret = true;
bool mid_grapheme_caret_enabled = false;
- bool wrap_enabled;
- int wrap_at;
- int wrap_right_offset;
-
- bool first_draw;
- bool setting_row;
- bool draw_tabs;
- bool draw_spaces;
- bool override_selected_font_color;
- bool cursor_changed_dirty;
- bool text_changed_dirty;
- bool undo_enabled;
- bool line_length_guidelines;
- int line_length_guideline_soft_col;
- int line_length_guideline_hard_col;
- bool hiding_enabled;
- bool draw_minimap;
- int minimap_width;
- Point2 minimap_char_size;
- int minimap_line_spacing;
-
- bool highlight_all_occurrences;
- bool scroll_past_end_of_file_enabled;
- bool auto_brace_completion_enabled;
- bool brace_matching_enabled;
- bool highlight_current_line;
- bool auto_indent;
+ bool wrap_enabled = false;
+ int wrap_at = 0;
+ int wrap_right_offset = 10;
+
+ bool first_draw = true;
+ bool setting_row = false;
+ bool draw_tabs = false;
+ bool draw_spaces = false;
+ bool override_selected_font_color = false;
+ bool cursor_changed_dirty = false;
+ bool text_changed_dirty = false;
+ bool undo_enabled = true;
+ bool line_length_guidelines = false;
+ int line_length_guideline_soft_col = 80;
+ int line_length_guideline_hard_col = 100;
+ bool hiding_enabled = false;
+ bool draw_minimap = false;
+ int minimap_width = 80;
+ Point2 minimap_char_size = Point2(1, 2);
+ int minimap_line_spacing = 1;
+
+ bool highlight_all_occurrences = false;
+ bool scroll_past_end_of_file_enabled = false;
+ bool auto_brace_completion_enabled = false;
+ bool brace_matching_enabled = false;
+ bool highlight_current_line = false;
+ bool auto_indent = false;
String cut_copy_line;
- bool insert_mode;
- bool select_identifiers_enabled;
-
- bool smooth_scroll_enabled;
- bool scrolling;
- bool dragging_selection;
- bool dragging_minimap;
- bool can_drag_minimap;
- bool minimap_clicked;
- double minimap_scroll_ratio;
- double minimap_scroll_click_pos;
- float target_v_scroll;
- float v_scroll_speed;
+ bool insert_mode = false;
+ bool select_identifiers_enabled = false;
+
+ bool smooth_scroll_enabled = false;
+ bool scrolling = false;
+ bool dragging_selection = false;
+ bool dragging_minimap = false;
+ bool can_drag_minimap = false;
+ bool minimap_clicked = false;
+ double minimap_scroll_ratio = 0.0;
+ double minimap_scroll_click_pos = 0.0;
+ float target_v_scroll = 0.0;
+ float v_scroll_speed = 80.0;
String highlighted_word;
- uint64_t last_dblclk;
+ uint64_t last_dblclk = 0;
Timer *idle_detect;
Timer *click_select_held;
HScrollBar *h_scroll;
VScrollBar *v_scroll;
- bool updating_scrolls;
+ bool updating_scrolls = false;
- Object *tooltip_obj;
+ Object *tooltip_obj = nullptr;
StringName tooltip_func;
Variant tooltip_ud;
- bool next_operation_is_complex;
+ bool next_operation_is_complex = false;
- bool callhint_below;
+ bool callhint_below = false;
Vector2 callhint_offset;
String search_text;
- uint32_t search_flags;
- int search_result_line;
- int search_result_col;
+ uint32_t search_flags = 0;
+ int search_result_line = 0;
+ int search_result_col = 0;
- bool selecting_enabled;
+ bool selecting_enabled = true;
- bool context_menu_enabled;
- bool shortcut_keys_enabled;
+ bool context_menu_enabled = true;
+ bool shortcut_keys_enabled = true;
bool virtual_keyboard_enabled = true;
void _generate_context_menu();
@@ -400,8 +373,8 @@ private:
void set_line_as_center_visible(int p_line, int p_wrap_index = 0);
void set_line_as_last_visible(int p_line, int p_wrap_index = 0);
int get_first_visible_line() const;
- int get_last_visible_line() const;
- int get_last_visible_line_wrap_index() const;
+ int get_last_full_visible_line() const;
+ int get_last_full_visible_line_wrap_index() const;
double get_visible_rows_offset() const;
double get_v_scroll_offset() const;
@@ -435,6 +408,7 @@ private:
int _get_control_height() const;
Point2 _get_local_mouse_pos() const;
+ int _get_menu_action_accelerator(const String &p_action);
void _reset_caret_blink_timer();
void _toggle_draw_caret();
@@ -468,6 +442,26 @@ private:
int _calculate_spaces_till_next_left_indent(int column);
int _calculate_spaces_till_next_right_indent(int column);
+ // Methods used in shortcuts
+ void _swap_current_input_direction();
+ void _new_line(bool p_split_current = true, bool p_above = false);
+ void _indent_right();
+ void _indent_left();
+ void _move_cursor_left(bool p_select, bool p_move_by_word = false);
+ void _move_cursor_right(bool p_select, bool p_move_by_word = false);
+ void _move_cursor_up(bool p_select);
+ void _move_cursor_down(bool p_select);
+ void _move_cursor_to_line_start(bool p_select);
+ void _move_cursor_to_line_end(bool p_select);
+ void _move_cursor_page_up(bool p_select);
+ void _move_cursor_page_down(bool p_select);
+ void _backspace(bool p_word = false, bool p_all_to_left = false);
+ void _delete(bool p_word = false, bool p_all_to_right = false);
+ void _delete_selection();
+ void _move_cursor_document_start(bool p_select);
+ void _move_cursor_document_end(bool p_select);
+ void _handle_unicode_character(uint32_t unicode, bool p_had_selection, bool p_update_auto_complete);
+
protected:
struct Cache {
Ref<Texture2D> tab_icon;
@@ -477,7 +471,9 @@ protected:
Ref<StyleBox> style_focus;
Ref<StyleBox> style_readonly;
Ref<Font> font;
- int font_size;
+ int font_size = 16;
+ int outline_size = 0;
+ Color outline_color;
Color completion_background_color;
Color completion_selected_color;
Color completion_existing_color;
@@ -498,12 +494,8 @@ protected:
Color search_result_border_color;
Color background_color;
- int line_spacing;
- int minimap_width;
- Cache() {
- line_spacing = 0;
- minimap_width = 0;
- }
+ int line_spacing = 1;
+ int minimap_width = 0;
} cache;
virtual String get_tooltip(const Point2 &p_pos) const override;
@@ -668,8 +660,8 @@ public:
int get_row_height() const;
void backspace_at_cursor();
- void indent_left();
- void indent_right();
+ void indent_selected_lines_left();
+ void indent_selected_lines_right();
int get_indent_level(int p_line) const;
bool is_line_comment(int p_line) const;
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index 23c48b0906..f43e3d1a9d 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -29,7 +29,9 @@
/*************************************************************************/
#include "texture_button.h"
+
#include "core/typedefs.h"
+
#include <stdlib.h>
Size2 TextureButton::get_minimum_size() const {
@@ -247,8 +249,8 @@ void TextureButton::_bind_methods() {
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_click_mask", "mask"), &TextureButton::set_click_mask);
- ClassDB::bind_method(D_METHOD("set_expand", "p_expand"), &TextureButton::set_expand);
- ClassDB::bind_method(D_METHOD("set_stretch_mode", "p_mode"), &TextureButton::set_stretch_mode);
+ ClassDB::bind_method(D_METHOD("set_expand", "expand"), &TextureButton::set_expand);
+ ClassDB::bind_method(D_METHOD("set_stretch_mode", "mode"), &TextureButton::set_stretch_mode);
ClassDB::bind_method(D_METHOD("set_flip_h", "enable"), &TextureButton::set_flip_h);
ClassDB::bind_method(D_METHOD("is_flipped_h"), &TextureButton::is_flipped_h);
ClassDB::bind_method(D_METHOD("set_flip_v", "enable"), &TextureButton::set_flip_v);
@@ -375,13 +377,4 @@ bool TextureButton::is_flipped_v() const {
return vflip;
}
-TextureButton::TextureButton() {
- expand = false;
- stretch_mode = STRETCH_SCALE;
- hflip = false;
- vflip = false;
-
- _texture_region = Rect2();
- _position_rect = Rect2();
- _tile = false;
-}
+TextureButton::TextureButton() {}
diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h
index 4b750c3fb1..8361f3c341 100644
--- a/scene/gui/texture_button.h
+++ b/scene/gui/texture_button.h
@@ -54,15 +54,15 @@ private:
Ref<Texture2D> disabled;
Ref<Texture2D> focused;
Ref<BitMap> click_mask;
- bool expand;
- StretchMode stretch_mode;
+ bool expand = false;
+ StretchMode stretch_mode = STRETCH_SCALE;
Rect2 _texture_region;
Rect2 _position_rect;
- bool _tile;
+ bool _tile = false;
- bool hflip;
- bool vflip;
+ bool hflip = false;
+ bool vflip = false;
protected:
virtual Size2 get_minimum_size() const override;
diff --git a/scene/gui/texture_progress_bar.cpp b/scene/gui/texture_progress_bar.cpp
index 76564e2b17..46ce9d5ca9 100644
--- a/scene/gui/texture_progress_bar.cpp
+++ b/scene/gui/texture_progress_bar.cpp
@@ -145,9 +145,9 @@ Point2 TextureProgressBar::unit_val_to_uv(float val) {
float angle = (val * Math_TAU) - Math_PI * 0.5;
Point2 dir = Vector2(Math::cos(angle), Math::sin(angle));
float t1 = 1.0;
- float cp = 0;
- float cq = 0;
- float cr = 0;
+ float cp = 0.0;
+ float cq = 0.0;
+ float cr = 0.0;
float edgeLeft = 0.0;
float edgeRight = 1.0;
float edgeBottom = 0.0;
@@ -540,17 +540,5 @@ void TextureProgressBar::_bind_methods() {
}
TextureProgressBar::TextureProgressBar() {
- mode = FILL_LEFT_TO_RIGHT;
- rad_init_angle = 0;
- rad_center_off = Point2();
- rad_max_degrees = 360;
set_mouse_filter(MOUSE_FILTER_PASS);
-
- nine_patch_stretch = false;
- stretch_margin[SIDE_LEFT] = 0;
- stretch_margin[SIDE_RIGHT] = 0;
- stretch_margin[SIDE_BOTTOM] = 0;
- stretch_margin[SIDE_TOP] = 0;
-
- tint_under = tint_progress = tint_over = Color(1, 1, 1);
}
diff --git a/scene/gui/texture_progress_bar.h b/scene/gui/texture_progress_bar.h
index ee33a915f7..a3883a7017 100644
--- a/scene/gui/texture_progress_bar.h
+++ b/scene/gui/texture_progress_bar.h
@@ -98,13 +98,15 @@ public:
TextureProgressBar();
private:
- FillMode mode;
- float rad_init_angle;
- float rad_max_degrees;
+ FillMode mode = FILL_LEFT_TO_RIGHT;
+ float rad_init_angle = 0.0;
+ float rad_max_degrees = 360.0;
Point2 rad_center_off;
- bool nine_patch_stretch;
- int stretch_margin[4];
- Color tint_under, tint_progress, tint_over;
+ bool nine_patch_stretch = false;
+ int stretch_margin[4] = {};
+ Color tint_under = Color(1, 1, 1);
+ Color tint_progress = Color(1, 1, 1);
+ Color tint_over = Color(1, 1, 1);
Point2 unit_val_to_uv(float val);
Point2 get_relative_center();
diff --git a/scene/gui/texture_rect.cpp b/scene/gui/texture_rect.cpp
index beb06b7739..1cba88e06f 100644
--- a/scene/gui/texture_rect.cpp
+++ b/scene/gui/texture_rect.cpp
@@ -217,11 +217,7 @@ bool TextureRect::is_flipped_v() const {
}
TextureRect::TextureRect() {
- expand = false;
- hflip = false;
- vflip = false;
set_mouse_filter(MOUSE_FILTER_PASS);
- stretch_mode = STRETCH_SCALE_ON_EXPAND;
}
TextureRect::~TextureRect() {
diff --git a/scene/gui/texture_rect.h b/scene/gui/texture_rect.h
index 0f3172f5bd..0f93d5732f 100644
--- a/scene/gui/texture_rect.h
+++ b/scene/gui/texture_rect.h
@@ -49,11 +49,11 @@ public:
};
private:
- bool expand;
- bool hflip;
- bool vflip;
+ bool expand = false;
+ bool hflip = false;
+ bool vflip = false;
Ref<Texture2D> texture;
- StretchMode stretch_mode;
+ StretchMode stretch_mode = STRETCH_SCALE_ON_EXPAND;
void _texture_changed();
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 0049b54f50..abfea241f3 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -410,6 +410,14 @@ bool TreeItem::is_collapsed() {
return collapsed;
}
+void TreeItem::uncollapse_tree() {
+ TreeItem *t = this;
+ while (t) {
+ t->set_collapsed(false);
+ t = t->parent;
+ }
+}
+
void TreeItem::set_custom_minimum_height(int p_height) {
custom_min_height = p_height;
_changed_notify();
@@ -842,6 +850,8 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collapsed", "enable"), &TreeItem::set_collapsed);
ClassDB::bind_method(D_METHOD("is_collapsed"), &TreeItem::is_collapsed);
+ ClassDB::bind_method(D_METHOD("uncollapse_tree"), &TreeItem::uncollapse_tree);
+
ClassDB::bind_method(D_METHOD("set_custom_minimum_height", "height"), &TreeItem::set_custom_minimum_height);
ClassDB::bind_method(D_METHOD("get_custom_minimum_height"), &TreeItem::get_custom_minimum_height);
@@ -1118,7 +1128,7 @@ int Tree::get_item_height(TreeItem *p_item) const {
return height;
}
-void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color) {
+void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color) {
ERR_FAIL_COND(cache.font.is_null());
Rect2i rect = p_rect;
@@ -1160,6 +1170,9 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
Point2 draw_pos = rect.position;
draw_pos.y += Math::floor((rect.size.y - p_cell.text_buf->get_size().y) / 2.0);
p_cell.text_buf->set_width(MAX(0, rect.size.width));
+ if (p_ol_size > 0 && p_ol_color.a > 0) {
+ 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 + cache.hseparation;
rect.size.x -= ts.width + cache.hseparation;
@@ -1182,6 +1195,9 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
Point2 draw_pos = rect.position;
draw_pos.y += Math::floor((rect.size.y - p_cell.text_buf->get_size().y) / 2.0);
p_cell.text_buf->set_width(MAX(0, rect.size.width));
+ if (p_ol_size > 0 && p_ol_color.a > 0) {
+ 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);
}
}
@@ -1434,6 +1450,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_theme_color(p_item->cells[i].selected ? "font_selected_color" : "font_color");
+ Color font_outline_color = get_theme_color("font_outline_color");
+ int outline_size = get_theme_constant("outline_size");
Color icon_col = p_item->cells[i].icon_color;
if (p_item->cells[i].dirty) {
@@ -1450,7 +1468,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
switch (p_item->cells[i].mode) {
case TreeItem::CELL_MODE_STRING: {
- draw_item_rect(p_item->cells.write[i], item_rect, col, icon_col);
+ draw_item_rect(p_item->cells.write[i], item_rect, col, icon_col, outline_size, font_outline_color);
} break;
case TreeItem::CELL_MODE_CHECK: {
Ref<Texture2D> checked = cache.checked;
@@ -1471,7 +1489,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
item_rect.size.x -= check_w;
item_rect.position.x += check_w;
- draw_item_rect(p_item->cells.write[i], item_rect, col, icon_col);
+ draw_item_rect(p_item->cells.write[i], item_rect, col, icon_col, outline_size, font_outline_color);
} break;
case TreeItem::CELL_MODE_RANGE: {
@@ -1485,8 +1503,14 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
p_item->cells.write[i].text_buf->set_width(cell_width);
if (rtl) {
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ p_item->cells[i].text_buf->draw_outline(ci, text_pos + Vector2(cell_width - text_width, 0), outline_size, font_outline_color);
+ }
p_item->cells[i].text_buf->draw(ci, text_pos + Vector2(cell_width - text_width, 0), col);
} else {
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ p_item->cells[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ }
p_item->cells[i].text_buf->draw(ci, text_pos, col);
}
@@ -1501,8 +1525,14 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
int cell_width = item_rect.size.x - updown->get_width();
if (rtl) {
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ p_item->cells[i].text_buf->draw_outline(ci, text_pos + Vector2(cell_width - text_width, 0), outline_size, font_outline_color);
+ }
p_item->cells[i].text_buf->draw(ci, text_pos + Vector2(cell_width - text_width, 0), col);
} else {
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ p_item->cells[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ }
p_item->cells[i].text_buf->draw(ci, text_pos, col);
}
@@ -1543,7 +1573,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
if (!p_item->cells[i].editable) {
- draw_item_rect(p_item->cells.write[i], item_rect, col, icon_col);
+ draw_item_rect(p_item->cells.write[i], item_rect, col, icon_col, outline_size, font_outline_color);
break;
}
@@ -1558,7 +1588,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (p_item->cells[i].custom_button) {
if (cache.hover_item == p_item && cache.hover_cell == i) {
- if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+ if (Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) {
draw_style_box(cache.custom_button_pressed, ir);
} else {
draw_style_box(cache.custom_button_hover, ir);
@@ -1571,7 +1601,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
ir.position += cache.custom_button->get_offset();
}
- draw_item_rect(p_item->cells.write[i], ir, col, icon_col);
+ draw_item_rect(p_item->cells.write[i], ir, col, icon_col, outline_size, font_outline_color);
downarrow->draw(ci, arrow_pos);
@@ -1795,7 +1825,7 @@ Rect2 Tree::search_item_rect(TreeItem *p_from, TreeItem *p_item) {
}
void Tree::_range_click_timeout() {
- if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+ if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) {
Point2 pos = get_local_mouse_position() - cache.bg->get_offset();
if (show_column_titles) {
pos.y -= _get_title_button_height();
@@ -1813,7 +1843,7 @@ void Tree::_range_click_timeout() {
propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case)
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, false, root, BUTTON_LEFT, mb);
+ propagate_mouse_event(pos + cache.offset, 0, 0, false, root, MOUSE_BUTTON_LEFT, mb);
blocked--;
if (range_click_timer->is_one_shot()) {
@@ -1930,7 +1960,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
col_width -= w + cache.button_margin;
}
- if (p_button == BUTTON_LEFT || (p_button == BUTTON_RIGHT && allow_rmb_select)) {
+ if (p_button == MOUSE_BUTTON_LEFT || (p_button == MOUSE_BUTTON_RIGHT && allow_rmb_select)) {
/* process selection */
if (p_doubleclick && (!c.editable || c.mode == TreeItem::CELL_MODE_CUSTOM || c.mode == TreeItem::CELL_MODE_ICON /*|| c.mode==TreeItem::CELL_MODE_CHECK*/)) { //it's confusing for check
@@ -1942,10 +1972,10 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
}
if (select_mode == SELECT_MULTI && p_mod->get_command() && c.selectable) {
- if (!c.selected || p_button == BUTTON_RIGHT) {
+ if (!c.selected || p_button == MOUSE_BUTTON_RIGHT) {
p_item->select(col);
emit_signal("multi_selected", p_item, col, true);
- if (p_button == BUTTON_RIGHT) {
+ if (p_button == MOUSE_BUTTON_RIGHT) {
emit_signal("item_rmb_selected", get_local_mouse_position());
}
@@ -1962,21 +1992,21 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
bool inrange = false;
select_single_item(p_item, root, col, selected_item, &inrange);
- if (p_button == BUTTON_RIGHT) {
+ if (p_button == MOUSE_BUTTON_RIGHT) {
emit_signal("item_rmb_selected", get_local_mouse_position());
}
} else {
int icount = _count_selected_items(root);
- if (select_mode == SELECT_MULTI && icount > 1 && p_button != BUTTON_RIGHT) {
+ if (select_mode == SELECT_MULTI && icount > 1 && p_button != MOUSE_BUTTON_RIGHT) {
single_select_defer = p_item;
single_select_defer_column = col;
} else {
- if (p_button != BUTTON_RIGHT || !c.selected) {
+ if (p_button != MOUSE_BUTTON_RIGHT || !c.selected) {
select_single_item(p_item, root, col);
}
- if (p_button == BUTTON_RIGHT) {
+ if (p_button == MOUSE_BUTTON_RIGHT) {
emit_signal("item_rmb_selected", get_local_mouse_position());
}
}
@@ -2046,7 +2076,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
/* touching the combo */
bool up = p_pos.y < (item_h / 2);
- if (p_button == BUTTON_LEFT) {
+ if (p_button == MOUSE_BUTTON_LEFT) {
if (range_click_timer->get_time_left() == 0) {
range_item_last = p_item;
range_up_last = up;
@@ -2063,13 +2093,13 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
item_edited(col, p_item);
- } else if (p_button == BUTTON_RIGHT) {
+ } else if (p_button == MOUSE_BUTTON_RIGHT) {
p_item->set_range(col, (up ? c.max : c.min));
item_edited(col, p_item);
- } else if (p_button == BUTTON_WHEEL_UP) {
+ } else if (p_button == MOUSE_BUTTON_WHEEL_UP) {
p_item->set_range(col, c.val + c.step);
item_edited(col, p_item);
- } else if (p_button == BUTTON_WHEEL_DOWN) {
+ } else if (p_button == MOUSE_BUTTON_WHEEL_DOWN) {
p_item->set_range(col, c.val - c.step);
item_edited(col, p_item);
}
@@ -2102,14 +2132,14 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
}
if (!p_item->cells[col].custom_button || !on_arrow) {
- item_edited(col, p_item, p_button == BUTTON_LEFT);
+ item_edited(col, p_item, p_button == MOUSE_BUTTON_LEFT);
}
click_handled = true;
return -1;
} break;
};
- if (!bring_up_editor || p_button != BUTTON_LEFT) {
+ if (!bring_up_editor || p_button != MOUSE_BUTTON_LEFT) {
return -1;
}
@@ -2149,7 +2179,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
item_h += child_h;
}
}
- if (p_item == root && p_button == BUTTON_RIGHT) {
+ if (p_item == root && p_button == MOUSE_BUTTON_RIGHT) {
emit_signal("empty_rmb", get_local_mouse_position());
}
}
@@ -2690,7 +2720,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
bool rtl = is_layout_rtl();
if (!b->is_pressed()) {
- if (b->get_button_index() == BUTTON_LEFT) {
+ if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
Point2 pos = b->get_position();
if (rtl) {
pos.x = get_size().width - pos.x;
@@ -2771,8 +2801,8 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
switch (b->get_button_index()) {
- case BUTTON_RIGHT:
- case BUTTON_LEFT: {
+ case MOUSE_BUTTON_RIGHT:
+ case MOUSE_BUTTON_LEFT: {
Ref<StyleBox> bg = cache.bg;
Point2 pos = b->get_position();
@@ -2785,7 +2815,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
pos.y -= _get_title_button_height();
if (pos.y < 0) {
- if (b->get_button_index() == BUTTON_LEFT) {
+ if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
pos.x += cache.offset.x;
int len = 0;
for (int i = 0; i < columns.size(); i++) {
@@ -2803,7 +2833,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
}
if (!root || (!root->get_children() && hide_root)) {
- if (b->get_button_index() == BUTTON_RIGHT && allow_rmb_select) {
+ if (b->get_button_index() == MOUSE_BUTTON_RIGHT && allow_rmb_select) {
emit_signal("empty_tree_rmb_selected", get_local_mouse_position());
}
break;
@@ -2824,7 +2854,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
}
- if (b->get_button_index() == BUTTON_RIGHT) {
+ if (b->get_button_index() == MOUSE_BUTTON_RIGHT) {
break;
}
@@ -2847,7 +2877,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
set_physics_process_internal(true);
}
- if (b->get_button_index() == BUTTON_LEFT) {
+ if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
if (get_item_at_position(b->get_position()) == nullptr && !b->get_shift() && !b->get_control() && !b->get_command()) {
emit_signal("nothing_selected");
}
@@ -2860,7 +2890,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
} break;
- case BUTTON_WHEEL_UP: {
+ case MOUSE_BUTTON_WHEEL_UP: {
double prev_value = v_scroll->get_value();
v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8);
if (v_scroll->get_value() != prev_value) {
@@ -2868,7 +2898,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
} break;
- case BUTTON_WHEEL_DOWN: {
+ case MOUSE_BUTTON_WHEEL_DOWN: {
double prev_value = v_scroll->get_value();
v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8);
if (v_scroll->get_value() != prev_value) {
@@ -3143,6 +3173,8 @@ void Tree::_notification(int p_what) {
Ref<StyleBox> bg = cache.bg;
Ref<StyleBox> bg_focus = get_theme_stylebox("bg_focus");
+ Color font_outline_color = get_theme_color("font_outline_color");
+ int outline_size = get_theme_constant("outline_size");
Point2 draw_ofs;
draw_ofs += bg->get_offset();
@@ -3179,7 +3211,12 @@ void Tree::_notification(int p_what) {
//text
int clip_w = tbrect.size.width - sb->get_minimum_size().width;
columns.write[i].text_buf->set_width(clip_w);
- columns[i].text_buf->draw(ci, tbrect.position + Point2i(sb->get_offset().x + (tbrect.size.width - columns[i].text_buf->get_size().x) / 2, (tbrect.size.height - columns[i].text_buf->get_size().y) / 2), cache.title_button_color);
+
+ Vector2 text_pos = tbrect.position + Point2i(sb->get_offset().x + (tbrect.size.width - columns[i].text_buf->get_size().x) / 2, (tbrect.size.height - columns[i].text_buf->get_size().y) / 2);
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ columns[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ }
+ columns[i].text_buf->draw(ci, text_pos, cache.title_button_color);
}
}
}
@@ -3315,6 +3352,9 @@ void Tree::item_selected(int p_column, TreeItem *p_item) {
//emit_signal("multi_selected",p_item,p_column,true); - NO this is for TreeItem::select
selected_col = p_column;
+ if (!selected_item) {
+ selected_item = p_item;
+ }
} else {
select_single_item(p_item, root, p_column);
}
@@ -3322,6 +3362,14 @@ void Tree::item_selected(int p_column, TreeItem *p_item) {
}
void Tree::item_deselected(int p_column, TreeItem *p_item) {
+ if (selected_item == p_item) {
+ selected_item = nullptr;
+
+ if (selected_col == p_column) {
+ selected_col = -1;
+ }
+ }
+
if (select_mode == SELECT_MULTI || select_mode == SELECT_SINGLE) {
p_item->cells.write[p_column].selected = false;
}
@@ -3468,9 +3516,13 @@ int Tree::get_column_width(int p_column) const {
return columns[p_column].min_width;
}
+ int expand_area = get_size().width;
+
Ref<StyleBox> bg = cache.bg;
- int expand_area = get_size().width - (bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT));
+ if (bg.is_valid()) {
+ expand_area -= bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
+ }
if (v_scroll->is_visible_in_tree()) {
expand_area -= v_scroll->get_combined_minimum_size().width;
@@ -4149,6 +4201,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_edited"), &Tree::get_edited);
ClassDB::bind_method(D_METHOD("get_edited_column"), &Tree::get_edited_column);
+ ClassDB::bind_method(D_METHOD("edit_selected"), &Tree::edit_selected);
ClassDB::bind_method(D_METHOD("get_custom_popup_rect"), &Tree::get_custom_popup_rect);
ClassDB::bind_method(D_METHOD("get_item_area_rect", "item", "column"), &Tree::_get_item_rect, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_item_at_position", "position"), &Tree::get_item_at_position);
@@ -4174,6 +4227,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_column_title_language", "column"), &Tree::get_column_title_language);
ClassDB::bind_method(D_METHOD("get_scroll"), &Tree::get_scroll);
+ ClassDB::bind_method(D_METHOD("scroll_to_item", "item"), &Tree::_scroll_to_item);
ClassDB::bind_method(D_METHOD("set_hide_folding", "hide"), &Tree::set_hide_folding);
ClassDB::bind_method(D_METHOD("is_folding_hidden"), &Tree::is_folding_hidden);
@@ -4223,19 +4277,8 @@ void Tree::_bind_methods() {
}
Tree::Tree() {
- selected_col = 0;
columns.resize(1);
- selected_item = nullptr;
- edited_item = nullptr;
- selected_col = -1;
- edited_col = -1;
- hide_root = false;
- select_mode = SELECT_SINGLE;
- root = nullptr;
- popup_menu = nullptr;
- popup_edited_item = nullptr;
- text_editor = nullptr;
set_focus_mode(FOCUS_ALL);
popup_menu = memnew(PopupMenu);
@@ -4279,50 +4322,9 @@ Tree::Tree() {
set_notify_transform(true);
- updating_value_editor = false;
- pressed_button = -1;
- show_column_titles = false;
-
- cache.click_type = Cache::CLICK_NONE;
- cache.hover_type = Cache::CLICK_NONE;
- cache.hover_index = -1;
- cache.click_index = -1;
- cache.click_id = -1;
- cache.click_item = nullptr;
- cache.click_column = 0;
- cache.hover_cell = -1;
- last_keypress = 0;
- focus_in_id = 0;
-
- blocked = 0;
-
- cursor_can_exit_tree = true;
set_mouse_filter(MOUSE_FILTER_STOP);
- drag_speed = 0;
- drag_touching = false;
- drag_touching_deaccel = false;
- pressing_for_editor = false;
- range_drag_enabled = false;
-
- hide_folding = false;
-
- drop_mode_flags = 0;
- drop_mode_over = nullptr;
- drop_mode_section = 0;
- single_select_defer = nullptr;
-
- scrolling = false;
- allow_rmb_select = false;
- force_edit_checkbox_only_on_checkbox = false;
-
set_clip_contents(true);
-
- cache.hover_item = nullptr;
- cache.hover_cell = -1;
-
- allow_reselect = false;
- propagate_mouse_activated = false;
}
Tree::~Tree() {
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 2136bada0b..d1407e24d4 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -62,7 +62,7 @@ private:
friend class Tree;
struct Cell {
- TreeCellMode mode;
+ TreeCellMode mode = TreeItem::CELL_MODE_STRING;
Ref<Texture2D> icon;
Rect2i icon_region;
@@ -74,24 +74,27 @@ private:
Control::StructuredTextParser st_parser = Control::STRUCTURED_TEXT_DEFAULT;
Array st_args;
Control::TextDirection text_direction = Control::TEXT_DIRECTION_INHERITED;
- bool dirty;
- double min, max, step, val;
- int icon_max_w;
- bool expr;
- bool checked;
- bool editable;
- bool selected;
- bool selectable;
- bool custom_color;
+ bool dirty = true;
+ double min = 0.0;
+ double max = 100.0;
+ double step = 1.0;
+ double val = 0.0;
+ int icon_max_w = 0;
+ bool expr = false;
+ bool checked = false;
+ bool editable = false;
+ bool selected = false;
+ bool selectable = true;
+ bool custom_color = false;
Color color;
- bool custom_bg_color;
- bool custom_bg_outline;
+ bool custom_bg_color = false;
+ bool custom_bg_outline = false;
Color bg_color;
- bool custom_button;
- bool expand_right;
- Color icon_color;
+ bool custom_button = false;
+ bool expand_right = false;
+ Color icon_color = Color(1, 1, 1);
- TextAlign text_align;
+ TextAlign text_align = ALIGN_LEFT;
Variant meta;
String tooltip;
@@ -100,42 +103,17 @@ private:
StringName custom_draw_callback;
struct Button {
- int id;
- bool disabled;
+ int id = 0;
+ bool disabled = false;
Ref<Texture2D> texture;
- Color color;
+ Color color = Color(1, 1, 1, 1);
String tooltip;
- Button() {
- id = 0;
- disabled = false;
- color = Color(1, 1, 1, 1);
- tooltip = "";
- }
};
Vector<Button> buttons;
Cell() {
text_buf.instance();
- dirty = true;
- custom_draw_obj = ObjectID();
- custom_button = false;
- mode = TreeItem::CELL_MODE_STRING;
- min = 0;
- max = 100;
- step = 1;
- val = 0;
- checked = false;
- editable = false;
- selected = false;
- selectable = true;
- custom_color = false;
- custom_bg_color = false;
- expr = false;
- icon_max_w = 0;
- text_align = ALIGN_LEFT;
- expand_right = false;
- icon_color = Color(1, 1, 1);
}
Size2 get_icon_size() const;
@@ -251,6 +229,8 @@ public:
void set_collapsed(bool p_collapsed);
bool is_collapsed();
+ void uncollapse_tree();
+
void set_custom_minimum_height(int p_height);
int get_custom_minimum_height() const;
@@ -332,46 +312,46 @@ public:
private:
friend class TreeItem;
- TreeItem *root;
- TreeItem *popup_edited_item;
- TreeItem *selected_item;
- TreeItem *edited_item;
+ TreeItem *root = nullptr;
+ TreeItem *popup_edited_item = nullptr;
+ TreeItem *selected_item = nullptr;
+ TreeItem *edited_item = nullptr;
- TreeItem *drop_mode_over;
- int drop_mode_section;
+ TreeItem *drop_mode_over = nullptr;
+ int drop_mode_section = 0;
- TreeItem *single_select_defer;
- int single_select_defer_column;
+ TreeItem *single_select_defer = nullptr;
+ int single_select_defer_column = 0;
- int pressed_button;
- bool pressing_for_editor;
+ int pressed_button = -1;
+ bool pressing_for_editor = false;
String pressing_for_editor_text;
Vector2 pressing_pos;
Rect2 pressing_item_rect;
- float range_drag_base;
- bool range_drag_enabled;
+ float range_drag_base = 0.0;
+ bool range_drag_enabled = false;
Vector2 range_drag_capture_pos;
- bool propagate_mouse_activated;
+ bool propagate_mouse_activated = false;
//TreeItem *cursor_item;
//int cursor_column;
Rect2 custom_popup_rect;
- int edited_col;
- int selected_col;
- int popup_edited_item_col;
- bool hide_root;
- SelectMode select_mode;
+ int edited_col = -1;
+ int selected_col = -1;
+ int popup_edited_item_col = -1;
+ bool hide_root = false;
+ SelectMode select_mode = SELECT_SINGLE;
- int blocked;
+ int blocked = 0;
- int drop_mode_flags;
+ int drop_mode_flags = 0;
struct ColumnInfo {
- int min_width;
- bool expand;
+ int min_width = 1;
+ bool expand = true;
String title;
Ref<TextLine> text_buf;
Dictionary opentype_features;
@@ -379,27 +359,25 @@ private:
Control::TextDirection text_direction = Control::TEXT_DIRECTION_INHERITED;
ColumnInfo() {
text_buf.instance();
- min_width = 1;
- expand = true;
}
};
- bool show_column_titles;
+ bool show_column_titles = false;
VBoxContainer *popup_editor_vb;
Popup *popup_editor;
- LineEdit *text_editor;
+ LineEdit *text_editor = nullptr;
HSlider *value_editor;
- bool updating_value_editor;
- uint64_t focus_in_id;
- PopupMenu *popup_menu;
+ bool updating_value_editor = false;
+ uint64_t focus_in_id = 0;
+ PopupMenu *popup_menu = nullptr;
Vector<ColumnInfo> columns;
Timer *range_click_timer;
- TreeItem *range_item_last;
- bool range_up_last;
+ TreeItem *range_item_last = nullptr;
+ bool range_up_last = false;
void _range_click_timeout();
int compute_item_height(TreeItem *p_item) const;
@@ -409,7 +387,7 @@ private:
void update_item_cell(TreeItem *p_item, int p_col);
void update_item_cache(TreeItem *p_item);
//void draw_item_text(String p_text,const Ref<Texture2D>& p_icon,int p_icon_max_w,bool p_tool,Rect2i p_rect,const Color& p_color);
- void draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color);
+ void draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color);
int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item);
void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = nullptr, bool *r_in_range = nullptr, bool p_force_deselect = false);
int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_doubleclick, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod);
@@ -434,8 +412,8 @@ private:
struct Cache {
Ref<Font> font;
Ref<Font> tb_font;
- int font_size;
- int tb_font_size;
+ int font_size = 0;
+ int tb_font_size = 0;
Ref<StyleBox> bg;
Ref<StyleBox> selected;
Ref<StyleBox> selected_focus;
@@ -465,15 +443,15 @@ private:
Color relationship_line_color;
Color custom_button_font_highlight;
- int hseparation;
- int vseparation;
- int item_margin;
- int button_margin;
+ int hseparation = 0;
+ int vseparation = 0;
+ int item_margin = 0;
+ int button_margin = 0;
Point2 offset;
- int draw_relationship_lines;
- int draw_guides;
- int scroll_border;
- int scroll_speed;
+ int draw_relationship_lines = 0;
+ int draw_guides = 0;
+ int scroll_border = 0;
+ int scroll_speed = 0;
enum ClickType {
CLICK_NONE,
@@ -482,17 +460,17 @@ private:
};
- ClickType click_type;
- ClickType hover_type;
- int click_index;
- int click_id;
- TreeItem *click_item;
- int click_column;
- int hover_index;
+ ClickType click_type = Cache::CLICK_NONE;
+ ClickType hover_type = Cache::CLICK_NONE;
+ int click_index = -1;
+ int click_id = -1;
+ TreeItem *click_item = nullptr;
+ int click_column = 0;
+ int hover_index = -1;
Point2 click_pos;
- TreeItem *hover_item;
- int hover_cell;
+ TreeItem *hover_item = nullptr;
+ int hover_cell = -1;
Point2i text_editor_position;
@@ -510,9 +488,9 @@ private:
Rect2 search_item_rect(TreeItem *p_from, TreeItem *p_item);
//Rect2 get_item_rect(TreeItem *p_item);
- uint64_t last_keypress;
+ uint64_t last_keypress = 0;
String incr_search;
- bool cursor_can_exit_tree;
+ bool cursor_can_exit_tree = true;
void _do_incr_search(const String &p_add);
TreeItem *_search_item_text(TreeItem *p_at, const String &p_find, int *r_col, bool p_selectable, bool p_backwards = false);
@@ -526,21 +504,21 @@ private:
float last_drag_time;
float time_since_motion;*/
- float drag_speed;
- float drag_from;
- float drag_accum;
+ float drag_speed = 0.0;
+ float drag_from = 0.0;
+ float drag_accum = 0.0;
Vector2 last_speed;
- bool drag_touching;
- bool drag_touching_deaccel;
- bool click_handled;
- bool allow_rmb_select;
- bool scrolling;
+ bool drag_touching = false;
+ bool drag_touching_deaccel = false;
+ bool click_handled = false;
+ bool allow_rmb_select = false;
+ bool scrolling = false;
- bool allow_reselect;
+ bool allow_reselect = false;
- bool force_edit_checkbox_only_on_checkbox;
+ bool force_edit_checkbox_only_on_checkbox = false;
- bool hide_folding;
+ bool hide_folding = false;
int _count_selected_items(TreeItem *p_from) const;
void _go_left();
@@ -564,6 +542,10 @@ protected:
return get_item_rect(Object::cast_to<TreeItem>(p_item), p_column);
}
+ void _scroll_to_item(Object *p_item) {
+ scroll_to_item(Object::cast_to<TreeItem>(p_item));
+ }
+
public:
virtual String get_tooltip(const Point2 &p_pos) const override;
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index 84d689369b..0590ae2415 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -462,25 +462,7 @@ void VideoPlayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");
}
-VideoPlayer::VideoPlayer() {
- volume = 1;
- loops = false;
- paused = false;
- autoplay = false;
- expand = true;
-
- audio_track = 0;
- bus_index = 0;
-
- buffering_ms = 500;
-
- // internal_stream.player=this;
- // stream_rid=AudioServer::get_singleton()->audio_stream_create(&internal_stream);
- last_audio_time = 0;
-
- wait_resampler = 0;
- wait_resampler_limit = 2;
-};
+VideoPlayer::VideoPlayer() {}
VideoPlayer::~VideoPlayer() {
// if (stream_rid.is_valid())
diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h
index 089337eed5..0edad296a1 100644
--- a/scene/gui/video_player.h
+++ b/scene/gui/video_player.h
@@ -41,8 +41,8 @@ class VideoPlayer : public Control {
struct Output {
AudioFrame vol;
- int bus_index;
- Viewport *viewport; //pointer only used for reference to previous mix
+ int bus_index = 0;
+ Viewport *viewport = nullptr; //pointer only used for reference to previous mix
};
Ref<VideoStreamPlayback> playback;
Ref<VideoStream> stream;
@@ -56,17 +56,18 @@ class VideoPlayer : public Control {
AudioRBResampler resampler;
Vector<AudioFrame> mix_buffer;
- int wait_resampler, wait_resampler_limit;
-
- bool paused;
- bool autoplay;
- float volume;
- double last_audio_time;
- bool expand;
- bool loops;
- int buffering_ms;
- int audio_track;
- int bus_index;
+ int wait_resampler = 0;
+ int wait_resampler_limit = 2;
+
+ bool paused = false;
+ bool autoplay = false;
+ float volume = 1.0;
+ double last_audio_time = 0.0;
+ bool expand = true;
+ bool loops = false;
+ int buffering_ms = 500;
+ int audio_track = 0;
+ int bus_index = 0;
StringName bus;
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index efef49fbf0..b18b2afb6d 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -203,7 +203,7 @@ CanvasItemMaterial::LightMode CanvasItemMaterial::get_light_mode() const {
void CanvasItemMaterial::set_particles_animation(bool p_particles_anim) {
particles_animation = p_particles_anim;
_queue_shader_change();
- _change_notify();
+ notify_property_list_changed();
}
bool CanvasItemMaterial::get_particles_animation() const {
@@ -387,7 +387,6 @@ void CanvasItem::show() {
}
_propagate_visibility_changed(true);
- _change_notify("visible");
}
void CanvasItem::hide() {
@@ -403,7 +402,6 @@ void CanvasItem::hide() {
}
_propagate_visibility_changed(false);
- _change_notify("visible");
}
CanvasItem *CanvasItem::current_item_drawn = nullptr;
@@ -731,13 +729,13 @@ void CanvasItem::item_rect_changed(bool p_size_changed) {
emit_signal(SceneStringNames::get_singleton()->item_rect_changed);
}
-void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) {
+void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width);
}
-void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width, bool p_antialiased) {
+void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width, bool p_antialiased) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
Vector<Color> colors;
@@ -745,25 +743,25 @@ void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_co
RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, colors, p_width, p_antialiased);
}
-void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
+void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width, bool p_antialiased) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased);
}
-void CanvasItem::draw_arc(const Vector2 &p_center, float p_radius, float p_start_angle, float p_end_angle, int p_point_count, const Color &p_color, float p_width, bool p_antialiased) {
+void CanvasItem::draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width, bool p_antialiased) {
Vector<Point2> points;
points.resize(p_point_count);
- const float delta_angle = p_end_angle - p_start_angle;
+ const real_t delta_angle = p_end_angle - p_start_angle;
for (int i = 0; i < p_point_count; i++) {
- float theta = (i / (p_point_count - 1.0f)) * delta_angle + p_start_angle;
+ real_t theta = (i / (p_point_count - 1.0f)) * delta_angle + p_start_angle;
points.set(i, p_center + Vector2(Math::cos(theta), Math::sin(theta)) * p_radius);
}
draw_polyline(points, p_color, p_width, p_antialiased);
}
-void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width) {
+void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
Vector<Color> colors;
@@ -771,13 +769,13 @@ void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_c
RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width);
}
-void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
+void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width);
}
-void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, float p_width) {
+void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
if (p_filled) {
@@ -789,7 +787,7 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
} else {
// Thick lines are offset depending on their width to avoid partial overlapping.
// Thin lines don't require an offset, so don't apply one in this case
- float offset;
+ real_t offset;
if (p_width >= 2) {
offset = p_width / 2.0;
} else {
@@ -823,7 +821,7 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
}
}
-void CanvasItem::draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color) {
+void CanvasItem::draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color);
@@ -858,14 +856,14 @@ void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p
p_style_box->draw(canvas_item, p_rect);
}
-void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture, float p_width) {
+void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture, real_t p_width) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
RenderingServer::get_singleton()->canvas_item_add_primitive(canvas_item, p_points, p_colors, p_uvs, rid, p_width);
}
-void CanvasItem::draw_set_transform(const Point2 &p_offset, float p_rot, const Size2 &p_scale) {
+void CanvasItem::draw_set_transform(const Point2 &p_offset, real_t p_rot, const Size2 &p_scale) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
Transform2D xform(p_rot, p_offset);
@@ -909,19 +907,19 @@ void CanvasItem::draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Tex
RenderingServer::get_singleton()->canvas_item_add_multimesh(canvas_item, p_multimesh->get_rid(), texture_rid);
}
-void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align, float p_width, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const {
+void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align, real_t p_width, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_font.is_null());
p_font->draw_string(canvas_item, p_pos, p_text, p_align, p_width, p_size, p_modulate, p_outline_size, p_outline_modulate, p_flags);
}
-void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align, float p_width, int p_max_lines, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const {
+void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align, real_t p_width, int p_max_lines, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_font.is_null());
p_font->draw_multiline_string(canvas_item, p_pos, p_text, p_align, p_width, p_max_lines, p_size, p_modulate, p_outline_size, p_outline_modulate, p_flags);
}
-float CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate) const {
+real_t CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate) const {
ERR_FAIL_COND_V_MSG(!drawing, 0.f, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND_V(p_font.is_null(), 0.f);
ERR_FAIL_COND_V(p_char.length() != 1, 0.f);
@@ -1035,7 +1033,7 @@ void CanvasItem::set_material(const Ref<Material> &p_material) {
rid = material->get_rid();
}
RS::get_singleton()->canvas_item_set_material(canvas_item, rid);
- _change_notify(); //properties for material exposed
+ notify_property_list_changed(); //properties for material exposed
}
void CanvasItem::set_use_parent_material(bool p_use_parent_material) {
@@ -1341,7 +1339,7 @@ void CanvasItem::set_texture_filter(TextureFilter p_texture_filter) {
}
texture_filter = p_texture_filter;
_update_texture_filter_changed(true);
- _change_notify();
+ notify_property_list_changed();
}
CanvasItem::TextureFilter CanvasItem::get_texture_filter() const {
@@ -1381,7 +1379,7 @@ void CanvasItem::set_texture_repeat(TextureRepeat p_texture_repeat) {
}
texture_repeat = p_texture_repeat;
_update_texture_repeat_changed(true);
- _change_notify();
+ notify_property_list_changed();
}
void CanvasItem::set_clip_children(bool p_enabled) {
@@ -1443,6 +1441,7 @@ void CanvasTexture::set_specular_texture(const Ref<Texture2D> &p_specular) {
RID tex_rid = specular_texture.is_valid() ? specular_texture->get_rid() : RID();
RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_SPECULAR, tex_rid);
}
+
Ref<Texture2D> CanvasTexture::get_specular_texture() const {
return specular_texture;
}
@@ -1451,15 +1450,17 @@ void CanvasTexture::set_specular_color(const Color &p_color) {
specular = p_color;
RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess);
}
+
Color CanvasTexture::get_specular_color() const {
return specular;
}
-void CanvasTexture::set_specular_shininess(float p_shininess) {
+void CanvasTexture::set_specular_shininess(real_t p_shininess) {
shininess = p_shininess;
RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess);
}
-float CanvasTexture::get_specular_shininess() const {
+
+real_t CanvasTexture::get_specular_shininess() const {
return shininess;
}
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index 64eb3f4e0a..0f86f2e0f8 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -90,7 +90,7 @@ private:
struct ShaderData {
RID shader;
- int users;
+ int users = 0;
};
static Map<MaterialKey, ShaderData> shader_map;
@@ -290,8 +290,8 @@ public:
// Used to rotate the node
virtual bool _edit_use_rotation() const { return false; };
- virtual void _edit_set_rotation(float p_rotation) {}
- virtual float _edit_get_rotation() const { return 0.0; };
+ virtual void _edit_set_rotation(real_t p_rotation) {}
+ virtual real_t _edit_get_rotation() const { return 0.0; };
// Used to resize/move the node
virtual bool _edit_use_rect() const { return false; }; // MAYBE REPLACE BY A _edit_get_editmode()
@@ -331,30 +331,30 @@ public:
/* DRAWING API */
- void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0);
- void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
- void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
- void draw_arc(const Vector2 &p_center, float p_radius, float p_start_angle, float p_end_angle, int p_point_count, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
- void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0);
- void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0);
- void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, float p_width = 1.0);
- void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color);
+ void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0);
+ void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false);
+ void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = 1.0, bool p_antialiased = false);
+ void draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false);
+ void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = 1.0);
+ void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = 1.0);
+ void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, real_t p_width = 1.0);
+ void draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color);
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_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>(), float p_width = 1);
+ 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);
void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>());
void draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>());
void draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture2D> &p_texture, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1));
void draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture2D> &p_texture);
- void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, float p_width = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
- void draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, float p_width = -1, int p_max_lines = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
- float draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next = "", int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0)) const;
+ void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
+ void draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_max_lines = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
+ real_t draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next = "", int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0)) const;
- void draw_set_transform(const Point2 &p_offset, float p_rot = 0.0, const Size2 &p_scale = Size2(1.0, 1.0));
+ void draw_set_transform(const Point2 &p_offset, real_t p_rot = 0.0, const Size2 &p_scale = Size2(1.0, 1.0));
void draw_set_transform_matrix(const Transform2D &p_matrix);
static CanvasItem *get_current_item_drawn();
@@ -437,7 +437,7 @@ class CanvasTexture : public Texture2D {
Ref<Texture2D> normal_texture;
Ref<Texture2D> specular_texture;
Color specular = Color(1, 1, 1, 1);
- float shininess = 1.0;
+ real_t shininess = 1.0;
RID canvas_texture;
@@ -460,8 +460,8 @@ public:
void set_specular_color(const Color &p_color);
Color get_specular_color() const;
- void set_specular_shininess(float p_shininess);
- float get_specular_shininess() const;
+ void set_specular_shininess(real_t p_shininess);
+ real_t get_specular_shininess() const;
void set_texture_filter(CanvasItem::TextureFilter p_filter);
CanvasItem::TextureFilter get_texture_filter() const;
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index 9826d9d4db..85d7edd64b 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -231,6 +231,7 @@ void CanvasLayer::set_follow_viewport(bool p_enable) {
follow_viewport = p_enable;
_update_follow_viewport();
+ notify_property_list_changed();
}
bool CanvasLayer::is_following_viewport() const {
@@ -257,6 +258,12 @@ void CanvasLayer::_update_follow_viewport(bool p_force_exit) {
}
}
+void CanvasLayer::_validate_property(PropertyInfo &property) const {
+ if (!follow_viewport && property.name == "follow_viewport_scale") {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+}
+
void CanvasLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_layer", "layer"), &CanvasLayer::set_layer);
ClassDB::bind_method(D_METHOD("get_layer"), &CanvasLayer::get_layer);
@@ -303,17 +310,7 @@ void CanvasLayer::_bind_methods() {
}
CanvasLayer::CanvasLayer() {
- vp = nullptr;
- scale = Vector2(1, 1);
- rot = 0;
- locrotscale_dirty = false;
- layer = 1;
canvas = RS::get_singleton()->canvas_create();
- custom_viewport = nullptr;
-
- sort_index = 0;
- follow_viewport = false;
- follow_viewport_scale = 1.0;
}
CanvasLayer::~CanvasLayer() {
diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h
index cb10c6299b..899039340a 100644
--- a/scene/main/canvas_layer.h
+++ b/scene/main/canvas_layer.h
@@ -38,24 +38,24 @@ class Viewport;
class CanvasLayer : public Node {
GDCLASS(CanvasLayer, Node);
- bool locrotscale_dirty;
+ bool locrotscale_dirty = false;
Vector2 ofs;
- Size2 scale;
- real_t rot;
- int layer;
+ Size2 scale = Vector2(1, 1);
+ real_t rot = 0.0;
+ int layer = 1;
Transform2D transform;
RID canvas;
ObjectID custom_viewport_id; // to check validity
- Viewport *custom_viewport;
+ Viewport *custom_viewport = nullptr;
RID viewport;
- Viewport *vp;
+ Viewport *vp = nullptr;
- int sort_index;
+ int sort_index = 0;
- bool follow_viewport;
- float follow_viewport_scale;
+ bool follow_viewport = false;
+ float follow_viewport_scale = 1.0;
void _update_xform();
void _update_locrotscale();
@@ -64,6 +64,7 @@ class CanvasLayer : public Node {
protected:
void _notification(int p_what);
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const override;
public:
void set_layer(int p_xform);
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 4c6b85d78b..e4ed5c6e6c 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -49,7 +49,7 @@ Error HTTPRequest::_parse_url(const String &p_url) {
got_response = false;
body_len = -1;
body.resize(0);
- downloaded = 0;
+ downloaded.set(0);
redirections = 0;
String url_lower = url.to_lower();
@@ -159,9 +159,9 @@ Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_cust
requesting = true;
- if (use_threads) {
- thread_done = false;
- thread_request_quit = false;
+ if (use_threads.is_set()) {
+ thread_done.clear();
+ thread_request_quit.clear();
client->set_blocking_mode(true);
thread.start(_thread_func, this);
} else {
@@ -186,7 +186,7 @@ void HTTPRequest::_thread_func(void *p_userdata) {
if (err != OK) {
hr->call_deferred("_request_done", RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
} else {
- while (!hr->thread_request_quit) {
+ while (!hr->thread_request_quit.is_set()) {
bool exit = hr->_update_connection();
if (exit) {
break;
@@ -195,7 +195,7 @@ void HTTPRequest::_thread_func(void *p_userdata) {
}
}
- hr->thread_done = true;
+ hr->thread_done.set();
}
void HTTPRequest::cancel_request() {
@@ -205,10 +205,10 @@ void HTTPRequest::cancel_request() {
return;
}
- if (!use_threads) {
+ if (!use_threads.is_set()) {
set_process_internal(false);
} else {
- thread_request_quit = true;
+ thread_request_quit.set();
thread.wait_to_finish();
}
@@ -236,7 +236,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
List<String> rheaders;
client->get_response_headers(&rheaders);
response_headers.resize(0);
- downloaded = 0;
+ downloaded.set(0);
for (List<String>::Element *E = rheaders.front(); E; E = E->next()) {
response_headers.push_back(E->get());
}
@@ -276,7 +276,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
got_response = false;
body_len = -1;
body.resize(0);
- downloaded = 0;
+ downloaded.set(0);
redirections = new_redirs;
*ret_value = false;
return true;
@@ -335,7 +335,7 @@ bool HTTPRequest::_update_connection() {
call_deferred("_request_done", RESULT_CHUNKED_BODY_SIZE_MISMATCH, response_code, response_headers, PackedByteArray());
return true;
- // Request migh have been done
+ // Request might have been done
} else {
// Did not request yet, do request
@@ -387,9 +387,12 @@ bool HTTPRequest::_update_connection() {
}
client->poll();
+ if (client->get_status() != HTTPClient::STATUS_BODY) {
+ return false;
+ }
PackedByteArray chunk = client->read_response_body_chunk();
- downloaded += chunk.size();
+ downloaded.add(chunk.size());
if (file) {
const uint8_t *r = chunk.ptr();
@@ -402,19 +405,20 @@ bool HTTPRequest::_update_connection() {
body.append_array(chunk);
}
- if (body_size_limit >= 0 && downloaded > body_size_limit) {
+ if (body_size_limit >= 0 && downloaded.get() > body_size_limit) {
call_deferred("_request_done", RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PackedByteArray());
return true;
}
if (body_len >= 0) {
- if (downloaded == body_len) {
+ if (downloaded.get() == body_len) {
call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, body);
return true;
}
} else if (client->get_status() == HTTPClient::STATUS_DISCONNECTED) {
// We read till EOF, with no errors. Request is done.
call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, body);
+ return true;
}
return false;
@@ -478,7 +482,7 @@ void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArra
void HTTPRequest::_notification(int p_what) {
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
- if (use_threads) {
+ if (use_threads.is_set()) {
return;
}
bool done = _update_connection();
@@ -497,11 +501,11 @@ void HTTPRequest::_notification(int p_what) {
void HTTPRequest::set_use_threads(bool p_use) {
ERR_FAIL_COND(get_http_client_status() != HTTPClient::STATUS_DISCONNECTED);
- use_threads = p_use;
+ use_threads.set_to(p_use);
}
bool HTTPRequest::is_using_threads() const {
- return use_threads;
+ return use_threads.is_set();
}
void HTTPRequest::set_accept_gzip(bool p_gzip) {
@@ -555,7 +559,7 @@ int HTTPRequest::get_max_redirects() const {
}
int HTTPRequest::get_downloaded_bytes() const {
- return downloaded;
+ return downloaded.get();
}
int HTTPRequest::get_body_size() const {
@@ -638,29 +642,11 @@ void HTTPRequest::_bind_methods() {
}
HTTPRequest::HTTPRequest() {
- port = 80;
- redirections = 0;
- max_redirects = 8;
- body_len = -1;
- got_response = false;
- validate_ssl = false;
- use_ssl = false;
- accept_gzip = true;
- response_code = 0;
- request_sent = false;
- requesting = false;
client.instance();
- use_threads = false;
- thread_done = false;
- downloaded = 0;
- body_size_limit = -1;
- file = nullptr;
-
timer = memnew(Timer);
timer->set_one_shot(true);
timer->connect("timeout", callable_mp(this, &HTTPRequest::_timeout));
add_child(timer);
- timeout = 0;
}
HTTPRequest::~HTTPRequest() {
diff --git a/scene/main/http_request.h b/scene/main/http_request.h
index 9dbf561cd4..92b0ff28e9 100644
--- a/scene/main/http_request.h
+++ b/scene/main/http_request.h
@@ -34,6 +34,7 @@
#include "core/io/http_client.h"
#include "core/os/file_access.h"
#include "core/os/thread.h"
+#include "core/templates/safe_refcount.h"
#include "node.h"
#include "scene/main/timer.h"
@@ -60,42 +61,42 @@ public:
};
private:
- bool requesting;
+ bool requesting = false;
String request_string;
String url;
- int port;
+ int port = 80;
Vector<String> headers;
- bool validate_ssl;
- bool use_ssl;
+ bool validate_ssl = false;
+ bool use_ssl = false;
HTTPClient::Method method;
Vector<uint8_t> request_data;
- bool request_sent;
+ bool request_sent = false;
Ref<HTTPClient> client;
PackedByteArray body;
- volatile bool use_threads;
- bool accept_gzip;
+ SafeFlag use_threads;
+ bool accept_gzip = true;
- bool got_response;
- int response_code;
+ bool got_response = false;
+ int response_code = 0;
Vector<String> response_headers;
String download_to_file;
- FileAccess *file;
+ FileAccess *file = nullptr;
- int body_len;
- volatile int downloaded;
- int body_size_limit;
+ int body_len = -1;
+ SafeNumeric<int> downloaded;
+ int body_size_limit = -1;
- int redirections;
+ int redirections = 0;
bool _update_connection();
- int max_redirects;
+ int max_redirects = 8;
- int timeout;
+ int timeout = 0;
void _redirect_request(const String &p_new_url);
@@ -107,8 +108,8 @@ private:
bool has_header(const PackedStringArray &p_headers, const String &p_header_name);
String get_header_value(const PackedStringArray &p_headers, const String &header_name);
- volatile bool thread_done;
- volatile bool thread_request_quit;
+ SafeFlag thread_done;
+ SafeFlag thread_request_quit;
Thread thread;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 0c01516032..933f67db68 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -46,7 +46,7 @@
#include <stdint.h>
-VARIANT_ENUM_CAST(Node::PauseMode);
+VARIANT_ENUM_CAST(Node::ProcessMode);
int Node::orphan_node_count = 0;
@@ -69,14 +69,14 @@ void Node::_notification(int p_notification) {
ERR_FAIL_COND(!get_viewport());
ERR_FAIL_COND(!get_tree());
- if (data.pause_mode == PAUSE_MODE_INHERIT) {
+ if (data.process_mode == PROCESS_MODE_INHERIT) {
if (data.parent) {
- data.pause_owner = data.parent->data.pause_owner;
+ data.process_owner = data.parent->data.process_owner;
} else {
- data.pause_owner = nullptr;
+ data.process_owner = nullptr;
}
} else {
- data.pause_owner = this;
+ data.process_owner = this;
}
if (data.input) {
@@ -110,7 +110,7 @@ void Node::_notification(int p_notification) {
remove_from_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_id()));
}
- data.pause_owner = nullptr;
+ data.process_owner = nullptr;
if (data.path_cache) {
memdelete(data.path_cache);
data.path_cache = nullptr;
@@ -367,8 +367,6 @@ void Node::set_physics_process(bool p_process) {
} else {
remove_from_group("physics_process");
}
-
- _change_notify("physics_process");
}
bool Node::is_physics_processing() const {
@@ -387,52 +385,87 @@ void Node::set_physics_process_internal(bool p_process_internal) {
} else {
remove_from_group("physics_process_internal");
}
-
- _change_notify("physics_process_internal");
}
bool Node::is_physics_processing_internal() const {
return data.physics_process_internal;
}
-void Node::set_pause_mode(PauseMode p_mode) {
- if (data.pause_mode == p_mode) {
+void Node::set_process_mode(ProcessMode p_mode) {
+ if (data.process_mode == p_mode) {
return;
}
- bool prev_inherits = data.pause_mode == PAUSE_MODE_INHERIT;
- data.pause_mode = p_mode;
if (!is_inside_tree()) {
- return; //pointless
- }
- if ((data.pause_mode == PAUSE_MODE_INHERIT) == prev_inherits) {
- return; ///nothing changed
+ data.process_mode = p_mode;
+ return;
}
- Node *owner = nullptr;
+ bool prev_can_process = can_process();
+
+ data.process_mode = p_mode;
- if (data.pause_mode == PAUSE_MODE_INHERIT) {
+ if (data.process_mode == PROCESS_MODE_INHERIT) {
if (data.parent) {
- owner = data.parent->data.pause_owner;
+ data.process_owner = data.parent->data.owner;
+ } else {
+ data.process_owner = nullptr;
}
} else {
- owner = this;
+ data.process_owner = this;
}
- _propagate_pause_owner(owner);
+ bool next_can_process = can_process();
+
+ int pause_notification = 0;
+
+ if (prev_can_process && !next_can_process) {
+ pause_notification = NOTIFICATION_PAUSED;
+ } else if (!prev_can_process && next_can_process) {
+ pause_notification = NOTIFICATION_UNPAUSED;
+ }
+
+ _propagate_process_owner(data.process_owner, pause_notification);
+#ifdef TOOLS_ENABLED
+ // This is required for the editor to update the visibility of disabled nodes
+ // It's very expensive during runtime to change, so editor-only
+ if (Engine::get_singleton()->is_editor_hint()) {
+ get_tree()->emit_signal("tree_process_mode_changed");
+ }
+#endif
}
-Node::PauseMode Node::get_pause_mode() const {
- return data.pause_mode;
+void Node::_propagate_pause_notification(bool p_enable) {
+ bool prev_can_process = _can_process(!p_enable);
+ bool next_can_process = _can_process(p_enable);
+
+ if (prev_can_process && !next_can_process) {
+ notification(NOTIFICATION_PAUSED);
+ } else if (!prev_can_process && next_can_process) {
+ notification(NOTIFICATION_UNPAUSED);
+ }
+
+ for (int i = 0; i < data.children.size(); i++) {
+ data.children[i]->_propagate_pause_notification(p_enable);
+ }
}
-void Node::_propagate_pause_owner(Node *p_owner) {
- if (this != p_owner && data.pause_mode != PAUSE_MODE_INHERIT) {
- return;
+Node::ProcessMode Node::get_process_mode() const {
+ return data.process_mode;
+}
+
+void Node::_propagate_process_owner(Node *p_owner, int p_notification) {
+ data.process_owner = p_owner;
+
+ if (p_notification != 0) {
+ notification(p_notification);
}
- data.pause_owner = p_owner;
+
for (int i = 0; i < data.children.size(); i++) {
- data.children[i]->_propagate_pause_owner(p_owner);
+ Node *c = data.children[i];
+ if (c->data.process_mode == PROCESS_MODE_INHERIT) {
+ c->_propagate_process_owner(p_owner, p_notification);
+ }
}
}
@@ -466,7 +499,7 @@ uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_
nd.name = p_method;
nd.mode = p_mode;
data.rpc_methods.push_back(nd);
- return ((uint16_t)data.rpc_properties.size() - 1) | (1 << 15);
+ return ((uint16_t)data.rpc_methods.size() - 1) | (1 << 15);
} else {
int c_mid = (~(1 << 15)) & mid;
data.rpc_methods.write[c_mid].mode = p_mode;
@@ -555,7 +588,7 @@ Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallEr
return Variant();
}
- if (p_args[0]->get_type() != Variant::STRING) {
+ if (p_args[0]->get_type() != Variant::STRING_NAME) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
@@ -584,7 +617,7 @@ Variant Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::Cal
return Variant();
}
- if (p_args[1]->get_type() != Variant::STRING) {
+ if (p_args[1]->get_type() != Variant::STRING_NAME) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::STRING;
@@ -607,7 +640,7 @@ Variant Node::_rpc_unreliable_bind(const Variant **p_args, int p_argcount, Calla
return Variant();
}
- if (p_args[0]->get_type() != Variant::STRING) {
+ if (p_args[0]->get_type() != Variant::STRING_NAME) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
@@ -636,7 +669,7 @@ Variant Node::_rpc_unreliable_id_bind(const Variant **p_args, int p_argcount, Ca
return Variant();
}
- if (p_args[1]->get_type() != Variant::STRING) {
+ if (p_args[1]->get_type() != Variant::STRING_NAME) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::STRING;
@@ -809,30 +842,33 @@ bool Node::can_process_notification(int p_what) const {
bool Node::can_process() const {
ERR_FAIL_COND_V(!is_inside_tree(), false);
+ return _can_process(get_tree()->is_paused());
+}
- if (get_tree()->is_paused()) {
- if (data.pause_mode == PAUSE_MODE_STOP) {
- return false;
- }
- if (data.pause_mode == PAUSE_MODE_PROCESS) {
- return true;
- }
- if (data.pause_mode == PAUSE_MODE_INHERIT) {
- if (!data.pause_owner) {
- return false; //clearly no pause owner by default
- }
-
- if (data.pause_owner->data.pause_mode == PAUSE_MODE_PROCESS) {
- return true;
- }
+bool Node::_can_process(bool p_paused) const {
+ ProcessMode process_mode;
- if (data.pause_owner->data.pause_mode == PAUSE_MODE_STOP) {
- return false;
- }
+ if (data.process_mode == PROCESS_MODE_INHERIT) {
+ if (!data.process_owner) {
+ process_mode = PROCESS_MODE_PAUSABLE;
+ } else {
+ process_mode = data.process_owner->data.process_mode;
}
+ } else {
+ process_mode = data.process_mode;
}
- return true;
+ if (process_mode == PROCESS_MODE_DISABLED) {
+ return false;
+ } else if (process_mode == PROCESS_MODE_ALWAYS) {
+ return true;
+ }
+
+ if (p_paused) {
+ return process_mode == PROCESS_MODE_WHEN_PAUSED;
+ } else {
+ return process_mode == PROCESS_MODE_PAUSABLE;
+ }
}
float Node::get_physics_process_delta_time() const {
@@ -863,8 +899,6 @@ void Node::set_process(bool p_process) {
} else {
remove_from_group("process");
}
-
- _change_notify("process");
}
bool Node::is_processing() const {
@@ -883,8 +917,6 @@ void Node::set_process_internal(bool p_process_internal) {
} else {
remove_from_group("process_internal");
}
-
- _change_notify("process_internal");
}
bool Node::is_processing_internal() const {
@@ -989,22 +1021,8 @@ void Node::_set_name_nocheck(const StringName &p_name) {
data.name = p_name;
}
-String Node::invalid_character = ". : @ / \"";
-
-bool Node::_validate_node_name(String &p_name) {
- String name = p_name;
- Vector<String> chars = Node::invalid_character.split(" ");
- for (int i = 0; i < chars.size(); i++) {
- name = name.replace(chars[i], "");
- }
- bool is_valid = name == p_name;
- p_name = name;
- return is_valid;
-}
-
void Node::set_name(const String &p_name) {
- String name = p_name;
- _validate_node_name(name);
+ String name = p_name.validate_node_name();
ERR_FAIL_COND(name == "");
data.name = name;
@@ -1112,11 +1130,11 @@ String increase_numeric_string(const String &s) {
void Node::_generate_serial_child_name(const Node *p_child, StringName &name) const {
if (name == StringName()) {
- //no name and a new nade is needed, create one.
+ //no name and a new name is needed, create one.
name = p_child->get_class();
// Adjust casing according to project setting. The current type name is expected to be in PascalCase.
- switch (ProjectSettings::get_singleton()->get("node/name_casing").operator int()) {
+ switch (ProjectSettings::get_singleton()->get("editor/node_naming/name_casing").operator int()) {
case NAME_CASING_PASCAL_CASE:
break;
case NAME_CASING_CAMEL_CASE: {
@@ -1138,7 +1156,7 @@ void Node::_generate_serial_child_name(const Node *p_child, StringName &name) co
bool exists = false;
for (int i = 0; i < cc; i++) {
- if (children_ptr[i] == p_child) { //exclude self in renaming if its already a child
+ if (children_ptr[i] == p_child) { //exclude self in renaming if it's already a child
continue;
}
if (children_ptr[i]->data.name == name) {
@@ -1410,7 +1428,15 @@ Node *Node::get_node_or_null(const NodePath &p_path) const {
Node *Node::get_node(const NodePath &p_path) const {
Node *node = get_node_or_null(p_path);
- ERR_FAIL_COND_V_MSG(!node, nullptr, "Node not found: " + p_path + ".");
+
+ if (p_path.is_absolute()) {
+ ERR_FAIL_COND_V_MSG(!node, nullptr,
+ vformat(R"(Node not found: "%s" (absolute path attempted from "%s").)", p_path, get_path()));
+ } else {
+ ERR_FAIL_COND_V_MSG(!node, nullptr,
+ vformat(R"(Node not found: "%s" (relative to "%s").)", p_path, get_path()));
+ }
+
return node;
}
@@ -1906,15 +1932,11 @@ String Node::get_filename() const {
}
void Node::set_editor_description(const String &p_editor_description) {
- set_meta("_editor_description_", p_editor_description);
+ data.editor_description = p_editor_description;
}
String Node::get_editor_description() const {
- if (has_meta("_editor_description_")) {
- return get_meta("_editor_description_");
- } else {
- return "";
- }
+ return data.editor_description;
}
void Node::set_editable_instance(Node *p_node, bool p_editable) {
@@ -1923,7 +1945,7 @@ void Node::set_editable_instance(Node *p_node, bool p_editable) {
if (!p_editable) {
p_node->data.editable_instance = false;
// Avoid this flag being needlessly saved;
- // also give more visual feedback if editable children is re-enabled
+ // also give more visual feedback if editable children are re-enabled
set_display_folded(false);
} else {
p_node->data.editable_instance = true;
@@ -1938,6 +1960,23 @@ bool Node::is_editable_instance(const Node *p_node) const {
return p_node->data.editable_instance;
}
+Node *Node::get_deepest_editable_node(Node *p_start_node) const {
+ ERR_FAIL_NULL_V(p_start_node, nullptr);
+ ERR_FAIL_COND_V(!is_a_parent_of(p_start_node), p_start_node);
+
+ Node const *iterated_item = p_start_node;
+ Node *node = p_start_node;
+
+ while (iterated_item->get_owner() && iterated_item->get_owner() != this) {
+ if (!is_editable_instance(iterated_item->get_owner()))
+ node = iterated_item->get_owner();
+
+ iterated_item = iterated_item->get_owner();
+ }
+
+ return node;
+}
+
void Node::set_scene_instance_state(const Ref<SceneState> &p_state) {
data.instance_state = p_state;
}
@@ -1999,6 +2038,7 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
if (get_filename() != "") { //an instance
node->set_filename(get_filename());
+ node->data.editable_instance = data.editable_instance;
}
StringName script_property_name = CoreStringNames::get_singleton()->_script;
@@ -2011,19 +2051,26 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
// Since nodes in the instanced hierarchy won't be duplicated explicitly, we need to make an inventory
// of all the nodes in the tree of the instanced scene in order to transfer the values of the properties
+ Vector<const Node *> instance_roots;
+ instance_roots.push_back(this);
+
for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) {
for (int i = 0; i < N->get()->get_child_count(); ++i) {
Node *descendant = N->get()->get_child(i);
// Skip nodes not really belonging to the instanced hierarchy; they'll be processed normally later
// but remember non-instanced nodes that are hidden below instanced ones
- if (descendant->data.owner != this) {
- if (descendant->get_parent() && descendant->get_parent() != this && descendant->get_parent()->data.owner == this && descendant->data.owner != descendant->get_parent()) {
+ if (!instance_roots.has(descendant->get_owner())) {
+ if (descendant->get_parent() && descendant->get_parent() != this && descendant->data.owner != descendant->get_parent()) {
hidden_roots.push_back(descendant);
}
continue;
}
node_tree.push_back(descendant);
+
+ if (descendant->get_filename() != "" && instance_roots.has(descendant->get_owner())) {
+ instance_roots.push_back(descendant);
+ }
}
}
}
@@ -2146,8 +2193,17 @@ Node *Node::duplicate(int p_flags) const {
#ifdef TOOLS_ENABLED
Node *Node::duplicate_from_editor(Map<const Node *, Node *> &r_duplimap) const {
+ return duplicate_from_editor(r_duplimap, Map<RES, RES>());
+}
+
+Node *Node::duplicate_from_editor(Map<const Node *, Node *> &r_duplimap, const Map<RES, RES> &p_resource_remap) const {
Node *dupe = _duplicate(DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANCING | 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()) {
+ remap_node_resources(dupe, p_resource_remap);
+ }
+
// Duplication of signals must happen after all the node descendants have been copied,
// because re-targeting of connections from some descendant to another is not possible
// if the emitter node comes later in tree order than the receiver
@@ -2155,75 +2211,55 @@ Node *Node::duplicate_from_editor(Map<const Node *, Node *> &r_duplimap) const {
return dupe;
}
-#endif
-
-void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p_reown_map) const {
- if (get_owner() != get_parent()->get_owner()) {
- return;
- }
-
- Node *node = nullptr;
-
- if (get_filename() != "") {
- Ref<PackedScene> res = ResourceLoader::load(get_filename());
- ERR_FAIL_COND_MSG(res.is_null(), "Cannot load scene: " + get_filename());
- node = res->instance();
- ERR_FAIL_COND(!node);
- } else {
- Object *obj = ClassDB::instance(get_class());
- ERR_FAIL_COND_MSG(!obj, "Node: Could not duplicate: " + String(get_class()) + ".");
- node = Object::cast_to<Node>(obj);
- if (!node) {
- memdelete(obj);
- ERR_FAIL_MSG("Node: Could not duplicate: " + String(get_class()) + ".");
- }
- }
- List<PropertyInfo> plist;
+void Node::remap_node_resources(Node *p_node, const Map<RES, RES> &p_resource_remap) const {
+ List<PropertyInfo> props;
+ p_node->get_property_list(&props);
- get_property_list(&plist);
-
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- String name = E->get().name;
-
- Variant value = get(name).duplicate(true);
- node->set(name, value);
+ Variant v = p_node->get(E->get().name);
+ if (v.is_ref()) {
+ RES res = v;
+ if (res.is_valid()) {
+ if (p_resource_remap.has(res)) {
+ p_node->set(E->get().name, p_resource_remap[res]);
+ remap_nested_resources(res, p_resource_remap);
+ }
+ }
+ }
}
- List<GroupInfo> groups;
- get_groups(&groups);
-
- for (List<GroupInfo>::Element *E = groups.front(); E; E = E->next()) {
- node->add_to_group(E->get().name, E->get().persistent);
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ remap_node_resources(p_node->get_child(i), p_resource_remap);
}
+}
- node->set_name(get_name());
- p_new_parent->add_child(node);
-
- Node *owner = get_owner();
+void Node::remap_nested_resources(RES p_resource, const Map<RES, RES> &p_resource_remap) const {
+ List<PropertyInfo> props;
+ p_resource->get_property_list(&props);
- if (p_reown_map.has(owner)) {
- owner = p_reown_map[owner];
- }
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ continue;
+ }
- if (owner) {
- NodePath p = get_path_to(owner);
- if (owner != this) {
- Node *new_owner = node->get_node(p);
- if (new_owner) {
- node->set_owner(new_owner);
+ Variant v = p_resource->get(E->get().name);
+ if (v.is_ref()) {
+ RES res = v;
+ if (res.is_valid()) {
+ if (p_resource_remap.has(res)) {
+ p_resource->set(E->get().name, p_resource_remap[res]);
+ remap_nested_resources(res, p_resource_remap);
+ }
}
}
}
-
- for (int i = 0; i < get_child_count(); i++) {
- get_child(i)->_duplicate_and_reown(node, p_reown_map);
- }
}
+#endif
// Duplication of signals must happen after all the node descendants have been copied,
// because re-targeting of connections from some descendant to another is not possible
@@ -2279,49 +2315,6 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const {
}
}
-Node *Node::duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const {
- ERR_FAIL_COND_V(get_filename() != "", nullptr);
-
- Object *obj = ClassDB::instance(get_class());
- ERR_FAIL_COND_V_MSG(!obj, nullptr, "Node: Could not duplicate: " + String(get_class()) + ".");
-
- Node *node = Object::cast_to<Node>(obj);
- if (!node) {
- memdelete(obj);
- ERR_FAIL_V_MSG(nullptr, "Node: Could not duplicate: " + String(get_class()) + ".");
- }
- node->set_name(get_name());
-
- List<PropertyInfo> plist;
-
- get_property_list(&plist);
-
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
- continue;
- }
- String name = E->get().name;
- node->set(name, get(name));
- }
-
- List<GroupInfo> groups;
- get_groups(&groups);
-
- for (List<GroupInfo>::Element *E = groups.front(); E; E = E->next()) {
- node->add_to_group(E->get().name, E->get().persistent);
- }
-
- for (int i = 0; i < get_child_count(); i++) {
- get_child(i)->_duplicate_and_reown(node, p_reown_map);
- }
-
- // Duplication of signals must happen after all the node descendants have been copied,
- // because re-targeting of connections from some descendant to another is not possible
- // if the emitter node comes later in tree order than the receiver
- _duplicate_signals(this, node);
- return node;
-}
-
static void find_owned_by(Node *p_by, Node *p_node, List<Node *> *p_owned) {
if (p_node->get_owner() == p_by) {
p_owned->push_back(p_node);
@@ -2676,10 +2669,10 @@ void Node::request_ready() {
}
void Node::_bind_methods() {
- GLOBAL_DEF("node/name_num_separator", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("node/name_num_separator", PropertyInfo(Variant::INT, "node/name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash"));
- GLOBAL_DEF("node/name_casing", NAME_CASING_PASCAL_CASE);
- ProjectSettings::get_singleton()->set_custom_property_info("node/name_casing", PropertyInfo(Variant::INT, "node/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case"));
+ GLOBAL_DEF("editor/node_naming/name_num_separator", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("editor/node_naming/name_num_separator", PropertyInfo(Variant::INT, "editor/node_naming/name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash"));
+ 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_method(D_METHOD("add_sibling", "sibling", "legible_unique_name"), &Node::add_sibling, DEFVAL(false));
@@ -2734,8 +2727,8 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_processing_unhandled_input"), &Node::is_processing_unhandled_input);
ClassDB::bind_method(D_METHOD("set_process_unhandled_key_input", "enable"), &Node::set_process_unhandled_key_input);
ClassDB::bind_method(D_METHOD("is_processing_unhandled_key_input"), &Node::is_processing_unhandled_key_input);
- ClassDB::bind_method(D_METHOD("set_pause_mode", "mode"), &Node::set_pause_mode);
- ClassDB::bind_method(D_METHOD("get_pause_mode"), &Node::get_pause_mode);
+ 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_stray_nodes"), &Node::_print_stray_nodes);
@@ -2773,12 +2766,12 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("rpc_config", "method", "mode"), &Node::rpc_config);
ClassDB::bind_method(D_METHOD("rset_config", "property", "mode"), &Node::rset_config);
- ClassDB::bind_method(D_METHOD("_set_editor_description", "editor_description"), &Node::set_editor_description);
- ClassDB::bind_method(D_METHOD("_get_editor_description"), &Node::get_editor_description);
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "editor_description", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_editor_description", "_get_editor_description");
+ ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description);
+ ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description);
ClassDB::bind_method(D_METHOD("_set_import_path", "import_path"), &Node::set_import_path);
ClassDB::bind_method(D_METHOD("_get_import_path"), &Node::get_import_path);
+
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "_import_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_import_path", "_get_import_path");
{
@@ -2842,9 +2835,11 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_OUT);
BIND_CONSTANT(NOTIFICATION_TEXT_SERVER_CHANGED);
- BIND_ENUM_CONSTANT(PAUSE_MODE_INHERIT);
- BIND_ENUM_CONSTANT(PAUSE_MODE_STOP);
- BIND_ENUM_CONSTANT(PAUSE_MODE_PROCESS);
+ BIND_ENUM_CONSTANT(PROCESS_MODE_INHERIT);
+ BIND_ENUM_CONSTANT(PROCESS_MODE_PAUSABLE);
+ BIND_ENUM_CONSTANT(PROCESS_MODE_WHEN_PAUSED);
+ BIND_ENUM_CONSTANT(PROCESS_MODE_ALWAYS);
+ BIND_ENUM_CONSTANT(PROCESS_MODE_DISABLED);
BIND_ENUM_CONSTANT(DUPLICATE_SIGNALS);
BIND_ENUM_CONSTANT(DUPLICATE_GROUPS);
@@ -2857,15 +2852,19 @@ void Node::_bind_methods() {
ADD_SIGNAL(MethodInfo("tree_exiting"));
ADD_SIGNAL(MethodInfo("tree_exited"));
- ADD_PROPERTY(PropertyInfo(Variant::INT, "pause_mode", PROPERTY_HINT_ENUM, "Inherit,Stop,Process"), "set_pause_mode", "get_pause_mode");
-
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "name", PROPERTY_HINT_NONE, "", 0), "set_name", "get_name");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "filename", PROPERTY_HINT_NONE, "", 0), "set_filename", "get_filename");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "owner", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_owner", "get_owner");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "", "get_multiplayer");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "set_custom_multiplayer", "get_custom_multiplayer");
+
+ ADD_GROUP("Process", "process_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Inherit,Pausable,WhenPaused,Always,Disabled"), "set_process_mode", "get_process_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_priority"), "set_process_priority", "get_process_priority");
+ ADD_GROUP("Editor Description", "editor_");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "editor_description", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "set_editor_description", "get_editor_description");
+
BIND_VMETHOD(MethodInfo("_process", PropertyInfo(Variant::FLOAT, "delta")));
BIND_VMETHOD(MethodInfo("_physics_process", PropertyInfo(Variant::FLOAT, "delta")));
BIND_VMETHOD(MethodInfo("_enter_tree"));
@@ -2878,7 +2877,7 @@ void Node::_bind_methods() {
}
String Node::_get_name_num_separator() {
- switch (ProjectSettings::get_singleton()->get("node/name_num_separator").operator int()) {
+ switch (ProjectSettings::get_singleton()->get("editor/node_naming/name_num_separator").operator int()) {
case 0:
return "";
case 1:
diff --git a/scene/main/node.h b/scene/main/node.h
index a0dca75791..b1e51d2aee 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -46,10 +46,12 @@ class Node : public Object {
OBJ_CATEGORY("Nodes");
public:
- enum PauseMode {
- PAUSE_MODE_INHERIT,
- PAUSE_MODE_STOP,
- PAUSE_MODE_PROCESS
+ enum ProcessMode {
+ PROCESS_MODE_INHERIT, // same as parent node
+ PROCESS_MODE_PAUSABLE, // process only if not paused
+ PROCESS_MODE_WHEN_PAUSED, // process only if paused
+ PROCESS_MODE_ALWAYS, // process always
+ PROCESS_MODE_DISABLED, // never process
};
enum DuplicateFlags {
@@ -80,7 +82,7 @@ private:
struct NetData {
StringName name;
- MultiplayerAPI::RPCMode mode;
+ MultiplayerAPI::RPCMode mode = MultiplayerAPI::RPCMode::RPC_MODE_DISABLED;
};
struct Data {
@@ -102,6 +104,7 @@ private:
#ifdef TOOLS_ENABLED
NodePath import_path; // Path used when imported, used by scene editors to keep tracking.
#endif
+ String editor_description;
Viewport *viewport = nullptr;
@@ -109,8 +112,8 @@ private:
List<Node *>::Element *OW = nullptr; // Owned element.
List<Node *> owned;
- PauseMode pause_mode = PAUSE_MODE_INHERIT;
- Node *pause_owner = nullptr;
+ ProcessMode process_mode = PROCESS_MODE_INHERIT;
+ Node *process_owner = nullptr;
int network_master = 1; // Server by default.
Vector<NetData> rpc_methods;
@@ -166,11 +169,10 @@ private:
void _propagate_after_exit_tree();
void _propagate_validate_owner();
void _print_stray_nodes();
- void _propagate_pause_owner(Node *p_owner);
+ void _propagate_process_owner(Node *p_owner, int p_notification);
Array _get_node_and_resource(const NodePath &p_path);
void _duplicate_signals(const Node *p_original, Node *p_copy) const;
- void _duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p_reown_map) const;
Node *_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap = nullptr) const;
TypedArray<Node> _get_children() const;
@@ -184,12 +186,9 @@ private:
friend class SceneTree;
void _set_tree(SceneTree *p_tree);
+ void _propagate_pause_notification(bool p_enable);
-#ifdef TOOLS_ENABLED
- friend class SceneTreeEditor;
-#endif
- static String invalid_character;
- static bool _validate_node_name(String &p_name);
+ _FORCE_INLINE_ bool _can_process(bool p_paused) const;
protected:
void _block() { data.blocked++; }
@@ -297,7 +296,7 @@ public:
struct GroupInfo {
StringName name;
- bool persistent;
+ bool persistent = false;
};
void get_groups(List<GroupInfo> *p_groups) const;
@@ -324,6 +323,7 @@ public:
void set_editable_instance(Node *p_node, bool p_editable);
bool is_editable_instance(const Node *p_node) const;
+ Node *get_deepest_editable_node(Node *p_start_node) const;
/* NOTIFICATIONS */
@@ -359,9 +359,11 @@ public:
bool is_processing_unhandled_key_input() const;
Node *duplicate(int p_flags = DUPLICATE_GROUPS | DUPLICATE_SIGNALS | DUPLICATE_SCRIPTS) const;
- Node *duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const;
#ifdef TOOLS_ENABLED
Node *duplicate_from_editor(Map<const Node *, Node *> &r_duplimap) const;
+ Node *duplicate_from_editor(Map<const Node *, Node *> &r_duplimap, const Map<RES, RES> &p_resource_remap) const;
+ void remap_node_resources(Node *p_node, const Map<RES, RES> &p_resource_remap) const;
+ void remap_nested_resources(RES p_resource, const Map<RES, RES> &p_resource_remap) const;
#endif
// used by editors, to save what has changed only
@@ -378,8 +380,8 @@ public:
void replace_by(Node *p_node, bool p_keep_data = false);
- void set_pause_mode(PauseMode p_mode);
- PauseMode get_pause_mode() const;
+ void set_process_mode(ProcessMode p_mode);
+ ProcessMode get_process_mode() const;
bool can_process() const;
bool can_process_notification(int p_what) const;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 1c9d81e87c..66f3a2ebde 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -54,6 +54,7 @@
#include "window.h"
#include <stdio.h>
+#include <stdlib.h>
void SceneTreeTimer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_time_left", "time"), &SceneTreeTimer::set_time_left);
@@ -72,12 +73,12 @@ float SceneTreeTimer::get_time_left() const {
return time_left;
}
-void SceneTreeTimer::set_pause_mode_process(bool p_pause_mode_process) {
- process_pause = p_pause_mode_process;
+void SceneTreeTimer::set_process_always(bool p_process_always) {
+ process_always = p_process_always;
}
-bool SceneTreeTimer::is_pause_mode_process() {
- return process_pause;
+bool SceneTreeTimer::is_process_always() {
+ return process_always;
}
void SceneTreeTimer::release_connections() {
@@ -90,10 +91,7 @@ void SceneTreeTimer::release_connections() {
}
}
-SceneTreeTimer::SceneTreeTimer() {
- time_left = 0;
- process_pause = true;
-}
+SceneTreeTimer::SceneTreeTimer() {}
void SceneTree::tree_changed() {
tree_version++;
@@ -391,6 +389,7 @@ void SceneTree::set_group(const StringName &p_group, const String &p_name, const
}
void SceneTree::initialize() {
+ ERR_FAIL_COND(!root);
initialized = true;
root->_set_tree(this);
MainLoop::initialize();
@@ -409,6 +408,7 @@ bool SceneTree::physics_process(float p_time) {
emit_signal("physics_frame");
_notify_group_pause("physics_process_internal", Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
+ call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_process_picking");
_notify_group_pause("physics_process", Node::NOTIFICATION_PHYSICS_PROCESS);
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
@@ -457,7 +457,7 @@ bool SceneTree::process(float p_time) {
for (List<Ref<SceneTreeTimer>>::Element *E = timers.front(); E;) {
List<Ref<SceneTreeTimer>>::Element *N = E->next();
- if (pause && !E->get()->is_pause_mode_process()) {
+ if (paused && !E->get()->is_process_always()) {
if (E == L) {
break; //break on last, so if new timers were added during list traversal, ignore them.
}
@@ -486,7 +486,7 @@ bool SceneTree::process(float p_time) {
if (Engine::get_singleton()->is_editor_hint()) {
//simple hack to reload fallback environment if it changed from editor
- String env_path = ProjectSettings::get_singleton()->get("rendering/environment/default_environment");
+ String env_path = ProjectSettings::get_singleton()->get("rendering/environment/defaults/default_environment");
env_path = env_path.strip_edges(); //user may have added a space or two
String cpath;
Ref<Environment> fallback = get_root()->get_world_3d()->get_fallback_environment();
@@ -498,7 +498,7 @@ bool SceneTree::process(float p_time) {
fallback = ResourceLoader::load(env_path);
if (fallback.is_null()) {
//could not load fallback, set as empty
- ProjectSettings::get_singleton()->set("rendering/environment/default_environment", "");
+ ProjectSettings::get_singleton()->set("rendering/environment/defaults/default_environment", "");
}
} else {
fallback.unref();
@@ -536,12 +536,7 @@ void SceneTree::finalize() {
}
void SceneTree::quit(int p_exit_code) {
- if (p_exit_code >= 0) {
- // Override the exit code if a positive argument is given (the default is `-1`).
- // This is a shorthand for calling `set_exit_code()` on the OS singleton then quitting.
- OS::get_singleton()->set_exit_code(p_exit_code);
- }
-
+ OS::get_singleton()->set_exit_code(p_exit_code);
_quit = true;
}
@@ -761,20 +756,20 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() {
}
void SceneTree::set_pause(bool p_enabled) {
- if (p_enabled == pause) {
+ if (p_enabled == paused) {
return;
}
- pause = p_enabled;
+ paused = p_enabled;
NavigationServer3D::get_singleton()->set_active(!p_enabled);
PhysicsServer3D::get_singleton()->set_active(!p_enabled);
PhysicsServer2D::get_singleton()->set_active(!p_enabled);
if (get_root()) {
- get_root()->propagate_notification(p_enabled ? Node::NOTIFICATION_PAUSED : Node::NOTIFICATION_UNPAUSED);
+ get_root()->_propagate_pause_notification(p_enabled);
}
}
bool SceneTree::is_paused() const {
- return pause;
+ return paused;
}
void SceneTree::_notify_group_pause(const StringName &p_group, int p_notification) {
@@ -958,6 +953,21 @@ bool SceneTree::has_group(const StringName &p_identifier) const {
return group_map.has(p_identifier);
}
+Node *SceneTree::get_first_node_in_group(const StringName &p_group) {
+ Map<StringName, Group>::Element *E = group_map.find(p_group);
+ if (!E) {
+ return nullptr; //no group
+ }
+
+ _update_group_order(E->get()); //update order just in case
+
+ if (E->get().nodes.size() == 0) {
+ return nullptr;
+ }
+
+ return E->get().nodes[0];
+}
+
void SceneTree::get_nodes_in_group(const StringName &p_group, List<Node *> *p_list) {
Map<StringName, Group>::Element *E = group_map.find(p_group);
if (!E) {
@@ -1072,10 +1082,10 @@ void SceneTree::add_current_scene(Node *p_current) {
root->add_child(p_current);
}
-Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_pause) {
+Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_always) {
Ref<SceneTreeTimer> stt;
stt.instance();
- stt->set_pause_mode_process(p_process_pause);
+ stt->set_process_always(p_process_always);
stt->set_time_left(p_delay_sec);
timers.push_back(stt);
return stt;
@@ -1188,11 +1198,11 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause);
ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused);
- ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "pause_mode_process"), &SceneTree::create_timer, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "process_always"), &SceneTree::create_timer, DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_node_count"), &SceneTree::get_node_count);
ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame);
- ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(EXIT_SUCCESS));
ClassDB::bind_method(D_METHOD("queue_delete", "obj"), &SceneTree::queue_delete);
@@ -1218,6 +1228,7 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_group", "group", "property", "value"), &SceneTree::set_group);
ClassDB::bind_method(D_METHOD("get_nodes_in_group", "group"), &SceneTree::_get_nodes_in_group);
+ ClassDB::bind_method(D_METHOD("get_first_node_in_group", "group"), &SceneTree::get_first_node_in_group);
ClassDB::bind_method(D_METHOD("set_current_scene", "child_node"), &SceneTree::set_current_scene);
ClassDB::bind_method(D_METHOD("get_current_scene"), &SceneTree::get_current_scene);
@@ -1256,6 +1267,7 @@ void SceneTree::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled");
ADD_SIGNAL(MethodInfo("tree_changed"));
+ ADD_SIGNAL(MethodInfo("tree_process_mode_changed")); //editor only signal, but due to API hash it cant be removed in run-time
ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("node_renamed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
@@ -1328,13 +1340,15 @@ SceneTree::SceneTree() {
if (singleton == nullptr) {
singleton = this;
}
- debug_collisions_color = GLOBAL_DEF("debug/shapes/collision/shape_color", Color(0.0, 0.6, 0.7, 0.5));
+ debug_collisions_color = GLOBAL_DEF("debug/shapes/collision/shape_color", Color(0.0, 0.6, 0.7, 0.42));
debug_collision_contact_color = GLOBAL_DEF("debug/shapes/collision/contact_color", Color(1.0, 0.2, 0.1, 0.8));
debug_navigation_color = GLOBAL_DEF("debug/shapes/navigation/geometry_color", Color(0.1, 1.0, 0.7, 0.4));
debug_navigation_disabled_color = GLOBAL_DEF("debug/shapes/navigation/disabled_geometry_color", Color(1.0, 0.7, 0.1, 0.4));
collision_debug_contacts = GLOBAL_DEF("debug/shapes/collision/max_contacts_displayed", 10000);
ProjectSettings::get_singleton()->set_custom_property_info("debug/shapes/collision/max_contacts_displayed", PropertyInfo(Variant::INT, "debug/shapes/collision/max_contacts_displayed", PROPERTY_HINT_RANGE, "0,20000,1")); // No negative
+ GLOBAL_DEF("debug/shapes/collision/draw_2d_outlines", true);
+
// Create with mainloop.
root = memnew(Window);
@@ -1351,39 +1365,39 @@ SceneTree::SceneTree() {
root->set_as_audio_listener_2d(true);
current_scene = nullptr;
- const int msaa_mode = GLOBAL_DEF("rendering/quality/screen_filters/msaa", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/screen_filters/msaa", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Fast),4x (Average),8x (Slow),16x (Slower)"));
+ const int msaa_mode = GLOBAL_DEF("rendering/anti_aliasing/quality/msaa", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/msaa", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Fast),4x (Average),8x (Slow),16x (Slower)"));
root->set_msaa(Viewport::MSAA(msaa_mode));
- const int ssaa_mode = GLOBAL_DEF("rendering/quality/screen_filters/screen_space_aa", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_aa", PropertyInfo(Variant::INT, "rendering/quality/screen_filters/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"));
+ const int ssaa_mode = GLOBAL_DEF("rendering/anti_aliasing/quality/screen_space_aa", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/screen_space_aa", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"));
root->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
- const bool use_debanding = GLOBAL_DEF("rendering/quality/screen_filters/use_debanding", false);
+ const bool use_debanding = GLOBAL_DEF("rendering/anti_aliasing/quality/use_debanding", false);
root->set_use_debanding(use_debanding);
- float lod_threshold = GLOBAL_DEF("rendering/quality/mesh_lod/threshold_pixels", 1.0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/mesh_lod/threshold_pixels", PropertyInfo(Variant::FLOAT, "rendering/quality/mesh_lod/threshold_pixels", PROPERTY_HINT_RANGE, "0,1024,0.1"));
+ float lod_threshold = GLOBAL_DEF("rendering/mesh_lod/lod_change/threshold_pixels", 1.0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/mesh_lod/lod_change/threshold_pixels", PropertyInfo(Variant::FLOAT, "rendering/mesh_lod/lod_change/threshold_pixels", PROPERTY_HINT_RANGE, "0,1024,0.1"));
root->set_lod_threshold(lod_threshold);
- bool snap_2d_transforms = GLOBAL_DEF("rendering/quality/2d/snap_2d_transforms_to_pixel", false);
+ bool snap_2d_transforms = GLOBAL_DEF("rendering/2d/snap/snap_2d_transforms_to_pixel", false);
root->set_snap_2d_transforms_to_pixel(snap_2d_transforms);
- bool snap_2d_vertices = GLOBAL_DEF("rendering/quality/2d/snap_2d_vertices_to_pixel", false);
+ bool snap_2d_vertices = GLOBAL_DEF("rendering/2d/snap/snap_2d_vertices_to_pixel", false);
root->set_snap_2d_vertices_to_pixel(snap_2d_vertices);
- int shadowmap_size = GLOBAL_DEF("rendering/quality/shadow_atlas/size", 4096);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384"));
- GLOBAL_DEF("rendering/quality/shadow_atlas/size.mobile", 2048);
- bool shadowmap_16_bits = GLOBAL_DEF("rendering/quality/shadow_atlas/16_bits", true);
- int atlas_q0 = GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_0_subdiv", 2);
- int atlas_q1 = GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_1_subdiv", 2);
- int atlas_q2 = GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_2_subdiv", 3);
- int atlas_q3 = GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_3_subdiv", 4);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+ int shadowmap_size = GLOBAL_DEF("rendering/shadows/shadow_atlas/size", 4096);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384"));
+ GLOBAL_DEF("rendering/shadows/shadow_atlas/size.mobile", 2048);
+ bool shadowmap_16_bits = GLOBAL_DEF("rendering/shadows/shadow_atlas/16_bits", true);
+ int atlas_q0 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_0_subdiv", 2);
+ int atlas_q1 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_1_subdiv", 2);
+ int atlas_q2 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_2_subdiv", 3);
+ int atlas_q3 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_3_subdiv", 4);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
root->set_shadow_atlas_size(shadowmap_size);
root->set_shadow_atlas_16_bits(shadowmap_16_bits);
@@ -1392,13 +1406,13 @@ SceneTree::SceneTree() {
root->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2));
root->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3));
- Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_DEF("rendering/quality/2d_sdf/oversize", 1)));
+ Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_DEF("rendering/2d/sdf/oversize", 1)));
root->set_sdf_oversize(sdf_oversize);
- Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_DEF("rendering/quality/2d_sdf/scale", 1)));
+ Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_DEF("rendering/2d/sdf/scale", 1)));
root->set_sdf_scale(sdf_scale);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/2d_sdf/oversize", PropertyInfo(Variant::INT, "rendering/quality/2d_sdf/oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/2d_sdf/scale", PropertyInfo(Variant::INT, "rendering/quality/2d_sdf/scale", PROPERTY_HINT_ENUM, "100%,50%,25%"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/sdf/oversize", PropertyInfo(Variant::INT, "rendering/2d/sdf/oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/sdf/scale", PropertyInfo(Variant::INT, "rendering/2d/sdf/scale", PROPERTY_HINT_ENUM, "100%,50%,25%"));
{ // Load default fallback environment.
// Get possible extensions.
@@ -1412,9 +1426,9 @@ SceneTree::SceneTree() {
ext_hint += "*." + E->get();
}
// Get path.
- String env_path = GLOBAL_DEF("rendering/environment/default_environment", "");
+ String env_path = GLOBAL_DEF("rendering/environment/defaults/default_environment", "");
// Setup property.
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/default_environment", PropertyInfo(Variant::STRING, "rendering/viewport/default_environment", PROPERTY_HINT_FILE, ext_hint));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/defaults/default_environment", PropertyInfo(Variant::STRING, "rendering/viewport/default_environment", PROPERTY_HINT_FILE, ext_hint));
env_path = env_path.strip_edges();
if (env_path != String()) {
Ref<Environment> env = ResourceLoader::load(env_path);
@@ -1423,7 +1437,7 @@ SceneTree::SceneTree() {
} else {
if (Engine::get_singleton()->is_editor_hint()) {
// File was erased, clear the field.
- ProjectSettings::get_singleton()->set("rendering/environment/default_environment", "");
+ ProjectSettings::get_singleton()->set("rendering/environment/defaults/default_environment", "");
} else {
// File was erased, notify user.
ERR_PRINT(RTR("Default Environment as specified in Project Settings (Rendering -> Environment -> Default Environment) could not be loaded."));
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 748908c8a6..a2f2adb8f8 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -51,8 +51,8 @@ class SceneDebugger;
class SceneTreeTimer : public Reference {
GDCLASS(SceneTreeTimer, Reference);
- float time_left;
- bool process_pause;
+ float time_left = 0.0;
+ bool process_always = true;
protected:
static void _bind_methods();
@@ -61,8 +61,8 @@ public:
void set_time_left(float p_time);
float get_time_left() const;
- void set_pause_mode_process(bool p_pause_mode_process);
- bool is_pause_mode_process();
+ void set_process_always(bool p_process_always);
+ bool is_process_always();
void release_connections();
@@ -80,8 +80,7 @@ public:
private:
struct Group {
Vector<Node *> nodes;
- bool changed;
- Group() { changed = false; };
+ bool changed = false;
};
Window *root = nullptr;
@@ -96,7 +95,7 @@ private:
bool debug_collisions_hint = false;
bool debug_navigation_hint = false;
#endif
- bool pause = false;
+ bool paused = false;
int root_lock = 0;
Map<StringName, Group> group_map;
@@ -246,7 +245,7 @@ public:
void set_auto_accept_quit(bool p_enable);
void set_quit_on_go_back(bool p_enable);
- void quit(int p_exit_code = -1);
+ void quit(int p_exit_code = EXIT_SUCCESS);
_FORCE_INLINE_ float get_physics_process_time() const { return physics_process_time; }
_FORCE_INLINE_ float get_process_time() const { return process_time; }
@@ -303,6 +302,7 @@ public:
void queue_delete(Object *p_object);
void get_nodes_in_group(const StringName &p_group, List<Node *> *p_list);
+ Node *get_first_node_in_group(const StringName &p_group);
bool has_group(const StringName &p_identifier) const;
//void change_scene(const String& p_path);
@@ -317,7 +317,7 @@ public:
Error change_scene_to(const Ref<PackedScene> &p_scene);
Error reload_current_scene();
- Ref<SceneTreeTimer> create_timer(float p_delay_sec, bool p_process_pause = true);
+ Ref<SceneTreeTimer> create_timer(float p_delay_sec, bool p_process_always = true);
//used by Main::start, don't use otherwise
void add_current_scene(Node *p_current);
diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp
index 4485cffff5..b6b2982155 100644
--- a/scene/main/shader_globals_override.cpp
+++ b/scene/main/shader_globals_override.cpp
@@ -277,6 +277,4 @@ void ShaderGlobalsOverride::_bind_methods() {
ClassDB::bind_method(D_METHOD("_activate"), &ShaderGlobalsOverride::_activate);
}
-ShaderGlobalsOverride::ShaderGlobalsOverride() {
- active = false;
-}
+ShaderGlobalsOverride::ShaderGlobalsOverride() {}
diff --git a/scene/main/shader_globals_override.h b/scene/main/shader_globals_override.h
index 9e666a0ec5..8d8794d465 100644
--- a/scene/main/shader_globals_override.h
+++ b/scene/main/shader_globals_override.h
@@ -43,7 +43,7 @@ class ShaderGlobalsOverride : public Node {
StringName *_remap(const StringName &p_name) const;
- bool active;
+ bool active = false;
mutable HashMap<StringName, Override> overrides;
mutable HashMap<StringName, StringName> param_remaps;
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index d7b2292ff5..4bc159f6aa 100644
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -46,7 +46,7 @@ void Timer::_notification(int p_what) {
}
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
- if (!processing || timer_process_mode == TIMER_PROCESS_PHYSICS || !is_processing_internal()) {
+ if (!processing || timer_process_callback == TIMER_PROCESS_PHYSICS || !is_processing_internal()) {
return;
}
time_left -= get_process_delta_time();
@@ -63,7 +63,7 @@ void Timer::_notification(int p_what) {
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
- if (!processing || timer_process_mode == TIMER_PROCESS_IDLE || !is_physics_processing_internal()) {
+ if (!processing || timer_process_callback == TIMER_PROCESS_IDLE || !is_physics_processing_internal()) {
return;
}
time_left -= get_physics_process_delta_time();
@@ -143,12 +143,12 @@ float Timer::get_time_left() const {
return time_left > 0 ? time_left : 0;
}
-void Timer::set_timer_process_mode(TimerProcessMode p_mode) {
- if (timer_process_mode == p_mode) {
+void Timer::set_timer_process_callback(TimerProcessCallback p_callback) {
+ if (timer_process_callback == p_callback) {
return;
}
- switch (timer_process_mode) {
+ switch (timer_process_callback) {
case TIMER_PROCESS_PHYSICS:
if (is_physics_processing_internal()) {
set_physics_process_internal(false);
@@ -162,15 +162,15 @@ void Timer::set_timer_process_mode(TimerProcessMode p_mode) {
}
break;
}
- timer_process_mode = p_mode;
+ timer_process_callback = p_callback;
}
-Timer::TimerProcessMode Timer::get_timer_process_mode() const {
- return timer_process_mode;
+Timer::TimerProcessCallback Timer::get_timer_process_callback() const {
+ return timer_process_callback;
}
void Timer::_set_process(bool p_process, bool p_force) {
- switch (timer_process_mode) {
+ switch (timer_process_callback) {
case TIMER_PROCESS_PHYSICS:
set_physics_process_internal(p_process && !paused);
break;
@@ -201,12 +201,12 @@ void Timer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_time_left"), &Timer::get_time_left);
- ClassDB::bind_method(D_METHOD("set_timer_process_mode", "mode"), &Timer::set_timer_process_mode);
- ClassDB::bind_method(D_METHOD("get_timer_process_mode"), &Timer::get_timer_process_mode);
+ ClassDB::bind_method(D_METHOD("set_timer_process_callback", "callback"), &Timer::set_timer_process_callback);
+ ClassDB::bind_method(D_METHOD("get_timer_process_callback"), &Timer::get_timer_process_callback);
ADD_SIGNAL(MethodInfo("timeout"));
- ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_timer_process_mode", "get_timer_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_timer_process_callback", "get_timer_process_callback");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wait_time", PROPERTY_HINT_EXP_RANGE, "0.001,4096,0.001,or_greater"), "set_wait_time", "get_wait_time");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "is_one_shot");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autostart"), "set_autostart", "has_autostart");
@@ -217,12 +217,4 @@ void Timer::_bind_methods() {
BIND_ENUM_CONSTANT(TIMER_PROCESS_IDLE);
}
-Timer::Timer() {
- timer_process_mode = TIMER_PROCESS_IDLE;
- autostart = false;
- wait_time = 1;
- one_shot = false;
- time_left = -1;
- processing = false;
- paused = false;
-}
+Timer::Timer() {}
diff --git a/scene/main/timer.h b/scene/main/timer.h
index 0604a2d990..3d9e21d7fc 100644
--- a/scene/main/timer.h
+++ b/scene/main/timer.h
@@ -36,20 +36,20 @@
class Timer : public Node {
GDCLASS(Timer, Node);
- float wait_time;
- bool one_shot;
- bool autostart;
- bool processing;
- bool paused;
+ float wait_time = 1.0;
+ bool one_shot = false;
+ bool autostart = false;
+ bool processing = false;
+ bool paused = false;
- double time_left;
+ double time_left = -1.0;
protected:
void _notification(int p_what);
static void _bind_methods();
public:
- enum TimerProcessMode {
+ enum TimerProcessCallback {
TIMER_PROCESS_PHYSICS,
TIMER_PROCESS_IDLE,
};
@@ -73,15 +73,15 @@ public:
float get_time_left() const;
- void set_timer_process_mode(TimerProcessMode p_mode);
- TimerProcessMode get_timer_process_mode() const;
+ void set_timer_process_callback(TimerProcessCallback p_callback);
+ TimerProcessCallback get_timer_process_callback() const;
Timer();
private:
- TimerProcessMode timer_process_mode;
+ TimerProcessCallback timer_process_callback = TIMER_PROCESS_IDLE;
void _set_process(bool p_process, bool p_force = false);
};
-VARIANT_ENUM_CAST(Timer::TimerProcessMode);
+VARIANT_ENUM_CAST(Timer::TimerProcessCallback);
#endif // TIMER_H
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 82053e1557..c6fe1117d1 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -144,7 +144,6 @@ void ViewportTexture::_bind_methods() {
}
ViewportTexture::ViewportTexture() {
- vp = nullptr;
set_local_to_scene(true);
}
@@ -184,26 +183,6 @@ public:
/////////////////////////////////////
-Viewport::GUI::GUI() {
- embed_subwindows_hint = false;
- embedding_subwindows = false;
-
- dragging = false;
- mouse_focus = nullptr;
- forced_mouse_focus = false;
- mouse_click_grabber = nullptr;
- mouse_focus_mask = 0;
- key_focus = nullptr;
- mouse_over = nullptr;
- drag_mouse_over = nullptr;
-
- tooltip_control = nullptr;
- tooltip_popup = nullptr;
- tooltip_label = nullptr;
-}
-
-/////////////////////////////////////
-
void Viewport::update_worlds() {
if (!is_inside_tree()) {
return;
@@ -299,6 +278,11 @@ void Viewport::_sub_window_update(Window *p_window) {
int x = (r.size.width - title_text.get_size().x) / 2;
int y = (-title_height - title_text.get_size().y) / 2;
+ Color font_outline_color = p_window->get_theme_color("title_outline_modulate");
+ int outline_size = p_window->get_theme_constant("title_outline_size");
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ title_text.draw_outline(sw.canvas_item, r.position + Point2(x, y), outline_size, font_outline_color);
+ }
title_text.draw(sw.canvas_item, r.position + Point2(x, y), title_color);
bool hl = gui.subwindow_focused == sw.window && gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE && gui.subwindow_drag_close_inside;
@@ -468,7 +452,7 @@ void Viewport::_notification(int p_what) {
//3D
PhysicsServer3D::get_singleton()->space_set_debug_contacts(find_world_3d()->get_space(), get_tree()->get_collision_debug_contact_count());
contact_3d_debug_multimesh = RenderingServer::get_singleton()->multimesh_create();
- RenderingServer::get_singleton()->multimesh_allocate(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), RS::MULTIMESH_TRANSFORM_3D, true);
+ RenderingServer::get_singleton()->multimesh_allocate_data(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), RS::MULTIMESH_TRANSFORM_3D, true);
RenderingServer::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, 0);
RenderingServer::get_singleton()->multimesh_set_mesh(contact_3d_debug_multimesh, get_tree()->get_debug_contact_mesh()->get_rid());
contact_3d_debug_instance = RenderingServer::get_singleton()->instance_create();
@@ -567,280 +551,297 @@ void Viewport::_notification(int p_what) {
int point_count = PhysicsServer3D::get_singleton()->space_get_contact_count(find_world_3d()->get_space());
RS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, point_count);
+
+ for (int i = 0; i < point_count; i++) {
+ Transform point_transform;
+ point_transform.origin = points[i];
+ RS::get_singleton()->multimesh_instance_set_transform(contact_3d_debug_multimesh, i, point_transform);
+ }
+ }
+ } break;
+ case NOTIFICATION_WM_MOUSE_EXIT: {
+ _drop_physics_mouseover();
+
+ // Unlike on loss of focus (NOTIFICATION_WM_WINDOW_FOCUS_OUT), do not
+ // drop the gui mouseover here, as a scrollbar may be dragged while the
+ // mouse is outside the window (without the window having lost focus).
+ // See bug #39634
+ } break;
+ case NOTIFICATION_WM_WINDOW_FOCUS_OUT: {
+ _drop_physics_mouseover();
+
+ if (gui.mouse_focus && !gui.forced_mouse_focus) {
+ _drop_mouse_focus();
}
+ } break;
+ }
+}
+
+void Viewport::_process_picking() {
+ if (!is_inside_tree()) {
+ return;
+ }
+ if (!physics_object_picking) {
+ return;
+ }
+ if (to_screen_rect != Rect2i() && Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED) {
+ return;
+ }
+
+ _drop_physics_mouseover(true);
- if (physics_object_picking && (to_screen_rect == Rect2i() || Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED)) {
#ifndef _3D_DISABLED
- Vector2 last_pos(1e20, 1e20);
- CollisionObject3D *last_object = nullptr;
- ObjectID last_id;
+ Vector2 last_pos(1e20, 1e20);
+ CollisionObject3D *last_object = nullptr;
+ ObjectID last_id;
#endif
- PhysicsDirectSpaceState3D::RayResult result;
- PhysicsDirectSpaceState2D *ss2d = PhysicsServer2D::get_singleton()->space_get_direct_state(find_world_2d()->get_space());
-
- if (physics_has_last_mousepos) {
- // if no mouse event exists, create a motion one. This is necessary because objects or camera may have moved.
- // while this extra event is sent, it is checked if both camera and last object and last ID did not move. If nothing changed, the event is discarded to avoid flooding with unnecessary motion events every frame
- bool has_mouse_event = false;
- for (List<Ref<InputEvent>>::Element *E = physics_picking_events.front(); E; E = E->next()) {
- Ref<InputEventMouse> m = E->get();
- if (m.is_valid()) {
- has_mouse_event = true;
- break;
- }
- }
+ PhysicsDirectSpaceState3D::RayResult result;
+ PhysicsDirectSpaceState2D *ss2d = PhysicsServer2D::get_singleton()->space_get_direct_state(find_world_2d()->get_space());
+
+ if (physics_has_last_mousepos) {
+ // if no mouse event exists, create a motion one. This is necessary because objects or camera may have moved.
+ // while this extra event is sent, it is checked if both camera and last object and last ID did not move. If nothing changed, the event is discarded to avoid flooding with unnecessary motion events every frame
+ bool has_mouse_event = false;
+ for (List<Ref<InputEvent>>::Element *E = physics_picking_events.front(); E; E = E->next()) {
+ Ref<InputEventMouse> m = E->get();
+ if (m.is_valid()) {
+ has_mouse_event = true;
+ break;
+ }
+ }
- if (!has_mouse_event) {
- Ref<InputEventMouseMotion> mm;
- mm.instance();
-
- mm->set_device(InputEvent::DEVICE_ID_INTERNAL);
- mm->set_global_position(physics_last_mousepos);
- mm->set_position(physics_last_mousepos);
- mm->set_alt(physics_last_mouse_state.alt);
- mm->set_shift(physics_last_mouse_state.shift);
- mm->set_control(physics_last_mouse_state.control);
- mm->set_metakey(physics_last_mouse_state.meta);
- mm->set_button_mask(physics_last_mouse_state.mouse_mask);
- physics_picking_events.push_back(mm);
- }
- }
+ if (!has_mouse_event) {
+ Ref<InputEventMouseMotion> mm;
+ mm.instance();
- while (physics_picking_events.size()) {
- Ref<InputEvent> ev = physics_picking_events.front()->get();
- physics_picking_events.pop_front();
+ mm->set_device(InputEvent::DEVICE_ID_INTERNAL);
+ mm->set_global_position(physics_last_mousepos);
+ mm->set_position(physics_last_mousepos);
+ mm->set_alt(physics_last_mouse_state.alt);
+ mm->set_shift(physics_last_mouse_state.shift);
+ mm->set_control(physics_last_mouse_state.control);
+ mm->set_metakey(physics_last_mouse_state.meta);
+ mm->set_button_mask(physics_last_mouse_state.mouse_mask);
+ physics_picking_events.push_back(mm);
+ }
+ }
- Vector2 pos;
- bool is_mouse = false;
+ while (physics_picking_events.size()) {
+ Ref<InputEvent> ev = physics_picking_events.front()->get();
+ physics_picking_events.pop_front();
- Ref<InputEventMouseMotion> mm = ev;
+ Vector2 pos;
+ bool is_mouse = false;
- if (mm.is_valid()) {
- pos = mm->get_position();
- is_mouse = true;
+ Ref<InputEventMouseMotion> mm = ev;
- physics_has_last_mousepos = true;
- physics_last_mousepos = pos;
- physics_last_mouse_state.alt = mm->get_alt();
- physics_last_mouse_state.shift = mm->get_shift();
- physics_last_mouse_state.control = mm->get_control();
- physics_last_mouse_state.meta = mm->get_metakey();
- physics_last_mouse_state.mouse_mask = mm->get_button_mask();
- }
+ if (mm.is_valid()) {
+ pos = mm->get_position();
+ is_mouse = true;
- Ref<InputEventMouseButton> mb = ev;
+ physics_has_last_mousepos = true;
+ physics_last_mousepos = pos;
+ physics_last_mouse_state.alt = mm->get_alt();
+ physics_last_mouse_state.shift = mm->get_shift();
+ physics_last_mouse_state.control = mm->get_control();
+ physics_last_mouse_state.meta = mm->get_metakey();
+ physics_last_mouse_state.mouse_mask = mm->get_button_mask();
+ }
- if (mb.is_valid()) {
- pos = mb->get_position();
- is_mouse = true;
+ Ref<InputEventMouseButton> mb = ev;
- physics_has_last_mousepos = true;
- physics_last_mousepos = pos;
- physics_last_mouse_state.alt = mb->get_alt();
- physics_last_mouse_state.shift = mb->get_shift();
- physics_last_mouse_state.control = mb->get_control();
- physics_last_mouse_state.meta = mb->get_metakey();
+ if (mb.is_valid()) {
+ pos = mb->get_position();
+ is_mouse = true;
- if (mb->is_pressed()) {
- physics_last_mouse_state.mouse_mask |= (1 << (mb->get_button_index() - 1));
- } else {
- physics_last_mouse_state.mouse_mask &= ~(1 << (mb->get_button_index() - 1));
+ physics_has_last_mousepos = true;
+ physics_last_mousepos = pos;
+ physics_last_mouse_state.alt = mb->get_alt();
+ physics_last_mouse_state.shift = mb->get_shift();
+ physics_last_mouse_state.control = mb->get_control();
+ physics_last_mouse_state.meta = mb->get_metakey();
- // If touch mouse raised, assume we don't know last mouse pos until new events come
- if (mb->get_device() == InputEvent::DEVICE_ID_TOUCH_MOUSE) {
- physics_has_last_mousepos = false;
- }
- }
- }
+ if (mb->is_pressed()) {
+ physics_last_mouse_state.mouse_mask |= (1 << (mb->get_button_index() - 1));
+ } else {
+ physics_last_mouse_state.mouse_mask &= ~(1 << (mb->get_button_index() - 1));
- Ref<InputEventKey> k = ev;
- if (k.is_valid()) {
- //only for mask
- physics_last_mouse_state.alt = k->get_alt();
- physics_last_mouse_state.shift = k->get_shift();
- physics_last_mouse_state.control = k->get_control();
- physics_last_mouse_state.meta = k->get_metakey();
- continue;
- }
+ // If touch mouse raised, assume we don't know last mouse pos until new events come
+ if (mb->get_device() == InputEvent::DEVICE_ID_TOUCH_MOUSE) {
+ physics_has_last_mousepos = false;
+ }
+ }
+ }
- Ref<InputEventScreenDrag> sd = ev;
+ Ref<InputEventKey> k = ev;
+ if (k.is_valid()) {
+ //only for mask
+ physics_last_mouse_state.alt = k->get_alt();
+ physics_last_mouse_state.shift = k->get_shift();
+ physics_last_mouse_state.control = k->get_control();
+ physics_last_mouse_state.meta = k->get_metakey();
+ continue;
+ }
- if (sd.is_valid()) {
- pos = sd->get_position();
- }
+ Ref<InputEventScreenDrag> sd = ev;
- Ref<InputEventScreenTouch> st = ev;
+ if (sd.is_valid()) {
+ pos = sd->get_position();
+ }
- if (st.is_valid()) {
- pos = st->get_position();
- }
+ Ref<InputEventScreenTouch> st = ev;
- if (ss2d) {
- //send to 2D
+ if (st.is_valid()) {
+ pos = st->get_position();
+ }
- uint64_t frame = get_tree()->get_frame();
+ if (ss2d) {
+ //send to 2D
- PhysicsDirectSpaceState2D::ShapeResult res[64];
- for (Set<CanvasLayer *>::Element *E = canvas_layers.front(); E; E = E->next()) {
- Transform2D canvas_transform;
- ObjectID canvas_layer_id;
- if (E->get()) {
- // A descendant CanvasLayer
- canvas_transform = E->get()->get_transform();
- canvas_layer_id = E->get()->get_instance_id();
- } else {
- // This Viewport's builtin canvas
- canvas_transform = get_canvas_transform();
- canvas_layer_id = ObjectID();
- }
+ uint64_t frame = get_tree()->get_frame();
- Vector2 point = canvas_transform.affine_inverse().xform(pos);
-
- int rc = ss2d->intersect_point_on_canvas(point, canvas_layer_id, res, 64, Set<RID>(), 0xFFFFFFFF, true, true, true);
- for (int i = 0; i < rc; i++) {
- if (res[i].collider_id.is_valid() && res[i].collider) {
- CollisionObject2D *co = Object::cast_to<CollisionObject2D>(res[i].collider);
- if (co) {
- bool send_event = true;
- if (is_mouse) {
- Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id);
-
- if (!F) {
- physics_2d_mouseover.insert(res[i].collider_id, frame);
- co->_mouse_enter();
- } else {
- F->get() = frame;
- // It was already hovered, so don't send the event if it's faked
- if (mm.is_valid() && mm->get_device() == InputEvent::DEVICE_ID_INTERNAL) {
- send_event = false;
- }
- }
- }
-
- if (send_event) {
- co->_input_event(this, ev, res[i].shape);
- }
+ PhysicsDirectSpaceState2D::ShapeResult res[64];
+ for (Set<CanvasLayer *>::Element *E = canvas_layers.front(); E; E = E->next()) {
+ Transform2D canvas_transform;
+ ObjectID canvas_layer_id;
+ if (E->get()) {
+ // A descendant CanvasLayer
+ canvas_transform = E->get()->get_transform();
+ canvas_layer_id = E->get()->get_instance_id();
+ } else {
+ // This Viewport's builtin canvas
+ canvas_transform = get_canvas_transform();
+ canvas_layer_id = ObjectID();
+ }
+
+ Vector2 point = canvas_transform.affine_inverse().xform(pos);
+
+ int rc = ss2d->intersect_point_on_canvas(point, canvas_layer_id, res, 64, Set<RID>(), 0xFFFFFFFF, true, true, true);
+ for (int i = 0; i < rc; i++) {
+ if (res[i].collider_id.is_valid() && res[i].collider) {
+ CollisionObject2D *co = Object::cast_to<CollisionObject2D>(res[i].collider);
+ if (co && co->can_process()) {
+ bool send_event = true;
+ if (is_mouse) {
+ Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id);
+
+ if (!F) {
+ physics_2d_mouseover.insert(res[i].collider_id, frame);
+ co->_mouse_enter();
+ } else {
+ F->get() = frame;
+ // It was already hovered, so don't send the event if it's faked
+ if (mm.is_valid() && mm->get_device() == InputEvent::DEVICE_ID_INTERNAL) {
+ send_event = false;
}
}
}
- }
- if (is_mouse) {
- List<Map<ObjectID, uint64_t>::Element *> to_erase;
-
- for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
- if (E->get() != frame) {
- Object *o = ObjectDB::get_instance(E->key());
- if (o) {
- CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
- if (co) {
- co->_mouse_exit();
- }
- }
- to_erase.push_back(E);
- }
+ if (send_event) {
+ co->_input_event(this, ev, res[i].shape);
}
+ }
+ }
+ }
+ }
+
+ if (is_mouse) {
+ List<Map<ObjectID, uint64_t>::Element *> to_erase;
- while (to_erase.size()) {
- physics_2d_mouseover.erase(to_erase.front()->get());
- to_erase.pop_front();
+ for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
+ if (E->get() != frame) {
+ Object *o = ObjectDB::get_instance(E->key());
+ if (o) {
+ CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
+ if (co) {
+ co->_mouse_exit();
}
}
+ to_erase.push_back(E);
}
+ }
+
+ while (to_erase.size()) {
+ physics_2d_mouseover.erase(to_erase.front()->get());
+ to_erase.pop_front();
+ }
+ }
+ }
#ifndef _3D_DISABLED
- bool captured = false;
-
- if (physics_object_capture.is_valid()) {
- CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_capture));
- if (co && camera) {
- _collision_object_input_event(co, camera, ev, Vector3(), Vector3(), 0);
- captured = true;
- if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) {
- physics_object_capture = ObjectID();
- }
+ bool captured = false;
+
+ if (physics_object_capture.is_valid()) {
+ CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_capture));
+ if (co && camera) {
+ _collision_object_input_event(co, camera, ev, Vector3(), Vector3(), 0);
+ captured = true;
+ if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) {
+ physics_object_capture = ObjectID();
+ }
- } else {
- physics_object_capture = ObjectID();
+ } else {
+ physics_object_capture = ObjectID();
+ }
+ }
+
+ if (captured) {
+ //none
+ } else if (pos == last_pos) {
+ if (last_id.is_valid()) {
+ if (ObjectDB::get_instance(last_id) && last_object) {
+ //good, exists
+ _collision_object_input_event(last_object, camera, ev, result.position, result.normal, result.shape);
+ if (last_object->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
+ physics_object_capture = last_id;
+ }
+ }
+ }
+ } else {
+ if (camera) {
+ Vector3 from = camera->project_ray_origin(pos);
+ Vector3 dir = camera->project_ray_normal(pos);
+
+ PhysicsDirectSpaceState3D *space = PhysicsServer3D::get_singleton()->space_get_direct_state(find_world_3d()->get_space());
+ if (space) {
+ bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true, true, true);
+ ObjectID new_collider;
+ if (col) {
+ CollisionObject3D *co = Object::cast_to<CollisionObject3D>(result.collider);
+ if (co && co->can_process()) {
+ _collision_object_input_event(co, camera, ev, result.position, result.normal, result.shape);
+ last_object = co;
+ last_id = result.collider_id;
+ new_collider = last_id;
+ if (co->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
+ physics_object_capture = last_id;
+ }
}
}
- if (captured) {
- //none
- } else if (pos == last_pos) {
- if (last_id.is_valid()) {
- if (ObjectDB::get_instance(last_id) && last_object) {
- //good, exists
- _collision_object_input_event(last_object, camera, ev, result.position, result.normal, result.shape);
- if (last_object->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
- physics_object_capture = last_id;
- }
+ if (is_mouse && new_collider != physics_object_over) {
+ if (physics_object_over.is_valid()) {
+ CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
+ if (co) {
+ co->_mouse_exit();
}
}
- } else {
- if (camera) {
- Vector3 from = camera->project_ray_origin(pos);
- Vector3 dir = camera->project_ray_normal(pos);
-
- PhysicsDirectSpaceState3D *space = PhysicsServer3D::get_singleton()->space_get_direct_state(find_world_3d()->get_space());
- if (space) {
- bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true, true, true);
- ObjectID new_collider;
- if (col) {
- CollisionObject3D *co = Object::cast_to<CollisionObject3D>(result.collider);
- if (co) {
- _collision_object_input_event(co, camera, ev, result.position, result.normal, result.shape);
- last_object = co;
- last_id = result.collider_id;
- new_collider = last_id;
- if (co->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
- physics_object_capture = last_id;
- }
- }
- }
- if (is_mouse && new_collider != physics_object_over) {
- if (physics_object_over.is_valid()) {
- CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
- if (co) {
- co->_mouse_exit();
- }
- }
-
- if (new_collider.is_valid()) {
- CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(new_collider));
- if (co) {
- co->_mouse_enter();
- }
- }
-
- physics_object_over = new_collider;
- }
+ if (new_collider.is_valid()) {
+ CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(new_collider));
+ if (co) {
+ co->_mouse_enter();
}
-
- last_pos = pos;
}
+
+ physics_object_over = new_collider;
}
-#endif
}
- }
-
- } break;
- case NOTIFICATION_WM_MOUSE_EXIT: {
- _drop_physics_mouseover();
- // Unlike on loss of focus (NOTIFICATION_WM_WINDOW_FOCUS_OUT), do not
- // drop the gui mouseover here, as a scrollbar may be dragged while the
- // mouse is outside the window (without the window having lost focus).
- // See bug #39634
- } break;
- case NOTIFICATION_WM_WINDOW_FOCUS_OUT: {
- _drop_physics_mouseover();
-
- if (gui.mouse_focus && !gui.forced_mouse_focus) {
- _drop_mouse_focus();
+ last_pos = pos;
}
- } break;
+ }
+#endif
}
}
@@ -1162,7 +1163,7 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
if (p_world_2d.is_valid()) {
world_2d = p_world_2d;
} else {
- WARN_PRINT("Invalid world_3d");
+ WARN_PRINT("Invalid world_2d");
world_2d = Ref<World2D>(memnew(World2D));
}
@@ -1620,10 +1621,10 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
Ref<InputEventMouseButton> mb = p_input;
bool cant_stop_me_now = (mb.is_valid() &&
- (mb->get_button_index() == BUTTON_WHEEL_DOWN ||
- mb->get_button_index() == BUTTON_WHEEL_UP ||
- mb->get_button_index() == BUTTON_WHEEL_LEFT ||
- mb->get_button_index() == BUTTON_WHEEL_RIGHT));
+ (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN ||
+ mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP ||
+ mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT ||
+ mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT));
Ref<InputEventPanGesture> pn = p_input;
cant_stop_me_now = pn.is_valid() || cant_stop_me_now;
@@ -1769,19 +1770,22 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
}
}
- if (!c) {
+ if (!c || c->data.mouse_filter == Control::MOUSE_FILTER_IGNORE) {
return nullptr;
}
matrix.affine_invert();
+ if (!c->has_point(matrix.xform(p_global))) {
+ return nullptr;
+ }
- //conditions for considering this as a valid control for return
- if (c->data.mouse_filter != Control::MOUSE_FILTER_IGNORE && c->has_point(matrix.xform(p_global)) && (!gui.drag_preview || (c != gui.drag_preview && !gui.drag_preview->is_a_parent_of(c)))) {
+ Control *drag_preview = _gui_get_drag_preview();
+ if (!drag_preview || (c != drag_preview && !drag_preview->is_a_parent_of(c))) {
r_inv_xform = matrix;
return c;
- } else {
- return nullptr;
}
+
+ return nullptr;
}
bool Viewport::_gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check) {
@@ -1856,7 +1860,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.mouse_focus_mask = 1 << (mb->get_button_index() - 1);
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
gui.drag_accum = Vector2();
gui.drag_attempted = false;
}
@@ -1879,7 +1883,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
#endif
- if (mb->get_button_index() == BUTTON_LEFT) { //assign focus
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { //assign focus
CanvasItem *ci = gui.mouse_focus;
while (ci) {
Control *control = Object::cast_to<Control>(ci);
@@ -1910,7 +1914,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
set_input_as_handled();
- if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) {
+ if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
//alternate drop use (when using force_drag(), as proposed by #5342
if (gui.mouse_focus) {
_gui_drop(gui.mouse_focus, pos, false);
@@ -1919,9 +1923,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.drag_data = Variant();
gui.dragging = false;
- if (gui.drag_preview) {
- memdelete(gui.drag_preview);
- gui.drag_preview = nullptr;
+ Control *drag_preview = _gui_get_drag_preview();
+ if (drag_preview) {
+ memdelete(drag_preview);
+ gui.drag_preview_id = ObjectID();
}
_propagate_viewport_notification(this, NOTIFICATION_DRAG_END);
//change mouse accordingly
@@ -1929,14 +1934,15 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
_gui_cancel_tooltip();
} else {
- if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) {
+ if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (gui.drag_mouse_over) {
_gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false);
}
- if (gui.drag_preview && mb->get_button_index() == BUTTON_LEFT) {
- memdelete(gui.drag_preview);
- gui.drag_preview = nullptr;
+ Control *drag_preview = _gui_get_drag_preview();
+ if (drag_preview) {
+ memdelete(drag_preview);
+ gui.drag_preview_id = ObjectID();
}
gui.drag_data = Variant();
@@ -1972,7 +1978,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
_gui_call_input(mouse_focus, mb);
}
- /*if (gui.drag_data.get_type()!=Variant::NIL && mb->get_button_index()==BUTTON_LEFT) {
+ /*if (gui.drag_data.get_type()!=Variant::NIL && mb->get_button_index()==MOUSE_BUTTON_LEFT) {
_propagate_viewport_notification(this,NOTIFICATION_DRAG_END);
gui.drag_data=Variant(); //always clear
}*/
@@ -2016,7 +2022,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *over = nullptr;
// D&D
- if (!gui.drag_attempted && gui.mouse_focus && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (!gui.drag_attempted && gui.mouse_focus && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
gui.drag_accum += mm->get_relative();
float len = gui.drag_accum.length();
if (len > 10) {
@@ -2033,10 +2039,11 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.mouse_focus_mask = 0;
break;
} else {
- if (gui.drag_preview != nullptr) {
+ Control *drag_preview = _gui_get_drag_preview();
+ if (drag_preview) {
ERR_PRINT("Don't set a drag preview and return null data. Preview was deleted and drag request ignored.");
- memdelete(gui.drag_preview);
- gui.drag_preview = nullptr;
+ memdelete(drag_preview);
+ gui.drag_preview_id = ObjectID();
}
gui.dragging = false;
}
@@ -2176,8 +2183,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.drag_data.get_type() != Variant::NIL) {
//handle dragandrop
- if (gui.drag_preview) {
- gui.drag_preview->set_position(mpos);
+ Control *drag_preview = _gui_get_drag_preview();
+ if (drag_preview) {
+ drag_preview->set_position(mpos);
}
gui.drag_mouse_over = over;
@@ -2193,7 +2201,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
embedder = this;
viewport_pos = mpos;
} else {
- //not an embeder, but may be a subwindow of an embedder
+ //not an embedder, but may be a subwindow of an embedder
Window *w = Object::cast_to<Window>(this);
if (w) {
if (w->is_embedded()) {
@@ -2258,7 +2266,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Transform2D localizer = gui.drag_mouse_over->get_global_transform_with_canvas().affine_inverse();
gui.drag_mouse_over_pos = localizer.xform(viewport_pos);
- if (mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
bool can_drop = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, true);
if (!can_drop) {
@@ -2385,7 +2393,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
//keyboard focus
//if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) {
Ref<InputEventKey> k = p_event;
- //need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/righ/etc> is handled here when it shouldn't be.
+ //need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/right/etc> is handled here when it shouldn't be.
bool mods = k.is_valid() && (k->get_control() || k->get_alt() || k->get_shift() || k->get_metakey());
if (from && p_event->is_pressed()) {
@@ -2452,15 +2460,29 @@ void Viewport::_gui_set_drag_preview(Control *p_base, Control *p_control) {
ERR_FAIL_COND(p_control->is_inside_tree());
ERR_FAIL_COND(p_control->get_parent() != nullptr);
- if (gui.drag_preview) {
- memdelete(gui.drag_preview);
+ Control *drag_preview = _gui_get_drag_preview();
+ if (drag_preview) {
+ memdelete(drag_preview);
}
p_control->set_as_top_level(true);
p_control->set_position(gui.last_mouse_pos);
p_base->get_root_parent_control()->add_child(p_control); //add as child of viewport
p_control->raise();
- gui.drag_preview = p_control;
+ gui.drag_preview_id = p_control->get_instance_id();
+}
+
+Control *Viewport::_gui_get_drag_preview() {
+ if (gui.drag_preview_id.is_null()) {
+ return nullptr;
+ } else {
+ Control *drag_preview = Object::cast_to<Control>(ObjectDB::get_instance(gui.drag_preview_id));
+ if (!drag_preview) {
+ ERR_PRINT("Don't free the control set as drag preview.");
+ gui.drag_preview_id = ObjectID();
+ }
+ return drag_preview;
+ }
}
void Viewport::_gui_remove_root_control(List<Control *>::Element *RI) {
@@ -2582,28 +2604,41 @@ void Viewport::_drop_mouse_focus() {
}
}
-void Viewport::_drop_physics_mouseover() {
+void Viewport::_drop_physics_mouseover(bool p_paused_only) {
physics_has_last_mousepos = false;
- while (physics_2d_mouseover.size()) {
- Object *o = ObjectDB::get_instance(physics_2d_mouseover.front()->key());
+ List<Map<ObjectID, uint64_t>::Element *> to_erase;
+
+ for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
+ Object *o = ObjectDB::get_instance(E->key());
if (o) {
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
- co->_mouse_exit();
+ if (co) {
+ if (p_paused_only && co->can_process()) {
+ continue;
+ }
+ co->_mouse_exit();
+ to_erase.push_back(E);
+ }
}
- physics_2d_mouseover.erase(physics_2d_mouseover.front());
+ }
+
+ while (to_erase.size()) {
+ physics_2d_mouseover.erase(to_erase.front()->get());
+ to_erase.pop_front();
}
#ifndef _3D_DISABLED
if (physics_object_over.is_valid()) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
if (co) {
- co->_mouse_exit();
+ if (!(p_paused_only && co->can_process())) {
+ co->_mouse_exit();
+ physics_object_over = ObjectID();
+ physics_object_capture = ObjectID();
+ }
}
}
-
- physics_object_over = ObjectID();
- physics_object_capture = ObjectID();
#endif
}
@@ -2637,7 +2672,7 @@ void Viewport::_post_gui_grab_click_focus() {
Ref<InputEventMouseButton> mb;
mb.instance();
- //send unclic
+ //send unclick
mb->set_position(click);
mb->set_button_index(i + 1);
@@ -2655,7 +2690,7 @@ void Viewport::_post_gui_grab_click_focus() {
Ref<InputEventMouseButton> mb;
mb.instance();
- //send clic
+ //send click
mb->set_position(click);
mb->set_button_index(i + 1);
@@ -2748,7 +2783,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND_V(gui.subwindow_focused == nullptr, false);
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE) {
if (gui.subwindow_drag_close_rect.has_point(mb->get_position())) {
//close window
@@ -2873,7 +2908,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
//if the event is a mouse button, we need to check whether another window was clicked
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
bool click_on_window = false;
for (int i = gui.sub_windows.size() - 1; i >= 0; i--) {
SubWindow &sw = gui.sub_windows.write[i];
@@ -3529,6 +3564,8 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lod_threshold", "pixels"), &Viewport::set_lod_threshold);
ClassDB::bind_method(D_METHOD("get_lod_threshold"), &Viewport::get_lod_threshold);
+ ClassDB::bind_method(D_METHOD("_process_picking"), &Viewport::_process_picking);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d");
@@ -3656,26 +3693,10 @@ Viewport::Viewport() {
viewport_textures.insert(default_texture.ptr());
default_texture->proxy = RS::get_singleton()->texture_proxy_create(texture_rid);
- audio_listener = false;
//internal_listener_2d = SpatialSound2DServer::get_singleton()->listener_create();
- audio_listener_2d = false;
- transparent_bg = false;
- parent = nullptr;
- listener = nullptr;
- camera = nullptr;
- override_canvas_transform = false;
canvas_layers.insert(nullptr); // This eases picking code (interpreted as the canvas of the Viewport)
- gen_mipmaps = false;
-
//clear=true;
-
- physics_object_picking = false;
- physics_has_last_mousepos = false;
- physics_last_mousepos = Vector2(Math_INF, Math_INF);
-
- shadow_atlas_16_bits = true;
- shadow_atlas_size = 2048;
set_shadow_atlas_size(shadow_atlas_size);
for (int i = 0; i < 4; i++) {
@@ -3694,50 +3715,11 @@ Viewport::Viewport() {
unhandled_input_group = "_vp_unhandled_input" + id;
unhandled_key_input_group = "_vp_unhandled_key_input" + id;
- disable_input = false;
-
// Window tooltip.
- gui.tooltip_timer = -1;
-
gui.tooltip_delay = GLOBAL_DEF("gui/timers/tooltip_delay_sec", 0.5);
ProjectSettings::get_singleton()->set_custom_property_info("gui/timers/tooltip_delay_sec", PropertyInfo(Variant::FLOAT, "gui/timers/tooltip_delay_sec", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); // No negative numbers
- gui.tooltip_control = nullptr;
- gui.tooltip_label = nullptr;
- gui.drag_preview = nullptr;
- gui.drag_attempted = false;
- gui.canvas_sort_index = 0;
- gui.roots_order_dirty = false;
- gui.mouse_focus = nullptr;
- gui.forced_mouse_focus = false;
- gui.last_mouse_focus = nullptr;
- gui.subwindow_focused = nullptr;
- gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED;
-
- msaa = MSAA_DISABLED;
- screen_space_aa = SCREEN_SPACE_AA_DISABLED;
- debug_draw = DEBUG_DRAW_DISABLED;
-
- snap_controls_to_pixels = true;
- snap_2d_transforms_to_pixel = false;
- snap_2d_vertices_to_pixel = false;
-
- physics_last_mouse_state.alt = false;
- physics_last_mouse_state.control = false;
- physics_last_mouse_state.shift = false;
- physics_last_mouse_state.meta = false;
- physics_last_mouse_state.mouse_mask = 0;
- local_input_handled = false;
- handle_input_locally = true;
-
- size_allocated = false;
-
- default_canvas_item_texture_filter = DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
- default_canvas_item_texture_repeat = DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
-
- sdf_oversize = SDF_OVERSIZE_120_PERCENT;
- sdf_scale = SDF_SCALE_50_PERCENT;
- set_sdf_oversize(SDF_OVERSIZE_120_PERCENT); //set to server
+ set_sdf_oversize(sdf_oversize); //set to server
}
Viewport::~Viewport() {
@@ -3869,12 +3851,6 @@ void SubViewport::_bind_methods() {
BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
}
-SubViewport::SubViewport() {
- xr = false;
- size_2d_override_stretch = false;
- update_mode = UPDATE_WHEN_VISIBLE;
- clear_mode = CLEAR_MODE_ALWAYS;
-}
+SubViewport::SubViewport() {}
-SubViewport::~SubViewport() {
-}
+SubViewport::~SubViewport() {}
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 17d4835c63..0f11e6fb19 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -56,7 +56,7 @@ class ViewportTexture : public Texture2D {
NodePath path;
friend class Viewport;
- Viewport *vp;
+ Viewport *vp = nullptr;
mutable RID proxy_ph;
mutable RID proxy;
@@ -186,9 +186,9 @@ public:
private:
friend class ViewportTexture;
- Viewport *parent;
+ Viewport *parent = nullptr;
- Listener3D *listener;
+ Listener3D *listener = nullptr;
Set<Listener3D *> listeners;
struct CameraOverrideData {
@@ -197,11 +197,11 @@ private:
PROJECTION_PERSPECTIVE,
PROJECTION_ORTHOGONAL
};
- Projection projection;
- float fov;
- float size;
- float z_near;
- float z_far;
+ Projection projection = Projection::PROJECTION_PERSPECTIVE;
+ float fov = 0.0;
+ float size = 0.0;
+ float z_near = 0.0;
+ float z_far = 0.0;
RID rid;
operator bool() const {
@@ -209,7 +209,7 @@ private:
}
} camera_override;
- Camera3D *camera;
+ Camera3D *camera = nullptr;
Set<Camera3D *> cameras;
Set<CanvasLayer *> canvas_layers;
@@ -217,13 +217,13 @@ private:
RID current_canvas;
RID subwindow_canvas;
- bool audio_listener;
+ bool audio_listener = false;
RID internal_listener;
- bool audio_listener_2d;
+ bool audio_listener_2d = false;
RID internal_listener_2d;
- bool override_canvas_transform;
+ bool override_canvas_transform = false;
Transform2D canvas_transform_override;
Transform2D canvas_transform;
@@ -232,7 +232,7 @@ private:
Size2i size;
Size2i size_2d_override;
- bool size_allocated;
+ bool size_allocated = false;
RID contact_2d_debug;
RID contact_3d_debug_multimesh;
@@ -240,36 +240,36 @@ private:
Rect2 last_vp_rect;
- bool transparent_bg;
+ bool transparent_bg = false;
bool filter;
- bool gen_mipmaps;
+ bool gen_mipmaps = false;
- bool snap_controls_to_pixels;
- bool snap_2d_transforms_to_pixel;
- bool snap_2d_vertices_to_pixel;
+ bool snap_controls_to_pixels = true;
+ bool snap_2d_transforms_to_pixel = false;
+ bool snap_2d_vertices_to_pixel = false;
- bool physics_object_picking;
+ bool physics_object_picking = false;
List<Ref<InputEvent>> physics_picking_events;
ObjectID physics_object_capture;
ObjectID physics_object_over;
Transform physics_last_object_transform;
Transform physics_last_camera_transform;
ObjectID physics_last_id;
- bool physics_has_last_mousepos;
- Vector2 physics_last_mousepos;
+ bool physics_has_last_mousepos = false;
+ Vector2 physics_last_mousepos = Vector2(Math_INF, Math_INF);
struct {
- bool alt;
- bool control;
- bool shift;
- bool meta;
- int mouse_mask;
+ bool alt = false;
+ bool control = false;
+ bool shift = false;
+ bool meta = false;
+ int mouse_mask = 0;
} physics_last_mouse_state;
void _collision_object_input_event(CollisionObject3D *p_object, Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape);
- bool handle_input_locally;
- bool local_input_handled;
+ bool handle_input_locally = true;
+ bool local_input_handled = false;
Map<ObjectID, uint64_t> physics_2d_mouseover;
@@ -294,22 +294,22 @@ private:
RID texture_rid;
- DebugDraw debug_draw;
+ DebugDraw debug_draw = DEBUG_DRAW_DISABLED;
- int shadow_atlas_size;
+ int shadow_atlas_size = 2048;
bool shadow_atlas_16_bits = true;
ShadowAtlasQuadrantSubdiv shadow_atlas_quadrant_subdiv[4];
- MSAA msaa;
- ScreenSpaceAA screen_space_aa;
+ MSAA msaa = MSAA_DISABLED;
+ ScreenSpaceAA screen_space_aa = SCREEN_SPACE_AA_DISABLED;
bool use_debanding = false;
float lod_threshold = 1.0;
Ref<ViewportTexture> default_texture;
Set<ViewportTexture *> viewport_textures;
- SDFOversize sdf_oversize;
- SDFScale sdf_scale;
+ SDFOversize sdf_oversize = SDF_OVERSIZE_120_PERCENT;
+ SDFScale sdf_scale = SDF_SCALE_50_PERCENT;
enum SubWindowDrag {
SUB_WINDOW_DRAG_DISABLED,
@@ -332,60 +332,58 @@ private:
};
struct SubWindow {
- Window *window;
+ Window *window = nullptr;
RID canvas_item;
};
struct GUI {
// info used when this is a window
- bool forced_mouse_focus; //used for menu buttons
- bool key_event_accepted;
- Control *mouse_focus;
- Control *last_mouse_focus;
- Control *mouse_click_grabber;
- int mouse_focus_mask;
- Control *key_focus;
- Control *mouse_over;
- Control *drag_mouse_over;
+ bool forced_mouse_focus = false; //used for menu buttons
+ bool key_event_accepted = false;
+ Control *mouse_focus = nullptr;
+ Control *last_mouse_focus = nullptr;
+ Control *mouse_click_grabber = nullptr;
+ int mouse_focus_mask = 0;
+ Control *key_focus = nullptr;
+ Control *mouse_over = nullptr;
+ Control *drag_mouse_over = nullptr;
Vector2 drag_mouse_over_pos;
- Control *tooltip_control;
- Window *tooltip_popup;
- Label *tooltip_label;
+ Control *tooltip_control = nullptr;
+ Window *tooltip_popup = nullptr;
+ Label *tooltip_label = nullptr;
Point2 tooltip_pos;
Point2 last_mouse_pos;
Point2 drag_accum;
- bool drag_attempted;
+ bool drag_attempted = false;
Variant drag_data;
- Control *drag_preview;
- float tooltip_timer;
- float tooltip_delay;
+ ObjectID drag_preview_id;
+ float tooltip_timer = -1.0;
+ float tooltip_delay = 0.0;
Transform2D focus_inv_xform;
- bool roots_order_dirty;
+ bool roots_order_dirty = false;
List<Control *> roots;
- int canvas_sort_index; //for sorting items with canvas as root
- bool dragging;
- bool embed_subwindows_hint;
- bool embedding_subwindows;
+ int canvas_sort_index = 0; //for sorting items with canvas as root
+ bool dragging = false;
+ bool embed_subwindows_hint = false;
+ bool embedding_subwindows = false;
- Window *subwindow_focused;
- SubWindowDrag subwindow_drag;
+ Window *subwindow_focused = nullptr;
+ SubWindowDrag subwindow_drag = SUB_WINDOW_DRAG_DISABLED;
Vector2 subwindow_drag_from;
Vector2 subwindow_drag_pos;
Rect2i subwindow_drag_close_rect;
- bool subwindow_drag_close_inside;
+ bool subwindow_drag_close_inside = false;
SubWindowResize subwindow_resize_mode;
Rect2i subwindow_resize_from_rect;
Vector<SubWindow> sub_windows;
-
- GUI();
} gui;
- DefaultCanvasItemTextureFilter default_canvas_item_texture_filter;
- DefaultCanvasItemTextureRepeat default_canvas_item_texture_repeat;
+ DefaultCanvasItemTextureFilter default_canvas_item_texture_filter = DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
+ DefaultCanvasItemTextureRepeat default_canvas_item_texture_repeat = DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
- bool disable_input;
+ bool disable_input = false;
void _gui_call_input(Control *p_control, const Ref<InputEvent> &p_input);
void _gui_call_notification(Control *p_control, int p_what);
@@ -417,6 +415,7 @@ private:
void _gui_force_drag(Control *p_base, const Variant &p_data, Control *p_control);
void _gui_set_drag_preview(Control *p_base, Control *p_control);
+ Control *_gui_get_drag_preview();
void _gui_remove_focus_for_window(Node *p_window);
void _gui_remove_focus();
@@ -450,7 +449,7 @@ private:
void _canvas_layer_remove(CanvasLayer *p_canvas_layer);
void _drop_mouse_focus();
- void _drop_physics_mouseover();
+ void _drop_physics_mouseover(bool p_paused_only = false);
void _update_canvas_items(Node *p_node);
@@ -479,6 +478,7 @@ protected:
bool _is_size_allocated() const;
void _notification(int p_what);
+ void _process_picking();
static void _bind_methods();
virtual void _validate_property(PropertyInfo &property) const override;
@@ -650,10 +650,10 @@ public:
};
private:
- UpdateMode update_mode;
- ClearMode clear_mode;
- bool xr;
- bool size_2d_override_stretch;
+ UpdateMode update_mode = UPDATE_WHEN_VISIBLE;
+ ClearMode clear_mode = CLEAR_MODE_ALWAYS;
+ bool xr = false;
+ bool size_2d_override_stretch = false;
protected:
static void _bind_methods();
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 0a541a2d07..bacb0030bb 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -232,7 +232,7 @@ void Window::_make_window() {
DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id);
DisplayServer::get_singleton()->window_set_max_size(max_size, window_id);
DisplayServer::get_singleton()->window_set_min_size(min_size, window_id);
- DisplayServer::get_singleton()->window_set_title(title, window_id);
+ DisplayServer::get_singleton()->window_set_title(tr(title), window_id);
DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
_update_window_size();
@@ -759,6 +759,10 @@ void Window::_notification(int p_what) {
}
}
+ if (p_what == NOTIFICATION_TRANSLATION_CHANGED) {
+ child_controls_changed();
+ }
+
if (p_what == NOTIFICATION_EXIT_TREE) {
if (transient) {
_clear_transient();
@@ -826,6 +830,9 @@ bool Window::is_using_font_oversampling() const {
}
DisplayServer::WindowID Window::get_window_id() const {
+ if (embedder) {
+ return parent->get_window_id();
+ }
return window_id;
}
@@ -881,10 +888,6 @@ bool Window::_can_consume_input_events() const {
}
void Window::_window_input(const Ref<InputEvent> &p_ev) {
- if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_ev.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_ev))) {
- return; //avoid joy input on editor
- }
-
if (EngineDebugger::is_active()) {
//quit from game window using F8
Ref<InputEventKey> k = p_ev;
@@ -894,12 +897,13 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) {
}
if (exclusive_child != nullptr) {
+ /*
Window *focus_target = exclusive_child;
focus_target->grab_focus();
while (focus_target->exclusive_child != nullptr) {
focus_target = focus_target->exclusive_child;
focus_target->grab_focus();
- }
+ }*/
if (!is_embedding_subwindows()) { //not embedding, no need for event
return;
@@ -1039,6 +1043,9 @@ void Window::popup_centered_ratio(float p_ratio) {
void Window::popup(const Rect2i &p_screen_rect) {
emit_signal("about_to_popup");
+ // Update window size to calculate the actual window size based on contents minimum size and minimum size.
+ _update_window_size();
+
if (p_screen_rect != Rect2i()) {
set_position(p_screen_rect.position);
set_size(p_screen_rect.size);
@@ -1283,14 +1290,14 @@ bool Window::is_layout_rtl() const {
if (parent) {
return parent->is_layout_rtl();
} else {
- if (GLOBAL_GET("display/window/force_right_to_left_layout_direction")) {
+ if (GLOBAL_GET("internationalization/rendering/force_right_to_left_layout_direction")) {
return true;
}
String locale = TranslationServer::get_singleton()->get_tool_locale();
return TS->is_locale_right_to_left(locale);
}
} else if (layout_dir == LAYOUT_DIRECTION_LOCALE) {
- if (GLOBAL_GET("display/window/force_right_to_left_layout_direction")) {
+ if (GLOBAL_GET("internationalization/rendering/force_right_to_left_layout_direction")) {
return true;
}
String locale = TranslationServer::get_singleton()->get_tool_locale();
@@ -1349,8 +1356,8 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_focus"), &Window::has_focus);
ClassDB::bind_method(D_METHOD("grab_focus"), &Window::grab_focus);
- ClassDB::bind_method(D_METHOD("set_ime_active"), &Window::set_ime_active);
- ClassDB::bind_method(D_METHOD("set_ime_position"), &Window::set_ime_position);
+ ClassDB::bind_method(D_METHOD("set_ime_active", "active"), &Window::set_ime_active);
+ ClassDB::bind_method(D_METHOD("set_ime_position", "position"), &Window::set_ime_position);
ClassDB::bind_method(D_METHOD("is_embedded"), &Window::is_embedded);
@@ -1466,11 +1473,6 @@ void Window::_bind_methods() {
}
Window::Window() {
- for (int i = 0; i < FLAG_MAX; i++) {
- flags[i] = false;
- }
- content_scale_mode = CONTENT_SCALE_MODE_DISABLED;
- content_scale_aspect = CONTENT_SCALE_ASPECT_IGNORE;
RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED);
}
diff --git a/scene/main/window.h b/scene/main/window.h
index 2ffeff03ff..38846ed00e 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -90,7 +90,7 @@ private:
mutable Size2i min_size;
mutable Size2i max_size;
mutable Mode mode = MODE_WINDOWED;
- mutable bool flags[FLAG_MAX];
+ mutable bool flags[FLAG_MAX] = {};
bool visible = true;
bool focused = false;
@@ -106,8 +106,8 @@ private:
void _update_child_controls();
Size2i content_scale_size;
- ContentScaleMode content_scale_mode;
- ContentScaleAspect content_scale_aspect;
+ ContentScaleMode content_scale_mode = CONTENT_SCALE_MODE_DISABLED;
+ ContentScaleAspect content_scale_aspect = CONTENT_SCALE_ASPECT_IGNORE;
void _make_window();
void _clear_window();
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index b14c44689e..fe8591e3d9 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -50,7 +50,6 @@
#include "scene/2d/line_2d.h"
#include "scene/2d/mesh_instance_2d.h"
#include "scene/2d/multimesh_instance_2d.h"
-#include "scene/2d/navigation_2d.h"
#include "scene/2d/navigation_agent_2d.h"
#include "scene/2d/navigation_obstacle_2d.h"
#include "scene/2d/parallax_background.h"
@@ -206,7 +205,6 @@
#include "scene/3d/listener_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/multimesh_instance_3d.h"
-#include "scene/3d/navigation_3d.h"
#include "scene/3d/navigation_agent_3d.h"
#include "scene/3d/navigation_obstacle_3d.h"
#include "scene/3d/navigation_region_3d.h"
@@ -516,7 +514,6 @@ void register_scene_types() {
ClassDB::register_class<ConeTwistJoint3D>();
ClassDB::register_class<Generic6DOFJoint3D>();
- ClassDB::register_class<Navigation3D>();
ClassDB::register_class<NavigationRegion3D>();
ClassDB::register_class<NavigationAgent3D>();
ClassDB::register_class<NavigationObstacle3D>();
@@ -793,7 +790,6 @@ void register_scene_types() {
ClassDB::register_class<PathFollow2D>();
ClassDB::register_class<NavigationMesh>();
- ClassDB::register_class<Navigation2D>();
ClassDB::register_class<NavigationPolygon>();
ClassDB::register_class<NavigationRegion2D>();
ClassDB::register_class<NavigationAgent2D>();
@@ -814,6 +810,8 @@ void register_scene_types() {
ClassDB::add_compatibility_class("DynamicFont", "Font");
ClassDB::add_compatibility_class("DynamicFontData", "FontData");
ClassDB::add_compatibility_class("ToolButton", "Button");
+ ClassDB::add_compatibility_class("Navigation3D", "Node3D");
+ ClassDB::add_compatibility_class("Navigation2D", "Node2D");
// Renamed in 4.0.
// Keep alphabetical ordering to easily locate classes and avoid duplicates.
@@ -865,7 +863,6 @@ void register_scene_types() {
ClassDB::add_compatibility_class("Listener", "Listener3D");
ClassDB::add_compatibility_class("MeshInstance", "MeshInstance3D");
ClassDB::add_compatibility_class("MultiMeshInstance", "MultiMeshInstance3D");
- ClassDB::add_compatibility_class("Navigation", "Navigation3D");
ClassDB::add_compatibility_class("NavigationAgent", "NavigationAgent3D");
ClassDB::add_compatibility_class("NavigationMeshInstance", "NavigationRegion3D");
ClassDB::add_compatibility_class("NavigationObstacle", "NavigationObstacle3D");
@@ -948,10 +945,12 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
for (int i = 0; i < 20; i++) {
- GLOBAL_DEF(vformat("layer_names/2d_render/layer_%d", i), "");
- GLOBAL_DEF(vformat("layer_names/2d_physics/layer_%d", i), "");
- GLOBAL_DEF(vformat("layer_names/3d_render/layer_%d", i), "");
- GLOBAL_DEF(vformat("layer_names/3d_physics/layer_%d", i), "");
+ GLOBAL_DEF_BASIC(vformat("layer_names/2d_render/layer_%d", i), "");
+ GLOBAL_DEF_BASIC(vformat("layer_names/2d_physics/layer_%d", i), "");
+ GLOBAL_DEF_BASIC(vformat("layer_names/2d_navigation/layer_%d", i), "");
+ GLOBAL_DEF_BASIC(vformat("layer_names/3d_render/layer_%d", i), "");
+ GLOBAL_DEF_BASIC(vformat("layer_names/3d_physics/layer_%d", i), "");
+ GLOBAL_DEF_BASIC(vformat("layer_names/3d_navigation/layer_%d", i), "");
}
bool default_theme_hidpi = GLOBAL_DEF("gui/theme/use_hidpi", false);
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 796fe1d106..6f64ac6d04 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -580,6 +580,10 @@ void Animation::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
+void Animation::reset_state() {
+ clear();
+}
+
int Animation::add_track(TrackType p_type, int p_at_pos) {
if (p_at_pos < 0 || p_at_pos >= tracks.size()) {
p_at_pos = tracks.size();
@@ -1604,7 +1608,7 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, Interpola
bool result = true;
int next = 0;
- float c = 0;
+ float c = 0.0;
// prepare for all cases of interpolation
if (loop && p_loop_wrap) {
@@ -2278,8 +2282,8 @@ float Animation::bezier_track_interpolate(int p_track, float p_time) const {
int iterations = 10;
float duration = bt->values[idx + 1].time - bt->values[idx].time; // time duration between our two keyframes
- float low = 0; // 0% of the current animation segment
- float high = 1; // 100% of the current animation segment
+ float low = 0.0; // 0% of the current animation segment
+ float high = 1.0; // 100% of the current animation segment
float middle;
Vector2 start(0, bt->values[idx].value.value);
@@ -2734,7 +2738,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons
real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1);
if (d > pd.length() * p_alowed_linear_err) {
- return false; //beyond allowed error for colinearity
+ return false; //beyond allowed error for collinearity
}
if (p_norm != Vector3() && Math::acos(pd.normalized().dot(p_norm)) > p_alowed_angular_err) {
@@ -2824,7 +2828,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons
real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1);
if (d > pd.length() * p_alowed_linear_err) {
- return false; //beyond allowed error for colinearity
+ return false; //beyond allowed error for collinearity
}
t[2] = (d1 - d0) / (d2 - d0);
@@ -2836,7 +2840,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons
erase = true;
} else {
erase = true;
- real_t lt = -1;
+ real_t lt = -1.0;
for (int j = 0; j < 3; j++) {
//search for t on first, one must be it
if (t[j] != -1) {
@@ -2919,11 +2923,7 @@ void Animation::optimize(float p_allowed_linear_err, float p_allowed_angular_err
}
}
-Animation::Animation() {
- step = 0.1;
- loop = false;
- length = 1;
-}
+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 fa374e6ad2..66bc71c834 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -65,28 +65,19 @@ public:
private:
struct Track {
- TrackType type;
- InterpolationType interpolation;
- bool loop_wrap;
+ TrackType type = TrackType::TYPE_ANIMATION;
+ InterpolationType interpolation = INTERPOLATION_LINEAR;
+ bool loop_wrap = true;
NodePath path; // path to something
- bool imported;
- bool enabled;
- Track() {
- interpolation = INTERPOLATION_LINEAR;
- imported = false;
- loop_wrap = true;
- enabled = true;
- }
+ bool imported = false;
+ bool enabled = true;
+ Track() {}
virtual ~Track() {}
};
struct Key {
- float transition;
- float time; // time in secs
- Key() {
- transition = 1;
- time = 0;
- }
+ float transition = 1.0;
+ float time = 0.0; // time in secs
};
// transform key holds either Vector3 or Quaternion
@@ -112,13 +103,12 @@ private:
/* PROPERTY VALUE TRACK */
struct ValueTrack : public Track {
- UpdateMode update_mode;
- bool update_on_seek;
+ UpdateMode update_mode = UPDATE_CONTINUOUS;
+ bool update_on_seek = false;
Vector<TKey<Variant>> values;
ValueTrack() {
type = TYPE_VALUE;
- update_mode = UPDATE_CONTINUOUS;
}
};
@@ -139,7 +129,7 @@ private:
struct BezierKey {
Vector2 in_handle; //relative (x always <0)
Vector2 out_handle; //relative (x always >0)
- float value;
+ float value = 0.0;
};
struct BezierTrack : public Track {
@@ -154,11 +144,9 @@ private:
struct AudioKey {
RES stream;
- float start_offset; //offset from start
- float end_offset; //offset from end, if 0 then full length or infinite
+ float start_offset = 0.0; //offset from start
+ float end_offset = 0.0; //offset from end, if 0 then full length or infinite
AudioKey() {
- start_offset = 0;
- end_offset = 0;
}
};
@@ -217,9 +205,9 @@ private:
_FORCE_INLINE_ void _value_track_get_key_indices_in_range(const ValueTrack *vt, float from_time, float to_time, List<int> *p_indices) const;
_FORCE_INLINE_ void _method_track_get_key_indices_in_range(const MethodTrack *mt, float from_time, float to_time, List<int> *p_indices) const;
- float length;
- float step;
- bool loop;
+ float length = 1.0;
+ float step = 0.1;
+ bool loop = false;
// bind helpers
private:
@@ -264,6 +252,8 @@ protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ virtual void reset_state() override;
+
static void _bind_methods();
public:
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp
index 8fdb004e65..06a91fb2f8 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_sample.cpp
@@ -403,11 +403,7 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in
}
}
-AudioStreamPlaybackSample::AudioStreamPlaybackSample() {
- active = false;
- offset = 0;
- sign = 1;
-}
+AudioStreamPlaybackSample::AudioStreamPlaybackSample() {}
/////////////////////
@@ -651,16 +647,7 @@ void AudioStreamSample::_bind_methods() {
BIND_ENUM_CONSTANT(LOOP_BACKWARD);
}
-AudioStreamSample::AudioStreamSample() {
- format = FORMAT_8_BITS;
- loop_mode = LOOP_DISABLED;
- stereo = false;
- loop_begin = 0;
- loop_end = 0;
- mix_rate = 44100;
- data = nullptr;
- data_bytes = 0;
-}
+AudioStreamSample::AudioStreamSample() {}
AudioStreamSample::~AudioStreamSample() {
if (data) {
diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h
index ba475c0888..70b8ba79ad 100644
--- a/scene/resources/audio_stream_sample.h
+++ b/scene/resources/audio_stream_sample.h
@@ -44,19 +44,19 @@ class AudioStreamPlaybackSample : public AudioStreamPlayback {
};
struct IMA_ADPCM_State {
- int16_t step_index;
- int32_t predictor;
+ int16_t step_index = 0;
+ int32_t predictor = 0;
/* values at loop point */
- int16_t loop_step_index;
- int32_t loop_predictor;
- int32_t last_nibble;
- int32_t loop_pos;
- int32_t window_ofs;
+ int16_t loop_step_index = 0;
+ int32_t loop_predictor = 0;
+ int32_t last_nibble = 0;
+ int32_t loop_pos = 0;
+ int32_t window_ofs = 0;
} ima_adpcm[2];
- int64_t offset;
- int sign;
- bool active;
+ int64_t offset = 0;
+ int sign = 1;
+ bool active = false;
friend class AudioStreamSample;
Ref<AudioStreamSample> base;
@@ -103,14 +103,14 @@ private:
DATA_PAD = 16 //padding for interpolation
};
- Format format;
- LoopMode loop_mode;
- bool stereo;
- int loop_begin;
- int loop_end;
- int mix_rate;
- void *data;
- uint32_t data_bytes;
+ Format format = FORMAT_8_BITS;
+ LoopMode loop_mode = LOOP_DISABLED;
+ bool stereo = false;
+ int loop_begin = 0;
+ int loop_end = 0;
+ int mix_rate = 44100;
+ void *data = nullptr;
+ uint32_t data_bytes = 0;
protected:
static void _bind_methods();
diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp
index dfb7a1fdfb..3cc1af59ae 100644
--- a/scene/resources/bit_map.cpp
+++ b/scene/resources/bit_map.cpp
@@ -285,7 +285,7 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start)
+---+---+
| 4 | |
+---+---+
- this normally go RIGHT, but if its coming from RIGHT, it should go LEFT
+ 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;
@@ -346,7 +346,7 @@ static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) {
}
int index = -1;
- float dist = 0;
+ float dist = 0.0;
//not looping first and last point
for (size_t i = 1, size = v.size(); i < size - 1; ++i) {
float cdist = perpendicular_distance(v[i], v[0], v[v.size() - 1]);
@@ -406,8 +406,8 @@ static Vector<Vector2> reduce(const Vector<Vector2> &points, const Rect2i &rect,
struct FillBitsStackEntry {
Point2i pos;
- int i;
- int j;
+ int i = 0;
+ int j = 0;
};
static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_pos, const Rect2i &rect) {
@@ -677,9 +677,6 @@ void BitMap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data");
}
-BitMap::BitMap() {
- width = 0;
- height = 0;
-}
+BitMap::BitMap() {}
//////////////////////////////////////
diff --git a/scene/resources/bit_map.h b/scene/resources/bit_map.h
index 7414265cee..68fd0b999a 100644
--- a/scene/resources/bit_map.h
+++ b/scene/resources/bit_map.h
@@ -40,8 +40,8 @@ class BitMap : public Resource {
OBJ_SAVE_TYPE(BitMap);
Vector<uint8_t> bitmask;
- int width;
- int height;
+ int width = 0;
+ int height = 0;
Vector<Vector2> _march_square(const Rect2i &rect, const Point2i &start) const;
diff --git a/scene/resources/box_shape_3d.cpp b/scene/resources/box_shape_3d.cpp
index fadbf21e43..6e7adc0bd7 100644
--- a/scene/resources/box_shape_3d.cpp
+++ b/scene/resources/box_shape_3d.cpp
@@ -60,7 +60,6 @@ void BoxShape3D::set_size(const Vector3 &p_size) {
size = p_size;
_update_shape();
notify_change_to_owners();
- _change_notify("size");
}
Vector3 BoxShape3D::get_size() const {
diff --git a/scene/resources/camera_effects.cpp b/scene/resources/camera_effects.cpp
index 695b14939f..34c6bc05bc 100644
--- a/scene/resources/camera_effects.cpp
+++ b/scene/resources/camera_effects.cpp
@@ -41,7 +41,7 @@ RID CameraEffects::get_rid() const {
void CameraEffects::set_dof_blur_far_enabled(bool p_enabled) {
dof_blur_far_enabled = p_enabled;
_update_dof_blur();
- _change_notify();
+ notify_property_list_changed();
}
bool CameraEffects::is_dof_blur_far_enabled() const {
@@ -69,7 +69,7 @@ float CameraEffects::get_dof_blur_far_transition() const {
void CameraEffects::set_dof_blur_near_enabled(bool p_enabled) {
dof_blur_near_enabled = p_enabled;
_update_dof_blur();
- _change_notify();
+ notify_property_list_changed();
}
bool CameraEffects::is_dof_blur_near_enabled() const {
@@ -120,6 +120,7 @@ void CameraEffects::_update_dof_blur() {
void CameraEffects::set_override_exposure_enabled(bool p_enabled) {
override_exposure_enabled = p_enabled;
_update_override_exposure();
+ notify_property_list_changed();
}
bool CameraEffects::is_override_exposure_enabled() const {
@@ -144,6 +145,14 @@ void CameraEffects::_update_override_exposure() {
// Private methods, constructor and destructor
+void CameraEffects::_validate_property(PropertyInfo &property) const {
+ if ((!dof_blur_far_enabled && (property.name == "dof_blur_far_distance" || property.name == "dof_blur_far_transition")) ||
+ (!dof_blur_near_enabled && (property.name == "dof_blur_near_distance" || property.name == "dof_blur_near_transition")) ||
+ (!override_exposure_enabled && property.name == "override_exposure")) {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+}
+
void CameraEffects::_bind_methods() {
// DOF blur
diff --git a/scene/resources/camera_effects.h b/scene/resources/camera_effects.h
index cf12b6d3c0..b9338f4806 100644
--- a/scene/resources/camera_effects.h
+++ b/scene/resources/camera_effects.h
@@ -42,12 +42,12 @@ private:
// DOF blur
bool dof_blur_far_enabled = false;
- float dof_blur_far_distance = 10;
- float dof_blur_far_transition = 5;
+ float dof_blur_far_distance = 10.0;
+ float dof_blur_far_transition = 5.0;
bool dof_blur_near_enabled = false;
- float dof_blur_near_distance = 2;
- float dof_blur_near_transition = 1;
+ float dof_blur_near_distance = 2.0;
+ float dof_blur_near_transition = 1.0;
float dof_blur_amount = 0.1;
void _update_dof_blur();
@@ -59,6 +59,7 @@ private:
protected:
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const override;
public:
virtual RID get_rid() const override;
diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp
index 63d90a8364..e5edba8a67 100644
--- a/scene/resources/capsule_shape_2d.cpp
+++ b/scene/resources/capsule_shape_2d.cpp
@@ -85,6 +85,11 @@ void CapsuleShape2D::draw(const RID &p_to_rid, const Color &p_color) {
Vector<Color> col;
col.push_back(p_color);
RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col);
+ if (is_collision_outline_enabled()) {
+ RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col);
+ // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`.
+ RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color);
+ }
}
Rect2 CapsuleShape2D::get_rect() const {
@@ -112,7 +117,5 @@ void CapsuleShape2D::_bind_methods() {
CapsuleShape2D::CapsuleShape2D() :
Shape2D(PhysicsServer2D::get_singleton()->capsule_shape_create()) {
- radius = 10;
- height = 20;
_update_shape();
}
diff --git a/scene/resources/capsule_shape_2d.h b/scene/resources/capsule_shape_2d.h
index 8c8c1b259b..439b67e8c3 100644
--- a/scene/resources/capsule_shape_2d.h
+++ b/scene/resources/capsule_shape_2d.h
@@ -36,8 +36,8 @@
class CapsuleShape2D : public Shape2D {
GDCLASS(CapsuleShape2D, Shape2D);
- real_t height;
- real_t radius;
+ real_t height = 20.0;
+ real_t radius = 10.0;
void _update_shape();
Vector<Vector2> _get_points() const;
diff --git a/scene/resources/capsule_shape_3d.cpp b/scene/resources/capsule_shape_3d.cpp
index a0b454a00f..226fe1ecd2 100644
--- a/scene/resources/capsule_shape_3d.cpp
+++ b/scene/resources/capsule_shape_3d.cpp
@@ -82,7 +82,6 @@ void CapsuleShape3D::set_radius(float p_radius) {
radius = p_radius;
_update_shape();
notify_change_to_owners();
- _change_notify("radius");
}
float CapsuleShape3D::get_radius() const {
@@ -93,7 +92,6 @@ void CapsuleShape3D::set_height(float p_height) {
height = p_height;
_update_shape();
notify_change_to_owners();
- _change_notify("height");
}
float CapsuleShape3D::get_height() const {
@@ -112,7 +110,5 @@ void CapsuleShape3D::_bind_methods() {
CapsuleShape3D::CapsuleShape3D() :
Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CAPSULE)) {
- radius = 1.0;
- height = 1.0;
_update_shape();
}
diff --git a/scene/resources/capsule_shape_3d.h b/scene/resources/capsule_shape_3d.h
index b5b8912445..25645ecf9d 100644
--- a/scene/resources/capsule_shape_3d.h
+++ b/scene/resources/capsule_shape_3d.h
@@ -35,8 +35,8 @@
class CapsuleShape3D : public Shape3D {
GDCLASS(CapsuleShape3D, Shape3D);
- float radius;
- float height;
+ float radius = 1.0;
+ float height = 1.0;
protected:
static void _bind_methods();
diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp
index a44c1b68bf..f06bc4248d 100644
--- a/scene/resources/circle_shape_2d.cpp
+++ b/scene/resources/circle_shape_2d.cpp
@@ -79,10 +79,14 @@ void CircleShape2D::draw(const RID &p_to_rid, const Color &p_color) {
Vector<Color> col;
col.push_back(p_color);
RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col);
+ if (is_collision_outline_enabled()) {
+ RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col);
+ // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`.
+ RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color);
+ }
}
CircleShape2D::CircleShape2D() :
Shape2D(PhysicsServer2D::get_singleton()->circle_shape_create()) {
- radius = 10;
_update_shape();
}
diff --git a/scene/resources/circle_shape_2d.h b/scene/resources/circle_shape_2d.h
index a066b773ef..333f299236 100644
--- a/scene/resources/circle_shape_2d.h
+++ b/scene/resources/circle_shape_2d.h
@@ -36,7 +36,7 @@
class CircleShape2D : public Shape2D {
GDCLASS(CircleShape2D, Shape2D);
- real_t radius;
+ real_t radius = 10.0;
void _update_shape();
protected:
diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp
index 3d6df3bb9c..0c767c8a52 100644
--- a/scene/resources/concave_polygon_shape_2d.cpp
+++ b/scene/resources/concave_polygon_shape_2d.cpp
@@ -98,7 +98,7 @@ Rect2 ConcavePolygonShape2D::get_rect() const {
real_t ConcavePolygonShape2D::get_enclosing_radius() const {
Vector<Vector2> data = get_segments();
const Vector2 *read = data.ptr();
- real_t r = 0;
+ real_t r = 0.0;
for (int i(0); i < data.size(); i++) {
r = MAX(read[i].length_squared(), r);
}
diff --git a/scene/resources/concave_polygon_shape_3d.cpp b/scene/resources/concave_polygon_shape_3d.cpp
index 358c99ad09..3fed700383 100644
--- a/scene/resources/concave_polygon_shape_3d.cpp
+++ b/scene/resources/concave_polygon_shape_3d.cpp
@@ -35,13 +35,12 @@
Vector<Vector3> ConcavePolygonShape3D::get_debug_mesh_lines() const {
Set<DrawEdge> edges;
- Vector<Vector3> data = get_faces();
- int datalen = data.size();
- ERR_FAIL_COND_V((datalen % 3) != 0, Vector<Vector3>());
+ int index_count = faces.size();
+ ERR_FAIL_COND_V((index_count % 3) != 0, Vector<Vector3>());
- const Vector3 *r = data.ptr();
+ const Vector3 *r = faces.ptr();
- for (int i = 0; i < datalen; i += 3) {
+ for (int i = 0; i < index_count; i += 3) {
for (int j = 0; j < 3; j++) {
DrawEdge de(r[i + j], r[i + ((j + 1) % 3)]);
edges.insert(de);
@@ -63,7 +62,7 @@ Vector<Vector3> ConcavePolygonShape3D::get_debug_mesh_lines() const {
real_t ConcavePolygonShape3D::get_enclosing_radius() const {
Vector<Vector3> data = get_faces();
const Vector3 *read = data.ptr();
- real_t r = 0;
+ real_t r = 0.0;
for (int i(0); i < data.size(); i++) {
r = MAX(read[i].length_squared(), r);
}
@@ -71,22 +70,46 @@ real_t ConcavePolygonShape3D::get_enclosing_radius() const {
}
void ConcavePolygonShape3D::_update_shape() {
+ Dictionary d;
+ d["faces"] = faces;
+ d["backface_collision"] = backface_collision;
+ PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d);
+
Shape3D::_update_shape();
}
void ConcavePolygonShape3D::set_faces(const Vector<Vector3> &p_faces) {
- PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), p_faces);
+ faces = p_faces;
+ _update_shape();
notify_change_to_owners();
}
Vector<Vector3> ConcavePolygonShape3D::get_faces() const {
- return PhysicsServer3D::get_singleton()->shape_get_data(get_shape());
+ return faces;
+}
+
+void ConcavePolygonShape3D::set_backface_collision_enabled(bool p_enabled) {
+ backface_collision = p_enabled;
+
+ if (!faces.is_empty()) {
+ _update_shape();
+ notify_change_to_owners();
+ }
+}
+
+bool ConcavePolygonShape3D::is_backface_collision_enabled() const {
+ return backface_collision;
}
void ConcavePolygonShape3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_faces", "faces"), &ConcavePolygonShape3D::set_faces);
ClassDB::bind_method(D_METHOD("get_faces"), &ConcavePolygonShape3D::get_faces);
+
+ ClassDB::bind_method(D_METHOD("set_backface_collision_enabled", "enabled"), &ConcavePolygonShape3D::set_backface_collision_enabled);
+ ClassDB::bind_method(D_METHOD("is_backface_collision_enabled"), &ConcavePolygonShape3D::is_backface_collision_enabled);
+
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_faces", "get_faces");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "backface_collision"), "set_backface_collision_enabled", "is_backface_collision_enabled");
}
ConcavePolygonShape3D::ConcavePolygonShape3D() :
diff --git a/scene/resources/concave_polygon_shape_3d.h b/scene/resources/concave_polygon_shape_3d.h
index 391459a3d7..bb28359dcc 100644
--- a/scene/resources/concave_polygon_shape_3d.h
+++ b/scene/resources/concave_polygon_shape_3d.h
@@ -36,6 +36,9 @@
class ConcavePolygonShape3D : public Shape3D {
GDCLASS(ConcavePolygonShape3D, Shape3D);
+ Vector<Vector3> faces;
+ bool backface_collision = false;
+
struct DrawEdge {
Vector3 a;
Vector3 b;
@@ -65,6 +68,9 @@ public:
void set_faces(const Vector<Vector3> &p_faces);
Vector<Vector3> get_faces() const;
+ void set_backface_collision_enabled(bool p_enabled);
+ bool is_backface_collision_enabled() const;
+
virtual Vector<Vector3> get_debug_mesh_lines() const override;
virtual real_t get_enclosing_radius() const override;
diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp
index 656e064356..6e56f6e7fc 100644
--- a/scene/resources/convex_polygon_shape_2d.cpp
+++ b/scene/resources/convex_polygon_shape_2d.cpp
@@ -72,9 +72,18 @@ void ConvexPolygonShape2D::_bind_methods() {
}
void ConvexPolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) {
+ if (points.size() < 3) {
+ return;
+ }
+
Vector<Color> col;
col.push_back(p_color);
RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col);
+ if (is_collision_outline_enabled()) {
+ RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col);
+ // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`.
+ RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color);
+ }
}
Rect2 ConvexPolygonShape2D::get_rect() const {
@@ -91,7 +100,7 @@ Rect2 ConvexPolygonShape2D::get_rect() const {
}
real_t ConvexPolygonShape2D::get_enclosing_radius() const {
- real_t r = 0;
+ real_t r = 0.0;
for (int i(0); i < get_points().size(); i++) {
r = MAX(get_points()[i].length_squared(), r);
}
diff --git a/scene/resources/convex_polygon_shape_3d.cpp b/scene/resources/convex_polygon_shape_3d.cpp
index 770d547231..9e030bc077 100644
--- a/scene/resources/convex_polygon_shape_3d.cpp
+++ b/scene/resources/convex_polygon_shape_3d.cpp
@@ -56,7 +56,7 @@ Vector<Vector3> ConvexPolygonShape3D::get_debug_mesh_lines() const {
real_t ConvexPolygonShape3D::get_enclosing_radius() const {
Vector<Vector3> data = get_points();
const Vector3 *read = data.ptr();
- real_t r = 0;
+ real_t r = 0.0;
for (int i(0); i < data.size(); i++) {
r = MAX(read[i].length_squared(), r);
}
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index 123c77a036..bc479e557a 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -47,11 +47,6 @@ static _FORCE_INLINE_ T _bezier_interp(real_t t, T start, T control_1, T control
const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed";
Curve::Curve() {
- _bake_resolution = 100;
- _baked_cache_dirty = false;
- _min_value = 0;
- _max_value = 1;
- _minmax_set_once = 0b00;
}
int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent, TangentMode left_mode, TangentMode right_mode) {
@@ -683,7 +678,7 @@ void Curve2D::_bake() const {
for (int i = 0; i < points.size() - 1; i++) {
float step = 0.1; // at least 10 substeps ought to be enough?
- float p = 0;
+ float p = 0.0;
while (p < 1.0) {
float np = p + step;
@@ -993,12 +988,9 @@ void Curve2D::_bind_methods() {
}
Curve2D::Curve2D() {
- baked_cache_dirty = false;
- baked_max_ofs = 0;
/* add_point(Vector2(-1,0,0));
add_point(Vector2(0,2,0));
add_point(Vector2(0,3,5));*/
- bake_interval = 5;
}
/***********************************************************************************/
@@ -1178,7 +1170,7 @@ void Curve3D::_bake() const {
for (int i = 0; i < points.size() - 1; i++) {
float step = 0.1; // at least 10 substeps ought to be enough?
- float p = 0;
+ float p = 0.0;
while (p < 1.0) {
float np = p + step;
@@ -1669,11 +1661,7 @@ void Curve3D::_bind_methods() {
}
Curve3D::Curve3D() {
- baked_cache_dirty = false;
- baked_max_ofs = 0;
/* add_point(Vector3(-1,0,0));
add_point(Vector3(0,2,0));
add_point(Vector3(0,3,5));*/
- bake_interval = 0.2;
- up_vector_enabled = true;
}
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index f33f3c5abe..402c893cd8 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -51,21 +51,17 @@ public:
struct Point {
Vector2 pos;
- real_t left_tangent;
- real_t right_tangent;
- TangentMode left_mode;
- TangentMode right_mode;
+ real_t left_tangent = 0.0;
+ real_t right_tangent = 0.0;
+ TangentMode left_mode = TANGENT_FREE;
+ TangentMode right_mode = TANGENT_FREE;
Point() {
- left_tangent = 0;
- right_tangent = 0;
- left_mode = TANGENT_FREE;
- right_mode = TANGENT_FREE;
}
Point(Vector2 p_pos,
- real_t p_left = 0,
- real_t p_right = 0,
+ real_t p_left = 0.0,
+ real_t p_right = 0.0,
TangentMode p_left_mode = TANGENT_FREE,
TangentMode p_right_mode = TANGENT_FREE) {
pos = p_pos;
@@ -137,12 +133,12 @@ private:
void mark_dirty();
Vector<Point> _points;
- bool _baked_cache_dirty;
+ bool _baked_cache_dirty = false;
Vector<real_t> _baked_cache;
- int _bake_resolution;
- float _min_value;
- float _max_value;
- int _minmax_set_once; // Encodes whether min and max have been set a first time, first bit for min and second for max.
+ int _bake_resolution = 100;
+ float _min_value = 0.0;
+ float _max_value = 1.0;
+ int _minmax_set_once = 0b00; // Encodes whether min and max have been set a first time, first bit for min and second for max.
};
VARIANT_ENUM_CAST(Curve::TangentMode)
@@ -159,17 +155,17 @@ class Curve2D : public Resource {
Vector<Point> points;
struct BakedPoint {
- float ofs;
+ float ofs = 0.0;
Vector2 point;
};
- mutable bool baked_cache_dirty;
+ mutable bool baked_cache_dirty = false;
mutable PackedVector2Array baked_point_cache;
- mutable float baked_max_ofs;
+ mutable float baked_max_ofs = 0.0;
void _bake() const;
- float bake_interval;
+ float bake_interval = 5.0;
void _bake_segment2d(Map<float, Vector2> &r_bake, float p_begin, float 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, float p_tol) const;
Dictionary _get_data() const;
@@ -214,28 +210,26 @@ class Curve3D : public Resource {
Vector3 in;
Vector3 out;
Vector3 pos;
- float tilt;
-
- Point() { tilt = 0; }
+ float tilt = 0.0;
};
Vector<Point> points;
struct BakedPoint {
- float ofs;
+ float ofs = 0.0;
Vector3 point;
};
- mutable bool baked_cache_dirty;
+ mutable bool baked_cache_dirty = false;
mutable PackedVector3Array baked_point_cache;
mutable PackedFloat32Array baked_tilt_cache;
mutable PackedVector3Array baked_up_vector_cache;
- mutable float baked_max_ofs;
+ mutable float baked_max_ofs = 0.0;
void _bake() const;
- float bake_interval;
- bool up_vector_enabled;
+ float bake_interval = 0.2;
+ bool up_vector_enabled = true;
void _bake_segment3d(Map<float, Vector3> &r_bake, float p_begin, float 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, float p_tol) const;
Dictionary _get_data() const;
diff --git a/scene/resources/cylinder_shape_3d.cpp b/scene/resources/cylinder_shape_3d.cpp
index 3e9cdca872..63bdc8d26d 100644
--- a/scene/resources/cylinder_shape_3d.cpp
+++ b/scene/resources/cylinder_shape_3d.cpp
@@ -75,7 +75,6 @@ void CylinderShape3D::set_radius(float p_radius) {
radius = p_radius;
_update_shape();
notify_change_to_owners();
- _change_notify("radius");
}
float CylinderShape3D::get_radius() const {
@@ -86,7 +85,6 @@ void CylinderShape3D::set_height(float p_height) {
height = p_height;
_update_shape();
notify_change_to_owners();
- _change_notify("height");
}
float CylinderShape3D::get_height() const {
@@ -105,7 +103,5 @@ void CylinderShape3D::_bind_methods() {
CylinderShape3D::CylinderShape3D() :
Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CYLINDER)) {
- radius = 1.0;
- height = 2.0;
_update_shape();
}
diff --git a/scene/resources/cylinder_shape_3d.h b/scene/resources/cylinder_shape_3d.h
index 93e8345727..d1b8364672 100644
--- a/scene/resources/cylinder_shape_3d.h
+++ b/scene/resources/cylinder_shape_3d.h
@@ -35,8 +35,8 @@
class CylinderShape3D : public Shape3D {
GDCLASS(CylinderShape3D, Shape3D);
- float radius;
- float height;
+ float radius = 1.0;
+ float height = 2.0;
protected:
static void _bind_methods();
diff --git a/scene/resources/default_theme/bar_arrow.png b/scene/resources/default_theme/bar_arrow.png
new file mode 100644
index 0000000000..7cf146b8da
--- /dev/null
+++ b/scene/resources/default_theme/bar_arrow.png
Binary files differ
diff --git a/scene/resources/default_theme/checked_disabled.png b/scene/resources/default_theme/checked_disabled.png
new file mode 100644
index 0000000000..70549e2edc
--- /dev/null
+++ b/scene/resources/default_theme/checked_disabled.png
Binary files differ
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index a0b65e9799..fabb93a933 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -43,7 +43,7 @@
typedef Map<const void *, Ref<ImageTexture>> TexCacheMap;
static TexCacheMap *tex_cache;
-static float scale = 1;
+static float scale = 1.0;
template <class T>
static Ref<StyleBoxTexture> make_stylebox(T p_src, float p_left, float p_top, float p_right, float p_bottom, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, bool p_draw_center = true) {
@@ -128,6 +128,38 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false,
return texture;
}
+static Ref<FontData> make_font(int p_height, int p_ascent, int p_charcount, const int *p_char_rects, int p_kerning_count, const int *p_kernings, int p_w, int p_h, const unsigned char *p_img) {
+ Ref<FontData> font(memnew(FontData));
+ font->new_bitmap(p_height, p_ascent, p_height);
+
+ Ref<Image> image = memnew(Image(p_img));
+ Ref<ImageTexture> tex = memnew(ImageTexture);
+ tex->create_from_image(image);
+
+ font->bitmap_add_texture(tex);
+
+ for (int i = 0; i < p_charcount; i++) {
+ const int *c = &p_char_rects[i * 8];
+
+ int chr = c[0];
+ Rect2 frect;
+ frect.position.x = c[1];
+ frect.position.y = c[2];
+ frect.size.x = c[3];
+ frect.size.y = c[4];
+ Point2 align(c[6], c[5]);
+ int advance = c[7];
+
+ font->bitmap_add_char(chr, 0, frect, align, advance);
+ }
+
+ for (int i = 0; i < p_kerning_count; i++) {
+ font->bitmap_add_kerning_pair(p_kernings[i * 3 + 0], p_kernings[i * 3 + 1], p_kernings[i * 3 + 2]);
+ }
+
+ return font;
+}
+
static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
Ref<StyleBox> style(memnew(StyleBoxEmpty));
@@ -210,7 +242,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_color", "LinkButton", control_font_color);
theme->set_color("font_pressed_color", "LinkButton", control_font_pressed_color);
theme->set_color("font_hover_color", "LinkButton", control_font_hover_color);
+ theme->set_color("font_outline_color", "LinkButton", Color(1, 1, 1));
+ theme->set_constant("outline_size", "LinkButton", 0);
theme->set_constant("underline_spacing", "LinkButton", 2 * scale);
// ColorPickerButton
@@ -228,8 +262,10 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_pressed_color", "ColorPickerButton", Color(0.8, 0.8, 0.8, 1));
theme->set_color("font_hover_color", "ColorPickerButton", Color(1, 1, 1, 1));
theme->set_color("font_disabled_color", "ColorPickerButton", Color(0.9, 0.9, 0.9, 0.3));
+ theme->set_color("font_outline_color", "ColorPickerButton", Color(1, 1, 1));
theme->set_constant("hseparation", "ColorPickerButton", 2 * scale);
+ theme->set_constant("outline_size", "ColorPickerButton", 0);
// OptionButton
@@ -265,9 +301,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_pressed_color", "OptionButton", control_font_pressed_color);
theme->set_color("font_hover_color", "OptionButton", control_font_hover_color);
theme->set_color("font_disabled_color", "OptionButton", control_font_disabled_color);
+ theme->set_color("font_outline_color", "OptionButton", Color(1, 1, 1));
theme->set_constant("hseparation", "OptionButton", 2 * scale);
theme->set_constant("arrow_margin", "OptionButton", 2 * scale);
+ theme->set_constant("outline_size", "OptionButton", 0);
// MenuButton
@@ -284,8 +322,10 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_pressed_color", "MenuButton", control_font_pressed_color);
theme->set_color("font_hover_color", "MenuButton", control_font_hover_color);
theme->set_color("font_disabled_color", "MenuButton", Color(1, 1, 1, 0.3));
+ theme->set_color("font_outline_color", "MenuButton", Color(1, 1, 1));
theme->set_constant("hseparation", "MenuButton", 3 * scale);
+ theme->set_constant("outline_size", "MenuButton", 0);
// CheckBox
@@ -308,9 +348,13 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_stylebox("focus", "CheckBox", cbx_focus);
theme->set_icon("checked", "CheckBox", make_icon(checked_png));
+ theme->set_icon("checked_disabled", "CheckBox", make_icon(checked_disabled_png));
theme->set_icon("unchecked", "CheckBox", make_icon(unchecked_png));
+ theme->set_icon("unchecked_disabled", "CheckBox", make_icon(unchecked_disabled_png));
theme->set_icon("radio_checked", "CheckBox", make_icon(radio_checked_png));
+ theme->set_icon("radio_checked_disabled", "CheckBox", make_icon(radio_checked_disabled_png));
theme->set_icon("radio_unchecked", "CheckBox", make_icon(radio_unchecked_png));
+ theme->set_icon("radio_unchecked_disabled", "CheckBox", make_icon(radio_unchecked_disabled_png));
theme->set_font("font", "CheckBox", Ref<Font>());
theme->set_font_size("font_size", "CheckBox", -1);
@@ -320,9 +364,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_hover_color", "CheckBox", control_font_hover_color);
theme->set_color("font_hover_pressed_color", "CheckBox", control_font_pressed_color);
theme->set_color("font_disabled_color", "CheckBox", control_font_disabled_color);
+ theme->set_color("font_outline_color", "CheckBox", Color(1, 1, 1));
theme->set_constant("hseparation", "CheckBox", 4 * scale);
theme->set_constant("check_vadjust", "CheckBox", 0 * scale);
+ theme->set_constant("outline_size", "CheckBox", 0);
// CheckButton
@@ -357,9 +403,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_hover_color", "CheckButton", control_font_hover_color);
theme->set_color("font_hover_pressed_color", "CheckButton", control_font_pressed_color);
theme->set_color("font_disabled_color", "CheckButton", control_font_disabled_color);
+ theme->set_color("font_outline_color", "CheckButton", Color(1, 1, 1));
theme->set_constant("hseparation", "CheckButton", 4 * scale);
theme->set_constant("check_vadjust", "CheckButton", 0 * scale);
+ theme->set_constant("outline_size", "CheckButton", 0);
// Label
@@ -373,7 +421,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("shadow_offset_x", "Label", 1 * scale);
theme->set_constant("shadow_offset_y", "Label", 1 * scale);
- theme->set_constant("outline_size", "Label", 0 * scale);
+ theme->set_constant("outline_size", "Label", 0);
theme->set_constant("shadow_outline_size", "Label", 1 * scale);
theme->set_constant("line_spacing", "Label", 3 * scale);
@@ -389,12 +437,14 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_color", "LineEdit", control_font_color);
theme->set_color("font_selected_color", "LineEdit", Color(0, 0, 0));
theme->set_color("font_uneditable_color", "LineEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f));
+ theme->set_color("font_outline_color", "LineEdit", Color(1, 1, 1));
theme->set_color("cursor_color", "LineEdit", control_font_hover_color);
theme->set_color("selection_color", "LineEdit", control_selection_color);
theme->set_color("clear_button_color", "LineEdit", control_font_color);
theme->set_color("clear_button_color_pressed", "LineEdit", control_font_pressed_color);
- theme->set_constant("minimum_spaces", "LineEdit", 12 * scale);
+ theme->set_constant("minimum_character_width", "LineEdit", 4);
+ theme->set_constant("outline_size", "LineEdit", 0);
theme->set_icon("clear", "LineEdit", make_icon(line_edit_clear_png));
@@ -408,6 +458,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_color", "ProgressBar", control_font_hover_color);
theme->set_color("font_shadow_color", "ProgressBar", Color(0, 0, 0));
+ theme->set_color("font_outline_color", "ProgressBar", Color(1, 1, 1));
+
+ theme->set_constant("outline_size", "ProgressBar", 0);
// TextEdit
@@ -431,6 +484,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_color", "TextEdit", control_font_color);
theme->set_color("font_selected_color", "TextEdit", Color(0, 0, 0));
theme->set_color("font_readonly_color", "TextEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f));
+ theme->set_color("font_outline_color", "TextEdit", Color(1, 1, 1));
theme->set_color("selection_color", "TextEdit", control_selection_color);
theme->set_color("mark_color", "TextEdit", Color(1.0, 0.4, 0.4, 0.4));
theme->set_color("code_folding_color", "TextEdit", Color(0.8, 0.8, 0.8, 0.8));
@@ -444,8 +498,10 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("completion_max_width", "TextEdit", 50);
theme->set_constant("completion_scroll_width", "TextEdit", 3);
theme->set_constant("line_spacing", "TextEdit", 4 * scale);
+ theme->set_constant("outline_size", "TextEdit", 0);
// CodeEdit
+
theme->set_stylebox("normal", "CodeEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0));
theme->set_stylebox("focus", "CodeEdit", focus);
theme->set_stylebox("read_only", "CodeEdit", make_stylebox(tree_bg_disabled_png, 4, 4, 4, 4, 0, 0, 0, 0));
@@ -471,6 +527,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_color", "CodeEdit", control_font_color);
theme->set_color("font_selected_color", "CodeEdit", Color(0, 0, 0));
theme->set_color("font_readonly_color", "CodeEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f));
+ theme->set_color("font_outline_color", "CodeEdit", Color(1, 1, 1));
theme->set_color("selection_color", "CodeEdit", control_selection_color);
theme->set_color("mark_color", "CodeEdit", Color(1.0, 0.4, 0.4, 0.4));
theme->set_color("bookmark_color", "CodeEdit", Color(0.5, 0.64, 1, 0.8));
@@ -489,6 +546,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("completion_max_width", "CodeEdit", 50);
theme->set_constant("completion_scroll_width", "CodeEdit", 3);
theme->set_constant("line_spacing", "CodeEdit", 4 * scale);
+ theme->set_constant("outline_size", "CodeEdit", 0);
Ref<Texture2D> empty_icon = memnew(ImageTexture);
@@ -544,7 +602,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_icon("updown", "SpinBox", make_icon(spinbox_updown_png));
- //scroll container
+ // ScrollContainer
+
Ref<StyleBoxEmpty> empty;
empty.instance();
theme->set_stylebox("bg", "ScrollContainer", empty);
@@ -556,7 +615,12 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("scaleborder_size", "Window", 4 * scale);
theme->set_font("title_font", "Window", large_font);
+ theme->set_font_size("title_font_size", "Window", -1);
+
theme->set_color("title_color", "Window", Color(0, 0, 0));
+ theme->set_color("title_outline_modulate", "Window", Color(1, 1, 1));
+
+ theme->set_constant("title_outline_size", "Window", 0);
theme->set_constant("title_height", "Window", 20 * scale);
theme->set_constant("resize_margin", "Window", 4 * scale);
@@ -611,9 +675,13 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_disabled_color", "PopupMenu", Color(0.4, 0.4, 0.4, 0.8));
theme->set_color("font_hover_color", "PopupMenu", control_font_color);
theme->set_color("font_separator_color", "PopupMenu", control_font_color);
+ theme->set_color("font_outline_color", "PopupMenu", Color(1, 1, 1));
theme->set_constant("hseparation", "PopupMenu", 4 * scale);
theme->set_constant("vseparation", "PopupMenu", 4 * scale);
+ theme->set_constant("outline_size", "PopupMenu", 0);
+ theme->set_constant("item_start_padding", "PopupMenu", 2 * scale);
+ theme->set_constant("item_end_padding", "PopupMenu", 2 * scale);
// GraphNode
@@ -682,6 +750,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("title_button_color", "Tree", control_font_color);
theme->set_color("font_color", "Tree", control_font_low_color);
theme->set_color("font_selected_color", "Tree", control_font_pressed_color);
+ theme->set_color("font_outline_color", "Tree", Color(1, 1, 1));
theme->set_color("guide_color", "Tree", Color(0, 0, 0, 0.1));
theme->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2));
theme->set_color("relationship_line_color", "Tree", Color(0.27, 0.27, 0.27));
@@ -695,8 +764,10 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("draw_guides", "Tree", 1);
theme->set_constant("scroll_border", "Tree", 4);
theme->set_constant("scroll_speed", "Tree", 12);
+ theme->set_constant("outline_size", "Tree", 0);
// ItemList
+
Ref<StyleBoxTexture> item_selected = make_stylebox(selection_png, 4, 4, 4, 4, 8, 2, 8, 2);
Ref<StyleBoxTexture> item_selected_oof = make_stylebox(selection_oof_png, 4, 4, 4, 4, 8, 2, 8, 2);
@@ -712,12 +783,15 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_color", "ItemList", control_font_lower_color);
theme->set_color("font_selected_color", "ItemList", control_font_pressed_color);
+ theme->set_color("font_outline_color", "ItemList", Color(1, 1, 1));
theme->set_color("guide_color", "ItemList", Color(0, 0, 0, 0.1));
theme->set_stylebox("selected", "ItemList", item_selected_oof);
theme->set_stylebox("selected_focus", "ItemList", item_selected);
theme->set_stylebox("cursor", "ItemList", focus);
theme->set_stylebox("cursor_unfocused", "ItemList", focus);
+ theme->set_constant("outline_size", "ItemList", 0);
+
// TabContainer
Ref<StyleBoxTexture> tc_sb = sb_expand(make_stylebox(tab_container_bg_png, 4, 4, 4, 4, 4, 4, 4, 4), 3, 3, 3, 3);
@@ -743,9 +817,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_selected_color", "TabContainer", control_font_hover_color);
theme->set_color("font_unselected_color", "TabContainer", control_font_low_color);
theme->set_color("font_disabled_color", "TabContainer", control_font_disabled_color);
+ theme->set_color("font_outline_color", "TabContainer", Color(1, 1, 1));
theme->set_constant("side_margin", "TabContainer", 8 * scale);
theme->set_constant("icon_separation", "TabContainer", 4 * scale);
+ theme->set_constant("outline_size", "TabContainer", 0);
// Tabs
@@ -768,8 +844,10 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_selected_color", "Tabs", control_font_hover_color);
theme->set_color("font_unselected_color", "Tabs", control_font_low_color);
theme->set_color("font_disabled_color", "Tabs", control_font_disabled_color);
+ theme->set_color("font_outline_color", "Tabs", Color(1, 1, 1));
theme->set_constant("hseparation", "Tabs", 4 * scale);
+ theme->set_constant("outline_size", "Tabs", 0);
// Separators
@@ -810,6 +888,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_icon("color_sample", "ColorPicker", make_icon(color_picker_sample_png));
theme->set_icon("preset_bg", "ColorPicker", make_icon(mini_checkerboard_png));
theme->set_icon("overbright_indicator", "ColorPicker", make_icon(overbright_indicator_png));
+ theme->set_icon("bar_arrow", "ColorPicker", make_icon(bar_arrow_png));
theme->set_icon("bg", "ColorPickerButton", make_icon(mini_checkerboard_png));
@@ -827,9 +906,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_color", "TooltipLabel", Color(0, 0, 0));
theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0.1));
+ theme->set_color("font_outline_color", "TooltipLabel", Color(1, 1, 1));
theme->set_constant("shadow_offset_x", "TooltipLabel", 1);
theme->set_constant("shadow_offset_y", "TooltipLabel", 1);
+ theme->set_constant("outline_size", "TooltipLabel", 0);
// RichTextLabel
@@ -854,6 +935,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0));
+ theme->set_color("font_outline_color", "RichTextLabel", Color(1, 1, 1));
+
theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * scale);
theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * scale);
theme->set_constant("shadow_as_outline", "RichTextLabel", 0 * scale);
@@ -862,9 +945,12 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("table_hseparation", "RichTextLabel", 3 * scale);
theme->set_constant("table_vseparation", "RichTextLabel", 3 * scale);
+ theme->set_constant("outline_size", "RichTextLabel", 0);
+
theme->set_color("table_odd_row_bg", "RichTextLabel", Color(0, 0, 0, 0));
theme->set_color("table_even_row_bg", "RichTextLabel", Color(0, 0, 0, 0));
theme->set_color("table_border", "RichTextLabel", Color(0, 0, 0, 0));
+
// Containers
theme->set_stylebox("bg", "VSplitContainer", make_stylebox(vsplit_bg_png, 1, 1, 1, 1));
@@ -904,6 +990,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("bezier_len_neg", "GraphEdit", 160 * scale);
// Visual Node Ports
+
theme->set_constant("port_grab_distance_horizontal", "GraphEdit", 48 * scale);
theme->set_constant("port_grab_distance_vertical", "GraphEdit", 6 * scale);
@@ -935,45 +1022,15 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) {
Ref<StyleBox> default_style;
Ref<Texture2D> default_icon;
Ref<Font> default_font;
- int default_font_size = 16;
+ int default_font_size = 14;
if (p_font.is_valid()) {
default_font = p_font;
} else if (p_hidpi) {
- TextServer::BitmapFontData data;
- data.height = _hidpi_font_height;
- data.ascent = _hidpi_font_ascent;
- data.charcount = _hidpi_font_charcount;
- data.char_rects = &_hidpi_font_charrects[0][0];
- data.kerning_count = _hidpi_font_kerning_pair_count;
- data.kernings = &_hidpi_font_kerning_pairs[0][0];
- data.w = _hidpi_font_img_width;
- data.h = _hidpi_font_img_height;
- data.img = _hidpi_font_img_data;
-
- Ref<FontData> font_data;
- font_data.instance();
- font_data->load_memory((const uint8_t *)&data, sizeof(data), "fnt");
- default_font_size = font_data->get_base_size();
-
+ Ref<FontData> font_data = make_font(_hidpi_font_height, _hidpi_font_ascent, _hidpi_font_charcount, &_hidpi_font_charrects[0][0], _hidpi_font_kerning_pair_count, &_hidpi_font_kerning_pairs[0][0], _hidpi_font_img_width, _hidpi_font_img_height, _hidpi_font_img_data);
default_font.instance();
default_font->add_data(font_data);
} else {
- TextServer::BitmapFontData data;
- data.height = _lodpi_font_height;
- data.ascent = _lodpi_font_ascent;
- data.charcount = _lodpi_font_charcount;
- data.char_rects = &_lodpi_font_charrects[0][0];
- data.kerning_count = _lodpi_font_kerning_pair_count;
- data.kernings = &_lodpi_font_kerning_pairs[0][0];
- data.w = _lodpi_font_img_width;
- data.h = _lodpi_font_img_height;
- data.img = _lodpi_font_img_data;
-
- Ref<FontData> font_data;
- font_data.instance();
- font_data->load_memory((const uint8_t *)&data, sizeof(data), "fnt");
- default_font_size = font_data->get_base_size();
-
+ Ref<FontData> font_data = make_font(_lodpi_font_height, _lodpi_font_ascent, _lodpi_font_charcount, &_lodpi_font_charrects[0][0], _lodpi_font_kerning_pair_count, &_lodpi_font_kerning_pairs[0][0], _lodpi_font_img_width, _lodpi_font_img_height, _lodpi_font_img_data);
default_font.instance();
default_font->add_data(font_data);
}
diff --git a/scene/resources/default_theme/radio_checked_disabled.png b/scene/resources/default_theme/radio_checked_disabled.png
new file mode 100644
index 0000000000..72f08ecb96
--- /dev/null
+++ b/scene/resources/default_theme/radio_checked_disabled.png
Binary files differ
diff --git a/scene/resources/default_theme/radio_unchecked_disabled.png b/scene/resources/default_theme/radio_unchecked_disabled.png
new file mode 100644
index 0000000000..a8f4c1b555
--- /dev/null
+++ b/scene/resources/default_theme/radio_unchecked_disabled.png
Binary files differ
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index b905c9db69..5d4dbd0758 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -14,6 +14,10 @@ static const unsigned char arrow_right_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x17, 0x3c, 0xf8, 0xf, 0x82, 0xf7, 0x13, 0x70, 0x48, 0x3c, 0xf8, 0xf2, 0x50, 0x1b, 0x43, 0x2, 0xa, 0xaf, 0xbe, 0xe0, 0xc6, 0x2e, 0xf1, 0xff, 0xe1, 0x7c, 0x12, 0x24, 0x10, 0x46, 0x11, 0xb6, 0x1c, 0xe1, 0x5c, 0xa, 0x0, 0x0, 0xe0, 0x14, 0x48, 0xb1, 0x3d, 0x1b, 0x7a, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
+static const unsigned char bar_arrow_png[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x14, 0x8, 0x4, 0x0, 0x0, 0x0, 0x2e, 0x6b, 0x75, 0xfc, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x1, 0x73, 0x52, 0x47, 0x42, 0x0, 0xae, 0xce, 0x1c, 0xe9, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc0, 0x0, 0x0, 0xe, 0xc0, 0x1, 0x6a, 0xd6, 0x89, 0x9, 0x0, 0x0, 0x0, 0x65, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0xfc, 0xcf, 0x80, 0x1f, 0x30, 0x8e, 0x20, 0x5, 0x8c, 0x38, 0x24, 0xff, 0x53, 0x5f, 0xc1, 0xb, 0xee, 0x9f, 0x53, 0x18, 0x18, 0xd8, 0x73, 0x24, 0xbe, 0x62, 0x55, 0x70, 0x5f, 0x83, 0x61, 0x15, 0xa3, 0x2e, 0x3, 0x3, 0xc3, 0xd, 0xe6, 0x30, 0xd9, 0xcb, 0x18, 0xa, 0x1e, 0xc6, 0xfd, 0x9f, 0xc6, 0xc0, 0xd, 0x35, 0xea, 0x3b, 0x63, 0x81, 0xfc, 0x2c, 0x14, 0x5, 0xf, 0x2a, 0x18, 0xda, 0xd1, 0x1c, 0x50, 0xa9, 0xd0, 0x1, 0x57, 0xf0, 0x10, 0x53, 0x9a, 0x81, 0x81, 0x81, 0xa1, 0x52, 0xbe, 0x83, 0x81, 0x81, 0xf1, 0x3f, 0x2e, 0x69, 0xa8, 0x12, 0x3a, 0x4, 0x14, 0x0, 0x7b, 0xda, 0x34, 0x1, 0xbb, 0xb5, 0x3e, 0x6c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
static const unsigned char bookmark_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x4, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0x8, 0x7c, 0x8, 0x64, 0x88, 0x0, 0x0, 0x0, 0x57, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xed, 0x93, 0x31, 0xa, 0xc0, 0x30, 0xc, 0x3, 0xa5, 0xd0, 0xff, 0x7f, 0x59, 0x1d, 0x8a, 0x42, 0x8, 0x9, 0x95, 0xc9, 0xd2, 0xa1, 0x9a, 0x8c, 0xf1, 0xdd, 0x62, 0x1b, 0x38, 0xc, 0x87, 0x5a, 0x5, 0xae, 0x79, 0xde, 0x2, 0x1, 0x80, 0x94, 0x39, 0x48, 0x76, 0x49, 0x17, 0xa4, 0xf0, 0x24, 0x61, 0x2b, 0x51, 0x8b, 0xfc, 0x82, 0xcf, 0xb, 0x48, 0x7a, 0xdf, 0x75, 0x81, 0xf, 0xe5, 0x29, 0xf7, 0x92, 0x6b, 0x3, 0x1a, 0x1e, 0xda, 0x7c, 0x3d, 0x77, 0x21, 0x7b, 0xa8, 0x74, 0x2e, 0xcb, 0xd, 0xc8, 0x75, 0x13, 0x28, 0x9, 0xed, 0xc2, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -42,6 +46,10 @@ static const unsigned char checked_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x8d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x58, 0x56, 0x63, 0xb0, 0xaf, 0xb5, 0x38, 0x37, 0x40, 0x20, 0x20, 0x24, 0xb6, 0xb6, 0xb9, 0x57, 0x57, 0x5a, 0x20, 0x20, 0x24, 0x38, 0x36, 0x40, 0x20, 0x20, 0x25, 0x1e, 0x1e, 0x22, 0x1f, 0x1f, 0x23, 0x8b, 0x8b, 0x8d, 0xff, 0xff, 0xff, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x23, 0x23, 0x28, 0x42, 0x42, 0x47, 0xf8, 0xf8, 0xf8, 0xfe, 0xfe, 0xfe, 0x25, 0x25, 0x2a, 0x4e, 0x4e, 0x52, 0x26, 0x26, 0x2b, 0xc5, 0xc5, 0xc7, 0xaa, 0xaa, 0xab, 0xb8, 0xb8, 0xba, 0x5f, 0x5f, 0x63, 0x74, 0x74, 0x77, 0xed, 0xed, 0xed, 0x33, 0x33, 0x38, 0x8d, 0x8d, 0x8f, 0xb8, 0xb8, 0xb9, 0x35, 0x35, 0x39, 0x3a, 0x3a, 0x3e, 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xfa, 0xb2, 0xb2, 0xb4, 0x45, 0x45, 0x49, 0x61, 0x61, 0x65, 0x8f, 0x8f, 0x92, 0x63, 0x63, 0x66, 0x2a, 0x2a, 0x2f, 0x40, 0x82, 0xb, 0xf6, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0x6a, 0x81, 0xb4, 0xfa, 0xdd, 0xfb, 0xfb, 0xb4, 0xfa, 0xb8, 0xf0, 0x7f, 0x59, 0x0, 0x0, 0x0, 0x7e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x5d, 0xca, 0x5, 0xb2, 0x2, 0x30, 0x18, 0x3, 0xe1, 0x4d, 0xed, 0xb9, 0x60, 0xf7, 0x3f, 0x20, 0xee, 0x4e, 0x99, 0xe0, 0xb0, 0x63, 0xfd, 0xbf, 0x86, 0xd7, 0x12, 0x72, 0x38, 0x69, 0x5b, 0x6b, 0x42, 0x45, 0xe5, 0xa, 0xab, 0x95, 0x41, 0x9f, 0x32, 0x20, 0x69, 0x2d, 0xbc, 0x50, 0x46, 0x3a, 0x10, 0x17, 0x5f, 0x49, 0x4, 0x7f, 0x90, 0x57, 0x89, 0xb7, 0xc5, 0x5f, 0x96, 0x17, 0x2e, 0x93, 0xcb, 0x8e, 0x3a, 0x83, 0xb, 0xc4, 0x8e, 0xd4, 0xff, 0x5c, 0x73, 0x83, 0x69, 0x9e, 0x95, 0xfc, 0x3b, 0xf4, 0x33, 0xe0, 0xf8, 0x61, 0xd3, 0xf1, 0x7d, 0x5d, 0x30, 0x7a, 0x6f, 0x89, 0xb, 0xd4, 0x5a, 0xe1, 0x40, 0xf, 0xfc, 0x34, 0x6c, 0xd2, 0x56, 0x80, 0xef, 0xfd, 0x9, 0xd2, 0x3a, 0x5e, 0x41, 0x15, 0x21, 0x77, 0x6, 0xc7, 0x6b, 0x47, 0x4e, 0x3a, 0x2f, 0x53, 0xb4, 0x10, 0xc7, 0x8c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
+static const unsigned char checked_disabled_png[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x99, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x73, 0x72, 0x7b, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x82, 0x80, 0x8a, 0x90, 0x90, 0x93, 0x6a, 0x69, 0x70, 0x6a, 0x68, 0x70, 0x93, 0x93, 0x95, 0x58, 0x58, 0x5c, 0x58, 0x58, 0x5b, 0x7d, 0x7d, 0x7f, 0x58, 0x58, 0x5b, 0xa4, 0xa4, 0xa4, 0x9e, 0x9e, 0xa0, 0x9e, 0x9e, 0x9e, 0x9b, 0x9b, 0x9c, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x93, 0x93, 0x94, 0x8f, 0x8f, 0x8f, 0x86, 0x86, 0x88, 0x85, 0x85, 0x86, 0x82, 0x82, 0x83, 0x81, 0x81, 0x83, 0x7f, 0x7f, 0x81, 0x7c, 0x7c, 0x7e, 0x7a, 0x7a, 0x7d, 0x78, 0x78, 0x7b, 0x71, 0x71, 0x74, 0x68, 0x68, 0x6c, 0x66, 0x66, 0x6a, 0x65, 0x65, 0x68, 0x63, 0x63, 0x66, 0x5f, 0x5f, 0x63, 0x5c, 0x5c, 0x60, 0x5c, 0x5c, 0x5f, 0x5a, 0x5a, 0x5e, 0x59, 0x59, 0x5d, 0x59, 0x59, 0x5c, 0x58, 0x58, 0x5b, 0x57, 0x57, 0x5a, 0x56, 0x56, 0x59, 0x10, 0x13, 0xbb, 0xf, 0x0, 0x0, 0x0, 0x10, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x27, 0x50, 0x66, 0x68, 0x6a, 0x81, 0xb4, 0xb4, 0xdd, 0xfa, 0xfa, 0xfb, 0xfb, 0x5b, 0xd1, 0xf1, 0xe6, 0x0, 0x0, 0x0, 0x96, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0x5d, 0x8f, 0xc9, 0x12, 0x82, 0x30, 0x14, 0x4, 0x87, 0x18, 0x50, 0x51, 0x44, 0x25, 0x42, 0x4, 0x77, 0xc4, 0x8d, 0x97, 0x0, 0xf9, 0xff, 0x8f, 0xb3, 0x88, 0xa4, 0x4a, 0xed, 0x63, 0x5f, 0xa6, 0x7, 0xf8, 0x7, 0x1e, 0xe3, 0x7e, 0x60, 0x19, 0x4f, 0x46, 0x1e, 0x0, 0x36, 0x8d, 0x4c, 0x67, 0x59, 0x65, 0x33, 0x6, 0x80, 0x47, 0xad, 0x56, 0x3d, 0xb7, 0x3c, 0x5d, 0x70, 0x0, 0xbe, 0xd1, 0x44, 0x65, 0x4d, 0x94, 0xc8, 0xc2, 0xf8, 0x0, 0x82, 0x4e, 0x91, 0x94, 0x15, 0x5d, 0xd2, 0xec, 0xde, 0x5, 0x83, 0x38, 0xc8, 0xe3, 0x63, 0x23, 0xce, 0xca, 0x9, 0x7a, 0x6e, 0xf3, 0x93, 0x48, 0x1a, 0x27, 0x14, 0x35, 0x3b, 0xb9, 0x5e, 0x56, 0xe4, 0x84, 0x22, 0xba, 0xa, 0x51, 0xd0, 0xb7, 0xa8, 0xcb, 0xfd, 0xcb, 0x9, 0x3b, 0xfb, 0x41, 0xdb, 0x59, 0x17, 0xa6, 0x94, 0x6e, 0xe3, 0x3e, 0x8c, 0x85, 0xf1, 0x90, 0x6e, 0xe6, 0x21, 0xfb, 0x39, 0xe7, 0x73, 0xe6, 0xfd, 0x5f, 0x7, 0xde, 0xc3, 0xb5, 0x16, 0x87, 0xb0, 0x9e, 0x42, 0x46, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
static const unsigned char checker_bg_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0xe1, 0x64, 0xe1, 0x57, 0x0, 0x0, 0x0, 0x14, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xfc, 0xcf, 0xc0, 0xc0, 0xd0, 0x0, 0xc4, 0xf8, 0x18, 0xf5, 0x84, 0x19, 0x0, 0x9f, 0x5f, 0xa, 0x1, 0xf8, 0xef, 0x65, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -282,10 +290,18 @@ static const unsigned char radio_checked_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x42, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0xd3, 0xd3, 0xd3, 0xa2, 0xa2, 0xa2, 0x79, 0x79, 0x79, 0x73, 0x73, 0x73, 0x1c, 0x1c, 0x1c, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0xd1, 0xa7, 0xf5, 0xaa, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x88, 0xd1, 0xf7, 0x64, 0xf6, 0x2, 0xb3, 0xed, 0xd7, 0x0, 0x0, 0x0, 0x63, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6d, 0x4f, 0x55, 0x2, 0x43, 0x31, 0x8, 0x4b, 0xe8, 0x6a, 0xf7, 0xbf, 0xeb, 0xc, 0x9b, 0x6b, 0x1f, 0x9f, 0xc4, 0x89, 0xbf, 0xbb, 0x3f, 0x2a, 0x49, 0x64, 0xa6, 0x3e, 0x1e, 0x1c, 0x7c, 0x3e, 0xf2, 0x14, 0xb7, 0xc7, 0xac, 0xf1, 0x10, 0xa6, 0xe8, 0x1, 0x44, 0xad, 0x42, 0xb9, 0x33, 0x22, 0x43, 0x95, 0x68, 0x55, 0xa4, 0xdc, 0x1f, 0x1e, 0xa1, 0x67, 0xa2, 0x57, 0x96, 0x22, 0x0, 0xc2, 0x3d, 0xf5, 0x44, 0x8c, 0x8a, 0x5d, 0x21, 0x80, 0x74, 0x83, 0x1e, 0x97, 0xc7, 0x22, 0x59, 0x4c, 0xd7, 0xd8, 0xb5, 0x18, 0x4a, 0x7b, 0x57, 0x57, 0xdb, 0x1a, 0xf7, 0x77, 0x17, 0x3a, 0x56, 0x4e, 0x11, 0x6f, 0x82, 0x20, 0xde, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
+static const unsigned char radio_checked_disabled_png[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x45, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0xd3, 0xd3, 0xd3, 0xa2, 0xa2, 0xa2, 0x79, 0x79, 0x79, 0x73, 0x73, 0x73, 0x1c, 0x1c, 0x1c, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x83, 0xac, 0xe9, 0xaf, 0x0, 0x0, 0x0, 0x1, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x40, 0xe6, 0xd8, 0x66, 0x0, 0x0, 0x0, 0x3f, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x63, 0x60, 0x20, 0xe, 0xf0, 0x8, 0x2, 0x1, 0xf, 0x9c, 0x2b, 0x2c, 0x8, 0x5, 0xc2, 0x50, 0x1, 0xb0, 0x34, 0x58, 0x11, 0x5c, 0xbd, 0x10, 0x3f, 0x10, 0x8, 0xc1, 0x74, 0x1, 0x65, 0xf8, 0xc1, 0x0, 0xa6, 0x4, 0x28, 0x1, 0x11, 0xe0, 0xc1, 0x2d, 0x80, 0xa6, 0x5, 0xc3, 0x50, 0xc, 0x6b, 0x31, 0x1d, 0x86, 0xe1, 0x74, 0xfc, 0x0, 0x0, 0x1b, 0xc, 0x7, 0xb9, 0xa, 0x5e, 0x2e, 0x12, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
static const unsigned char radio_unchecked_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x2a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0x2b, 0x6e, 0xf2, 0xbf, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x88, 0xd1, 0xf7, 0x64, 0xf6, 0x2, 0xb3, 0xed, 0xd7, 0x0, 0x0, 0x0, 0x49, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x2, 0x61, 0x15, 0xed, 0xa9, 0x20, 0x5a, 0x72, 0xf5, 0x99, 0x33, 0xbb, 0x26, 0x1, 0x19, 0x73, 0xcf, 0x0, 0xc1, 0x4d, 0x6, 0x6, 0xd6, 0x35, 0x20, 0xc6, 0xa9, 0x0, 0x6, 0xb6, 0x3d, 0x20, 0xc6, 0xe9, 0x4, 0x6, 0xf6, 0x33, 0x60, 0x50, 0xc0, 0xc0, 0x1, 0x61, 0x34, 0xc0, 0x19, 0x70, 0x29, 0xb8, 0x62, 0xb8, 0x76, 0x84, 0x81, 0xc, 0x96, 0x20, 0x2b, 0xa6, 0xc0, 0x2d, 0x45, 0x0, 0x0, 0x37, 0xca, 0x3d, 0x81, 0xb4, 0x84, 0xb6, 0x80, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
+static const unsigned char radio_unchecked_disabled_png[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0xf, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x54, 0x54, 0x54, 0xad, 0xad, 0xad, 0x80, 0x80, 0x81, 0x64, 0x64, 0x64, 0xf4, 0x17, 0x36, 0x28, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1b, 0xfc, 0xf6, 0x4, 0xd4, 0x0, 0x0, 0x0, 0x40, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0x7d, 0x8d, 0xb1, 0x11, 0x80, 0x40, 0xc, 0xc3, 0x94, 0xd, 0x12, 0x60, 0x1, 0xc4, 0x4, 0xb0, 0x1, 0xfb, 0x2f, 0x45, 0xe5, 0x3b, 0xaa, 0x57, 0xe5, 0xc2, 0xb6, 0x20, 0xc0, 0xcc, 0xc, 0x40, 0xed, 0x7a, 0x37, 0x70, 0xa8, 0xbe, 0x50, 0x9b, 0xea, 0xd9, 0xd4, 0xa3, 0x7a, 0x35, 0xa5, 0xaa, 0xeb, 0x90, 0x72, 0xe6, 0x39, 0xfc, 0x2b, 0x22, 0xd, 0x1f, 0xe7, 0x64, 0xa, 0x5d, 0x6c, 0xfe, 0xc1, 0x3b, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
static const unsigned char scroll_bg_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x3, 0x0, 0x0, 0x0, 0x61, 0xab, 0xac, 0xd5, 0x0, 0x0, 0x0, 0x45, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x40, 0x3e, 0x4a, 0x2a, 0x29, 0x2f, 0x20, 0x20, 0x24, 0x3f, 0x3e, 0x49, 0x1f, 0x1f, 0x24, 0x20, 0x20, 0x24, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x3f, 0x3e, 0x49, 0x3f, 0x3e, 0x49, 0x1e, 0x1e, 0x23, 0x20, 0x20, 0x25, 0x22, 0x22, 0x27, 0x23, 0x23, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0x14, 0xee, 0x69, 0x20, 0x0, 0x0, 0x0, 0x11, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0x19, 0x40, 0x5d, 0x66, 0x28, 0x93, 0xf0, 0xfc, 0x94, 0xfc, 0xfd, 0x67, 0x1a, 0x96, 0x95, 0x1c, 0xf0, 0x43, 0x52, 0x0, 0x0, 0x0, 0x55, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x55, 0x8e, 0x45, 0x2, 0x80, 0x50, 0x10, 0x42, 0xc1, 0xee, 0xfb, 0x5f, 0xd4, 0xd6, 0xdf, 0xfd, 0x36, 0xd3, 0x3, 0x4, 0xd, 0x90, 0x6, 0xb2, 0x25, 0x39, 0xe0, 0xd2, 0xf9, 0xcb, 0x6a, 0x60, 0x6f, 0x27, 0xb7, 0xbc, 0x58, 0xb7, 0x53, 0x4d, 0x0, 0xf2, 0x3f, 0x5e, 0x36, 0x43, 0x5f, 0xc3, 0xf0, 0xdf, 0x17, 0xd7, 0xa6, 0xae, 0x60, 0x10, 0xff, 0x57, 0x16, 0xc5, 0x5a, 0xf1, 0x60, 0xe3, 0xe7, 0x5f, 0x37, 0x46, 0x74, 0xba, 0x9a, 0x16, 0xef, 0x37, 0x1c, 0x6f, 0x61, 0x47, 0x1, 0xa5, 0xc7, 0x32, 0x47, 0x38, 0x12, 0x92, 0xb1, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -430,6 +446,10 @@ static const unsigned char unchecked_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x38, 0x37, 0x40, 0x20, 0x20, 0x24, 0x20, 0x20, 0x24, 0x38, 0x36, 0x40, 0x20, 0x20, 0x25, 0x1e, 0x1e, 0x22, 0x1f, 0x1f, 0x23, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0x23, 0xc3, 0x49, 0x39, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0xb4, 0xfa, 0xfb, 0xb4, 0xfa, 0xa4, 0x7f, 0xe1, 0x5a, 0x0, 0x0, 0x0, 0x4f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xb5, 0xcf, 0x45, 0x2, 0x80, 0x40, 0x8, 0x0, 0x40, 0x97, 0x66, 0xfb, 0xff, 0x9f, 0xb5, 0xdb, 0xb3, 0x73, 0xa4, 0x19, 0xbe, 0x2, 0x20, 0xf1, 0x8a, 0x10, 0xc2, 0x1c, 0x0, 0xd1, 0x94, 0x57, 0x49, 0x5, 0xe6, 0x0, 0x6a, 0xa9, 0x6d, 0x55, 0x8b, 0xe2, 0x1c, 0xa0, 0x54, 0xfb, 0xae, 0x26, 0x9a, 0x3, 0x9c, 0xdb, 0x11, 0x68, 0x99, 0xff, 0xa, 0x7c, 0xd6, 0xde, 0xf, 0x33, 0x9c, 0x3, 0xe0, 0x76, 0x9c, 0x1e, 0x1d, 0xbe, 0xcf, 0x7d, 0x4c, 0x93, 0xe2, 0x8, 0xa4, 0x66, 0x3c, 0xec, 0xed, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
+static const unsigned char unchecked_disabled_png[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x6a, 0x69, 0x70, 0x6a, 0x68, 0x70, 0x58, 0x58, 0x5c, 0x58, 0x58, 0x5b, 0x58, 0x58, 0x5b, 0x5c, 0x5c, 0x5f, 0x5a, 0x5a, 0x5e, 0x59, 0x59, 0x5d, 0x58, 0x58, 0x5b, 0x57, 0x57, 0x5a, 0x56, 0x56, 0x59, 0x27, 0xa1, 0xa6, 0x53, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0xb4, 0xb4, 0xfa, 0xfa, 0xfb, 0xc7, 0x8b, 0xf6, 0x7e, 0x0, 0x0, 0x0, 0x52, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0xb5, 0xcf, 0x31, 0x12, 0xc0, 0x20, 0x8, 0x44, 0xd1, 0x15, 0x50, 0x83, 0x11, 0xe5, 0xfe, 0xa7, 0xcd, 0xe8, 0xc4, 0x22, 0xf4, 0x79, 0xe5, 0x36, 0x7c, 0x80, 0x8, 0x89, 0x58, 0xf2, 0x26, 0x4c, 0x9, 0x0, 0x15, 0xf5, 0xb9, 0xb9, 0x16, 0x2, 0xc0, 0x3a, 0xac, 0x6f, 0x36, 0x94, 0x1, 0x88, 0xdb, 0xfd, 0x32, 0x17, 0x0, 0x79, 0xf6, 0x33, 0xf4, 0x99, 0xff, 0x1a, 0xe2, 0xd9, 0x4f, 0x58, 0x5b, 0x61, 0x54, 0xdb, 0x49, 0xbf, 0xea, 0x4a, 0x8f, 0xcf, 0x45, 0xf, 0x4, 0x40, 0x7, 0x90, 0xb0, 0x7b, 0x47, 0x4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
static const unsigned char updown_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0x81, 0x83, 0xf6, 0xf6, 0x0, 0x0, 0x0, 0x57, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x8d, 0x4e, 0xb5, 0x1, 0xc0, 0x30, 0xc, 0xf3, 0x15, 0xfe, 0xff, 0x96, 0x64, 0xa, 0x6c, 0xca, 0x56, 0xd2, 0x25, 0x65, 0xe6, 0xc8, 0x8b, 0x49, 0x20, 0x79, 0x28, 0x95, 0x81, 0xa1, 0xd4, 0x7d, 0x4, 0xbb, 0xa1, 0x50, 0xea, 0x3c, 0xa6, 0x71, 0x98, 0x96, 0x69, 0x58, 0x31, 0xcc, 0xb7, 0xe5, 0x2f, 0x48, 0x63, 0x26, 0xf6, 0xa2, 0xd4, 0x18, 0xf9, 0x7, 0x2d, 0xe3, 0x46, 0x89, 0xb4, 0xd2, 0xf8, 0xa3, 0x68, 0xe3, 0xd7, 0x14, 0x20, 0xe6, 0xc3, 0x3d, 0xd8, 0xca, 0x5e, 0x94, 0x32, 0xd0, 0x3, 0x91, 0xba, 0x5f, 0x1b, 0x4a, 0x9b, 0x12, 0x62, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
diff --git a/scene/resources/default_theme/unchecked_disabled.png b/scene/resources/default_theme/unchecked_disabled.png
new file mode 100644
index 0000000000..bef9316f58
--- /dev/null
+++ b/scene/resources/default_theme/unchecked_disabled.png
Binary files differ
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index b7b5f72fcd..c04b271d81 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -44,7 +44,7 @@ RID Environment::get_rid() const {
void Environment::set_background(BGMode p_bg) {
bg_mode = p_bg;
RS::get_singleton()->environment_set_background(environment, RS::EnvironmentBG(p_bg));
- _change_notify();
+ notify_property_list_changed();
if (bg_mode != BG_SKY) {
set_fog_aerial_perspective(0.0);
}
@@ -138,7 +138,7 @@ Color Environment::get_ambient_light_color() const {
void Environment::set_ambient_source(AmbientSource p_source) {
ambient_source = p_source;
_update_ambient_light();
- _change_notify();
+ notify_property_list_changed();
}
Environment::AmbientSource Environment::get_ambient_source() const {
@@ -166,7 +166,7 @@ float Environment::get_ambient_light_sky_contribution() const {
void Environment::set_reflection_source(ReflectionSource p_source) {
reflection_source = p_source;
_update_ambient_light();
- _change_notify();
+ notify_property_list_changed();
}
Environment::ReflectionSource Environment::get_reflection_source() const {
@@ -224,7 +224,7 @@ float Environment::get_tonemap_white() const {
void Environment::set_tonemap_auto_exposure_enabled(bool p_enabled) {
tonemap_auto_exposure_enabled = p_enabled;
_update_tonemap();
- _change_notify();
+ notify_property_list_changed();
}
bool Environment::is_tonemap_auto_exposure_enabled() const {
@@ -285,7 +285,7 @@ void Environment::_update_tonemap() {
void Environment::set_ssr_enabled(bool p_enabled) {
ssr_enabled = p_enabled;
_update_ssr();
- _change_notify();
+ notify_property_list_changed();
}
bool Environment::is_ssr_enabled() const {
@@ -343,7 +343,7 @@ void Environment::_update_ssr() {
void Environment::set_ssao_enabled(bool p_enabled) {
ssao_enabled = p_enabled;
_update_ssao();
- _change_notify();
+ notify_property_list_changed();
}
bool Environment::is_ssao_enabled() const {
@@ -441,6 +441,7 @@ void Environment::_update_ssao() {
void Environment::set_sdfgi_enabled(bool p_enabled) {
sdfgi_enabled = p_enabled;
_update_sdfgi();
+ notify_property_list_changed();
}
bool Environment::is_sdfgi_enabled() const {
@@ -458,8 +459,6 @@ Environment::SDFGICascades Environment::get_sdfgi_cascades() const {
void Environment::set_sdfgi_min_cell_size(float p_size) {
sdfgi_min_cell_size = p_size;
- _change_notify("sdfgi_max_distance");
- _change_notify("sdfgi_cascade0_distance");
_update_sdfgi();
}
@@ -475,8 +474,6 @@ void Environment::set_sdfgi_max_distance(float p_distance) {
p_distance *= 0.5; //halve for each cascade
}
sdfgi_min_cell_size = p_distance;
- _change_notify("sdfgi_min_cell_size");
- _change_notify("sdfgi_cascade0_distance");
_update_sdfgi();
}
@@ -493,8 +490,6 @@ float Environment::get_sdfgi_max_distance() const {
void Environment::set_sdfgi_cascade0_distance(float p_distance) {
sdfgi_min_cell_size = p_distance / 64.0;
- _change_notify("sdfgi_min_cell_size");
- _change_notify("sdfgi_max_distance");
_update_sdfgi();
}
@@ -520,13 +515,12 @@ bool Environment::is_sdfgi_using_occlusion() const {
return sdfgi_use_occlusion;
}
-void Environment::set_sdfgi_use_multi_bounce(bool p_enabled) {
- sdfgi_use_multibounce = p_enabled;
+void Environment::set_sdfgi_bounce_feedback(float p_amount) {
+ sdfgi_bounce_feedback = p_amount;
_update_sdfgi();
}
-
-bool Environment::is_sdfgi_using_multi_bounce() const {
- return sdfgi_use_multibounce;
+float Environment::get_sdfgi_bounce_feedback() const {
+ return sdfgi_bounce_feedback;
}
void Environment::set_sdfgi_read_sky_light(bool p_enabled) {
@@ -573,7 +567,7 @@ void Environment::_update_sdfgi() {
sdfgi_min_cell_size,
RS::EnvironmentSDFGIYScale(sdfgi_y_scale),
sdfgi_use_occlusion,
- sdfgi_use_multibounce,
+ sdfgi_bounce_feedback,
sdfgi_read_sky_light,
sdfgi_energy,
sdfgi_normal_bias,
@@ -585,7 +579,7 @@ void Environment::_update_sdfgi() {
void Environment::set_glow_enabled(bool p_enabled) {
glow_enabled = p_enabled;
_update_glow();
- _change_notify();
+ notify_property_list_changed();
}
bool Environment::is_glow_enabled() const {
@@ -655,7 +649,7 @@ float Environment::get_glow_bloom() const {
void Environment::set_glow_blend_mode(GlowBlendMode p_mode) {
glow_blend_mode = p_mode;
_update_glow();
- _change_notify();
+ notify_property_list_changed();
}
Environment::GlowBlendMode Environment::get_glow_blend_mode() const {
@@ -723,7 +717,7 @@ void Environment::_update_glow() {
void Environment::set_fog_enabled(bool p_enabled) {
fog_enabled = p_enabled;
_update_fog();
- _change_notify();
+ notify_property_list_changed();
}
bool Environment::is_fog_enabled() const {
@@ -797,13 +791,13 @@ void Environment::_update_fog() {
// Volumetric Fog
void Environment::_update_volumetric_fog() {
- RS::get_singleton()->environment_set_volumetric_fog(environment, volumetric_fog_enabled, volumetric_fog_density, volumetric_fog_light, volumetric_fog_light_energy, volumetric_fog_length, volumetric_fog_detail_spread, volumetric_fog_gi_inject, RS::EnvVolumetricFogShadowFilter(volumetric_fog_shadow_filter));
+ RS::get_singleton()->environment_set_volumetric_fog(environment, volumetric_fog_enabled, volumetric_fog_density, volumetric_fog_light, volumetric_fog_light_energy, volumetric_fog_length, volumetric_fog_detail_spread, volumetric_fog_gi_inject, volumetric_fog_temporal_reproject, volumetric_fog_temporal_reproject_amount);
}
void Environment::set_volumetric_fog_enabled(bool p_enable) {
volumetric_fog_enabled = p_enable;
_update_volumetric_fog();
- _change_notify();
+ notify_property_list_changed();
}
bool Environment::is_volumetric_fog_enabled() const {
@@ -854,13 +848,20 @@ float Environment::get_volumetric_fog_gi_inject() const {
return volumetric_fog_gi_inject;
}
-void Environment::set_volumetric_fog_shadow_filter(VolumetricFogShadowFilter p_filter) {
- volumetric_fog_shadow_filter = p_filter;
+void Environment::set_volumetric_fog_temporal_reprojection_enabled(bool p_enable) {
+ volumetric_fog_temporal_reproject = p_enable;
+ _update_volumetric_fog();
+}
+bool Environment::is_volumetric_fog_temporal_reprojection_enabled() const {
+ return volumetric_fog_temporal_reproject;
+}
+void Environment::set_volumetric_fog_temporal_reprojection_amount(float p_amount) {
+ volumetric_fog_temporal_reproject_amount = p_amount;
_update_volumetric_fog();
}
-Environment::VolumetricFogShadowFilter Environment::get_volumetric_fog_shadow_filter() const {
- return volumetric_fog_shadow_filter;
+float Environment::get_volumetric_fog_temporal_reprojection_amount() const {
+ return volumetric_fog_temporal_reproject_amount;
}
// Adjustment
@@ -868,7 +869,7 @@ Environment::VolumetricFogShadowFilter Environment::get_volumetric_fog_shadow_fi
void Environment::set_adjustment_enabled(bool p_enabled) {
adjustment_enabled = p_enabled;
_update_adjustment();
- _change_notify();
+ notify_property_list_changed();
}
bool Environment::is_adjustment_enabled() const {
@@ -983,6 +984,7 @@ void Environment::_validate_property(PropertyInfo &property) const {
"auto_exposure_",
"ss_reflections_",
"ssao_",
+ "sdfgi_",
"glow_",
"adjustment_",
nullptr
@@ -1200,8 +1202,8 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_sdfgi_y_scale"), &Environment::get_sdfgi_y_scale);
ClassDB::bind_method(D_METHOD("set_sdfgi_use_occlusion", "enable"), &Environment::set_sdfgi_use_occlusion);
ClassDB::bind_method(D_METHOD("is_sdfgi_using_occlusion"), &Environment::is_sdfgi_using_occlusion);
- ClassDB::bind_method(D_METHOD("set_sdfgi_use_multi_bounce", "enable"), &Environment::set_sdfgi_use_multi_bounce);
- ClassDB::bind_method(D_METHOD("is_sdfgi_using_multi_bounce"), &Environment::is_sdfgi_using_multi_bounce);
+ ClassDB::bind_method(D_METHOD("set_sdfgi_bounce_feedback", "amount"), &Environment::set_sdfgi_bounce_feedback);
+ ClassDB::bind_method(D_METHOD("get_sdfgi_bounce_feedback"), &Environment::get_sdfgi_bounce_feedback);
ClassDB::bind_method(D_METHOD("set_sdfgi_read_sky_light", "enable"), &Environment::set_sdfgi_read_sky_light);
ClassDB::bind_method(D_METHOD("is_sdfgi_reading_sky_light"), &Environment::is_sdfgi_reading_sky_light);
ClassDB::bind_method(D_METHOD("set_sdfgi_energy", "amount"), &Environment::set_sdfgi_energy);
@@ -1213,9 +1215,9 @@ void Environment::_bind_methods() {
ADD_GROUP("SDFGI", "sdfgi_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_enabled"), "set_sdfgi_enabled", "is_sdfgi_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_use_multi_bounce"), "set_sdfgi_use_multi_bounce", "is_sdfgi_using_multi_bounce");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_use_occlusion"), "set_sdfgi_use_occlusion", "is_sdfgi_using_occlusion");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_read_sky_light"), "set_sdfgi_read_sky_light", "is_sdfgi_reading_sky_light");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_bounce_feedback", PROPERTY_HINT_RANGE, "0,1.99,0.01"), "set_sdfgi_bounce_feedback", "get_sdfgi_bounce_feedback");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_cascades", PROPERTY_HINT_ENUM, "4 Cascades,6 Cascades,8 Cascades"), "set_sdfgi_cascades", "get_sdfgi_cascades");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_min_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_sdfgi_min_cell_size", "get_sdfgi_min_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_cascade0_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_cascade0_distance", "get_sdfgi_cascade0_distance");
@@ -1317,8 +1319,10 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_volumetric_fog_detail_spread"), &Environment::get_volumetric_fog_detail_spread);
ClassDB::bind_method(D_METHOD("set_volumetric_fog_gi_inject", "gi_inject"), &Environment::set_volumetric_fog_gi_inject);
ClassDB::bind_method(D_METHOD("get_volumetric_fog_gi_inject"), &Environment::get_volumetric_fog_gi_inject);
- ClassDB::bind_method(D_METHOD("set_volumetric_fog_shadow_filter", "shadow_filter"), &Environment::set_volumetric_fog_shadow_filter);
- ClassDB::bind_method(D_METHOD("get_volumetric_fog_shadow_filter"), &Environment::get_volumetric_fog_shadow_filter);
+ ClassDB::bind_method(D_METHOD("set_volumetric_fog_temporal_reprojection_enabled", "enabled"), &Environment::set_volumetric_fog_temporal_reprojection_enabled);
+ ClassDB::bind_method(D_METHOD("is_volumetric_fog_temporal_reprojection_enabled"), &Environment::is_volumetric_fog_temporal_reprojection_enabled);
+ ClassDB::bind_method(D_METHOD("set_volumetric_fog_temporal_reprojection_amount", "temporal_reprojection_amount"), &Environment::set_volumetric_fog_temporal_reprojection_amount);
+ ClassDB::bind_method(D_METHOD("get_volumetric_fog_temporal_reprojection_amount"), &Environment::get_volumetric_fog_temporal_reprojection_amount);
ADD_GROUP("Volumetric Fog", "volumetric_fog_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "volumetric_fog_enabled"), "set_volumetric_fog_enabled", "is_volumetric_fog_enabled");
@@ -1328,7 +1332,9 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_gi_inject", PROPERTY_HINT_EXP_RANGE, "0.00,16,0.01"), "set_volumetric_fog_gi_inject", "get_volumetric_fog_gi_inject");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_length", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_volumetric_fog_length", "get_volumetric_fog_length");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_detail_spread", PROPERTY_HINT_EXP_EASING, "0.01,16,0.01"), "set_volumetric_fog_detail_spread", "get_volumetric_fog_detail_spread");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "volumetric_fog_shadow_filter", PROPERTY_HINT_ENUM, "Disabled,Low,Medium,High"), "set_volumetric_fog_shadow_filter", "get_volumetric_fog_shadow_filter");
+ ADD_SUBGROUP("Temporal Reprojection", "volumetric_fog_temporal_reprojection_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "volumetric_fog_temporal_reprojection_enabled"), "set_volumetric_fog_temporal_reprojection_enabled", "is_volumetric_fog_temporal_reprojection_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_temporal_reprojection_amount", PROPERTY_HINT_RANGE, "0.0,0.999,0.001"), "set_volumetric_fog_temporal_reprojection_amount", "get_volumetric_fog_temporal_reprojection_amount");
// Adjustment
@@ -1417,7 +1423,7 @@ Environment::Environment() {
_update_fog();
_update_adjustment();
_update_volumetric_fog();
- _change_notify();
+ notify_property_list_changed();
}
Environment::~Environment() {
diff --git a/scene/resources/environment.h b/scene/resources/environment.h
index 1676a28b39..0df2c3cc27 100644
--- a/scene/resources/environment.h
+++ b/scene/resources/environment.h
@@ -103,7 +103,7 @@ private:
// Background
BGMode bg_mode = BG_CLEAR_COLOR;
Ref<Sky> bg_sky;
- float bg_sky_custom_fov = 0;
+ float bg_sky_custom_fov = 0.0;
Vector3 bg_sky_rotation;
Color bg_color;
float bg_energy = 1.0;
@@ -125,7 +125,7 @@ private:
float tonemap_white = 1.0;
bool tonemap_auto_exposure_enabled = false;
float tonemap_auto_exposure_min = 0.05;
- float tonemap_auto_exposure_max = 8;
+ float tonemap_auto_exposure_max = 8.0;
float tonemap_auto_exposure_speed = 0.5;
float tonemap_auto_exposure_grey = 0.4;
void _update_tonemap();
@@ -156,7 +156,7 @@ private:
float sdfgi_min_cell_size = 0.2;
SDFGIYScale sdfgi_y_scale = SDFGI_Y_SCALE_DISABLED;
bool sdfgi_use_occlusion = false;
- bool sdfgi_use_multibounce = false;
+ float sdfgi_bounce_feedback = 0.0;
bool sdfgi_read_sky_light = false;
float sdfgi_energy = 1.0;
float sdfgi_normal_bias = 1.1;
@@ -196,8 +196,9 @@ private:
float volumetric_fog_light_energy = 1.0;
float volumetric_fog_length = 64.0;
float volumetric_fog_detail_spread = 2.0;
- VolumetricFogShadowFilter volumetric_fog_shadow_filter = VOLUMETRIC_FOG_SHADOW_FILTER_LOW;
float volumetric_fog_gi_inject = 0.0;
+ bool volumetric_fog_temporal_reproject = true;
+ float volumetric_fog_temporal_reproject_amount = 0.9;
void _update_volumetric_fog();
// Adjustment
@@ -317,8 +318,8 @@ public:
SDFGIYScale get_sdfgi_y_scale() const;
void set_sdfgi_use_occlusion(bool p_enabled);
bool is_sdfgi_using_occlusion() const;
- void set_sdfgi_use_multi_bounce(bool p_enabled);
- bool is_sdfgi_using_multi_bounce() const;
+ void set_sdfgi_bounce_feedback(float p_amount);
+ float get_sdfgi_bounce_feedback() const;
void set_sdfgi_read_sky_light(bool p_enabled);
bool is_sdfgi_reading_sky_light() const;
void set_sdfgi_energy(float p_energy);
@@ -385,10 +386,12 @@ public:
float get_volumetric_fog_length() const;
void set_volumetric_fog_detail_spread(float p_detail_spread);
float get_volumetric_fog_detail_spread() const;
- void set_volumetric_fog_shadow_filter(VolumetricFogShadowFilter p_filter);
- VolumetricFogShadowFilter get_volumetric_fog_shadow_filter() const;
void set_volumetric_fog_gi_inject(float p_gi_inject);
float get_volumetric_fog_gi_inject() const;
+ void set_volumetric_fog_temporal_reprojection_enabled(bool p_enable);
+ bool is_volumetric_fog_temporal_reprojection_enabled() const;
+ void set_volumetric_fog_temporal_reprojection_amount(float p_amount);
+ float get_volumetric_fog_temporal_reprojection_amount() const;
// Adjustment
void set_adjustment_enabled(bool p_enabled);
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 1c06d7b519..6f87c524d8 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -39,6 +39,11 @@
void FontData::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_resource", "filename", "base_size"), &FontData::load_resource, DEFVAL(16));
ClassDB::bind_method(D_METHOD("load_memory", "data", "type", "base_size"), &FontData::_load_memory, DEFVAL(16));
+ ClassDB::bind_method(D_METHOD("new_bitmap", "height", "ascent", "base_size"), &FontData::new_bitmap);
+
+ ClassDB::bind_method(D_METHOD("bitmap_add_texture", "texture"), &FontData::bitmap_add_texture);
+ ClassDB::bind_method(D_METHOD("bitmap_add_char", "char", "texture_idx", "rect", "align", "advance"), &FontData::bitmap_add_char);
+ ClassDB::bind_method(D_METHOD("bitmap_add_kerning_pair", "A", "B", "kerning"), &FontData::bitmap_add_kerning_pair);
ClassDB::bind_method(D_METHOD("set_data_path", "path"), &FontData::set_data_path);
ClassDB::bind_method(D_METHOD("get_data_path"), &FontData::get_data_path);
@@ -50,6 +55,9 @@ void FontData::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_underline_position", "size"), &FontData::get_underline_position);
ClassDB::bind_method(D_METHOD("get_underline_thickness", "size"), &FontData::get_underline_thickness);
+ ClassDB::bind_method(D_METHOD("get_spacing", "type"), &FontData::get_spacing);
+ ClassDB::bind_method(D_METHOD("set_spacing", "type", "value"), &FontData::set_spacing);
+
ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &FontData::set_antialiased);
ClassDB::bind_method(D_METHOD("get_antialiased"), &FontData::get_antialiased);
@@ -100,6 +108,13 @@ void FontData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_field_hint"), "set_distance_field_hint", "get_distance_field_hint");
ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting");
+
+ ADD_GROUP("Extra Spacing", "extra_spacing");
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "extra_spacing_glyph"), "set_spacing", "get_spacing", SPACING_GLYPH);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "extra_spacing_space"), "set_spacing", "get_spacing", SPACING_SPACE);
+
+ BIND_ENUM_CONSTANT(SPACING_GLYPH);
+ BIND_ENUM_CONSTANT(SPACING_SPACE);
}
bool FontData::_set(const StringName &p_name, const Variant &p_value) {
@@ -177,6 +192,14 @@ void FontData::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
+void FontData::reset_state() {
+ if (rid != RID()) {
+ TS->free(rid);
+ }
+ base_size = 16;
+ path = String();
+}
+
RID FontData::get_rid() const {
return rid;
}
@@ -211,6 +234,34 @@ void FontData::load_memory(const uint8_t *p_data, size_t p_size, const String &p
emit_changed();
}
+void FontData::new_bitmap(float p_height, float p_ascent, int p_base_size) {
+ if (rid != RID()) {
+ TS->free(rid);
+ }
+ rid = TS->create_font_bitmap(p_height, p_ascent, p_base_size);
+ path = TTR("(Bitmap: " + String::num_int64(rid.get_id(), 16, true) + ")");
+ base_size = TS->font_get_base_size(rid);
+ emit_changed();
+}
+
+void FontData::bitmap_add_texture(const Ref<Texture> &p_texture) {
+ if (rid != RID()) {
+ TS->font_bitmap_add_texture(rid, p_texture);
+ }
+}
+
+void FontData::bitmap_add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) {
+ if (rid != RID()) {
+ TS->font_bitmap_add_char(rid, p_char, p_texture_idx, p_rect, p_align, p_advance);
+ }
+}
+
+void FontData::bitmap_add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) {
+ if (rid != RID()) {
+ TS->font_bitmap_add_kerning_pair(rid, p_A, p_B, p_kerning);
+ }
+}
+
void FontData::set_data_path(const String &p_path) {
load_resource(p_path, base_size);
}
@@ -281,6 +332,27 @@ double FontData::get_variation(const String &p_name) const {
return TS->font_get_variation(rid, p_name);
}
+int FontData::get_spacing(int p_type) const {
+ if (rid == RID()) {
+ return 0;
+ }
+ if (p_type == SPACING_GLYPH) {
+ return TS->font_get_spacing_glyph(rid);
+ } else {
+ return TS->font_get_spacing_space(rid);
+ }
+}
+
+void FontData::set_spacing(int p_type, int p_value) {
+ ERR_FAIL_COND(rid == RID());
+ if (p_type == SPACING_GLYPH) {
+ TS->font_set_spacing_glyph(rid, p_value);
+ } else {
+ TS->font_set_spacing_space(rid, p_value);
+ }
+ emit_changed();
+}
+
void FontData::set_antialiased(bool p_antialiased) {
ERR_FAIL_COND(rid == RID());
TS->font_set_antialiased(rid, p_antialiased);
@@ -509,7 +581,7 @@ void Font::_data_changed() {
cache_wrap.clear();
emit_changed();
- _change_notify();
+ notify_property_list_changed();
}
bool Font::_set(const StringName &p_name, const Variant &p_value) {
@@ -588,6 +660,14 @@ void Font::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::OBJECT, "data/" + itos(data.size()), PROPERTY_HINT_RESOURCE_TYPE, "FontData"));
}
+void Font::reset_state() {
+ spacing_top = 0;
+ spacing_bottom = 0;
+ cache.clear();
+ cache_wrap.clear();
+ data.clear();
+}
+
void Font::add_data(const Ref<FontData> &p_data) {
ERR_FAIL_COND(p_data.is_null());
data.push_back(p_data);
@@ -600,7 +680,7 @@ void Font::add_data(const Ref<FontData> &p_data) {
cache_wrap.clear();
emit_changed();
- _change_notify();
+ notify_property_list_changed();
}
void Font::set_data(int p_idx, const Ref<FontData> &p_data) {
@@ -621,7 +701,7 @@ void Font::set_data(int p_idx, const Ref<FontData> &p_data) {
cache_wrap.clear();
emit_changed();
- _change_notify();
+ notify_property_list_changed();
}
int Font::get_data_count() const {
@@ -646,7 +726,7 @@ void Font::remove_data(int p_idx) {
cache_wrap.clear();
emit_changed();
- _change_notify();
+ notify_property_list_changed();
}
Dictionary Font::get_feature_list() const {
@@ -718,7 +798,7 @@ void Font::set_spacing(int p_type, int p_value) {
}
emit_changed();
- _change_notify();
+ notify_property_list_changed();
}
// Drawing string and string sizes, cached.
@@ -781,6 +861,8 @@ Size2 Font::get_multiline_string_size(const String &p_text, float p_width, int p
}
void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align, float p_width, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const {
+ ERR_FAIL_COND(data.is_empty());
+
uint64_t hash = p_text.hash64();
hash = hash_djb2_one_64(p_size, hash);
@@ -811,6 +893,8 @@ void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_t
}
void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align, float p_width, int p_max_lines, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const {
+ ERR_FAIL_COND(data.is_empty());
+
uint64_t hash = p_text.hash64();
hash = hash_djb2_one_64(p_size, hash);
@@ -951,7 +1035,7 @@ Font::~Font() {
/*************************************************************************/
-RES ResourceFormatLoaderFont::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderFont::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
}
@@ -1006,7 +1090,7 @@ String ResourceFormatLoaderFont::get_resource_type(const String &p_path) const {
#ifndef DISABLE_DEPRECATED
-RES ResourceFormatLoaderCompatFont::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderCompatFont::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
}
diff --git a/scene/resources/font.h b/scene/resources/font.h
index 086226c082..200373aa8c 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -42,6 +42,13 @@
class FontData : public Resource {
GDCLASS(FontData, Resource);
+public:
+ enum SpacingType {
+ SPACING_GLYPH,
+ SPACING_SPACE,
+ };
+
+private:
RID rid;
int base_size = 16;
String path;
@@ -53,6 +60,8 @@ protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ virtual void reset_state() override;
+
public:
virtual RID get_rid() const override;
@@ -60,6 +69,12 @@ public:
void load_memory(const uint8_t *p_data, size_t p_size, const String &p_type, int p_base_size = 16);
void _load_memory(const PackedByteArray &p_data, const String &p_type, int p_base_size = 16);
+ void new_bitmap(float p_height, float p_ascent, int p_base_size = 16);
+
+ void bitmap_add_texture(const Ref<Texture> &p_texture);
+ void bitmap_add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance);
+ void bitmap_add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning);
+
void set_data_path(const String &p_path);
String get_data_path() const;
@@ -76,6 +91,9 @@ public:
float get_underline_position(int p_size) const;
float get_underline_thickness(int p_size) const;
+ int get_spacing(int p_type) const;
+ void set_spacing(int p_type, int p_value);
+
void set_antialiased(bool p_antialiased);
bool get_antialiased() const;
@@ -132,7 +150,7 @@ class Font : public Resource {
public:
enum SpacingType {
SPACING_TOP,
- SPACING_BOTTOM
+ SPACING_BOTTOM,
};
private:
@@ -151,6 +169,8 @@ protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ virtual void reset_state() override;
+
void _data_changed();
public:
@@ -195,13 +215,14 @@ public:
~Font();
};
+VARIANT_ENUM_CAST(FontData::SpacingType);
VARIANT_ENUM_CAST(Font::SpacingType);
/*************************************************************************/
class ResourceFormatLoaderFont : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
@@ -212,7 +233,7 @@ public:
class ResourceFormatLoaderCompatFont : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
diff --git a/scene/resources/gradient.cpp b/scene/resources/gradient.cpp
index b87235518f..7b9b942142 100644
--- a/scene/resources/gradient.cpp
+++ b/scene/resources/gradient.cpp
@@ -39,7 +39,6 @@ Gradient::Gradient() {
points.write[0].offset = 0;
points.write[1].color = Color(1, 1, 1, 1);
points.write[1].offset = 1;
- is_sorted = true;
}
Gradient::~Gradient() {
diff --git a/scene/resources/gradient.h b/scene/resources/gradient.h
index 344a3fd283..cf5b179c45 100644
--- a/scene/resources/gradient.h
+++ b/scene/resources/gradient.h
@@ -39,7 +39,7 @@ class Gradient : public Resource {
public:
struct Point {
- float offset;
+ float offset = 0.0;
Color color;
bool operator<(const Point &p_ponit) const {
return offset < p_ponit.offset;
@@ -48,7 +48,7 @@ public:
private:
Vector<Point> points;
- bool is_sorted;
+ bool is_sorted = true;
_FORCE_INLINE_ void _update_sorting() {
if (!is_sorted) {
points.sort();
diff --git a/scene/resources/height_map_shape_3d.cpp b/scene/resources/height_map_shape_3d.cpp
index a32cc1c4df..5593bb766f 100644
--- a/scene/resources/height_map_shape_3d.cpp
+++ b/scene/resources/height_map_shape_3d.cpp
@@ -107,8 +107,6 @@ void HeightMapShape3D::set_map_width(int p_new) {
_update_shape();
notify_change_to_owners();
- _change_notify("map_width");
- _change_notify("map_data");
}
}
@@ -133,8 +131,6 @@ void HeightMapShape3D::set_map_depth(int p_new) {
_update_shape();
notify_change_to_owners();
- _change_notify("map_depth");
- _change_notify("map_data");
}
}
@@ -171,7 +167,6 @@ void HeightMapShape3D::set_map_data(PackedFloat32Array p_new) {
_update_shape();
notify_change_to_owners();
- _change_notify("map_data");
}
PackedFloat32Array HeightMapShape3D::get_map_data() const {
@@ -193,16 +188,12 @@ void HeightMapShape3D::_bind_methods() {
HeightMapShape3D::HeightMapShape3D() :
Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_HEIGHTMAP)) {
- map_width = 2;
- map_depth = 2;
map_data.resize(map_width * map_depth);
real_t *w = map_data.ptrw();
w[0] = 0.0;
w[1] = 0.0;
w[2] = 0.0;
w[3] = 0.0;
- min_height = 0.0;
- max_height = 0.0;
_update_shape();
}
diff --git a/scene/resources/height_map_shape_3d.h b/scene/resources/height_map_shape_3d.h
index eda405fc06..6fc88cff90 100644
--- a/scene/resources/height_map_shape_3d.h
+++ b/scene/resources/height_map_shape_3d.h
@@ -36,11 +36,11 @@
class HeightMapShape3D : public Shape3D {
GDCLASS(HeightMapShape3D, Shape3D);
- int map_width;
- int map_depth;
+ int map_width = 2;
+ int map_depth = 2;
PackedFloat32Array map_data;
- float min_height;
- float max_height;
+ float min_height = 0.0;
+ float max_height = 0.0;
protected:
static void _bind_methods();
diff --git a/scene/resources/line_shape_2d.cpp b/scene/resources/line_shape_2d.cpp
index 2b08c21c34..d206f12287 100644
--- a/scene/resources/line_shape_2d.cpp
+++ b/scene/resources/line_shape_2d.cpp
@@ -113,7 +113,5 @@ void LineShape2D::_bind_methods() {
LineShape2D::LineShape2D() :
Shape2D(PhysicsServer2D::get_singleton()->line_shape_create()) {
- normal = Vector2(0, 1);
- distance = 0;
_update_shape();
}
diff --git a/scene/resources/line_shape_2d.h b/scene/resources/line_shape_2d.h
index 043be1eebe..9f0405ad29 100644
--- a/scene/resources/line_shape_2d.h
+++ b/scene/resources/line_shape_2d.h
@@ -36,8 +36,8 @@
class LineShape2D : public Shape2D {
GDCLASS(LineShape2D, Shape2D);
- Vector2 normal;
- real_t distance;
+ Vector2 normal = Vector2(0, 1);
+ real_t distance = 0.0;
void _update_shape();
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 92d2fb1c6d..0d02bde90d 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -192,7 +192,7 @@ Variant ShaderMaterial::property_get_revert(const String &p_name) {
void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) {
// Only connect/disconnect the signal when running in the editor.
- // This can be a slow operation, and `_change_notify()` (which is called by `_shader_changed()`)
+ // This can be a slow operation, and `notify_property_list_changed()` (which is called by `_shader_changed()`)
// does nothing in non-editor builds anyway. See GH-34741 for details.
if (shader.is_valid() && Engine::get_singleton()->is_editor_hint()) {
shader->disconnect("changed", callable_mp(this, &ShaderMaterial::_shader_changed));
@@ -210,7 +210,7 @@ void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) {
}
RS::get_singleton()->material_set_shader(_get_material(), rid);
- _change_notify(); //properties for shader exposed
+ notify_property_list_changed(); //properties for shader exposed
emit_changed();
}
@@ -227,7 +227,7 @@ Variant ShaderMaterial::get_shader_param(const StringName &p_param) const {
}
void ShaderMaterial::_shader_changed() {
- _change_notify(); //update all properties
+ notify_property_list_changed(); //update all properties
}
void ShaderMaterial::_bind_methods() {
@@ -1489,7 +1489,7 @@ void BaseMaterial3D::set_transparency(Transparency p_transparency) {
transparency = p_transparency;
_queue_shader_change();
- _change_notify();
+ notify_property_list_changed();
}
BaseMaterial3D::Transparency BaseMaterial3D::get_transparency() const {
@@ -1503,7 +1503,7 @@ void BaseMaterial3D::set_alpha_antialiasing(AlphaAntiAliasing p_alpha_aa) {
alpha_antialiasing_mode = p_alpha_aa;
_queue_shader_change();
- _change_notify();
+ notify_property_list_changed();
}
BaseMaterial3D::AlphaAntiAliasing BaseMaterial3D::get_alpha_antialiasing() const {
@@ -1517,7 +1517,7 @@ void BaseMaterial3D::set_shading_mode(ShadingMode p_shading_mode) {
shading_mode = p_shading_mode;
_queue_shader_change();
- _change_notify();
+ notify_property_list_changed();
}
BaseMaterial3D::ShadingMode BaseMaterial3D::get_shading_mode() const {
@@ -1584,8 +1584,8 @@ void BaseMaterial3D::set_flag(Flags p_flag, bool p_enabled) {
}
flags[p_flag] = p_enabled;
- if (p_flag == FLAG_USE_SHADOW_TO_OPACITY || p_flag == FLAG_USE_TEXTURE_REPEAT || p_flag == FLAG_SUBSURFACE_MODE_SKIN) {
- _change_notify();
+ if (p_flag == FLAG_USE_SHADOW_TO_OPACITY || p_flag == FLAG_USE_TEXTURE_REPEAT || p_flag == FLAG_SUBSURFACE_MODE_SKIN || p_flag == FLAG_USE_POINT_SIZE) {
+ notify_property_list_changed();
}
_queue_shader_change();
}
@@ -1602,7 +1602,7 @@ void BaseMaterial3D::set_feature(Feature p_feature, bool p_enabled) {
}
features[p_feature] = p_enabled;
- _change_notify();
+ notify_property_list_changed();
_queue_shader_change();
}
@@ -1620,7 +1620,7 @@ void BaseMaterial3D::set_texture(TextureParam p_param, const Ref<Texture2D> &p_t
RS::get_singleton()->material_set_param(_get_material(), shader_names->albedo_texture_size,
Vector2i(p_texture->get_width(), p_texture->get_height()));
}
- _change_notify();
+ notify_property_list_changed();
_queue_shader_change();
}
@@ -1650,7 +1650,7 @@ BaseMaterial3D::TextureFilter BaseMaterial3D::get_texture_filter() const {
void BaseMaterial3D::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const {
if (property.name.begins_with(text) && property.name != text + "_enabled" && !features[feature]) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NOEDITOR;
}
}
@@ -1683,19 +1683,27 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
property.usage = 0;
}
- if (property.name == "params_grow_amount" && !grow_enabled) {
- property.usage = 0;
+ if (property.name == "billboard_keep_scale" && billboard_mode == BILLBOARD_DISABLED) {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+
+ if (property.name == "grow_amount" && !grow_enabled) {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+
+ if (property.name == "point_size" && !flags[FLAG_USE_POINT_SIZE]) {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
}
if (property.name == "proximity_fade_distance" && !proximity_fade_enabled) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NOEDITOR;
}
if ((property.name == "distance_fade_max_distance" || property.name == "distance_fade_min_distance") && distance_fade == DISTANCE_FADE_DISABLED) {
- property.usage = 0;
+ property.usage = PROPERTY_USAGE_NOEDITOR;
}
- // you can only enable anti-aliasing (in mataerials) on alpha scissor and alpha hash
+ // you can only enable anti-aliasing (in materials) on alpha scissor and alpha hash
const bool can_select_aa = (transparency == TRANSPARENCY_ALPHA_SCISSOR || transparency == TRANSPARENCY_ALPHA_HASH);
// alpha anti aliasiasing is only enabled when you can select aa
const bool alpha_aa_enabled = (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) && can_select_aa;
@@ -1714,7 +1722,7 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
property.usage = 0;
}
- // we cant choose an antialiasing mode if alpha isnt possible
+ // we can't choose an antialiasing mode if alpha isn't possible
if (property.name == "alpha_antialiasing_edge" && !alpha_aa_enabled) {
property.usage = 0;
}
@@ -1860,7 +1868,7 @@ float BaseMaterial3D::get_uv2_triplanar_blend_sharpness() const {
void BaseMaterial3D::set_billboard_mode(BillboardMode p_mode) {
billboard_mode = p_mode;
_queue_shader_change();
- _change_notify();
+ notify_property_list_changed();
}
BaseMaterial3D::BillboardMode BaseMaterial3D::get_billboard_mode() const {
@@ -1897,7 +1905,7 @@ bool BaseMaterial3D::get_particles_anim_loop() const {
void BaseMaterial3D::set_heightmap_deep_parallax(bool p_enable) {
deep_parallax = p_enable;
_queue_shader_change();
- _change_notify();
+ notify_property_list_changed();
}
bool BaseMaterial3D::is_heightmap_deep_parallax_enabled() const {
@@ -1943,7 +1951,7 @@ bool BaseMaterial3D::get_heightmap_deep_parallax_flip_binormal() const {
void BaseMaterial3D::set_grow_enabled(bool p_enable) {
grow_enabled = p_enable;
_queue_shader_change();
- _change_notify();
+ notify_property_list_changed();
}
bool BaseMaterial3D::is_grow_enabled() const {
@@ -2093,7 +2101,7 @@ void BaseMaterial3D::set_on_top_of_alpha() {
void BaseMaterial3D::set_proximity_fade(bool p_enable) {
proximity_fade_enabled = p_enable;
_queue_shader_change();
- _change_notify();
+ notify_property_list_changed();
}
bool BaseMaterial3D::is_proximity_fade_enabled() const {
@@ -2112,7 +2120,7 @@ float BaseMaterial3D::get_proximity_fade_distance() const {
void BaseMaterial3D::set_distance_fade(DistanceFadeMode p_mode) {
distance_fade = p_mode;
_queue_shader_change();
- _change_notify();
+ notify_property_list_changed();
}
BaseMaterial3D::DistanceFadeMode BaseMaterial3D::get_distance_fade() const {
@@ -2655,9 +2663,6 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
element(this) {
orm = p_orm;
// Initialize to the same values as the shader
- shading_mode = SHADING_MODE_PER_PIXEL;
- transparency = TRANSPARENCY_DISABLED;
- alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
set_albedo(Color(1.0, 1.0, 1.0, 1.0));
set_specular(0.5);
set_roughness(1.0);
@@ -2689,7 +2694,6 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
set_particles_anim_h_frames(1);
set_particles_anim_v_frames(1);
set_particles_anim_loop(false);
- emission_op = EMISSION_OP_ADD;
set_transparency(TRANSPARENCY_DISABLED);
set_alpha_antialiasing(ALPHA_ANTIALIASING_OFF);
@@ -2697,8 +2701,6 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
set_alpha_hash_scale(1.0);
set_alpha_antialiasing_edge(0.3);
- proximity_fade_enabled = false;
- distance_fade = DISTANCE_FADE_DISABLED;
set_proximity_fade_distance(1);
set_distance_fade_min_distance(0);
set_distance_fade_max_distance(10);
@@ -2710,35 +2712,14 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
set_ao_texture_channel(TEXTURE_CHANNEL_RED);
set_refraction_texture_channel(TEXTURE_CHANNEL_RED);
- grow_enabled = false;
set_grow(0.0);
- deep_parallax = false;
- heightmap_parallax_flip_tangent = false;
- heightmap_parallax_flip_binormal = false;
set_heightmap_deep_parallax_min_layers(8);
set_heightmap_deep_parallax_max_layers(32);
set_heightmap_deep_parallax_flip_tangent(false); //also sets binormal
- detail_uv = DETAIL_UV_1;
- blend_mode = BLEND_MODE_MIX;
- detail_blend_mode = BLEND_MODE_MIX;
- depth_draw_mode = DEPTH_DRAW_OPAQUE_ONLY;
- cull_mode = CULL_BACK;
- for (int i = 0; i < FLAG_MAX; i++) {
- flags[i] = false;
- }
flags[FLAG_USE_TEXTURE_REPEAT] = true;
- diffuse_mode = DIFFUSE_BURLEY;
- specular_mode = SPECULAR_SCHLICK_GGX;
-
- for (int i = 0; i < FEATURE_MAX; i++) {
- features[i] = false;
- }
-
- texture_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS;
-
_queue_shader_change();
}
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 0048b43c8b..70452a5f74 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -330,7 +330,7 @@ private:
struct ShaderData {
RID shader;
- int users;
+ int users = 0;
};
static Map<MaterialKey, ShaderData> shader_map;
@@ -468,16 +468,16 @@ private:
float alpha_scissor_threshold;
float alpha_hash_scale;
float alpha_antialiasing_edge;
- bool grow_enabled;
+ bool grow_enabled = false;
float ao_light_affect;
float grow;
int particles_anim_h_frames;
int particles_anim_v_frames;
bool particles_anim_loop;
- Transparency transparency;
- ShadingMode shading_mode;
+ Transparency transparency = TRANSPARENCY_DISABLED;
+ ShadingMode shading_mode = SHADING_MODE_PER_PIXEL;
- TextureFilter texture_filter;
+ TextureFilter texture_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS;
Vector3 uv1_scale;
Vector3 uv1_offset;
@@ -487,39 +487,39 @@ private:
Vector3 uv2_offset;
float uv2_triplanar_sharpness;
- DetailUV detail_uv;
+ DetailUV detail_uv = DETAIL_UV_1;
- bool deep_parallax;
+ bool deep_parallax = false;
int deep_parallax_min_layers;
int deep_parallax_max_layers;
- bool heightmap_parallax_flip_tangent;
- bool heightmap_parallax_flip_binormal;
+ bool heightmap_parallax_flip_tangent = false;
+ bool heightmap_parallax_flip_binormal = false;
- bool proximity_fade_enabled;
+ bool proximity_fade_enabled = false;
float proximity_fade_distance;
- DistanceFadeMode distance_fade;
+ DistanceFadeMode distance_fade = DISTANCE_FADE_DISABLED;
float distance_fade_max_distance;
float distance_fade_min_distance;
- BlendMode blend_mode;
- BlendMode detail_blend_mode;
- DepthDrawMode depth_draw_mode;
- CullMode cull_mode;
- bool flags[FLAG_MAX];
- SpecularMode specular_mode;
- DiffuseMode diffuse_mode;
+ BlendMode blend_mode = BLEND_MODE_MIX;
+ BlendMode detail_blend_mode = BLEND_MODE_MIX;
+ DepthDrawMode depth_draw_mode = DEPTH_DRAW_OPAQUE_ONLY;
+ CullMode cull_mode = CULL_BACK;
+ bool flags[FLAG_MAX] = {};
+ SpecularMode specular_mode = SPECULAR_SCHLICK_GGX;
+ DiffuseMode diffuse_mode = DIFFUSE_BURLEY;
BillboardMode billboard_mode;
- EmissionOperator emission_op;
+ EmissionOperator emission_op = EMISSION_OP_ADD;
TextureChannel metallic_texture_channel;
TextureChannel roughness_texture_channel;
TextureChannel ao_texture_channel;
TextureChannel refraction_texture_channel;
- AlphaAntiAliasing alpha_antialiasing_mode;
+ AlphaAntiAliasing alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
- bool features[FEATURE_MAX];
+ bool features[FEATURE_MAX] = {};
Ref<Texture2D> textures[TEXTURE_MAX];
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index e812ad3a01..1a2b21299a 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -1095,6 +1095,15 @@ bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const {
return true;
}
+void ArrayMesh::reset_state() {
+ clear_surfaces();
+ clear_blend_shapes();
+
+ aabb = AABB();
+ blend_shape_mode = BLEND_SHAPE_MODE_RELATIVE;
+ custom_aabb = AABB();
+}
+
void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const {
if (_is_generated()) {
return;
@@ -1156,7 +1165,7 @@ void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const
RenderingServer::get_singleton()->mesh_add_surface(mesh, sd);
clear_cache();
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -1278,7 +1287,6 @@ void ArrayMesh::surface_set_material(int p_idx, const Ref<Material> &p_material)
surfaces.write[p_idx].material = p_material;
RenderingServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid());
- _change_notify("material");
emit_changed();
}
@@ -1375,8 +1383,8 @@ bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_v
struct ArrayMeshLightmapSurface {
Ref<Material> material;
LocalVector<SurfaceTool::Vertex> vertices;
- Mesh::PrimitiveType primitive;
- uint32_t format;
+ Mesh::PrimitiveType primitive = Mesh::PrimitiveType::PRIMITIVE_MAX;
+ uint32_t format = 0;
};
Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texel_size) {
@@ -1633,13 +1641,12 @@ void ArrayMesh::reload_from_file() {
Resource::reload_from_file();
- _change_notify();
+ notify_property_list_changed();
}
ArrayMesh::ArrayMesh() {
//mesh is now created on demand
//mesh = RenderingServer::get_singleton()->mesh_create();
- blend_shape_mode = BLEND_SHAPE_MODE_RELATIVE;
}
ArrayMesh::~ArrayMesh() {
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 1fd45c880a..2ce519e644 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -180,20 +180,20 @@ class ArrayMesh : public Mesh {
private:
struct Surface {
- uint32_t format;
- int array_length;
- int index_array_length;
- PrimitiveType primitive;
+ uint32_t format = 0;
+ int array_length = 0;
+ int index_array_length = 0;
+ PrimitiveType primitive = PrimitiveType::PRIMITIVE_MAX;
String name;
AABB aabb;
Ref<Material> material;
- bool is_2d;
+ bool is_2d = false;
};
Vector<Surface> surfaces;
mutable RID mesh;
AABB aabb;
- BlendShapeMode blend_shape_mode;
+ BlendShapeMode blend_shape_mode = BLEND_SHAPE_MODE_RELATIVE;
Vector<StringName> blend_shapes;
AABB custom_aabb;
@@ -207,6 +207,8 @@ protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ virtual void reset_state() override;
+
static void _bind_methods();
public:
diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp
index 1b82aca386..3fb4f8f211 100644
--- a/scene/resources/mesh_data_tool.cpp
+++ b/scene/resources/mesh_data_tool.cpp
@@ -50,6 +50,28 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf
int vcount = varray.size();
ERR_FAIL_COND_V(vcount == 0, ERR_INVALID_PARAMETER);
+ Vector<int> indices;
+
+ if (arrays[Mesh::ARRAY_INDEX].get_type() != Variant::NIL) {
+ indices = arrays[Mesh::ARRAY_INDEX];
+ } else {
+ //make code simpler
+ indices.resize(vcount);
+ int *iw = indices.ptrw();
+ for (int i = 0; i < vcount; i++) {
+ iw[i] = i;
+ }
+ }
+
+ int icount = indices.size();
+ const int *r = indices.ptr();
+
+ ERR_FAIL_COND_V(icount == 0, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(icount % 3, ERR_INVALID_PARAMETER);
+ for (int i = 0; i < icount; i++) {
+ ERR_FAIL_INDEX_V(r[i], vcount, ERR_INVALID_PARAMETER);
+ }
+
clear();
format = p_mesh->surface_get_format(p_surface);
material = p_mesh->surface_get_material(p_surface);
@@ -128,22 +150,6 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf
vertices.write[i] = v;
}
- Vector<int> indices;
-
- if (arrays[Mesh::ARRAY_INDEX].get_type() != Variant::NIL) {
- indices = arrays[Mesh::ARRAY_INDEX];
- } else {
- //make code simpler
- indices.resize(vcount);
- int *iw = indices.ptrw();
- for (int i = 0; i < vcount; i++) {
- iw[i] = i;
- }
- }
-
- int icount = indices.size();
- const int *r = indices.ptr();
-
Map<Point2i, int> edge_indices;
for (int i = 0; i < icount; i += 3) {
diff --git a/scene/resources/mesh_data_tool.h b/scene/resources/mesh_data_tool.h
index d8b8d85900..f5c8f11437 100644
--- a/scene/resources/mesh_data_tool.h
+++ b/scene/resources/mesh_data_tool.h
@@ -36,7 +36,7 @@
class MeshDataTool : public Reference {
GDCLASS(MeshDataTool, Reference);
- int format;
+ int format = 0;
struct Vertex {
Vector3 vertex;
Color color;
@@ -54,7 +54,7 @@ class MeshDataTool : public Reference {
Vector<Vertex> vertices;
struct Edge {
- int vertex[2];
+ int vertex[2] = {};
Vector<int> faces;
Variant meta;
};
@@ -62,8 +62,8 @@ class MeshDataTool : public Reference {
Vector<Edge> edges;
struct Face {
- int v[3];
- int edges[3];
+ int v[3] = {};
+ int edges[3] = {};
Variant meta;
};
diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp
index 96d3a5750e..ad90481fbd 100644
--- a/scene/resources/mesh_library.cpp
+++ b/scene/resources/mesh_library.cpp
@@ -109,14 +109,14 @@ void MeshLibrary::create_item(int p_item) {
ERR_FAIL_COND(p_item < 0);
ERR_FAIL_COND(item_map.has(p_item));
item_map[p_item] = Item();
- _change_notify();
+ notify_property_list_changed();
}
void MeshLibrary::set_item_name(int p_item, const String &p_name) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
item_map[p_item].name = p_name;
emit_changed();
- _change_notify();
+ notify_property_list_changed();
}
void MeshLibrary::set_item_mesh(int p_item, const Ref<Mesh> &p_mesh) {
@@ -124,25 +124,25 @@ void MeshLibrary::set_item_mesh(int p_item, const Ref<Mesh> &p_mesh) {
item_map[p_item].mesh = p_mesh;
notify_change_to_owners();
emit_changed();
- _change_notify();
+ notify_property_list_changed();
}
void MeshLibrary::set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
item_map[p_item].shapes = p_shapes;
- _change_notify();
+ notify_property_list_changed();
notify_change_to_owners();
emit_changed();
- _change_notify();
+ notify_property_list_changed();
}
void MeshLibrary::set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
item_map[p_item].navmesh = p_navmesh;
- _change_notify();
+ notify_property_list_changed();
notify_change_to_owners();
emit_changed();
- _change_notify();
+ notify_property_list_changed();
}
void MeshLibrary::set_item_navmesh_transform(int p_item, const Transform &p_transform) {
@@ -150,14 +150,14 @@ void MeshLibrary::set_item_navmesh_transform(int p_item, const Transform &p_tran
item_map[p_item].navmesh_transform = p_transform;
notify_change_to_owners();
emit_changed();
- _change_notify();
+ notify_property_list_changed();
}
void MeshLibrary::set_item_preview(int p_item, const Ref<Texture2D> &p_preview) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
item_map[p_item].preview = p_preview;
emit_changed();
- _change_notify();
+ notify_property_list_changed();
}
String MeshLibrary::get_item_name(int p_item) const {
@@ -198,14 +198,14 @@ void MeshLibrary::remove_item(int p_item) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
item_map.erase(p_item);
notify_change_to_owners();
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
void MeshLibrary::clear() {
item_map.clear();
notify_change_to_owners();
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -264,6 +264,9 @@ Array MeshLibrary::_get_item_shapes(int p_item) const {
return ret;
}
+void MeshLibrary::reset_state() {
+ clear();
+}
void MeshLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_item", "id"), &MeshLibrary::create_item);
ClassDB::bind_method(D_METHOD("set_item_name", "id", "name"), &MeshLibrary::set_item_name);
diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h
index 5c302fcf08..1da624c275 100644
--- a/scene/resources/mesh_library.h
+++ b/scene/resources/mesh_library.h
@@ -65,6 +65,7 @@ protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ virtual void reset_state() override;
static void _bind_methods();
public:
diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp
index 050e398ca4..4991887eb3 100644
--- a/scene/resources/multimesh.cpp
+++ b/scene/resources/multimesh.cpp
@@ -217,7 +217,7 @@ Ref<Mesh> MultiMesh::get_mesh() const {
void MultiMesh::set_instance_count(int p_count) {
ERR_FAIL_COND(p_count < 0);
- RenderingServer::get_singleton()->multimesh_allocate(multimesh, p_count, RS::MultimeshTransformFormat(transform_format), use_colors, use_custom_data);
+ RenderingServer::get_singleton()->multimesh_allocate_data(multimesh, p_count, RS::MultimeshTransformFormat(transform_format), use_colors, use_custom_data);
instance_count = p_count;
}
@@ -361,11 +361,6 @@ void MultiMesh::_bind_methods() {
MultiMesh::MultiMesh() {
multimesh = RenderingServer::get_singleton()->multimesh_create();
- use_colors = false;
- use_custom_data = false;
- transform_format = TRANSFORM_2D;
- visible_instance_count = -1;
- instance_count = 0;
}
MultiMesh::~MultiMesh() {
diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h
index 633d754b8e..ca5c42d47a 100644
--- a/scene/resources/multimesh.h
+++ b/scene/resources/multimesh.h
@@ -47,11 +47,11 @@ public:
private:
Ref<Mesh> mesh;
RID multimesh;
- TransformFormat transform_format;
- bool use_colors;
- bool use_custom_data;
- int instance_count;
- int visible_instance_count;
+ TransformFormat transform_format = TRANSFORM_2D;
+ bool use_colors = false;
+ bool use_custom_data = false;
+ int instance_count = 0;
+ int visible_instance_count = -1;
protected:
static void _bind_methods();
diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp
index 43c3ef4edc..8c12f59a00 100644
--- a/scene/resources/navigation_mesh.cpp
+++ b/scene/resources/navigation_mesh.cpp
@@ -31,6 +31,8 @@
#include "navigation_mesh.h"
void NavigationMesh::create_from_mesh(const Ref<Mesh> &p_mesh) {
+ ERR_FAIL_COND(p_mesh.is_null());
+
vertices = Vector<Vector3>();
clear_polygons();
@@ -74,7 +76,7 @@ int NavigationMesh::get_sample_partition_type() const {
void NavigationMesh::set_parsed_geometry_type(int p_value) {
ERR_FAIL_COND(p_value >= PARSED_GEOMETRY_MAX);
parsed_geometry_type = static_cast<ParsedGeometryType>(p_value);
- _change_notify();
+ notify_property_list_changed();
}
int NavigationMesh::get_parsed_geometry_type() const {
@@ -106,7 +108,7 @@ bool NavigationMesh::get_collision_mask_bit(int p_bit) const {
void NavigationMesh::set_source_geometry_mode(int p_geometry_mode) {
ERR_FAIL_INDEX(p_geometry_mode, SOURCE_GEOMETRY_MAX);
source_geometry_mode = static_cast<SourceGeometryMode>(p_geometry_mode);
- _change_notify();
+ notify_property_list_changed();
}
int NavigationMesh::get_source_geometry_mode() const {
@@ -251,7 +253,7 @@ bool NavigationMesh::get_filter_walkable_low_height_spans() const {
void NavigationMesh::set_vertices(const Vector<Vector3> &p_vertices) {
vertices = p_vertices;
- _change_notify();
+ notify_property_list_changed();
}
Vector<Vector3> NavigationMesh::get_vertices() const {
@@ -263,7 +265,7 @@ void NavigationMesh::_set_polygons(const Array &p_array) {
for (int i = 0; i < p_array.size(); i++) {
polygons.write[i].indices = p_array[i];
}
- _change_notify();
+ notify_property_list_changed();
}
Array NavigationMesh::_get_polygons() const {
@@ -280,7 +282,7 @@ void NavigationMesh::add_polygon(const Vector<int> &p_polygon) {
Polygon polygon;
polygon.indices = p_polygon;
polygons.push_back(polygon);
- _change_notify();
+ notify_property_list_changed();
}
int NavigationMesh::get_polygon_count() const {
@@ -510,27 +512,4 @@ void NavigationMesh::_validate_property(PropertyInfo &property) const {
}
}
-NavigationMesh::NavigationMesh() {
- cell_size = 0.3f;
- cell_height = 0.2f;
- agent_height = 2.0f;
- agent_radius = 0.6f;
- agent_max_climb = 0.9f;
- agent_max_slope = 45.0f;
- region_min_size = 8.0f;
- region_merge_size = 20.0f;
- edge_max_length = 12.0f;
- edge_max_error = 1.3f;
- verts_per_poly = 6.0f;
- detail_sample_distance = 6.0f;
- detail_sample_max_error = 1.0f;
-
- partition_type = SAMPLE_PARTITION_WATERSHED;
- parsed_geometry_type = PARSED_GEOMETRY_MESH_INSTANCES;
- collision_mask = 0xFFFFFFFF;
- source_geometry_mode = SOURCE_GEOMETRY_NAVMESH_CHILDREN;
- source_group_name = "navmesh";
- filter_low_hanging_obstacles = false;
- filter_ledge_spans = false;
- filter_walkable_low_height_spans = false;
-}
+NavigationMesh::NavigationMesh() {}
diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h
index 693c4184bc..966221c7c6 100644
--- a/scene/resources/navigation_mesh.h
+++ b/scene/resources/navigation_mesh.h
@@ -82,30 +82,30 @@ public:
};
protected:
- float cell_size;
- float cell_height;
- float agent_height;
- float agent_radius;
- float agent_max_climb;
- float agent_max_slope;
- float region_min_size;
- float region_merge_size;
- float edge_max_length;
- float edge_max_error;
- float verts_per_poly;
- float detail_sample_distance;
- float detail_sample_max_error;
-
- SamplePartitionType partition_type;
- ParsedGeometryType parsed_geometry_type;
- uint32_t collision_mask;
-
- SourceGeometryMode source_geometry_mode;
- StringName source_group_name;
-
- bool filter_low_hanging_obstacles;
- bool filter_ledge_spans;
- bool filter_walkable_low_height_spans;
+ float cell_size = 0.3f;
+ float cell_height = 0.2f;
+ float agent_height = 2.0f;
+ float agent_radius = 0.6f;
+ float agent_max_climb = 0.9f;
+ float agent_max_slope = 45.0f;
+ float region_min_size = 8.0f;
+ 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 detail_sample_distance = 6.0f;
+ float detail_sample_max_error = 1.0f;
+
+ SamplePartitionType partition_type = SAMPLE_PARTITION_WATERSHED;
+ 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";
+
+ bool filter_low_hanging_obstacles = false;
+ bool filter_ledge_spans = false;
+ bool filter_walkable_low_height_spans = false;
public:
// Recast settings
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 794b281100..ab8a4b7934 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -147,15 +147,20 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
}
#endif
}
- } else if (ClassDB::is_class_enabled(snames[n.type])) {
- //node belongs to this scene and must be created
- Object *obj = ClassDB::instance(snames[n.type]);
+ } else {
+ Object *obj = nullptr;
+
+ if (ClassDB::is_class_enabled(snames[n.type])) {
+ //node belongs to this scene and must be created
+ obj = ClassDB::instance(snames[n.type]);
+ }
+
if (!Object::cast_to<Node>(obj)) {
if (obj) {
memdelete(obj);
obj = nullptr;
}
- WARN_PRINT(String("Warning node of type " + snames[n.type].operator String() + " does not exist.").ascii().get_data());
+ WARN_PRINT(vformat("Node %s of type %s cannot be created. A placeholder will be created instead.", snames[n.name], snames[n.type]).ascii().get_data());
if (n.parent >= 0 && n.parent < nc && ret_nodes[n.parent]) {
if (Object::cast_to<Node3D>(ret_nodes[n.parent])) {
obj = memnew(Node3D);
@@ -172,10 +177,6 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
}
node = Object::cast_to<Node>(obj);
-
- } else {
- //print_line("Class is disabled for: " + itos(n.type));
- //print_line("name: " + String(snames[n.type]));
}
if (node) {
@@ -469,6 +470,11 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
p_node->get_property_list(&plist);
StringName type = p_node->get_class();
+ Ref<Script> script = p_node->get_script();
+ if (script.is_valid()) {
+ script->update_exports();
+ }
+
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
continue;
@@ -484,7 +490,6 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
isdefault = bool(Variant::evaluate(Variant::OP_EQUAL, value, default_value));
}
- Ref<Script> script = p_node->get_script();
if (!isdefault && script.is_valid() && script->get_property_default_value(name, default_value)) {
isdefault = bool(Variant::evaluate(Variant::OP_EQUAL, value, default_value));
}
@@ -1589,8 +1594,6 @@ void SceneState::_bind_methods() {
}
SceneState::SceneState() {
- base_scene_idx = -1;
- last_modified_time = 0;
}
////////////////
@@ -1663,6 +1666,9 @@ void PackedScene::set_path(const String &p_path, bool p_take_over) {
Resource::set_path(p_path, p_take_over);
}
+void PackedScene::reset_state() {
+ clear();
+}
void PackedScene::_bind_methods() {
ClassDB::bind_method(D_METHOD("pack", "path"), &PackedScene::pack);
ClassDB::bind_method(D_METHOD("instance", "edit_state"), &PackedScene::instance, DEFVAL(GEN_EDIT_STATE_DISABLED));
diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h
index a31dcd8d39..78a0aeaa9a 100644
--- a/scene/resources/packed_scene.h
+++ b/scene/resources/packed_scene.h
@@ -44,7 +44,7 @@ class SceneState : public Reference {
mutable HashMap<NodePath, int> node_path_cache;
mutable Map<int, int> base_scene_node_remap;
- int base_scene_idx;
+ int base_scene_idx = -1;
enum {
NO_PARENT_SAVED = 0x7FFFFFFF,
@@ -53,16 +53,16 @@ class SceneState : public Reference {
};
struct NodeData {
- int parent;
- int owner;
- int type;
- int name;
- int instance;
- int index;
+ int parent = 0;
+ int owner = 0;
+ int type = 0;
+ int name = 0;
+ int instance = 0;
+ int index = 0;
struct Property {
- int name;
- int value;
+ int name = 0;
+ int value = 0;
};
Vector<Property> properties;
@@ -71,18 +71,17 @@ class SceneState : public Reference {
struct PackState {
Ref<SceneState> state;
- int node;
- PackState() { node = -1; }
+ int node = -1;
};
Vector<NodeData> nodes;
struct ConnectionData {
- int from;
- int to;
- int signal;
- int method;
- int flags;
+ int from = 0;
+ int to = 0;
+ int signal = 0;
+ int method = 0;
+ int flags = 0;
Vector<int> binds;
};
@@ -93,7 +92,7 @@ class SceneState : public Reference {
String path;
- uint64_t last_modified_time;
+ uint64_t last_modified_time = 0;
_FORCE_INLINE_ Ref<SceneState> _get_base_scene_state() const;
@@ -201,6 +200,7 @@ class PackedScene : public Resource {
protected:
virtual bool editor_can_reload_from_file() override { return false; } // this is handled by editor better
static void _bind_methods();
+ virtual void reset_state() override;
public:
enum GenEditState {
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index c5a295e13f..a0f4bf9409 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -911,7 +911,7 @@ void ParticlesMaterial::set_color_ramp(const Ref<Texture2D> &p_texture) {
color_ramp = p_texture;
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, p_texture);
_queue_shader_change();
- _change_notify();
+ notify_property_list_changed();
}
Ref<Texture2D> ParticlesMaterial::get_color_ramp() const {
@@ -923,7 +923,7 @@ void ParticlesMaterial::set_particle_flag(ParticleFlags p_particle_flag, bool p_
particle_flags[p_particle_flag] = p_enable;
_queue_shader_change();
if (p_particle_flag == PARTICLE_FLAG_DISABLE_Z) {
- _change_notify();
+ notify_property_list_changed();
}
}
@@ -935,7 +935,7 @@ bool ParticlesMaterial::get_particle_flag(ParticleFlags p_particle_flag) const {
void ParticlesMaterial::set_emission_shape(EmissionShape p_shape) {
ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX);
emission_shape = p_shape;
- _change_notify();
+ notify_property_list_changed();
_queue_shader_change();
}
@@ -1066,7 +1066,7 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const {
void ParticlesMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) {
sub_emitter_mode = p_sub_emitter_mode;
_queue_shader_change();
- _change_notify();
+ notify_property_list_changed();
}
ParticlesMaterial::SubEmitterMode ParticlesMaterial::get_sub_emitter_mode() const {
@@ -1075,7 +1075,7 @@ ParticlesMaterial::SubEmitterMode ParticlesMaterial::get_sub_emitter_mode() cons
void ParticlesMaterial::set_sub_emitter_frequency(float p_frequency) {
sub_emitter_frequency = p_frequency;
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_frequency, 1.0 / p_frequency); //pas delta instead of frequency, since its easier to compute
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_frequency, 1.0 / p_frequency); //pass delta instead of frequency, since its easier to compute
}
float ParticlesMaterial::get_sub_emitter_frequency() const {
return sub_emitter_frequency;
@@ -1370,7 +1370,6 @@ ParticlesMaterial::ParticlesMaterial() :
set_emission_box_extents(Vector3(1, 1, 1));
set_gravity(Vector3(0, -9.8, 0));
set_lifetime_randomness(0);
- emission_point_count = 1;
set_sub_emitter_mode(SUB_EMITTER_DISABLED);
set_sub_emitter_frequency(4);
@@ -1393,7 +1392,6 @@ ParticlesMaterial::ParticlesMaterial() :
set_color(Color(1, 1, 1, 1));
- current_key.key = 0;
current_key.invalid_key = 1;
_queue_shader_change();
diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h
index 49b48a01b7..3f874bd68c 100644
--- a/scene/resources/particles_material.h
+++ b/scene/resources/particles_material.h
@@ -100,7 +100,7 @@ private:
uint32_t collision_scale : 1;
};
- uint32_t key;
+ uint32_t key = 0;
bool operator<(const MaterialKey &p_key) const {
return key < p_key.key;
@@ -109,7 +109,7 @@ private:
struct ShaderData {
RID shader;
- int users;
+ int users = 0;
};
static Map<MaterialKey, ShaderData> shader_map;
@@ -235,7 +235,7 @@ private:
Ref<Texture2D> emission_point_texture;
Ref<Texture2D> emission_normal_texture;
Ref<Texture2D> emission_color_texture;
- int emission_point_count;
+ int emission_point_count = 1;
bool anim_loop;
diff --git a/scene/resources/physics_material.h b/scene/resources/physics_material.h
index dfb2d1480b..d302800823 100644
--- a/scene/resources/physics_material.h
+++ b/scene/resources/physics_material.h
@@ -39,9 +39,9 @@ class PhysicsMaterial : public Resource {
OBJ_SAVE_TYPE(PhysicsMaterial);
RES_BASE_EXTENSION("phymat");
- real_t friction = 1;
+ real_t friction = 1.0;
bool rough = false;
- real_t bounce = 0;
+ real_t bounce = 0.0;
bool absorbent = false;
protected:
diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp
index f292140d6b..536318ed16 100644
--- a/scene/resources/polygon_path_finder.cpp
+++ b/scene/resources/polygon_path_finder.cpp
@@ -77,7 +77,7 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int>
outside_point.x += 20.451 + Math::randf() * 10.2039;
outside_point.y += 21.193 + Math::randf() * 12.5412;
- //insert edges (which are also connetions)
+ //insert edges (which are also connections)
for (int i = 0; i < p_connections.size(); i += 2) {
Edge e(p_connections[i], p_connections[i + 1]);
@@ -335,7 +335,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector
//oh this was visited already, can we win the cost?
if (p.distance > distance) {
- p.prev = least_cost_point; //reasign previous
+ p.prev = least_cost_point; //reassign previous
p.distance = distance;
}
} else {
diff --git a/scene/resources/polygon_path_finder.h b/scene/resources/polygon_path_finder.h
index 410e1dba52..2f3cb634fb 100644
--- a/scene/resources/polygon_path_finder.h
+++ b/scene/resources/polygon_path_finder.h
@@ -39,13 +39,13 @@ class PolygonPathFinder : public Resource {
struct Point {
Vector2 pos;
Set<int> connections;
- float distance;
- float penalty;
- int prev;
+ float distance = 0.0;
+ float penalty = 0.0;
+ int prev = 0;
};
struct Edge {
- int points[2];
+ int points[2] = {};
_FORCE_INLINE_ bool operator<(const Edge &p_edge) const {
if (points[0] == p_edge.points[0]) {
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 398bce0602..ba6c4591c9 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -214,7 +214,7 @@ void PrimitiveMesh::set_material(const Ref<Material> &p_material) {
if (!pending_request) {
// just apply it, else it'll happen when _update is called.
RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
- _change_notify();
+ notify_property_list_changed();
emit_changed();
};
}
@@ -247,18 +247,7 @@ bool PrimitiveMesh::get_flip_faces() const {
}
PrimitiveMesh::PrimitiveMesh() {
- flip_faces = false;
- // defaults
mesh = RenderingServer::get_singleton()->mesh_create();
-
- // assume primitive triangles as the type, correct for all but one and it will change this :)
- primitive_type = Mesh::PRIMITIVE_TRIANGLES;
-
- // make sure we do an update after we've finished constructing our object
- pending_request = true;
-
- array_len = 0;
- index_array_len = 0;
}
PrimitiveMesh::~PrimitiveMesh() {
@@ -468,13 +457,7 @@ int CapsuleMesh::get_rings() const {
return rings;
}
-CapsuleMesh::CapsuleMesh() {
- // defaults
- radius = 1.0;
- mid_height = 1.0;
- radial_segments = 64;
- rings = 8;
-}
+CapsuleMesh::CapsuleMesh() {}
/**
BoxMesh
@@ -725,13 +708,7 @@ int BoxMesh::get_subdivide_depth() const {
return subdivide_d;
}
-BoxMesh::BoxMesh() {
- // defaults
- size = Vector3(2.0, 2.0, 2.0);
- subdivide_w = 0;
- subdivide_h = 0;
- subdivide_d = 0;
-}
+BoxMesh::BoxMesh() {}
/**
CylinderMesh
@@ -938,14 +915,7 @@ int CylinderMesh::get_rings() const {
return rings;
}
-CylinderMesh::CylinderMesh() {
- // defaults
- top_radius = 1.0;
- bottom_radius = 1.0;
- height = 2.0;
- radial_segments = 64;
- rings = 4;
-}
+CylinderMesh::CylinderMesh() {}
/**
PlaneMesh
@@ -1053,12 +1023,7 @@ int PlaneMesh::get_subdivide_depth() const {
return subdivide_d;
}
-PlaneMesh::PlaneMesh() {
- // defaults
- size = Size2(2.0, 2.0);
- subdivide_w = 0;
- subdivide_d = 0;
-}
+PlaneMesh::PlaneMesh() {}
/**
PrismMesh
@@ -1338,14 +1303,7 @@ int PrismMesh::get_subdivide_depth() const {
return subdivide_d;
}
-PrismMesh::PrismMesh() {
- // defaults
- left_to_right = 0.5;
- size = Vector3(2.0, 2.0, 2.0);
- subdivide_w = 0;
- subdivide_h = 0;
- subdivide_d = 0;
-}
+PrismMesh::PrismMesh() {}
/**
QuadMesh
@@ -1409,7 +1367,6 @@ void QuadMesh::_bind_methods() {
QuadMesh::QuadMesh() {
primitive_type = PRIMITIVE_TRIANGLES;
- size = Size2(1.0, 1.0);
}
void QuadMesh::set_size(const Size2 &p_size) {
@@ -1561,14 +1518,7 @@ bool SphereMesh::get_is_hemisphere() const {
return is_hemisphere;
}
-SphereMesh::SphereMesh() {
- // defaults
- radius = 1.0;
- height = 2.0;
- radial_segments = 64;
- rings = 32;
- is_hemisphere = false;
-}
+SphereMesh::SphereMesh() {}
/**
PointMesh
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index d0ca4b10e7..bb3df9d10e 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -49,17 +49,19 @@ private:
mutable AABB aabb;
AABB custom_aabb;
- mutable int array_len;
- mutable int index_array_len;
+ mutable int array_len = 0;
+ mutable int index_array_len = 0;
Ref<Material> material;
- bool flip_faces;
+ bool flip_faces = false;
- mutable bool pending_request;
+ // make sure we do an update after we've finished constructing our object
+ mutable bool pending_request = true;
void _update() const;
protected:
- Mesh::PrimitiveType primitive_type;
+ // assume primitive triangles as the type, correct for all but one and it will change this :)
+ Mesh::PrimitiveType primitive_type = Mesh::PRIMITIVE_TRIANGLES;
static void _bind_methods();
@@ -104,10 +106,10 @@ class CapsuleMesh : public PrimitiveMesh {
GDCLASS(CapsuleMesh, PrimitiveMesh);
private:
- float radius;
- float mid_height;
- int radial_segments;
- int rings;
+ float radius = 1.0;
+ float mid_height = 1.0;
+ int radial_segments = 64;
+ int rings = 8;
protected:
static void _bind_methods();
@@ -136,10 +138,10 @@ class BoxMesh : public PrimitiveMesh {
GDCLASS(BoxMesh, PrimitiveMesh);
private:
- Vector3 size;
- int subdivide_w;
- int subdivide_h;
- int subdivide_d;
+ Vector3 size = Vector3(2.0, 2.0, 2.0);
+ int subdivide_w = 0;
+ int subdivide_h = 0;
+ int subdivide_d = 0;
protected:
static void _bind_methods();
@@ -169,11 +171,11 @@ class CylinderMesh : public PrimitiveMesh {
GDCLASS(CylinderMesh, PrimitiveMesh);
private:
- float top_radius;
- float bottom_radius;
- float height;
- int radial_segments;
- int rings;
+ float top_radius = 1.0;
+ float bottom_radius = 1.0;
+ float height = 2.0;
+ int radial_segments = 64;
+ int rings = 4;
protected:
static void _bind_methods();
@@ -205,9 +207,9 @@ class PlaneMesh : public PrimitiveMesh {
GDCLASS(PlaneMesh, PrimitiveMesh);
private:
- Size2 size;
- int subdivide_w;
- int subdivide_d;
+ Size2 size = Size2(2.0, 2.0);
+ int subdivide_w = 0;
+ int subdivide_d = 0;
protected:
static void _bind_methods();
@@ -233,11 +235,11 @@ class PrismMesh : public PrimitiveMesh {
GDCLASS(PrismMesh, PrimitiveMesh);
private:
- float left_to_right;
- Vector3 size;
- int subdivide_w;
- int subdivide_h;
- int subdivide_d;
+ float left_to_right = 0.5;
+ Vector3 size = Vector3(2.0, 2.0, 2.0);
+ int subdivide_w = 0;
+ int subdivide_h = 0;
+ int subdivide_d = 0;
protected:
static void _bind_methods();
@@ -270,7 +272,7 @@ class QuadMesh : public PrimitiveMesh {
GDCLASS(QuadMesh, PrimitiveMesh);
private:
- Size2 size;
+ Size2 size = Size2(1.0, 1.0);
protected:
static void _bind_methods();
@@ -290,11 +292,11 @@ class SphereMesh : public PrimitiveMesh {
GDCLASS(SphereMesh, PrimitiveMesh);
private:
- float radius;
- float height;
- int radial_segments;
- int rings;
- bool is_hemisphere;
+ float radius = 1.0;
+ float height = 2.0;
+ int radial_segments = 64;
+ int rings = 32;
+ bool is_hemisphere = false;
protected:
static void _bind_methods();
diff --git a/scene/resources/ray_shape_2d.cpp b/scene/resources/ray_shape_2d.cpp
index 98fd160810..fb8f4b9985 100644
--- a/scene/resources/ray_shape_2d.cpp
+++ b/scene/resources/ray_shape_2d.cpp
@@ -42,17 +42,33 @@ void RayShape2D::_update_shape() {
}
void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) {
- Vector2 tip = Vector2(0, get_length());
- RS::get_singleton()->canvas_item_add_line(p_to_rid, Vector2(), tip, p_color, 3);
+ const Vector2 target_position = Vector2(0, get_length());
+
+ const float max_arrow_size = 6;
+ const float line_width = 1.4;
+ bool no_line = target_position.length() < line_width;
+ float arrow_size = CLAMP(target_position.length() * 2 / 3, line_width, max_arrow_size);
+
+ if (no_line) {
+ arrow_size = target_position.length();
+ } else {
+ RS::get_singleton()->canvas_item_add_line(p_to_rid, Vector2(), target_position - target_position.normalized() * arrow_size, p_color, line_width);
+ }
+
+ Transform2D xf;
+ xf.rotate(target_position.angle());
+ xf.translate(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
+
Vector<Vector2> pts;
- float tsize = 4;
- pts.push_back(tip + Vector2(0, tsize));
- pts.push_back(tip + Vector2(Math_SQRT12 * tsize, 0));
- pts.push_back(tip + Vector2(-Math_SQRT12 * tsize, 0));
+ pts.push_back(xf.xform(Vector2(arrow_size, 0)));
+ pts.push_back(xf.xform(Vector2(0, 0.5 * arrow_size)));
+ pts.push_back(xf.xform(Vector2(0, -0.5 * arrow_size)));
+
Vector<Color> cols;
for (int i = 0; i < 3; i++) {
cols.push_back(p_color);
}
+
RS::get_singleton()->canvas_item_add_primitive(p_to_rid, pts, cols, Vector<Point2>(), RID());
}
@@ -99,7 +115,5 @@ bool RayShape2D::get_slips_on_slope() const {
RayShape2D::RayShape2D() :
Shape2D(PhysicsServer2D::get_singleton()->ray_shape_create()) {
- length = 20;
- slips_on_slope = false;
_update_shape();
}
diff --git a/scene/resources/ray_shape_2d.h b/scene/resources/ray_shape_2d.h
index 3570b7be52..56ecfa2722 100644
--- a/scene/resources/ray_shape_2d.h
+++ b/scene/resources/ray_shape_2d.h
@@ -36,8 +36,8 @@
class RayShape2D : public Shape2D {
GDCLASS(RayShape2D, Shape2D);
- real_t length;
- bool slips_on_slope;
+ real_t length = 20.0;
+ bool slips_on_slope = false;
void _update_shape();
diff --git a/scene/resources/ray_shape_3d.cpp b/scene/resources/ray_shape_3d.cpp
index a332bb575f..5446b4daab 100644
--- a/scene/resources/ray_shape_3d.cpp
+++ b/scene/resources/ray_shape_3d.cpp
@@ -56,7 +56,6 @@ void RayShape3D::set_length(float p_length) {
length = p_length;
_update_shape();
notify_change_to_owners();
- _change_notify("length");
}
float RayShape3D::get_length() const {
@@ -67,7 +66,6 @@ void RayShape3D::set_slips_on_slope(bool p_active) {
slips_on_slope = p_active;
_update_shape();
notify_change_to_owners();
- _change_notify("slips_on_slope");
}
bool RayShape3D::get_slips_on_slope() const {
@@ -87,12 +85,7 @@ void RayShape3D::_bind_methods() {
RayShape3D::RayShape3D() :
Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_RAY)) {
- length = 1.0;
- slips_on_slope = false;
-
/* Code copied from setters to prevent the use of uninitialized variables */
_update_shape();
notify_change_to_owners();
- _change_notify("length");
- _change_notify("slips_on_slope");
}
diff --git a/scene/resources/ray_shape_3d.h b/scene/resources/ray_shape_3d.h
index 2c27d56c63..2da6311321 100644
--- a/scene/resources/ray_shape_3d.h
+++ b/scene/resources/ray_shape_3d.h
@@ -34,8 +34,8 @@
class RayShape3D : public Shape3D {
GDCLASS(RayShape3D, Shape3D);
- float length;
- bool slips_on_slope;
+ float length = 1.0;
+ bool slips_on_slope = false;
protected:
static void _bind_methods();
diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp
index a5b909c9a7..dc4c6dc2d7 100644
--- a/scene/resources/rectangle_shape_2d.cpp
+++ b/scene/resources/rectangle_shape_2d.cpp
@@ -33,7 +33,7 @@
#include "servers/physics_server_2d.h"
#include "servers/rendering_server.h"
void RectangleShape2D::_update_shape() {
- PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), size / 2);
+ PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), size * 0.5);
emit_changed();
}
@@ -47,11 +47,29 @@ Vector2 RectangleShape2D::get_size() const {
}
void RectangleShape2D::draw(const RID &p_to_rid, const Color &p_color) {
- RenderingServer::get_singleton()->canvas_item_add_rect(p_to_rid, Rect2(-size / 2, size), p_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_to_rid, Rect2(-size * 0.5, size), p_color);
+ if (is_collision_outline_enabled()) {
+ // Draw an outlined rectangle to make individual shapes easier to distinguish.
+ Vector<Vector2> stroke_points;
+ stroke_points.resize(5);
+ stroke_points.write[0] = -size * 0.5;
+ stroke_points.write[1] = Vector2(size.x, -size.y) * 0.5;
+ stroke_points.write[2] = size * 0.5;
+ stroke_points.write[3] = Vector2(-size.x, size.y) * 0.5;
+ stroke_points.write[4] = -size * 0.5;
+
+ Vector<Color> stroke_colors;
+ stroke_colors.resize(5);
+ for (int i = 0; i < 5; i++) {
+ stroke_colors.write[i] = (p_color);
+ }
+
+ RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, stroke_points, stroke_colors);
+ }
}
Rect2 RectangleShape2D::get_rect() const {
- return Rect2(-size / 2, size);
+ return Rect2(-size * 0.5, size);
}
real_t RectangleShape2D::get_enclosing_radius() const {
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index 433e3392e3..f2751b7604 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -114,23 +114,8 @@ Error ResourceLoaderText::_parse_sub_resource(VariantParser::Stream *p_stream, R
}
int index = token.value;
-
- if (use_nocache) {
- r_res = int_resources[index];
- } else {
- String path = local_path + "::" + itos(index);
-
- if (!ignore_resource_parsing) {
- if (!ResourceCache::has(path)) {
- r_err_str = "Can't load cached sub-resource: " + path;
- return ERR_PARSE_ERROR;
- }
-
- r_res = RES(ResourceCache::get(path));
- } else {
- r_res = RES();
- }
- }
+ ERR_FAIL_COND_V(!int_resources.has(index), ERR_INVALID_PARAMETER);
+ r_res = int_resources[index];
VariantParser::get_token(p_stream, token, line, r_err_str);
if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
@@ -440,7 +425,7 @@ Error ResourceLoaderText::load() {
er.type = type;
if (use_sub_threads) {
- Error err = ResourceLoader::load_threaded_request(path, type, use_sub_threads, local_path);
+ Error err = ResourceLoader::load_threaded_request(path, type, use_sub_threads, ResourceFormatLoader::CACHE_MODE_REUSE, local_path);
if (err != OK) {
if (ResourceLoader::get_abort_on_missing_resources()) {
@@ -517,29 +502,44 @@ Error ResourceLoaderText::load() {
//bool exists=ResourceCache::has(path);
Ref<Resource> res;
+ bool do_assign = false;
- if (use_nocache || !ResourceCache::has(path)) { //only if it doesn't exist
-
- Object *obj = ClassDB::instance(type);
- if (!obj) {
- error_text += "Can't create sub resource of type: " + type;
- _printerr();
- error = ERR_FILE_CORRUPT;
- return error;
+ if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(path)) {
+ //reuse existing
+ Resource *r = ResourceCache::get(path);
+ if (r && r->get_class() == type) {
+ res = Ref<Resource>(r);
+ res->reset_state();
+ do_assign = true;
}
+ }
- Resource *r = Object::cast_to<Resource>(obj);
- if (!r) {
- error_text += "Can't create sub resource of type, because not a resource: " + type;
- _printerr();
- error = ERR_FILE_CORRUPT;
- return error;
- }
+ if (res.is_null()) { //not reuse
+ if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE && ResourceCache::has(path)) { //only if it doesn't exist
+ //cached, do not assign
+ Resource *r = ResourceCache::get(path);
+ res = Ref<Resource>(r);
+ } else {
+ //create
- res = Ref<Resource>(r);
- int_resources[id] = res;
- if (!use_nocache) {
- res->set_path(path);
+ Object *obj = ClassDB::instance(type);
+ if (!obj) {
+ error_text += "Can't create sub resource of type: " + type;
+ _printerr();
+ error = ERR_FILE_CORRUPT;
+ return error;
+ }
+
+ Resource *r = Object::cast_to<Resource>(obj);
+ if (!r) {
+ error_text += "Can't create sub resource of type, because not a resource: " + type;
+ _printerr();
+ error = ERR_FILE_CORRUPT;
+ return error;
+ }
+
+ res = Ref<Resource>(r);
+ do_assign = true;
}
}
@@ -557,7 +557,7 @@ Error ResourceLoaderText::load() {
}
if (assign != String()) {
- if (res.is_valid()) {
+ if (do_assign) {
res->set(assign, value);
}
//it's assignment
@@ -572,6 +572,11 @@ Error ResourceLoaderText::load() {
}
}
+ 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);
+ }
+
if (progress && resources_total > 0) {
*progress = resource_current / float(resources_total);
}
@@ -589,23 +594,33 @@ Error ResourceLoaderText::load() {
return error;
}
- Object *obj = ClassDB::instance(res_type);
- if (!obj) {
- error_text += "Can't create sub resource of type: " + res_type;
- _printerr();
- error = ERR_FILE_CORRUPT;
- return error;
+ if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(local_path)) {
+ Resource *r = ResourceCache::get(local_path);
+ if (r->get_class() == res_type) {
+ r->reset_state();
+ resource = Ref<Resource>(r);
+ }
}
- Resource *r = Object::cast_to<Resource>(obj);
- if (!r) {
- error_text += "Can't create sub resource of type, because not a resource: " + res_type;
- _printerr();
- error = ERR_FILE_CORRUPT;
- return error;
- }
+ if (!resource.is_valid()) {
+ Object *obj = ClassDB::instance(res_type);
+ if (!obj) {
+ error_text += "Can't create sub resource of type: " + res_type;
+ _printerr();
+ error = ERR_FILE_CORRUPT;
+ return error;
+ }
+
+ Resource *r = Object::cast_to<Resource>(obj);
+ if (!r) {
+ error_text += "Can't create sub resource of type, because not a resource: " + res_type;
+ _printerr();
+ error = ERR_FILE_CORRUPT;
+ return error;
+ }
- resource = Ref<Resource>(r);
+ resource = Ref<Resource>(r);
+ }
resource_current++;
@@ -620,7 +635,7 @@ Error ResourceLoaderText::load() {
_printerr();
} else {
error = OK;
- if (!use_nocache) {
+ if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
if (!ResourceCache::has(res_path)) {
resource->set_path(res_path);
}
@@ -668,7 +683,7 @@ Error ResourceLoaderText::load() {
error = OK;
//get it here
resource = packed_scene;
- if (!use_nocache && !ResourceCache::has(res_path)) {
+ if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE && !ResourceCache::has(res_path)) {
packed_scene->set_path(res_path);
}
@@ -699,18 +714,7 @@ void ResourceLoaderText::set_translation_remapped(bool p_remapped) {
translation_remapped = p_remapped;
}
-ResourceLoaderText::ResourceLoaderText() {
- use_nocache = false;
-
- resources_total = 0;
- resource_current = 0;
-
- progress = nullptr;
- lines = false;
- translation_remapped = false;
- use_sub_threads = false;
- error = OK;
-}
+ResourceLoaderText::ResourceLoaderText() {}
ResourceLoaderText::~ResourceLoaderText() {
memdelete(f);
@@ -1252,7 +1256,7 @@ String ResourceLoaderText::recognize(FileAccess *p_f) {
/////////////////////
-RES ResourceFormatLoaderText::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderText::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
@@ -1265,7 +1269,7 @@ RES ResourceFormatLoaderText::load(const String &p_path, const String &p_origina
ResourceLoaderText loader;
String path = p_original_path != "" ? p_original_path : p_path;
- loader.use_nocache = p_no_cache;
+ loader.cache_mode = p_cache_mode;
loader.use_sub_threads = p_use_sub_threads;
loader.local_path = ProjectSettings::get_singleton()->localize_path(path);
loader.progress = r_progress;
@@ -1317,7 +1321,7 @@ String ResourceFormatLoaderText::get_resource_type(const String &p_path) const {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
- return ""; //could not rwead
+ return ""; //could not read
}
ResourceLoaderText loader;
diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h
index e67a13d41a..2dc683415d 100644
--- a/scene/resources/resource_format_text.h
+++ b/scene/resources/resource_format_text.h
@@ -38,12 +38,12 @@
#include "scene/resources/packed_scene.h"
class ResourceLoaderText {
- bool translation_remapped;
+ bool translation_remapped = false;
String local_path;
String res_path;
String error_text;
- FileAccess *f;
+ FileAccess *f = nullptr;
VariantParser::StreamFile stream;
@@ -53,28 +53,28 @@ class ResourceLoaderText {
String type;
};
- bool is_scene;
+ bool is_scene = false;
String res_type;
- bool ignore_resource_parsing;
+ bool ignore_resource_parsing = false;
//Map<String,String> remaps;
Map<int, ExtResource> ext_resources;
Map<int, RES> int_resources;
- int resources_total;
- int resource_current;
+ int resources_total = 0;
+ int resource_current = 0;
String resource_type;
VariantParser::Tag next_tag;
- bool use_nocache;
+ ResourceFormatLoader::CacheMode cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE;
- bool use_sub_threads;
- float *progress;
+ bool use_sub_threads = false;
+ float *progress = nullptr;
- mutable int lines;
+ mutable int lines = 0;
Map<String, String> remaps;
//void _printerr();
@@ -107,7 +107,7 @@ class ResourceLoaderText {
friend class ResourceFormatLoaderText;
- Error error;
+ Error error = OK;
RES resource;
@@ -134,7 +134,7 @@ public:
class ResourceFormatLoaderText : public ResourceFormatLoader {
public:
static ResourceFormatLoaderText *singleton;
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
@@ -152,11 +152,11 @@ class ResourceFormatSaverTextInstance {
Ref<PackedScene> packed_scene;
- bool takeover_paths;
- bool relative_paths;
- bool bundle_resources;
- bool skip_editor;
- FileAccess *f;
+ bool takeover_paths = false;
+ bool relative_paths = false;
+ bool bundle_resources = false;
+ bool skip_editor = false;
+ FileAccess *f = nullptr;
struct NonPersistentKey { //for resource properties generated on the fly
RES base;
@@ -173,7 +173,7 @@ class ResourceFormatSaverTextInstance {
struct ResourceSort {
RES resource;
- int index;
+ int index = 0;
bool operator<(const ResourceSort &p_right) const {
return index < p_right.index;
}
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index 53f3dd1a4b..77c6199794 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -152,9 +152,7 @@ void Shader::_bind_methods() {
}
Shader::Shader() {
- mode = MODE_SPATIAL;
shader = RenderingServer::get_singleton()->shader_create();
- params_cache_dirty = true;
}
Shader::~Shader() {
@@ -163,7 +161,7 @@ Shader::~Shader() {
////////////
-RES ResourceFormatLoaderShader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderShader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
}
diff --git a/scene/resources/shader.h b/scene/resources/shader.h
index a3f9330055..6563181ca2 100644
--- a/scene/resources/shader.h
+++ b/scene/resources/shader.h
@@ -51,12 +51,12 @@ public:
private:
RID shader;
- Mode mode;
+ Mode mode = MODE_SPATIAL;
// hack the name of performance
// shaders keep a list of ShaderMaterial -> RenderingServer name translations, to make
// conversion fast and save memory.
- mutable bool params_cache_dirty;
+ mutable bool params_cache_dirty = true;
mutable Map<StringName, StringName> params_cache; //map a shader param to a material param..
Map<StringName, Ref<Texture2D>> default_textures;
@@ -102,7 +102,7 @@ VARIANT_ENUM_CAST(Shader::Mode);
class ResourceFormatLoaderShader : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp
index 6f3897b0cd..013b1ef1a9 100644
--- a/scene/resources/shape_2d.cpp
+++ b/scene/resources/shape_2d.cpp
@@ -29,7 +29,11 @@
/*************************************************************************/
#include "shape_2d.h"
+
+#include "core/config/engine.h"
+#include "core/config/project_settings.h"
#include "servers/physics_server_2d.h"
+
RID Shape2D::get_rid() const {
return shape;
}
@@ -105,9 +109,17 @@ void Shape2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_solver_bias", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_custom_solver_bias", "get_custom_solver_bias");
}
+bool Shape2D::is_collision_outline_enabled() {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return true;
+ }
+#endif
+ return GLOBAL_DEF("debug/shapes/collision/draw_2d_outlines", true);
+}
+
Shape2D::Shape2D(const RID &p_rid) {
shape = p_rid;
- custom_bias = 0;
}
Shape2D::~Shape2D() {
diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h
index f5814c42f8..14bdd60e4b 100644
--- a/scene/resources/shape_2d.h
+++ b/scene/resources/shape_2d.h
@@ -38,7 +38,7 @@ class Shape2D : public Resource {
OBJ_SAVE_TYPE(Shape2D);
RID shape;
- real_t custom_bias;
+ real_t custom_bias = 0.0;
protected:
static void _bind_methods();
@@ -61,6 +61,9 @@ public:
/// Returns the radius of a circle that fully enclose this shape
virtual real_t get_enclosing_radius() const = 0;
virtual RID get_rid() const override;
+
+ static bool is_collision_outline_enabled();
+
Shape2D();
~Shape2D();
};
diff --git a/scene/resources/skin.cpp b/scene/resources/skin.cpp
index e2df965138..fee8fdbde2 100644
--- a/scene/resources/skin.cpp
+++ b/scene/resources/skin.cpp
@@ -58,7 +58,7 @@ void Skin::set_bind_name(int p_index, const StringName &p_name) {
binds_ptr[p_index].name = p_name;
emit_changed();
if (notify_change) {
- _change_notify();
+ notify_property_list_changed();
}
}
@@ -81,6 +81,10 @@ void Skin::clear_binds() {
emit_changed();
}
+void Skin::reset_state() {
+ clear_binds();
+}
+
bool Skin::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
if (name == "bind_count") {
@@ -153,6 +157,4 @@ void Skin::_bind_methods() {
}
Skin::Skin() {
- bind_count = 0;
- binds_ptr = nullptr;
}
diff --git a/scene/resources/skin.h b/scene/resources/skin.h
index 64fe24bbe4..f5d64f96aa 100644
--- a/scene/resources/skin.h
+++ b/scene/resources/skin.h
@@ -44,14 +44,15 @@ class Skin : public Resource {
Vector<Bind> binds;
- Bind *binds_ptr;
- int bind_count;
+ Bind *binds_ptr = nullptr;
+ int bind_count = 0;
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;
+ virtual void reset_state() override;
static void _bind_methods();
public:
diff --git a/scene/resources/sky.cpp b/scene/resources/sky.cpp
index 8fcd92bb89..71424ba8ac 100644
--- a/scene/resources/sky.cpp
+++ b/scene/resources/sky.cpp
@@ -102,8 +102,6 @@ void Sky::_bind_methods() {
}
Sky::Sky() {
- mode = PROCESS_MODE_AUTOMATIC;
- radiance_size = RADIANCE_SIZE_256;
sky = RS::get_singleton()->sky_create();
}
diff --git a/scene/resources/sky.h b/scene/resources/sky.h
index 46f645a53d..f0226d321d 100644
--- a/scene/resources/sky.h
+++ b/scene/resources/sky.h
@@ -59,8 +59,8 @@ public:
private:
RID sky;
- ProcessMode mode;
- RadianceSize radiance_size;
+ ProcessMode mode = PROCESS_MODE_AUTOMATIC;
+ RadianceSize radiance_size = RADIANCE_SIZE_256;
Ref<Material> sky_material;
protected:
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index ee6a26bc65..b2efecb1cb 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -597,5 +597,4 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() {
PhysicalSkyMaterial::~PhysicalSkyMaterial() {
RS::get_singleton()->free(shader);
- RS::get_singleton()->material_set_shader(_get_material(), RID());
}
diff --git a/scene/resources/sphere_shape_3d.cpp b/scene/resources/sphere_shape_3d.cpp
index 008cb3e1d6..e4b4398063 100644
--- a/scene/resources/sphere_shape_3d.cpp
+++ b/scene/resources/sphere_shape_3d.cpp
@@ -66,7 +66,6 @@ void SphereShape3D::set_radius(float p_radius) {
radius = p_radius;
_update_shape();
notify_change_to_owners();
- _change_notify("radius");
}
float SphereShape3D::get_radius() const {
diff --git a/scene/resources/sprite_frames.cpp b/scene/resources/sprite_frames.cpp
new file mode 100644
index 0000000000..90c702081b
--- /dev/null
+++ b/scene/resources/sprite_frames.cpp
@@ -0,0 +1,241 @@
+/*************************************************************************/
+/* sprite_frames.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "sprite_frames.h"
+
+#include "scene/scene_string_names.h"
+
+void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture2D> &p_frame, int p_at_pos) {
+ Map<StringName, Anim>::Element *E = animations.find(p_anim);
+ ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
+
+ if (p_at_pos >= 0 && p_at_pos < E->get().frames.size()) {
+ E->get().frames.insert(p_at_pos, p_frame);
+ } else {
+ E->get().frames.push_back(p_frame);
+ }
+
+ emit_changed();
+}
+
+int SpriteFrames::get_frame_count(const StringName &p_anim) const {
+ const Map<StringName, Anim>::Element *E = animations.find(p_anim);
+ ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist.");
+
+ return E->get().frames.size();
+}
+
+void SpriteFrames::remove_frame(const StringName &p_anim, int p_idx) {
+ Map<StringName, Anim>::Element *E = animations.find(p_anim);
+ ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
+
+ E->get().frames.remove(p_idx);
+ emit_changed();
+}
+
+void SpriteFrames::clear(const StringName &p_anim) {
+ Map<StringName, Anim>::Element *E = animations.find(p_anim);
+ ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
+
+ E->get().frames.clear();
+ emit_changed();
+}
+
+void SpriteFrames::clear_all() {
+ animations.clear();
+ add_animation("default");
+}
+
+void SpriteFrames::add_animation(const StringName &p_anim) {
+ ERR_FAIL_COND_MSG(animations.has(p_anim), "SpriteFrames already has animation '" + p_anim + "'.");
+
+ animations[p_anim] = Anim();
+}
+
+bool SpriteFrames::has_animation(const StringName &p_anim) const {
+ return animations.has(p_anim);
+}
+
+void SpriteFrames::remove_animation(const StringName &p_anim) {
+ animations.erase(p_anim);
+}
+
+void SpriteFrames::rename_animation(const StringName &p_prev, const StringName &p_next) {
+ ERR_FAIL_COND_MSG(!animations.has(p_prev), "SpriteFrames doesn't have animation '" + String(p_prev) + "'.");
+ ERR_FAIL_COND_MSG(animations.has(p_next), "Animation '" + String(p_next) + "' already exists.");
+
+ Anim anim = animations[p_prev];
+ animations.erase(p_prev);
+ animations[p_next] = anim;
+}
+
+Vector<String> SpriteFrames::_get_animation_list() const {
+ Vector<String> ret;
+ List<StringName> al;
+ get_animation_list(&al);
+ for (List<StringName>::Element *E = al.front(); E; E = E->next()) {
+ ret.push_back(E->get());
+ }
+
+ return ret;
+}
+
+void SpriteFrames::get_animation_list(List<StringName> *r_animations) const {
+ for (const Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) {
+ r_animations->push_back(E->key());
+ }
+}
+
+Vector<String> SpriteFrames::get_animation_names() const {
+ Vector<String> names;
+ for (const Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) {
+ names.push_back(E->key());
+ }
+ names.sort();
+ return names;
+}
+
+void SpriteFrames::set_animation_speed(const StringName &p_anim, float p_fps) {
+ ERR_FAIL_COND_MSG(p_fps < 0, "Animation speed cannot be negative (" + itos(p_fps) + ").");
+ Map<StringName, Anim>::Element *E = animations.find(p_anim);
+ ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
+ E->get().speed = p_fps;
+}
+
+float SpriteFrames::get_animation_speed(const StringName &p_anim) const {
+ const Map<StringName, Anim>::Element *E = animations.find(p_anim);
+ ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist.");
+ return E->get().speed;
+}
+
+void SpriteFrames::set_animation_loop(const StringName &p_anim, bool p_loop) {
+ Map<StringName, Anim>::Element *E = animations.find(p_anim);
+ ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
+ E->get().loop = p_loop;
+}
+
+bool SpriteFrames::get_animation_loop(const StringName &p_anim) const {
+ const Map<StringName, Anim>::Element *E = animations.find(p_anim);
+ ERR_FAIL_COND_V_MSG(!E, false, "Animation '" + String(p_anim) + "' doesn't exist.");
+ return E->get().loop;
+}
+
+void SpriteFrames::_set_frames(const Array &p_frames) {
+ clear_all();
+ Map<StringName, Anim>::Element *E = animations.find(SceneStringNames::get_singleton()->_default);
+ ERR_FAIL_COND(!E);
+
+ E->get().frames.resize(p_frames.size());
+ for (int i = 0; i < E->get().frames.size(); i++) {
+ E->get().frames.write[i] = p_frames[i];
+ }
+}
+
+Array SpriteFrames::_get_frames() const {
+ return Array();
+}
+
+Array SpriteFrames::_get_animations() const {
+ Array anims;
+ for (Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) {
+ Dictionary d;
+ d["name"] = E->key();
+ d["speed"] = E->get().speed;
+ d["loop"] = E->get().loop;
+ Array frames;
+ for (int i = 0; i < E->get().frames.size(); i++) {
+ frames.push_back(E->get().frames[i]);
+ }
+ d["frames"] = frames;
+ anims.push_back(d);
+ }
+
+ return anims;
+}
+
+void SpriteFrames::_set_animations(const Array &p_animations) {
+ animations.clear();
+ for (int i = 0; i < p_animations.size(); i++) {
+ Dictionary d = p_animations[i];
+
+ ERR_CONTINUE(!d.has("name"));
+ ERR_CONTINUE(!d.has("speed"));
+ ERR_CONTINUE(!d.has("loop"));
+ ERR_CONTINUE(!d.has("frames"));
+
+ Anim anim;
+ anim.speed = d["speed"];
+ anim.loop = d["loop"];
+ Array frames = d["frames"];
+ for (int j = 0; j < frames.size(); j++) {
+ RES res = frames[j];
+ anim.frames.push_back(res);
+ }
+
+ animations[d["name"]] = anim;
+ }
+}
+
+void SpriteFrames::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("add_animation", "anim"), &SpriteFrames::add_animation);
+ ClassDB::bind_method(D_METHOD("has_animation", "anim"), &SpriteFrames::has_animation);
+ ClassDB::bind_method(D_METHOD("remove_animation", "anim"), &SpriteFrames::remove_animation);
+ ClassDB::bind_method(D_METHOD("rename_animation", "anim", "newname"), &SpriteFrames::rename_animation);
+
+ ClassDB::bind_method(D_METHOD("get_animation_names"), &SpriteFrames::get_animation_names);
+
+ ClassDB::bind_method(D_METHOD("set_animation_speed", "anim", "speed"), &SpriteFrames::set_animation_speed);
+ ClassDB::bind_method(D_METHOD("get_animation_speed", "anim"), &SpriteFrames::get_animation_speed);
+
+ ClassDB::bind_method(D_METHOD("set_animation_loop", "anim", "loop"), &SpriteFrames::set_animation_loop);
+ ClassDB::bind_method(D_METHOD("get_animation_loop", "anim"), &SpriteFrames::get_animation_loop);
+
+ ClassDB::bind_method(D_METHOD("add_frame", "anim", "frame", "at_position"), &SpriteFrames::add_frame, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("get_frame_count", "anim"), &SpriteFrames::get_frame_count);
+ ClassDB::bind_method(D_METHOD("get_frame", "anim", "idx"), &SpriteFrames::get_frame);
+ ClassDB::bind_method(D_METHOD("set_frame", "anim", "idx", "txt"), &SpriteFrames::set_frame);
+ ClassDB::bind_method(D_METHOD("remove_frame", "anim", "idx"), &SpriteFrames::remove_frame);
+ ClassDB::bind_method(D_METHOD("clear", "anim"), &SpriteFrames::clear);
+ ClassDB::bind_method(D_METHOD("clear_all"), &SpriteFrames::clear_all);
+
+ ClassDB::bind_method(D_METHOD("_set_frames"), &SpriteFrames::_set_frames);
+ ClassDB::bind_method(D_METHOD("_get_frames"), &SpriteFrames::_get_frames);
+
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "frames", PROPERTY_HINT_NONE, "", 0), "_set_frames", "_get_frames"); //compatibility
+
+ ClassDB::bind_method(D_METHOD("_set_animations"), &SpriteFrames::_set_animations);
+ ClassDB::bind_method(D_METHOD("_get_animations"), &SpriteFrames::_get_animations);
+
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations"); //compatibility
+}
+
+SpriteFrames::SpriteFrames() {
+ add_animation(SceneStringNames::get_singleton()->_default);
+}
diff --git a/editor/input_map_editor.h b/scene/resources/sprite_frames.h
index cc6ac1660d..282c5f20ab 100644
--- a/editor/input_map_editor.h
+++ b/scene/resources/sprite_frames.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* input_map_editor.h */
+/* sprite_frames.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,82 +28,75 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef INPUT_MAP_EDITOR_H
-#define INPUT_MAP_EDITOR_H
+#ifndef SPRITE_FRAMES_H
+#define SPRITE_FRAMES_H
-#include "core/object/undo_redo.h"
-#include "editor/editor_data.h"
+#include "scene/resources/texture.h"
-class InputMapEditor : public Control {
- GDCLASS(InputMapEditor, Control);
+class SpriteFrames : public Resource {
+ GDCLASS(SpriteFrames, Resource);
- enum InputType {
- INPUT_KEY,
- INPUT_KEY_PHYSICAL,
- INPUT_JOY_BUTTON,
- INPUT_JOY_MOTION,
- INPUT_MOUSE_BUTTON
+ struct Anim {
+ float speed = 5.0;
+ bool loop = true;
+ Vector<Ref<Texture2D>> frames;
};
- Tree *input_editor;
- LineEdit *action_name;
- Button *action_add;
- Label *action_add_error;
-
- InputType add_type;
- String add_at;
- int edit_idx;
-
- PopupMenu *popup_add;
- ConfirmationDialog *press_a_key;
- bool press_a_key_physical;
- Label *press_a_key_label;
- ConfirmationDialog *device_input;
- OptionButton *device_id;
- OptionButton *device_index;
- Label *device_index_label;
- MenuButton *popup_copy_to_feature;
-
- Ref<InputEventKey> last_wait_for_key;
-
- AcceptDialog *message;
- UndoRedo *undo_redo;
- String inputmap_changed;
- bool setting = false;
-
- void _update_actions();
- void _add_item(int p_item, Ref<InputEvent> p_exiting_event = Ref<InputEvent>());
- void _edit_item(Ref<InputEvent> p_exiting_event);
-
- void _action_check(String p_action);
- void _action_adds(String);
- void _action_add();
- void _device_input_add();
-
- void _action_selected();
- void _action_edited();
- void _action_activated();
- void _action_button_pressed(Object *p_obj, int p_column, int p_id);
- void _wait_for_key(const Ref<InputEvent> &p_event);
- void _press_a_key_confirm();
- void _show_last_added(const Ref<InputEvent> &p_event, const String &p_name);
-
- String _get_joypad_motion_event_text(const Ref<InputEventJoypadMotion> &p_event);
-
- 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);
+ Map<StringName, Anim> animations;
-protected:
- int _get_current_device();
- void _set_current_device(int i_device);
- String _get_device_string(int i_device);
+ Array _get_frames() const;
+ void _set_frames(const Array &p_frames);
+
+ Array _get_animations() const;
+ void _set_animations(const Array &p_animations);
- void _notification(int p_what);
+ Vector<String> _get_animation_list() const;
+
+protected:
static void _bind_methods();
public:
- InputMapEditor();
+ void add_animation(const StringName &p_anim);
+ bool has_animation(const StringName &p_anim) const;
+ void remove_animation(const StringName &p_anim);
+ void rename_animation(const StringName &p_prev, const StringName &p_next);
+
+ void get_animation_list(List<StringName> *r_animations) const;
+ Vector<String> get_animation_names() const;
+
+ void set_animation_speed(const StringName &p_anim, float p_fps);
+ float get_animation_speed(const StringName &p_anim) const;
+
+ void set_animation_loop(const StringName &p_anim, bool p_loop);
+ bool get_animation_loop(const StringName &p_anim) const;
+
+ void add_frame(const StringName &p_anim, const Ref<Texture2D> &p_frame, int p_at_pos = -1);
+ int get_frame_count(const StringName &p_anim) const;
+ _FORCE_INLINE_ Ref<Texture2D> get_frame(const StringName &p_anim, int p_idx) const {
+ const Map<StringName, Anim>::Element *E = animations.find(p_anim);
+ ERR_FAIL_COND_V_MSG(!E, Ref<Texture2D>(), "Animation '" + String(p_anim) + "' doesn't exist.");
+ ERR_FAIL_COND_V(p_idx < 0, Ref<Texture2D>());
+ if (p_idx >= E->get().frames.size()) {
+ return Ref<Texture2D>();
+ }
+
+ return E->get().frames[p_idx];
+ }
+
+ void set_frame(const StringName &p_anim, int p_idx, const Ref<Texture2D> &p_frame) {
+ Map<StringName, Anim>::Element *E = animations.find(p_anim);
+ ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
+ ERR_FAIL_COND(p_idx < 0);
+ if (p_idx >= E->get().frames.size()) {
+ return;
+ }
+ E->get().frames.write[p_idx] = p_frame;
+ }
+ void remove_frame(const StringName &p_anim, int p_idx);
+ void clear(const StringName &p_anim);
+ void clear_all();
+
+ SpriteFrames();
};
-#endif // INPUT_MAP_EDITOR_H
+#endif // SPRITE_FRAMES_H
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index 7504a05a49..2159f1bc97 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -123,7 +123,6 @@ void StyleBoxTexture::set_texture(Ref<Texture2D> p_texture) {
}
emit_signal("texture_changed");
emit_changed();
- _change_notify("texture");
}
Ref<Texture2D> StyleBoxTexture::get_texture() const {
@@ -135,13 +134,6 @@ void StyleBoxTexture::set_margin_size(Side p_side, float p_size) {
margin[p_side] = p_size;
emit_changed();
- static const char *margin_prop[4] = {
- "content_margin_left",
- "content_margin_top",
- "content_margin_right",
- "content_margin_bottom",
- };
- _change_notify(margin_prop[p_side]);
}
float StyleBoxTexture::get_margin_size(Side p_side) const {
@@ -228,7 +220,6 @@ void StyleBoxTexture::set_region_rect(const Rect2 &p_region_rect) {
region_rect = p_region_rect;
emit_changed();
- _change_notify("region");
}
Rect2 StyleBoxTexture::get_region_rect() const {
@@ -320,20 +311,9 @@ void StyleBoxTexture::_bind_methods() {
BIND_ENUM_CONSTANT(AXIS_STRETCH_MODE_TILE_FIT);
}
-StyleBoxTexture::StyleBoxTexture() {
- for (int i = 0; i < 4; i++) {
- margin[i] = 0;
- expand_margin[i] = 0;
- }
- draw_center = true;
- modulate = Color(1, 1, 1, 1);
-
- axis_h = AXIS_STRETCH_MODE_STRETCH;
- axis_v = AXIS_STRETCH_MODE_STRETCH;
-}
+StyleBoxTexture::StyleBoxTexture() {}
-StyleBoxTexture::~StyleBoxTexture() {
-}
+StyleBoxTexture::~StyleBoxTexture() {}
////////////////
@@ -480,6 +460,7 @@ Point2 StyleBoxFlat::get_shadow_offset() const {
void StyleBoxFlat::set_anti_aliased(const bool &p_anti_aliased) {
anti_aliased = p_anti_aliased;
emit_changed();
+ notify_property_list_changed();
}
bool StyleBoxFlat::is_anti_aliased() const {
@@ -801,6 +782,12 @@ float StyleBoxFlat::get_style_margin(Side p_side) const {
return border_width[p_side];
}
+void StyleBoxFlat::_validate_property(PropertyInfo &property) const {
+ if (!anti_aliased && property.name == "anti_aliasing_size") {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+}
+
void StyleBoxFlat::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &StyleBoxFlat::set_bg_color);
ClassDB::bind_method(D_METHOD("get_bg_color"), &StyleBoxFlat::get_bg_color);
@@ -888,38 +875,9 @@ void StyleBoxFlat::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "anti_aliasing_size", PROPERTY_HINT_RANGE, "1,5,1"), "set_aa_size", "get_aa_size");
}
-StyleBoxFlat::StyleBoxFlat() {
- bg_color = Color(0.6, 0.6, 0.6);
- shadow_color = Color(0, 0, 0, 0.6);
- border_color = Color(0.8, 0.8, 0.8);
-
- blend_border = false;
- draw_center = true;
- anti_aliased = true;
+StyleBoxFlat::StyleBoxFlat() {}
- shadow_size = 0;
- shadow_offset = Point2(0, 0);
- corner_detail = 8;
- aa_size = 1;
-
- border_width[0] = 0;
- border_width[1] = 0;
- border_width[2] = 0;
- border_width[3] = 0;
-
- expand_margin[0] = 0;
- expand_margin[1] = 0;
- expand_margin[2] = 0;
- expand_margin[3] = 0;
-
- corner_radius[0] = 0;
- corner_radius[1] = 0;
- corner_radius[2] = 0;
- corner_radius[3] = 0;
-}
-
-StyleBoxFlat::~StyleBoxFlat() {
-}
+StyleBoxFlat::~StyleBoxFlat() {}
void StyleBoxLine::set_color(const Color &p_color) {
color = p_color;
@@ -986,8 +944,17 @@ void StyleBoxLine::_bind_methods() {
}
float StyleBoxLine::get_style_margin(Side p_side) const {
- ERR_FAIL_INDEX_V((int)p_side, 4, thickness);
- return thickness;
+ ERR_FAIL_INDEX_V((int)p_side, 4, 0);
+
+ if (vertical) {
+ if (p_side == SIDE_LEFT || p_side == SIDE_RIGHT) {
+ return thickness / 2.0;
+ }
+ } else if (p_side == SIDE_TOP || p_side == SIDE_BOTTOM) {
+ return thickness / 2.0;
+ }
+
+ return 0;
}
Size2 StyleBoxLine::get_center_size() const {
@@ -1011,12 +978,6 @@ void StyleBoxLine::draw(RID p_canvas_item, const Rect2 &p_rect) const {
vs->canvas_item_add_rect(p_canvas_item, r, color);
}
-StyleBoxLine::StyleBoxLine() {
- grow_begin = 1.0;
- grow_end = 1.0;
- thickness = 1;
- color = Color(0.0, 0.0, 0.0);
- vertical = false;
-}
+StyleBoxLine::StyleBoxLine() {}
StyleBoxLine::~StyleBoxLine() {}
diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h
index c133f0c825..dd5c873a00 100644
--- a/scene/resources/style_box.h
+++ b/scene/resources/style_box.h
@@ -86,14 +86,14 @@ public:
};
private:
- float expand_margin[4];
- float margin[4];
+ float expand_margin[4] = {};
+ float margin[4] = {};
Rect2 region_rect;
Ref<Texture2D> texture;
- bool draw_center;
- Color modulate;
- AxisStretchMode axis_h;
- AxisStretchMode axis_v;
+ bool draw_center = true;
+ Color modulate = Color(1, 1, 1, 1);
+ AxisStretchMode axis_h = AXIS_STRETCH_MODE_STRETCH;
+ AxisStretchMode axis_v = AXIS_STRETCH_MODE_STRETCH;
protected:
virtual float get_style_margin(Side p_side) const override;
@@ -139,26 +139,27 @@ VARIANT_ENUM_CAST(StyleBoxTexture::AxisStretchMode)
class StyleBoxFlat : public StyleBox {
GDCLASS(StyleBoxFlat, StyleBox);
- Color bg_color;
- Color shadow_color;
- Color border_color;
+ Color bg_color = Color(0.6, 0.6, 0.6);
+ Color shadow_color = Color(0, 0, 0, 0.6);
+ Color border_color = Color(0.8, 0.8, 0.8);
- int border_width[4];
- int expand_margin[4];
- int corner_radius[4];
+ int border_width[4] = {};
+ int expand_margin[4] = {};
+ int corner_radius[4] = {};
- bool draw_center;
- bool blend_border;
- bool anti_aliased;
+ bool draw_center = true;
+ bool blend_border = false;
+ bool anti_aliased = true;
- int corner_detail;
- int shadow_size;
+ int corner_detail = 8;
+ int shadow_size = 0;
Point2 shadow_offset;
- int aa_size;
+ int aa_size = 1;
protected:
virtual float get_style_margin(Side p_side) const override;
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const override;
public:
//Color
@@ -231,10 +232,10 @@ public:
class StyleBoxLine : public StyleBox {
GDCLASS(StyleBoxLine, StyleBox);
Color color;
- int thickness;
- bool vertical;
- float grow_begin;
- float grow_end;
+ int thickness = 1;
+ bool vertical = false;
+ float grow_begin = 1.0;
+ float grow_end = 1.0;
protected:
virtual float get_style_margin(Side p_side) const override;
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index dbf5268762..3d3900ecc5 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -160,7 +160,7 @@ void SurfaceTool::add_vertex(const Vector3 &p_vertex) {
//cap
weights.resize(expected_vertices);
//renormalize
- float total = 0;
+ float total = 0.0;
for (int i = 0; i < expected_vertices; i++) {
total += weights[i].weight;
}
@@ -299,6 +299,7 @@ void SurfaceTool::add_triangle_fan(const Vector<Vector3> &p_vertices, const Vect
void SurfaceTool::add_index(int p_index) {
ERR_FAIL_COND(!begun);
+ ERR_FAIL_COND(p_index < 0);
format |= Mesh::ARRAY_FORMAT_INDEX;
index_array.push_back(p_index);
@@ -1058,6 +1059,10 @@ void SurfaceTool::set_material(const Ref<Material> &p_material) {
material = p_material;
}
+Ref<Material> SurfaceTool::get_material() const {
+ return material;
+}
+
void SurfaceTool::clear() {
begun = false;
primitive = Mesh::PRIMITIVE_LINES;
@@ -1087,6 +1092,10 @@ void SurfaceTool::set_custom_format(int p_index, CustomFormat p_format) {
ERR_FAIL_COND(begun);
last_custom_format[p_index] = p_format;
}
+
+Mesh::PrimitiveType SurfaceTool::get_primitive() const {
+ return primitive;
+}
SurfaceTool::CustomFormat SurfaceTool::get_custom_format(int p_index) const {
ERR_FAIL_INDEX_V(p_index, RS::ARRAY_CUSTOM_COUNT, CUSTOM_MAX);
return last_custom_format[p_index];
@@ -1173,6 +1182,7 @@ void SurfaceTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("generate_lod", "nd_threshold", "target_index_count"), &SurfaceTool::generate_lod, DEFVAL(3));
ClassDB::bind_method(D_METHOD("set_material", "material"), &SurfaceTool::set_material);
+ ClassDB::bind_method(D_METHOD("get_primitive"), &SurfaceTool::get_primitive);
ClassDB::bind_method(D_METHOD("clear"), &SurfaceTool::clear);
@@ -1196,12 +1206,7 @@ void SurfaceTool::_bind_methods() {
}
SurfaceTool::SurfaceTool() {
- first = false;
- begun = false;
for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
last_custom_format[i] = CUSTOM_MAX;
}
- primitive = Mesh::PRIMITIVE_LINES;
- skin_weights = SKIN_4_WEIGHTS;
- format = 0;
}
diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h
index ea6069e7c1..28addf2245 100644
--- a/scene/resources/surface_tool.h
+++ b/scene/resources/surface_tool.h
@@ -89,17 +89,17 @@ private:
};
struct WeightSort {
- int index;
- float weight;
+ int index = 0;
+ float weight = 0.0;
bool operator<(const WeightSort &p_right) const {
return weight < p_right.weight;
}
};
- bool begun;
- bool first;
- Mesh::PrimitiveType primitive;
- uint32_t format;
+ bool begun = false;
+ bool first = false;
+ Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_LINES;
+ uint32_t format = 0;
Ref<Material> material;
//arrays
LocalVector<Vertex> vertex_array;
@@ -115,7 +115,7 @@ private:
Plane last_tangent;
uint32_t last_smooth_group = 0;
- SkinWeightCount skin_weights;
+ SkinWeightCount skin_weights = SKIN_4_WEIGHTS;
Color last_custom[RS::ARRAY_CUSTOM_COUNT];
@@ -143,6 +143,8 @@ public:
void set_custom_format(int p_index, CustomFormat p_format);
CustomFormat get_custom_format(int p_index) const;
+ Mesh::PrimitiveType get_primitive() const;
+
void begin(Mesh::PrimitiveType p_primitive);
void set_color(Color p_color);
@@ -171,6 +173,7 @@ public:
Vector<int> generate_lod(float p_threshold, int p_target_index_count = 3);
void set_material(const Ref<Material> &p_material);
+ Ref<Material> get_material() const;
void clear();
diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp
index f3f881a774..9dd00849f4 100644
--- a/scene/resources/syntax_highlighter.cpp
+++ b/scene/resources/syntax_highlighter.cpp
@@ -110,16 +110,13 @@ TextEdit *SyntaxHighlighter::get_text_edit() {
}
void SyntaxHighlighter::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_line_syntax_highlighting", "p_line"), &SyntaxHighlighter::get_line_syntax_highlighting);
+ ClassDB::bind_method(D_METHOD("get_line_syntax_highlighting", "line"), &SyntaxHighlighter::get_line_syntax_highlighting);
ClassDB::bind_method(D_METHOD("update_cache"), &SyntaxHighlighter::update_cache);
ClassDB::bind_method(D_METHOD("clear_highlighting_cache"), &SyntaxHighlighter::clear_highlighting_cache);
ClassDB::bind_method(D_METHOD("get_text_edit"), &SyntaxHighlighter::get_text_edit);
- ClassDB::bind_method(D_METHOD("_get_line_syntax_highlighting", "p_line"), &SyntaxHighlighter::_get_line_syntax_highlighting);
- ClassDB::bind_method(D_METHOD("_update_cache"), &SyntaxHighlighter::_update_cache);
- ClassDB::bind_method(D_METHOD("_clear_highlighting_cache"), &SyntaxHighlighter::_clear_highlighting_cache);
-
- BIND_VMETHOD(MethodInfo(Variant::DICTIONARY, "_get_line_syntax_highlighting", PropertyInfo(Variant::INT, "p_line")));
+ BIND_VMETHOD(MethodInfo(Variant::DICTIONARY, "_get_line_syntax_highlighting", PropertyInfo(Variant::INT, "line")));
+ BIND_VMETHOD(MethodInfo("_clear_highlighting_cache"));
BIND_VMETHOD(MethodInfo("_update_cache"));
}
@@ -576,11 +573,11 @@ void CodeHighlighter::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_member_keyword_colors"), &CodeHighlighter::clear_member_keyword_colors);
ClassDB::bind_method(D_METHOD("get_member_keyword_colors"), &CodeHighlighter::get_member_keyword_colors);
- ClassDB::bind_method(D_METHOD("add_color_region", "p_start_key", "p_end_key", "p_color", "p_line_only"), &CodeHighlighter::add_color_region, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("remove_color_region", "p_start_key"), &CodeHighlighter::remove_color_region);
- ClassDB::bind_method(D_METHOD("has_color_region", "p_start_key"), &CodeHighlighter::has_color_region);
+ ClassDB::bind_method(D_METHOD("add_color_region", "start_key", "end_key", "color", "line_only"), &CodeHighlighter::add_color_region, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("remove_color_region", "start_key"), &CodeHighlighter::remove_color_region);
+ ClassDB::bind_method(D_METHOD("has_color_region", "start_key"), &CodeHighlighter::has_color_region);
- ClassDB::bind_method(D_METHOD("set_color_regions", "p_color_regions"), &CodeHighlighter::set_color_regions);
+ ClassDB::bind_method(D_METHOD("set_color_regions", "color_regions"), &CodeHighlighter::set_color_regions);
ClassDB::bind_method(D_METHOD("clear_color_regions"), &CodeHighlighter::clear_color_regions);
ClassDB::bind_method(D_METHOD("get_color_regions"), &CodeHighlighter::get_color_regions);
diff --git a/scene/resources/syntax_highlighter.h b/scene/resources/syntax_highlighter.h
index c9db8e31a2..f3964b0c8f 100644
--- a/scene/resources/syntax_highlighter.h
+++ b/scene/resources/syntax_highlighter.h
@@ -75,7 +75,7 @@ private:
Color color;
String start_key;
String end_key;
- bool line_only;
+ bool line_only = false;
};
Vector<ColorRegion> color_regions;
Map<int, int> color_region_cache;
diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp
index ed69c093cf..925867a1f2 100644
--- a/scene/resources/text_line.cpp
+++ b/scene/resources/text_line.cpp
@@ -167,6 +167,7 @@ void TextLine::set_bidi_override(const Vector<Vector2i> &p_override) {
}
bool TextLine::add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language) {
+ ERR_FAIL_COND_V(p_fonts.is_null(), false);
bool res = TS->shaped_text_add_string(rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language);
spacing_top = p_fonts->get_spacing(Font::SPACING_TOP);
spacing_bottom = p_fonts->get_spacing(Font::SPACING_BOTTOM);
diff --git a/scene/resources/text_line.h b/scene/resources/text_line.h
index 3e0a74a84b..74d4f2c32c 100644
--- a/scene/resources/text_line.h
+++ b/scene/resources/text_line.h
@@ -45,7 +45,7 @@ class TextLine : public Reference {
bool dirty = true;
- float width = -1;
+ float width = -1.0;
uint8_t flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA;
HAlign align = HALIGN_LEFT;
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index 94957df510..444a4bb22a 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -243,6 +243,7 @@ TextServer::Orientation TextParagraph::get_orientation() const {
}
bool TextParagraph::set_dropcap(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Rect2 &p_dropcap_margins, const Dictionary &p_opentype_features, const String &p_language) {
+ ERR_FAIL_COND_V(p_fonts.is_null(), false);
TS->shaped_text_clear(dropcap_rid);
dropcap_margins = p_dropcap_margins;
bool res = TS->shaped_text_add_string(dropcap_rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language);
@@ -257,6 +258,7 @@ void TextParagraph::clear_dropcap() {
}
bool TextParagraph::add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language) {
+ ERR_FAIL_COND_V(p_fonts.is_null(), false);
bool res = TS->shaped_text_add_string(rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language);
spacing_top = p_fonts->get_spacing(Font::SPACING_TOP);
spacing_bottom = p_fonts->get_spacing(Font::SPACING_BOTTOM);
diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h
index e58c157b01..a16fa8c3c4 100644
--- a/scene/resources/text_paragraph.h
+++ b/scene/resources/text_paragraph.h
@@ -50,7 +50,7 @@ class TextParagraph : public Reference {
bool dirty_lines = true;
- float width = -1;
+ float width = -1.0;
uint8_t flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA;
HAlign align = HALIGN_LEFT;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 9a987ae8b1..d2bb1338d8 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -94,7 +94,7 @@ void ImageTexture::reload_from_file() {
create_from_image(img);
} else {
Resource::reload_from_file();
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
}
@@ -146,12 +146,12 @@ void ImageTexture::_reload_hook(const RID &p_hook) {
RID new_texture = RenderingServer::get_singleton()->texture_2d_create(img);
RenderingServer::get_singleton()->texture_replace(texture, new_texture);
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
void ImageTexture::create_from_image(const Ref<Image> &p_image) {
- ERR_FAIL_COND_MSG(p_image.is_null(), "Invalid image");
+ ERR_FAIL_COND_MSG(p_image.is_null() || p_image->is_empty(), "Invalid image");
w = p_image->get_width();
h = p_image->get_height();
format = p_image->get_format();
@@ -163,7 +163,7 @@ void ImageTexture::create_from_image(const Ref<Image> &p_image) {
RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_image);
RenderingServer::get_singleton()->texture_replace(texture, new_texture);
}
- _change_notify();
+ notify_property_list_changed();
emit_changed();
image_stored = true;
@@ -189,7 +189,7 @@ void ImageTexture::update(const Ref<Image> &p_image, bool p_immediate) {
RenderingServer::get_singleton()->texture_2d_update(texture, p_image);
}
- _change_notify();
+ notify_property_list_changed();
emit_changed();
alpha_cache.unref();
@@ -310,12 +310,7 @@ void ImageTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("_reload_hook", "rid"), &ImageTexture::_reload_hook);
}
-ImageTexture::ImageTexture() {
- w = h = 0;
- image_stored = false;
- mipmaps = false;
- format = Image::FORMAT_L8;
-}
+ImageTexture::ImageTexture() {}
ImageTexture::~ImageTexture() {
if (texture.is_valid()) {
@@ -617,7 +612,7 @@ Error StreamTexture2D::load(const String &p_path) {
}
#endif
- _change_notify();
+ notify_property_list_changed();
emit_changed();
return OK;
}
@@ -733,11 +728,7 @@ void StreamTexture2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path");
}
-StreamTexture2D::StreamTexture2D() {
- format = Image::FORMAT_MAX;
- w = 0;
- h = 0;
-}
+StreamTexture2D::StreamTexture2D() {}
StreamTexture2D::~StreamTexture2D() {
if (texture.is_valid()) {
@@ -745,7 +736,7 @@ StreamTexture2D::~StreamTexture2D() {
}
}
-RES ResourceFormatLoaderStreamTexture2D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderStreamTexture2D::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<StreamTexture2D> st;
st.instance();
Error err = st->load(p_path);
@@ -968,7 +959,7 @@ Error StreamTexture3D::load(const String &p_path) {
RenderingServer::get_singleton()->texture_set_path(texture, p_path);
}
- _change_notify();
+ notify_property_list_changed();
emit_changed();
return OK;
}
@@ -1033,13 +1024,7 @@ void StreamTexture3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path");
}
-StreamTexture3D::StreamTexture3D() {
- format = Image::FORMAT_MAX;
- w = 0;
- h = 0;
- d = 0;
- mipmaps = false;
-}
+StreamTexture3D::StreamTexture3D() {}
StreamTexture3D::~StreamTexture3D() {
if (texture.is_valid()) {
@@ -1049,7 +1034,7 @@ StreamTexture3D::~StreamTexture3D() {
/////////////////////////////
-RES ResourceFormatLoaderStreamTexture3D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderStreamTexture3D::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<StreamTexture3D> st;
st.instance();
Error err = st->load(p_path);
@@ -1125,7 +1110,6 @@ void AtlasTexture::set_atlas(const Ref<Texture2D> &p_atlas) {
}
atlas = p_atlas;
emit_changed();
- _change_notify("atlas");
}
Ref<Texture2D> AtlasTexture::get_atlas() const {
@@ -1138,7 +1122,6 @@ void AtlasTexture::set_region(const Rect2 &p_region) {
}
region = p_region;
emit_changed();
- _change_notify("region");
}
Rect2 AtlasTexture::get_region() const {
@@ -1151,7 +1134,6 @@ void AtlasTexture::set_margin(const Rect2 &p_margin) {
}
margin = p_margin;
emit_changed();
- _change_notify("margin");
}
Rect2 AtlasTexture::get_margin() const {
@@ -1161,7 +1143,6 @@ Rect2 AtlasTexture::get_margin() const {
void AtlasTexture::set_filter_clip(const bool p_enable) {
filter_clip = p_enable;
emit_changed();
- _change_notify("filter_clip");
}
bool AtlasTexture::has_filter_clip() const {
@@ -1295,9 +1276,7 @@ bool AtlasTexture::is_pixel_opaque(int p_x, int p_y) const {
return atlas->is_pixel_opaque(x, y);
}
-AtlasTexture::AtlasTexture() {
- filter_clip = false;
-}
+AtlasTexture::AtlasTexture() {}
/////////////////////////////////////////
@@ -1698,9 +1677,7 @@ RID CurveTexture::get_rid() const {
return _texture;
}
-CurveTexture::CurveTexture() {
- _width = 2048;
-}
+CurveTexture::CurveTexture() {}
CurveTexture::~CurveTexture() {
if (_texture.is_valid()) {
@@ -1711,9 +1688,6 @@ CurveTexture::~CurveTexture() {
//////////////////
GradientTexture::GradientTexture() {
- update_pending = false;
- width = 2048;
-
_queue_update();
}
@@ -1926,7 +1900,7 @@ void AnimatedTexture::_update_proxy() {
}
}
time -= frame_limit;
- _change_notify("current_frame");
+
} else {
break;
}
@@ -2128,13 +2102,6 @@ AnimatedTexture::AnimatedTexture() {
proxy = RS::get_singleton()->texture_proxy_create(proxy_ph);
RenderingServer::get_singleton()->texture_set_force_redraw_if_visible(proxy, true);
- time = 0;
- frame_count = 1;
- fps = 4;
- prev_ticks = 0;
- current_frame = 0;
- pause = false;
- oneshot = false;
RenderingServer::get_singleton()->connect("frame_pre_draw", callable_mp(this, &AnimatedTexture::_update_proxy));
}
@@ -2288,11 +2255,6 @@ void ImageTextureLayered::_bind_methods() {
ImageTextureLayered::ImageTextureLayered(LayeredType p_layered_type) {
layered_type = p_layered_type;
- format = Image::FORMAT_MAX;
-
- width = 0;
- height = 0;
- layers = 0;
}
ImageTextureLayered::~ImageTextureLayered() {
@@ -2389,7 +2351,7 @@ Error StreamTextureLayered::load(const String &p_path) {
RenderingServer::get_singleton()->texture_set_path(texture, p_path);
}
- _change_notify();
+ notify_property_list_changed();
emit_changed();
return OK;
}
@@ -2460,11 +2422,6 @@ void StreamTextureLayered::_bind_methods() {
StreamTextureLayered::StreamTextureLayered(LayeredType p_type) {
layered_type = p_type;
- format = Image::FORMAT_MAX;
- w = 0;
- h = 0;
- layers = 0;
- mipmaps = false;
}
StreamTextureLayered::~StreamTextureLayered() {
@@ -2475,7 +2432,7 @@ StreamTextureLayered::~StreamTextureLayered() {
/////////////////////////////////////////////////
-RES ResourceFormatLoaderStreamTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
+RES ResourceFormatLoaderStreamTextureLayered::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<StreamTextureLayered> st;
if (p_path.get_extension().to_lower() == "stexarray") {
Ref<StreamTexture2DArray> s;
@@ -2593,7 +2550,7 @@ Ref<Image> CameraTexture::get_data() const {
void CameraTexture::set_camera_feed_id(int p_new_id) {
camera_feed_id = p_new_id;
- _change_notify();
+ notify_property_list_changed();
}
int CameraTexture::get_camera_feed_id() const {
@@ -2602,7 +2559,7 @@ int CameraTexture::get_camera_feed_id() const {
void CameraTexture::set_which_feed(CameraServer::FeedImage p_which) {
which_feed = p_which;
- _change_notify();
+ notify_property_list_changed();
}
CameraServer::FeedImage CameraTexture::get_which_feed() const {
@@ -2613,7 +2570,7 @@ void CameraTexture::set_camera_active(bool p_active) {
Ref<CameraFeed> feed = CameraServer::get_singleton()->get_feed_by_id(camera_feed_id);
if (feed.is_valid()) {
feed->set_active(p_active);
- _change_notify();
+ notify_property_list_changed();
}
}
@@ -2626,10 +2583,7 @@ bool CameraTexture::get_camera_active() const {
}
}
-CameraTexture::CameraTexture() {
- camera_feed_id = 0;
- which_feed = CameraServer::FEED_RGBA_IMAGE;
-}
+CameraTexture::CameraTexture() {}
CameraTexture::~CameraTexture() {
// nothing to do here yet
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 83ef0c44ae..a0d917fd86 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -83,12 +83,13 @@ class ImageTexture : public Texture2D {
RES_BASE_EXTENSION("tex");
mutable RID texture;
- Image::Format format;
- bool mipmaps;
- int w, h;
+ Image::Format format = Image::FORMAT_L8;
+ bool mipmaps = false;
+ int w = 0;
+ int h = 0;
Size2 size_override;
mutable Ref<BitMap> alpha_cache;
- bool image_stored;
+ bool image_stored = false;
protected:
virtual void reload_from_file() override;
@@ -160,8 +161,9 @@ private:
Error _load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit = 0);
String path_to_file;
mutable RID texture;
- Image::Format format;
- int w, h;
+ Image::Format format = Image::FORMAT_MAX;
+ int w = 0;
+ int h = 0;
mutable Ref<BitMap> alpha_cache;
virtual void reload_from_file() override;
@@ -209,7 +211,7 @@ public:
class ResourceFormatLoaderStreamTexture2D : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
@@ -223,7 +225,7 @@ protected:
Ref<Texture2D> atlas;
Rect2 region;
Rect2 margin;
- bool filter_clip;
+ bool filter_clip = false;
static void _bind_methods();
@@ -370,12 +372,12 @@ class ImageTextureLayered : public TextureLayered {
LayeredType layered_type;
mutable RID texture;
- Image::Format format;
+ Image::Format format = Image::FORMAT_MAX;
- int width;
- int height;
- int layers;
- bool mipmaps;
+ int width = 0;
+ int height = 0;
+ int layers = 0;
+ bool mipmaps = false;
Error _create_from_images(const Array &p_images);
@@ -453,10 +455,12 @@ private:
Error _load_data(const String &p_path, Vector<Ref<Image>> &images, int &mipmap_limit, int p_size_limit = 0);
String path_to_file;
mutable RID texture;
- Image::Format format;
- int w, h, layers;
- bool mipmaps;
- LayeredType layered_type;
+ Image::Format format = Image::FORMAT_MAX;
+ int w = 0;
+ int h = 0;
+ int layers = 0;
+ bool mipmaps = false;
+ LayeredType layered_type = LayeredType::LAYERED_TYPE_2D_ARRAY;
virtual void reload_from_file() override;
@@ -509,7 +513,7 @@ public:
class ResourceFormatLoaderStreamTextureLayered : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
@@ -594,9 +598,11 @@ private:
Error _load_data(const String &p_path, Vector<Ref<Image>> &r_data, Image::Format &r_format, int &r_width, int &r_height, int &r_depth, bool &r_mipmaps);
String path_to_file;
mutable RID texture;
- Image::Format format;
- int w, h, d;
- bool mipmaps;
+ Image::Format format = Image::FORMAT_MAX;
+ int w = 0;
+ int h = 0;
+ int d = 0;
+ bool mipmaps = false;
virtual void reload_from_file() override;
@@ -625,7 +631,7 @@ public:
class ResourceFormatLoaderStreamTexture3D : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
@@ -638,7 +644,7 @@ class CurveTexture : public Texture2D {
private:
mutable RID _texture;
Ref<Curve> _curve;
- int _width;
+ int _width = 2048;
void _update();
@@ -680,7 +686,7 @@ class GradientTexture : public Texture2D {
public:
struct Point {
- float offset;
+ float offset = 0.0;
Color color;
bool operator<(const Point &p_ponit) const {
return offset < p_ponit.offset;
@@ -689,9 +695,9 @@ public:
private:
Ref<Gradient> gradient;
- bool update_pending;
+ bool update_pending = false;
RID texture;
- int width;
+ int width = 2048;
void _queue_update();
void _update();
@@ -758,23 +764,19 @@ private:
struct Frame {
Ref<Texture2D> texture;
- float delay_sec;
-
- Frame() {
- delay_sec = 0;
- }
+ float delay_sec = 0.0;
};
Frame frames[MAX_FRAMES];
- int frame_count;
- int current_frame;
- bool pause;
- bool oneshot;
- float fps;
+ int frame_count = 1.0;
+ int current_frame = 0;
+ bool pause = false;
+ bool oneshot = false;
+ float fps = 4.0;
- float time;
+ float time = 0.0;
- uint64_t prev_ticks;
+ uint64_t prev_ticks = 0;
void _update_proxy();
@@ -822,8 +824,8 @@ class CameraTexture : public Texture2D {
GDCLASS(CameraTexture, Texture2D);
private:
- int camera_feed_id;
- CameraServer::FeedImage which_feed;
+ int camera_feed_id = 0;
+ CameraServer::FeedImage which_feed = CameraServer::FEED_RGBA_IMAGE;
protected:
static void _bind_methods();
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index 5279f59d77..0405ea98bb 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -358,7 +358,7 @@ void Theme::set_default_theme_font(const Ref<Font> &p_default_font) {
default_theme_font->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED);
}
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -373,7 +373,7 @@ void Theme::set_default_theme_font_size(int p_font_size) {
default_theme_font_size = p_font_size;
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -436,7 +436,7 @@ void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, co
}
if (new_value) {
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
}
@@ -463,7 +463,7 @@ void Theme::clear_icon(const StringName &p_name, const StringName &p_node_type)
icon_map[p_node_type].erase(p_name);
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -506,7 +506,7 @@ void Theme::set_stylebox(const StringName &p_name, const StringName &p_node_type
}
if (new_value) {
- _change_notify();
+ notify_property_list_changed();
}
emit_changed();
}
@@ -533,7 +533,7 @@ void Theme::clear_stylebox(const StringName &p_name, const StringName &p_node_ty
style_map[p_node_type].erase(p_name);
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -576,7 +576,7 @@ void Theme::set_font(const StringName &p_name, const StringName &p_node_type, co
}
if (new_value) {
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
}
@@ -604,7 +604,7 @@ void Theme::clear_font(const StringName &p_name, const StringName &p_node_type)
}
font_map[p_node_type].erase(p_name);
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -637,7 +637,7 @@ void Theme::set_font_size(const StringName &p_name, const StringName &p_node_typ
font_size_map[p_node_type][p_name] = p_font_size;
if (new_value) {
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
}
@@ -661,7 +661,7 @@ void Theme::clear_font_size(const StringName &p_name, const StringName &p_node_t
ERR_FAIL_COND(!font_size_map[p_node_type].has(p_name));
font_size_map[p_node_type].erase(p_name);
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -685,7 +685,7 @@ void Theme::set_color(const StringName &p_name, const StringName &p_node_type, c
color_map[p_node_type][p_name] = p_color;
if (new_value) {
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
}
@@ -707,7 +707,7 @@ void Theme::clear_color(const StringName &p_name, const StringName &p_node_type)
ERR_FAIL_COND(!color_map[p_node_type].has(p_name));
color_map[p_node_type].erase(p_name);
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -739,7 +739,7 @@ void Theme::set_constant(const StringName &p_name, const StringName &p_node_type
constant_map[p_node_type][p_name] = p_constant;
if (new_value) {
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
}
@@ -761,7 +761,7 @@ void Theme::clear_constant(const StringName &p_name, const StringName &p_node_ty
ERR_FAIL_COND(!constant_map[p_node_type].has(p_name));
constant_map[p_node_type].erase(p_name);
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -835,7 +835,7 @@ void Theme::clear() {
color_map.clear();
constant_map.clear();
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -887,7 +887,7 @@ void Theme::copy_theme(const Ref<Theme> &p_other) {
color_map = p_other->color_map;
constant_map = p_other->constant_map;
- _change_notify();
+ notify_property_list_changed();
emit_changed();
}
@@ -930,6 +930,9 @@ void Theme::get_type_list(List<StringName> *p_list) const {
}
}
+void Theme::reset_state() {
+ clear();
+}
void Theme::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_icon", "name", "node_type", "texture"), &Theme::set_icon);
ClassDB::bind_method(D_METHOD("get_icon", "name", "node_type"), &Theme::get_icon);
diff --git a/scene/resources/theme.h b/scene/resources/theme.h
index c802ba2536..35481126ea 100644
--- a/scene/resources/theme.h
+++ b/scene/resources/theme.h
@@ -80,6 +80,8 @@ protected:
static void _bind_methods();
+ virtual void reset_state() override;
+
public:
static Ref<Theme> get_default();
static void set_default(const Ref<Theme> &p_default);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index ae536a2928..84be69d0d6 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -369,14 +369,14 @@ void TileSet::create_tile(int p_id) {
ERR_FAIL_COND(tile_map.has(p_id));
tile_map[p_id] = TileData();
tile_map[p_id].autotile_data = AutotileData();
- _change_notify("");
+ notify_property_list_changed();
emit_changed();
}
void TileSet::autotile_set_bitmask_mode(int p_id, BitmaskMode p_mode) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].autotile_data.bitmask_mode = p_mode;
- _change_notify("");
+ notify_property_list_changed();
emit_changed();
}
@@ -389,7 +389,6 @@ void TileSet::tile_set_texture(int p_id, const Ref<Texture2D> &p_texture) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].texture = p_texture;
emit_changed();
- _change_notify("texture");
}
Ref<Texture2D> TileSet::tile_get_texture(int p_id) const {
@@ -412,7 +411,6 @@ void TileSet::tile_set_modulate(int p_id, const Color &p_modulate) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].modulate = p_modulate;
emit_changed();
- _change_notify("modulate");
}
Color TileSet::tile_get_modulate(int p_id) const {
@@ -435,7 +433,6 @@ void TileSet::tile_set_region(int p_id, const Rect2 &p_region) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].region = p_region;
emit_changed();
- _change_notify("region");
}
Rect2 TileSet::tile_get_region(int p_id) const {
@@ -447,7 +444,6 @@ void TileSet::tile_set_tile_mode(int p_id, TileMode p_tile_mode) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].tile_mode = p_tile_mode;
emit_changed();
- _change_notify("tile_mode");
}
TileSet::TileMode TileSet::tile_get_tile_mode(int p_id) const {
@@ -669,7 +665,6 @@ void TileSet::tile_set_name(int p_id, const String &p_name) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].name = p_name;
emit_changed();
- _change_notify("name");
}
String TileSet::tile_get_name(int p_id) const {
@@ -1060,7 +1055,7 @@ bool TileSet::is_tile_bound(int p_drawn_id, int p_neighbor_id) {
void TileSet::remove_tile(int p_id) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map.erase(p_id);
- _change_notify("");
+ notify_property_list_changed();
emit_changed();
}
@@ -1081,9 +1076,13 @@ int TileSet::find_tile_by_name(const String &p_name) const {
return -1;
}
+void TileSet::reset_state() {
+ clear();
+}
+
void TileSet::clear() {
tile_map.clear();
- _change_notify("");
+ notify_property_list_changed();
emit_changed();
}
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 210520350f..0a8721f35b 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -136,6 +136,8 @@ protected:
static void _bind_methods();
+ virtual void reset_state() override;
+
public:
void create_tile(int p_id);
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 72724d5ee1..859546694f 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -585,6 +585,12 @@ bool VisualShader::is_port_types_compatible(int p_a, int p_b) const {
void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
ERR_FAIL_INDEX(p_type, TYPE_MAX);
Graph *g = &graph[p_type];
+
+ ERR_FAIL_COND(!g->nodes.has(p_from_node));
+ ERR_FAIL_INDEX(p_from_port, g->nodes[p_from_node].node->get_output_port_count());
+ ERR_FAIL_COND(!g->nodes.has(p_to_node));
+ ERR_FAIL_INDEX(p_to_port, g->nodes[p_to_node].node->get_input_port_count());
+
Connection c;
c.from_node = p_from_node;
c.from_port = p_from_port;
@@ -675,6 +681,8 @@ void VisualShader::get_node_connections(Type p_type, List<Connection> *r_connect
}
void VisualShader::set_mode(Mode p_mode) {
+ ERR_FAIL_INDEX_MSG(p_mode, Mode::MODE_MAX, vformat("Invalid shader mode: %d.", p_mode));
+
if (shader_mode == p_mode) {
return;
}
@@ -730,7 +738,7 @@ void VisualShader::set_mode(Mode p_mode) {
}
_queue_update();
- _change_notify();
+ notify_property_list_changed();
}
void VisualShader::set_graph_offset(const Vector2 &p_offset) {
@@ -1095,6 +1103,12 @@ bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const {
return false;
}
+void VisualShader::reset_state() {
+#ifndef _MSC_VER
+#warning everything needs to be cleared here
+#endif
+ emit_changed();
+}
void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
//mode
p_list->push_back(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Node3D,CanvasItem,Particles,Sky"));
@@ -1392,11 +1406,11 @@ bool VisualShader::has_func_name(RenderingServer::ShaderMode p_mode, const Strin
}
void VisualShader::_update_shader() const {
- if (!dirty) {
+ if (!dirty.is_set()) {
return;
}
- dirty = false;
+ dirty.clear();
StringBuilder global_code;
StringBuilder global_code_per_node;
@@ -1582,15 +1596,16 @@ void VisualShader::_update_shader() const {
}
void VisualShader::_queue_update() {
- if (dirty) {
+ if (dirty.is_set()) {
return;
}
- dirty = true;
+ dirty.set();
call_deferred("_update_shader");
}
void VisualShader::_input_type_changed(Type p_type, int p_id) {
+ ERR_FAIL_INDEX(p_type, TYPE_MAX);
//erase connections using this input, as type changed
Graph *g = &graph[p_type];
@@ -1605,7 +1620,7 @@ void VisualShader::_input_type_changed(Type p_type, int p_id) {
}
void VisualShader::rebuild() {
- dirty = true;
+ dirty.set();
_update_shader();
}
@@ -1659,6 +1674,7 @@ void VisualShader::_bind_methods() {
}
VisualShader::VisualShader() {
+ dirty.set();
for (int i = 0; i < TYPE_MAX; i++) {
Ref<VisualShaderNodeOutput> output;
output.instance();
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index 9396a53e8b..ef724c7650 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -32,6 +32,7 @@
#define VISUAL_SHADER_H
#include "core/string/string_builder.h"
+#include "core/templates/safe_refcount.h"
#include "scene/gui/control.h"
#include "scene/resources/shader.h"
@@ -57,10 +58,10 @@ public:
};
struct Connection {
- int from_node;
- int from_port;
- int to_node;
- int to_port;
+ int from_node = 0;
+ int from_port = 0;
+ int to_node = 0;
+ int to_port = 0;
};
struct DefaultTextureParam {
@@ -90,7 +91,7 @@ private:
Vector2 graph_offset;
struct RenderModeEnums {
- Shader::Mode mode;
+ Shader::Mode mode = Shader::Mode::MODE_MAX;
const char *string;
};
@@ -99,7 +100,7 @@ private:
static RenderModeEnums render_mode_enums[];
- volatile mutable bool dirty = true;
+ mutable SafeFlag dirty;
void _queue_update();
union ConnectionKey {
@@ -107,7 +108,7 @@ private:
uint64_t node : 32;
uint64_t port : 32;
};
- uint64_t key;
+ uint64_t key = 0;
bool operator<(const ConnectionKey &p_key) const {
return key < p_key.key;
}
@@ -126,6 +127,8 @@ protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ virtual void reset_state() override;
+
public: // internal methods
void set_shader_type(Type p_type);
Type get_shader_type() const;
@@ -265,7 +268,7 @@ class VisualShaderNodeCustom : public VisualShaderNode {
struct Port {
String name;
- int type;
+ int type = 0;
};
List<Port> input_ports;
@@ -305,9 +308,9 @@ class VisualShaderNodeInput : public VisualShaderNode {
Shader::Mode shader_mode = Shader::MODE_MAX;
struct Port {
- Shader::Mode mode;
- VisualShader::Type shader_type;
- PortType type;
+ Shader::Mode mode = Shader::Mode::MODE_MAX;
+ VisualShader::Type shader_type = VisualShader::Type::TYPE_MAX;
+ PortType type = PortType::PORT_TYPE_MAX;
const char *name;
const char *string;
};
@@ -356,13 +359,13 @@ class VisualShaderNodeOutput : public VisualShaderNode {
public:
friend class VisualShader;
- VisualShader::Type shader_type;
- Shader::Mode shader_mode;
+ VisualShader::Type shader_type = VisualShader::Type::TYPE_MAX;
+ Shader::Mode shader_mode = Shader::Mode::MODE_MAX;
struct Port {
- Shader::Mode mode;
- VisualShader::Type shader_type;
- PortType type;
+ Shader::Mode mode = Shader::Mode::MODE_MAX;
+ VisualShader::Type shader_type = VisualShader::Type::TYPE_MAX;
+ PortType type = PortType::PORT_TYPE_MAX;
const char *name;
const char *string;
};
@@ -519,7 +522,7 @@ protected:
bool editable = false;
struct Port {
- PortType type;
+ PortType type = PortType::PORT_TYPE_MAX;
String name;
};
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index d6200059f6..a99c09e89c 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -2742,8 +2742,6 @@ int VisualShaderNodeClamp::get_input_port_count() const {
VisualShaderNodeClamp::PortType VisualShaderNodeClamp::get_input_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_FLOAT:
- return PORT_TYPE_SCALAR;
case OP_TYPE_INT:
return PORT_TYPE_SCALAR_INT;
case OP_TYPE_VECTOR:
@@ -2771,8 +2769,6 @@ int VisualShaderNodeClamp::get_output_port_count() const {
VisualShaderNodeClamp::PortType VisualShaderNodeClamp::get_output_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_FLOAT:
- return PORT_TYPE_SCALAR;
case OP_TYPE_INT:
return PORT_TYPE_SCALAR_INT;
case OP_TYPE_VECTOR:
@@ -2954,18 +2950,11 @@ int VisualShaderNodeStep::get_input_port_count() const {
VisualShaderNodeStep::PortType VisualShaderNodeStep::get_input_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_SCALAR:
- return PORT_TYPE_SCALAR;
case OP_TYPE_VECTOR:
return PORT_TYPE_VECTOR;
case OP_TYPE_VECTOR_SCALAR:
- switch (p_port) {
- case 0:
- return PORT_TYPE_SCALAR;
- case 1:
- return PORT_TYPE_VECTOR;
- default:
- break;
+ if (p_port == 1) {
+ return PORT_TYPE_VECTOR;
}
break;
default:
@@ -2989,8 +2978,6 @@ int VisualShaderNodeStep::get_output_port_count() const {
VisualShaderNodeStep::PortType VisualShaderNodeStep::get_output_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_SCALAR:
- return PORT_TYPE_SCALAR;
case OP_TYPE_VECTOR:
return PORT_TYPE_VECTOR;
case OP_TYPE_VECTOR_SCALAR:
@@ -3032,7 +3019,7 @@ void VisualShaderNodeStep::set_op_type(OpType p_op_type) {
set_input_port_default_value(0, 0.0); // edge
}
if (op_type == OP_TYPE_SCALAR) {
- set_input_port_default_value(1, 0.0); // x
+ set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // x
}
break;
default:
@@ -3085,20 +3072,11 @@ int VisualShaderNodeSmoothStep::get_input_port_count() const {
VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_input_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_SCALAR:
- return PORT_TYPE_SCALAR;
case OP_TYPE_VECTOR:
return PORT_TYPE_VECTOR;
case OP_TYPE_VECTOR_SCALAR:
- switch (p_port) {
- case 0:
- return PORT_TYPE_SCALAR; // edge0
- case 1:
- return PORT_TYPE_SCALAR; // edge1
- case 2:
- return PORT_TYPE_VECTOR; // x
- default:
- break;
+ if (p_port == 2) {
+ return PORT_TYPE_VECTOR; // x
}
break;
default:
@@ -3124,8 +3102,6 @@ int VisualShaderNodeSmoothStep::get_output_port_count() const {
VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_output_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_SCALAR:
- return PORT_TYPE_SCALAR;
case OP_TYPE_VECTOR:
return PORT_TYPE_VECTOR;
case OP_TYPE_VECTOR_SCALAR:
@@ -3319,16 +3295,11 @@ int VisualShaderNodeMix::get_input_port_count() const {
VisualShaderNodeMix::PortType VisualShaderNodeMix::get_input_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_SCALAR:
- return PORT_TYPE_SCALAR;
case OP_TYPE_VECTOR:
- if (p_port == 2) {
- return PORT_TYPE_VECTOR;
- }
return PORT_TYPE_VECTOR;
case OP_TYPE_VECTOR_SCALAR:
if (p_port == 2) {
- return PORT_TYPE_SCALAR;
+ break;
}
return PORT_TYPE_VECTOR;
default:
@@ -3353,8 +3324,6 @@ int VisualShaderNodeMix::get_output_port_count() const {
VisualShaderNodeMix::PortType VisualShaderNodeMix::get_output_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_SCALAR:
- return PORT_TYPE_SCALAR;
case OP_TYPE_VECTOR:
return PORT_TYPE_VECTOR;
case OP_TYPE_VECTOR_SCALAR:
@@ -4540,9 +4509,7 @@ int VisualShaderNodeTextureUniformTriplanar::get_input_port_count() const {
}
VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniformTriplanar::get_input_port_type(int p_port) const {
- if (p_port == 0) {
- return PORT_TYPE_VECTOR;
- } else if (p_port == 1) {
+ if (p_port == 0 || p_port == 1) {
return PORT_TYPE_VECTOR;
}
return PORT_TYPE_SCALAR;
@@ -4923,8 +4890,6 @@ VisualShaderNodeSwitch::PortType VisualShaderNodeSwitch::get_input_port_type(int
}
if (p_port == 1 || p_port == 2) {
switch (op_type) {
- case OP_TYPE_FLOAT:
- return PORT_TYPE_SCALAR;
case OP_TYPE_INT:
return PORT_TYPE_SCALAR_INT;
case OP_TYPE_VECTOR:
@@ -4959,8 +4924,6 @@ int VisualShaderNodeSwitch::get_output_port_count() const {
VisualShaderNodeSwitch::PortType VisualShaderNodeSwitch::get_output_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_FLOAT:
- return PORT_TYPE_SCALAR;
case OP_TYPE_INT:
return PORT_TYPE_SCALAR_INT;
case OP_TYPE_VECTOR:
@@ -5238,9 +5201,6 @@ int VisualShaderNodeCompare::get_input_port_count() const {
}
VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_input_port_type(int p_port) const {
- if (p_port == 2) {
- return PORT_TYPE_SCALAR;
- }
switch (ctype) {
case CTYPE_SCALAR:
return PORT_TYPE_SCALAR;
@@ -5252,8 +5212,9 @@ VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_input_port_type(i
return PORT_TYPE_BOOLEAN;
case CTYPE_TRANSFORM:
return PORT_TYPE_TRANSFORM;
+ default:
+ return PORT_TYPE_SCALAR;
}
- return PORT_TYPE_VECTOR;
}
String VisualShaderNodeCompare::get_input_port_name(int p_port) const {
@@ -5472,10 +5433,10 @@ int VisualShaderNodeMultiplyAdd::get_input_port_count() const {
}
VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_input_port_type(int p_port) const {
- if (op_type == OP_TYPE_SCALAR) {
- return PORT_TYPE_SCALAR;
+ if (op_type == OP_TYPE_VECTOR) {
+ return PORT_TYPE_VECTOR;
}
- return PORT_TYPE_VECTOR;
+ return PORT_TYPE_SCALAR;
}
String VisualShaderNodeMultiplyAdd::get_input_port_name(int p_port) const {
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index cadbd93fed..ccdc5bebd0 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -34,12 +34,13 @@
#include "scene/2d/camera_2d.h"
#include "scene/2d/visibility_notifier_2d.h"
#include "scene/main/window.h"
+#include "servers/navigation_server_2d.h"
#include "servers/physics_server_2d.h"
#include "servers/rendering_server.h"
struct SpatialIndexer2D {
struct CellRef {
- int ref;
+ int ref = 0;
_FORCE_INLINE_ int inc() {
ref++;
@@ -49,10 +50,6 @@ struct SpatialIndexer2D {
ref--;
return ref;
}
-
- _FORCE_INLINE_ CellRef() {
- ref = 0;
- }
};
struct CellKey {
@@ -61,7 +58,7 @@ struct SpatialIndexer2D {
int32_t x;
int32_t y;
};
- uint64_t key;
+ uint64_t key = 0;
};
bool operator==(const CellKey &p_key) const { return key == p_key.key; }
@@ -86,9 +83,9 @@ struct SpatialIndexer2D {
Map<Viewport *, ViewportData> viewports;
- bool changed;
+ bool changed = false;
- uint64_t pass;
+ uint64_t pass = 0;
void _notifier_update_cells(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect, bool p_add) {
Point2i begin = p_rect.position;
@@ -287,8 +284,6 @@ struct SpatialIndexer2D {
}
SpatialIndexer2D() {
- pass = 0;
- changed = false;
cell_size = GLOBAL_DEF("world/2d/cell_size", 100);
}
};
@@ -321,14 +316,18 @@ void World2D::_update() {
indexer->_update();
}
-RID World2D::get_canvas() {
+RID World2D::get_canvas() const {
return canvas;
}
-RID World2D::get_space() {
+RID World2D::get_space() const {
return space;
}
+RID World2D::get_navigation_map() const {
+ return navigation_map;
+}
+
void World2D::get_viewport_list(List<Viewport *> *r_viewports) {
for (Map<Viewport *, SpatialIndexer2D::ViewportData>::Element *E = indexer->viewports.front(); E; E = E->next()) {
r_viewports->push_back(E->key());
@@ -338,11 +337,13 @@ void World2D::get_viewport_list(List<Viewport *> *r_viewports) {
void World2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_canvas"), &World2D::get_canvas);
ClassDB::bind_method(D_METHOD("get_space"), &World2D::get_space);
+ ClassDB::bind_method(D_METHOD("get_navigation_map"), &World2D::get_navigation_map);
ClassDB::bind_method(D_METHOD("get_direct_space_state"), &World2D::get_direct_space_state);
ADD_PROPERTY(PropertyInfo(Variant::RID, "canvas", PROPERTY_HINT_NONE, "", 0), "", "get_canvas");
ADD_PROPERTY(PropertyInfo(Variant::RID, "space", PROPERTY_HINT_NONE, "", 0), "", "get_space");
+ ADD_PROPERTY(PropertyInfo(Variant::RID, "navigation_map", PROPERTY_HINT_NONE, "", 0), "", "get_navigation_map");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectSpaceState2D", 0), "", "get_direct_space_state");
}
@@ -352,9 +353,9 @@ PhysicsDirectSpaceState2D *World2D::get_direct_space_state() {
World2D::World2D() {
canvas = RenderingServer::get_singleton()->canvas_create();
- space = PhysicsServer2D::get_singleton()->space_create();
- //set space2D to be more friendly with pixels than meters, by adjusting some constants
+ // Create and configure space2D to be more friendly with pixels than meters
+ space = PhysicsServer2D::get_singleton()->space_create();
PhysicsServer2D::get_singleton()->space_set_active(space, true);
PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 98));
PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/2d/default_gravity_vector", Vector2(0, 1)));
@@ -362,11 +363,19 @@ World2D::World2D() {
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/2d/default_angular_damp", 1.0));
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
+
+ // Create and configure the navigation_map to be more friendly with pixels than meters.
+ navigation_map = NavigationServer2D::get_singleton()->map_create();
+ NavigationServer2D::get_singleton()->map_set_active(navigation_map, true);
+ NavigationServer2D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/2d/default_cell_size", 10));
+ NavigationServer2D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/2d/default_edge_connection_margin", 5));
+
indexer = memnew(SpatialIndexer2D);
}
World2D::~World2D() {
RenderingServer::get_singleton()->free(canvas);
PhysicsServer2D::get_singleton()->free(space);
+ NavigationServer2D::get_singleton()->free(navigation_map);
memdelete(indexer);
}
diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h
index ae13367421..38abf3d7ad 100644
--- a/scene/resources/world_2d.h
+++ b/scene/resources/world_2d.h
@@ -44,6 +44,7 @@ class World2D : public Resource {
RID canvas;
RID space;
+ RID navigation_map;
SpatialIndexer2D *indexer;
@@ -63,8 +64,9 @@ protected:
void _update();
public:
- RID get_canvas();
- RID get_space();
+ RID get_canvas() const;
+ RID get_space() const;
+ RID get_navigation_map() const;
PhysicsDirectSpaceState2D *get_direct_space_state();
diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp
index 9c0317454b..0e9f7a6cf2 100644
--- a/scene/resources/world_3d.cpp
+++ b/scene/resources/world_3d.cpp
@@ -35,6 +35,7 @@
#include "scene/3d/camera_3d.h"
#include "scene/3d/visibility_notifier_3d.h"
#include "scene/scene_string_names.h"
+#include "servers/navigation_server_3d.h"
struct SpatialIndexer {
Octree<VisibilityNotifier3D> octree;
@@ -243,6 +244,10 @@ RID World3D::get_space() const {
return space;
}
+RID World3D::get_navigation_map() const {
+ return navigation_map;
+}
+
RID World3D::get_scenario() const {
return scenario;
}
@@ -310,6 +315,7 @@ void World3D::get_camera_list(List<Camera3D *> *r_cameras) {
void World3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_space"), &World3D::get_space);
+ ClassDB::bind_method(D_METHOD("get_navigation_map"), &World3D::get_navigation_map);
ClassDB::bind_method(D_METHOD("get_scenario"), &World3D::get_scenario);
ClassDB::bind_method(D_METHOD("set_environment", "env"), &World3D::set_environment);
ClassDB::bind_method(D_METHOD("get_environment"), &World3D::get_environment);
@@ -322,6 +328,7 @@ void World3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_fallback_environment", "get_fallback_environment");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_camera_effects", "get_camera_effects");
ADD_PROPERTY(PropertyInfo(Variant::RID, "space", PROPERTY_HINT_NONE, "", 0), "", "get_space");
+ ADD_PROPERTY(PropertyInfo(Variant::RID, "navigation_map", PROPERTY_HINT_NONE, "", 0), "", "get_navigation_map");
ADD_PROPERTY(PropertyInfo(Variant::RID, "scenario", PROPERTY_HINT_NONE, "", 0), "", "get_scenario");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectSpaceState3D", 0), "", "get_direct_space_state");
}
@@ -338,6 +345,11 @@ World3D::World3D() {
PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/3d/default_angular_damp", 0.1));
ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
+ navigation_map = NavigationServer3D::get_singleton()->map_create();
+ NavigationServer3D::get_singleton()->map_set_active(navigation_map, true);
+ NavigationServer3D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/3d/default_cell_size", 0.3));
+ NavigationServer3D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/3d/default_edge_connection_margin", 5.0)); // Five meters, depends a lot on the agent's radius
+
#ifdef _3D_DISABLED
indexer = nullptr;
#else
@@ -348,6 +360,7 @@ World3D::World3D() {
World3D::~World3D() {
PhysicsServer3D::get_singleton()->free(space);
RenderingServer::get_singleton()->free(scenario);
+ NavigationServer3D::get_singleton()->free(navigation_map);
#ifndef _3D_DISABLED
memdelete(indexer);
diff --git a/scene/resources/world_3d.h b/scene/resources/world_3d.h
index 3d6c33997e..4e2717a2bb 100644
--- a/scene/resources/world_3d.h
+++ b/scene/resources/world_3d.h
@@ -46,6 +46,7 @@ class World3D : public Resource {
private:
RID space;
+ RID navigation_map;
RID scenario;
SpatialIndexer *indexer;
Ref<Environment> environment;
@@ -70,6 +71,7 @@ protected:
public:
RID get_space() const;
+ RID get_navigation_map() const;
RID get_scenario() const;
void set_environment(const Ref<Environment> &p_environment);
diff --git a/scene/resources/world_margin_shape_3d.cpp b/scene/resources/world_margin_shape_3d.cpp
index 79cbb3bbe0..28d50e1921 100644
--- a/scene/resources/world_margin_shape_3d.cpp
+++ b/scene/resources/world_margin_shape_3d.cpp
@@ -69,7 +69,6 @@ void WorldMarginShape3D::set_plane(Plane p_plane) {
plane = p_plane;
_update_shape();
notify_change_to_owners();
- _change_notify("plane");
}
Plane WorldMarginShape3D::get_plane() const {
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index faddced155..a28dcb1015 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -39,11 +39,11 @@ Error AudioDriverDummy::init() {
exit_thread = false;
samples_in = nullptr;
- mix_rate = GLOBAL_GET("audio/mix_rate");
+ mix_rate = GLOBAL_GET("audio/driver/mix_rate");
speaker_mode = SPEAKER_MODE_STEREO;
channels = 2;
- int latency = GLOBAL_GET("audio/output_latency");
+ int latency = GLOBAL_GET("audio/driver/output_latency");
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
samples_in = memnew_arr(int32_t, buffer_frames * channels);
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
index efdcb916ed..3c8a1469cd 100644
--- a/servers/audio/audio_rb_resampler.cpp
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -131,7 +131,7 @@ bool AudioRBResampler::mix(AudioFrame *p_dest, int p_frames) {
src_read = read_space;
}
- rb_read_pos = (rb_read_pos + src_read) & rb_mask;
+ rb_read_pos.set((rb_read_pos.get() + src_read) & rb_mask);
// Create fadeout effect for the end of stream (note that it can be because of slow writer)
if (p_frames - target_todo > 0) {
@@ -183,8 +183,8 @@ Error AudioRBResampler::setup(int p_channels, int p_src_mix_rate, int p_target_m
src_mix_rate = p_src_mix_rate;
target_mix_rate = p_target_mix_rate;
offset = 0;
- rb_read_pos = 0;
- rb_write_pos = 0;
+ rb_read_pos.set(0);
+ rb_write_pos.set(0);
//avoid maybe strange noises upon load
for (unsigned int i = 0; i < (rb_len * channels); i++) {
@@ -205,8 +205,8 @@ void AudioRBResampler::clear() {
memdelete_arr(read_buf);
rb = nullptr;
offset = 0;
- rb_read_pos = 0;
- rb_write_pos = 0;
+ rb_read_pos.set(0);
+ rb_write_pos.set(0);
read_buf = nullptr;
}
@@ -214,8 +214,8 @@ AudioRBResampler::AudioRBResampler() {
rb = nullptr;
offset = 0;
read_buf = nullptr;
- rb_read_pos = 0;
- rb_write_pos = 0;
+ rb_read_pos.set(0);
+ rb_write_pos.set(0);
rb_bits = 0;
rb_len = 0;
diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h
index 7b74e3a2a1..c0f981704b 100644
--- a/servers/audio/audio_rb_resampler.h
+++ b/servers/audio/audio_rb_resampler.h
@@ -32,6 +32,7 @@
#define AUDIO_RB_RESAMPLER_H
#include "core/os/memory.h"
+#include "core/templates/safe_refcount.h"
#include "core/typedefs.h"
#include "servers/audio_server.h"
@@ -44,8 +45,8 @@ struct AudioRBResampler {
uint32_t src_mix_rate;
uint32_t target_mix_rate;
- volatile int rb_read_pos;
- volatile int rb_write_pos;
+ SafeNumeric<int> rb_read_pos;
+ SafeNumeric<int> rb_write_pos;
int32_t offset; //contains the fractional remainder of the resampler
enum {
@@ -62,8 +63,8 @@ struct AudioRBResampler {
public:
_FORCE_INLINE_ void flush() {
- rb_read_pos = 0;
- rb_write_pos = 0;
+ rb_read_pos.set(0);
+ rb_write_pos.set(0);
offset = 0;
}
@@ -78,8 +79,8 @@ public:
_FORCE_INLINE_ int get_writer_space() const {
int space, r, w;
- r = rb_read_pos;
- w = rb_write_pos;
+ r = rb_read_pos.get();
+ w = rb_write_pos.get();
if (r == w) {
space = rb_len - 1;
@@ -95,8 +96,8 @@ public:
_FORCE_INLINE_ int get_reader_space() const {
int space, r, w;
- r = rb_read_pos;
- w = rb_write_pos;
+ r = rb_read_pos.get();
+ w = rb_write_pos.get();
if (r == w) {
space = 0;
@@ -110,48 +111,52 @@ public:
}
_FORCE_INLINE_ bool has_data() const {
- return rb && rb_read_pos != rb_write_pos;
+ return rb && rb_read_pos.get() != rb_write_pos.get();
}
_FORCE_INLINE_ float *get_write_buffer() { return read_buf; }
_FORCE_INLINE_ void write(uint32_t p_frames) {
ERR_FAIL_COND(p_frames >= rb_len);
+ int wp = rb_write_pos.get();
+
switch (channels) {
case 1: {
for (uint32_t i = 0; i < p_frames; i++) {
- rb[rb_write_pos] = read_buf[i];
- rb_write_pos = (rb_write_pos + 1) & rb_mask;
+ rb[wp] = read_buf[i];
+ wp = (wp + 1) & rb_mask;
}
} break;
case 2: {
for (uint32_t i = 0; i < p_frames; i++) {
- rb[(rb_write_pos << 1) + 0] = read_buf[(i << 1) + 0];
- rb[(rb_write_pos << 1) + 1] = read_buf[(i << 1) + 1];
- rb_write_pos = (rb_write_pos + 1) & rb_mask;
+ rb[(wp << 1) + 0] = read_buf[(i << 1) + 0];
+ rb[(wp << 1) + 1] = read_buf[(i << 1) + 1];
+ wp = (wp + 1) & rb_mask;
}
} break;
case 4: {
for (uint32_t i = 0; i < p_frames; i++) {
- rb[(rb_write_pos << 2) + 0] = read_buf[(i << 2) + 0];
- rb[(rb_write_pos << 2) + 1] = read_buf[(i << 2) + 1];
- rb[(rb_write_pos << 2) + 2] = read_buf[(i << 2) + 2];
- rb[(rb_write_pos << 2) + 3] = read_buf[(i << 2) + 3];
- rb_write_pos = (rb_write_pos + 1) & rb_mask;
+ rb[(wp << 2) + 0] = read_buf[(i << 2) + 0];
+ rb[(wp << 2) + 1] = read_buf[(i << 2) + 1];
+ rb[(wp << 2) + 2] = read_buf[(i << 2) + 2];
+ rb[(wp << 2) + 3] = read_buf[(i << 2) + 3];
+ wp = (wp + 1) & rb_mask;
}
} break;
case 6: {
for (uint32_t i = 0; i < p_frames; i++) {
- rb[(rb_write_pos * 6) + 0] = read_buf[(i * 6) + 0];
- rb[(rb_write_pos * 6) + 1] = read_buf[(i * 6) + 1];
- rb[(rb_write_pos * 6) + 2] = read_buf[(i * 6) + 2];
- rb[(rb_write_pos * 6) + 3] = read_buf[(i * 6) + 3];
- rb[(rb_write_pos * 6) + 4] = read_buf[(i * 6) + 4];
- rb[(rb_write_pos * 6) + 5] = read_buf[(i * 6) + 5];
- rb_write_pos = (rb_write_pos + 1) & rb_mask;
+ rb[(wp * 6) + 0] = read_buf[(i * 6) + 0];
+ rb[(wp * 6) + 1] = read_buf[(i * 6) + 1];
+ rb[(wp * 6) + 2] = read_buf[(i * 6) + 2];
+ rb[(wp * 6) + 3] = read_buf[(i * 6) + 3];
+ rb[(wp * 6) + 4] = read_buf[(i * 6) + 4];
+ rb[(wp * 6) + 5] = read_buf[(i * 6) + 5];
+ wp = (wp + 1) & rb_mask;
}
} break;
}
+
+ rb_write_pos.set(wp);
}
int get_channel_count() const;
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 91fce5d34e..ae07f999ed 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -54,21 +54,21 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
for (int i = 0; i < p_frames; i++) {
uint32_t idx = CUBIC_INTERP_HISTORY + uint32_t(mix_offset >> FP_BITS);
- //standard cubic interpolation (great quality/performance ratio)
- //this used to be moved to a LUT for greater performance, but nowadays CPU speed is generally faster than memory.
+ // 4 point, 4th order optimal resampling algorithm from: http://yehar.com/blog/wp-content/uploads/2009/08/deip.pdf
float mu = (mix_offset & FP_MASK) / float(FP_LEN);
AudioFrame y0 = internal_buffer[idx - 3];
AudioFrame y1 = internal_buffer[idx - 2];
AudioFrame y2 = internal_buffer[idx - 1];
AudioFrame y3 = internal_buffer[idx - 0];
- float mu2 = mu * mu;
- AudioFrame a0 = y3 - y2 - y0 + y1;
- AudioFrame a1 = y0 - y1 - a0;
- AudioFrame a2 = y2 - y0;
- AudioFrame a3 = y1;
-
- p_buffer[i] = (a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3);
+ AudioFrame even1 = y2 + y1, odd1 = y2 - y1;
+ AudioFrame even2 = y3 + y0, odd2 = y3 - y0;
+ AudioFrame c0 = even1 * 0.46835497211269561 + even2 * 0.03164502784253309;
+ AudioFrame c1 = odd1 * 0.56001293337091440 + odd2 * 0.14666238593949288;
+ AudioFrame c2 = even1 * -0.250038759826233691 + even2 * 0.25003876124297131;
+ AudioFrame c3 = odd1 * -0.49949850957839148 + odd2 * 0.16649935475113800;
+ AudioFrame c4 = even1 * 0.00016095224137360 + even2 * -0.00016095810460478;
+ p_buffer[i] = (((c4 * mu + c3) * mu + c2) * mu + c1) * mu + c0;
mix_offset += mix_increment;
@@ -184,7 +184,7 @@ void AudioStreamPlaybackMicrophone::start(float p_from_pos) {
return;
}
- if (!GLOBAL_GET("audio/enable_audio_input")) {
+ if (!GLOBAL_GET("audio/driver/enable_input")) {
WARN_PRINT("Need to enable Project settings > Audio > Enable Audio Input option to use capturing.");
return;
}
diff --git a/servers/audio/effects/audio_effect_capture.cpp b/servers/audio/effects/audio_effect_capture.cpp
index f37938eec8..78837c7531 100644
--- a/servers/audio/effects/audio_effect_capture.cpp
+++ b/servers/audio/effects/audio_effect_capture.cpp
@@ -91,8 +91,6 @@ Ref<AudioEffectInstance> AudioEffectCapture::instance() {
}
void AudioEffectCapture::set_buffer_length(float p_buffer_length_seconds) {
- ERR_FAIL_COND(buffer_initialized);
-
buffer_length_seconds = p_buffer_length_seconds;
}
@@ -106,7 +104,7 @@ int AudioEffectCapture::get_frames_available() const {
}
int64_t AudioEffectCapture::get_discarded_frames() const {
- return discarded_frames;
+ return discarded_frames.get();
}
int AudioEffectCapture::get_buffer_length_frames() const {
@@ -115,7 +113,7 @@ int AudioEffectCapture::get_buffer_length_frames() const {
}
int64_t AudioEffectCapture::get_pushed_frames() const {
- return pushed_frames;
+ return pushed_frames.get();
}
void AudioEffectCaptureInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
@@ -129,9 +127,9 @@ void AudioEffectCaptureInstance::process(const AudioFrame *p_src_frames, AudioFr
// Add incoming audio frames to the IO ring buffer
int32_t ret = buffer.write(p_src_frames, p_frame_count);
ERR_FAIL_COND_MSG(ret != p_frame_count, "Failed to add data to effect capture ring buffer despite sufficient space.");
- atomic_add(&base->pushed_frames, p_frame_count);
+ base->pushed_frames.add(p_frame_count);
} else {
- atomic_add(&base->discarded_frames, p_frame_count);
+ base->discarded_frames.add(p_frame_count);
}
}
diff --git a/servers/audio/effects/audio_effect_capture.h b/servers/audio/effects/audio_effect_capture.h
index b154be85de..81d4ed6b0f 100644
--- a/servers/audio/effects/audio_effect_capture.h
+++ b/servers/audio/effects/audio_effect_capture.h
@@ -55,8 +55,8 @@ class AudioEffectCapture : public AudioEffect {
friend class AudioEffectCaptureInstance;
RingBuffer<AudioFrame> buffer;
- uint64_t discarded_frames = 0;
- uint64_t pushed_frames = 0;
+ SafeNumeric<uint64_t> discarded_frames;
+ SafeNumeric<uint64_t> pushed_frames;
float buffer_length_seconds = 0.1f;
bool buffer_initialized = false;
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
index 76a995eb37..eb2268aa2e 100644
--- a/servers/audio/effects/audio_effect_chorus.cpp
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -309,7 +309,7 @@ void AudioEffectChorus::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_dry", "amount"), &AudioEffectChorus::set_dry);
ClassDB::bind_method(D_METHOD("get_dry"), &AudioEffectChorus::get_dry);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "voice_count", PROPERTY_HINT_RANGE, "1,4,1"), "set_voice_count", "get_voice_count");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "voice_count", PROPERTY_HINT_RANGE, "1,4,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_voice_count", "get_voice_count");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dry", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dry", "get_dry");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wet", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_wet", "get_wet");
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
index b79434e7c2..06d51776a3 100644
--- a/servers/audio/effects/audio_effect_distortion.cpp
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -58,7 +58,8 @@ void AudioEffectDistortionInstance::process(const AudioFrame *p_src_frames, Audi
switch (base->mode) {
case AudioEffectDistortion::MODE_CLIP: {
- a = powf(a, 1.0001 - drive_f);
+ float a_sign = a < 0 ? -1.0f : 1.0f;
+ a = powf(abs(a), 1.0001 - drive_f) * a_sign;
if (a > 1.0) {
a = 1.0;
} else if (a < (-1.0)) {
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 16c6a26595..138cb6e1f8 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -188,10 +188,10 @@ int AudioDriverManager::get_driver_count() {
}
void AudioDriverManager::initialize(int p_driver) {
- GLOBAL_DEF_RST("audio/enable_audio_input", false);
- GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
- GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
- GLOBAL_DEF_RST("audio/output_latency.web", 50); // Safer default output_latency for web.
+ GLOBAL_DEF_RST("audio/driver/enable_input", false);
+ GLOBAL_DEF_RST("audio/driver/mix_rate", DEFAULT_MIX_RATE);
+ GLOBAL_DEF_RST("audio/driver/output_latency", DEFAULT_OUTPUT_LATENCY);
+ GLOBAL_DEF_RST("audio/driver/output_latency.web", 50); // Safer default output_latency for web.
int failed_driver = -1;
@@ -939,9 +939,9 @@ void AudioServer::init_channels_and_buffers() {
}
void AudioServer::init() {
- channel_disable_threshold_db = GLOBAL_DEF_RST("audio/channel_disable_threshold_db", -60.0);
- channel_disable_frames = float(GLOBAL_DEF_RST("audio/channel_disable_time", 2.0)) * get_mix_rate();
- ProjectSettings::get_singleton()->set_custom_property_info("audio/channel_disable_time", PropertyInfo(Variant::FLOAT, "audio/channel_disable_time", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
+ channel_disable_threshold_db = GLOBAL_DEF_RST("audio/buses/channel_disable_threshold_db", -60.0);
+ channel_disable_frames = float(GLOBAL_DEF_RST("audio/buses/channel_disable_time", 2.0)) * get_mix_rate();
+ ProjectSettings::get_singleton()->set_custom_property_info("audio/buses/channel_disable_time", PropertyInfo(Variant::FLOAT, "audio/buses/channel_disable_time", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
buffer_size = 1024; //hardcoded for now
init_channels_and_buffers();
@@ -958,7 +958,7 @@ void AudioServer::init() {
set_edited(false); //avoid editors from thinking this was edited
#endif
- GLOBAL_DEF_RST("audio/video_delay_compensation_ms", 0);
+ GLOBAL_DEF_RST("audio/video/video_delay_compensation_ms", 0);
}
void AudioServer::update() {
@@ -1035,7 +1035,7 @@ void AudioServer::update() {
}
void AudioServer::load_default_bus_layout() {
- String layout_path = ProjectSettings::get_singleton()->get("audio/default_bus_layout");
+ String layout_path = ProjectSettings::get_singleton()->get("audio/buses/default_bus_layout");
if (ResourceLoader::exists(layout_path)) {
Ref<AudioBusLayout> default_layout = ResourceLoader::load(layout_path);
diff --git a/servers/camera/camera_feed.cpp b/servers/camera/camera_feed.cpp
index be812cf62d..eab4c61591 100644
--- a/servers/camera/camera_feed.cpp
+++ b/servers/camera/camera_feed.cpp
@@ -184,9 +184,10 @@ CameraFeed::~CameraFeed() {
#endif
}
-void CameraFeed::set_RGB_img(Ref<Image> p_rgb_img) {
+void CameraFeed::set_RGB_img(const Ref<Image> &p_rgb_img) {
// FIXME: Disabled during Vulkan refactoring, should be ported.
#if 0
+ ERR_FAIL_COND(p_rgb_img.is_null());
if (active) {
RenderingServer *vs = RenderingServer::get_singleton();
@@ -207,9 +208,10 @@ void CameraFeed::set_RGB_img(Ref<Image> p_rgb_img) {
#endif
}
-void CameraFeed::set_YCbCr_img(Ref<Image> p_ycbcr_img) {
+void CameraFeed::set_YCbCr_img(const Ref<Image> &p_ycbcr_img) {
// FIXME: Disabled during Vulkan refactoring, should be ported.
#if 0
+ ERR_FAIL_COND(p_ycbcr_img.is_null());
if (active) {
RenderingServer *vs = RenderingServer::get_singleton();
@@ -230,9 +232,11 @@ void CameraFeed::set_YCbCr_img(Ref<Image> p_ycbcr_img) {
#endif
}
-void CameraFeed::set_YCbCr_imgs(Ref<Image> p_y_img, Ref<Image> p_cbcr_img) {
+void CameraFeed::set_YCbCr_imgs(const Ref<Image> &p_y_img, const Ref<Image> &p_cbcr_img) {
// FIXME: Disabled during Vulkan refactoring, should be ported.
#if 0
+ ERR_FAIL_COND(p_y_img.is_null());
+ ERR_FAIL_COND(p_cbcr_img.is_null());
if (active) {
RenderingServer *vs = RenderingServer::get_singleton();
diff --git a/servers/camera/camera_feed.h b/servers/camera/camera_feed.h
index fc02af4249..eb4ef155bc 100644
--- a/servers/camera/camera_feed.h
+++ b/servers/camera/camera_feed.h
@@ -100,9 +100,9 @@ public:
virtual ~CameraFeed();
FeedDataType get_datatype() const;
- void set_RGB_img(Ref<Image> p_rgb_img);
- void set_YCbCr_img(Ref<Image> p_ycbcr_img);
- void set_YCbCr_imgs(Ref<Image> p_y_img, Ref<Image> p_cbcr_img);
+ void set_RGB_img(const Ref<Image> &p_rgb_img);
+ void set_YCbCr_img(const Ref<Image> &p_ycbcr_img);
+ void set_YCbCr_imgs(const Ref<Image> &p_y_img, const Ref<Image> &p_cbcr_img);
// FIXME: Disabled during Vulkan refactoring, should be ported.
#if 0
void allocate_texture(int p_width, int p_height, Image::Format p_format, RenderingServer::TextureType p_texture_type, FeedDataType p_data_type);
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 29c1c9fc60..2fa333cc05 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -477,7 +477,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("enable_for_stealing_focus", "process_id"), &DisplayServer::enable_for_stealing_focus);
- ClassDB::bind_method(D_METHOD("native_video_play", "path", "volume", "audio_track", "subtitle_track"), &DisplayServer::native_video_play);
+ ClassDB::bind_method(D_METHOD("native_video_play", "path", "volume", "audio_track", "subtitle_track", "screen"), &DisplayServer::native_video_play);
ClassDB::bind_method(D_METHOD("native_video_is_playing"), &DisplayServer::native_video_is_playing);
ClassDB::bind_method(D_METHOD("native_video_stop"), &DisplayServer::native_video_stop);
ClassDB::bind_method(D_METHOD("native_video_pause"), &DisplayServer::native_video_pause);
@@ -504,6 +504,11 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_native_icon", "filename"), &DisplayServer::set_native_icon);
ClassDB::bind_method(D_METHOD("set_icon", "image"), &DisplayServer::set_icon);
+ ClassDB::bind_method(D_METHOD("tablet_get_driver_count"), &DisplayServer::tablet_get_driver_count);
+ ClassDB::bind_method(D_METHOD("tablet_get_driver_name", "idx"), &DisplayServer::tablet_get_driver_name);
+ ClassDB::bind_method(D_METHOD("tablet_get_current_driver"), &DisplayServer::tablet_get_current_driver);
+ ClassDB::bind_method(D_METHOD("tablet_set_current_driver", "name"), &DisplayServer::tablet_set_current_driver);
+
BIND_ENUM_CONSTANT(FEATURE_GLOBAL_MENU);
BIND_ENUM_CONSTANT(FEATURE_SUBWINDOWS);
BIND_ENUM_CONSTANT(FEATURE_TOUCHSCREEN);
diff --git a/servers/display_server.h b/servers/display_server.h
index fc34a2a228..3aab572120 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -83,7 +83,7 @@ protected:
static DisplayServerCreate server_create_functions[MAX_SERVERS];
static int server_create_count;
- friend class RenderingServerDefault;
+ friend class RendererViewport;
virtual void _set_use_vsync(bool p_enable);
public:
@@ -340,6 +340,11 @@ public:
virtual String keyboard_get_layout_language(int p_index) const;
virtual String keyboard_get_layout_name(int p_index) const;
+ virtual int tablet_get_driver_count() const { return 1; };
+ virtual String tablet_get_driver_name(int p_driver) const { return "default"; };
+ virtual String tablet_get_current_driver() const { return "default"; };
+ virtual void tablet_set_current_driver(const String &p_driver){};
+
virtual void process_events() = 0;
virtual void force_process_and_drop_events();
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index df348d2add..9e32bc209b 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -80,6 +80,18 @@ NavigationServer2D *NavigationServer2D::singleton = nullptr;
return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3)); \
}
+#define FORWARD_5_R_C(CONV_R, FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, T_4, D_4, CONV_0, CONV_1, CONV_2, CONV_3, CONV_4) \
+ NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3, T_4 D_4) \
+ const { \
+ return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3), CONV_4(D_4))); \
+ }
+
+#define FORWARD_5_C(FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, T_4, D_4, CONV_0, CONV_1, CONV_2, CONV_3, CONV_4) \
+ NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3, T_4 D_4) \
+ const { \
+ return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3), CONV_4(D_4)); \
+ }
+
static RID rid_to_rid(const RID d) {
return d;
}
@@ -92,6 +104,10 @@ static int int_to_int(const int d) {
return d;
}
+static uint32_t uint32_to_uint32(const uint32_t d) {
+ return d;
+}
+
static real_t real_to_real(const real_t d) {
return d;
}
@@ -116,7 +132,8 @@ static Vector<Vector2> vector_v3_to_v2(const Vector<Vector3> &d) {
static Transform trf2_to_trf3(const Transform2D &d) {
Vector3 o(v2_to_v3(d.get_origin()));
Basis b;
- b.rotate(Vector3(0, 1, 0), d.get_rotation());
+ b.rotate(Vector3(0, -1, 0), d.get_rotation());
+ b.scale(v2_to_v3(d.get_scale()));
return Transform(b, o);
}
@@ -140,6 +157,10 @@ static Ref<NavigationMesh> poly_to_mesh(Ref<NavigationPolygon> d) {
}
}
+void NavigationServer2D::_emit_map_changed(RID p_map) {
+ emit_signal("map_changed", p_map);
+}
+
void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer2D::map_create);
ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer2D::map_set_active);
@@ -148,14 +169,19 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer2D::map_get_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize"), &NavigationServer2D::map_get_path);
+ ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer2D::map_get_path, DEFVAL(1));
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer2D::map_get_closest_point);
ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner);
ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer2D::region_create);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer2D::region_set_map);
+ ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer2D::region_set_layers);
+ ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer2D::region_get_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_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);
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map);
@@ -171,10 +197,14 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer2D::agent_set_callback, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("free", "object"), &NavigationServer2D::free);
+
+ ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
}
NavigationServer2D::NavigationServer2D() {
singleton = this;
+ ERR_FAIL_COND_MSG(!NavigationServer3D::get_singleton(), "The Navigation3D singleton should be initialized before the 2D one.");
+ NavigationServer3D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationServer2D::_emit_map_changed));
}
NavigationServer2D::~NavigationServer2D() {
@@ -193,20 +223,25 @@ real_t FORWARD_1_C(map_get_cell_size, RID, p_map, rid_to_rid);
void FORWARD_2_C(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin, rid_to_rid, real_to_real);
real_t FORWARD_1_C(map_get_edge_connection_margin, RID, p_map, rid_to_rid);
-Vector<Vector2> FORWARD_4_R_C(vector_v3_to_v2, map_get_path, RID, p_map, Vector2, p_origin, Vector2, p_destination, bool, p_optimize, rid_to_rid, v2_to_v3, v2_to_v3, bool_to_bool);
+Vector<Vector2> FORWARD_5_R_C(vector_v3_to_v2, map_get_path, RID, p_map, Vector2, p_origin, Vector2, p_destination, bool, p_optimize, uint32_t, p_layers, rid_to_rid, v2_to_v3, v2_to_v3, bool_to_bool, uint32_to_uint32);
Vector2 FORWARD_2_R_C(v3_to_v2, map_get_closest_point, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3);
RID FORWARD_2_C(map_get_closest_point_owner, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3);
RID FORWARD_0_C(region_create);
void FORWARD_2_C(region_set_map, RID, p_region, RID, p_map, rid_to_rid, rid_to_rid);
-
+void FORWARD_2_C(region_set_layers, RID, p_region, uint32_t, p_layers, rid_to_rid, uint32_to_uint32);
+uint32_t FORWARD_1_C(region_get_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));
}
+int FORWARD_1_C(region_get_connections_count, RID, p_region, rid_to_rid);
+Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_start, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int);
+Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_end, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int);
+
RID NavigationServer2D::agent_create() const {
RID agent = NavigationServer3D::get_singleton()->agent_create();
NavigationServer3D::get_singleton()->agent_set_ignore_y(agent, true);
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 7be5a74cb3..d56c719839 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -45,12 +45,14 @@ class NavigationServer2D : public Object {
static NavigationServer2D *singleton;
+ void _emit_map_changed(RID p_map);
+
protected:
static void _bind_methods();
public:
/// Thread safe, can be used across many threads.
- static const NavigationServer2D *get_singleton() { return singleton; }
+ static NavigationServer2D *get_singleton() { return singleton; }
/// MUST be used in single thread!
static NavigationServer2D *get_singleton_mut() { return singleton; }
@@ -77,7 +79,7 @@ public:
virtual real_t map_get_edge_connection_margin(RID p_map) const;
/// Returns the navigation path to reach the destination from the origin.
- virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize) const;
+ virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_layers = 1) const;
virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const;
virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const;
@@ -88,12 +90,21 @@ public:
/// Set the map of this region.
virtual void region_set_map(RID p_region, RID p_map) const;
+ /// Set the region's layers
+ virtual void region_set_layers(RID p_region, uint32_t p_layers) const;
+ virtual uint32_t region_get_layers(RID p_region) const;
+
/// Set the global transformation of this region.
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;
+ /// Get a list of a region's connection to other regions.
+ virtual int region_get_connections_count(RID p_region) const;
+ virtual Vector2 region_get_connection_pathway_start(RID p_region, int p_connection_id) const;
+ virtual Vector2 region_get_connection_pathway_end(RID p_region, int p_connection_id) const;
+
/// Creates the agent.
virtual RID agent_create() const;
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 0e5ae82b0d..b0047a250a 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -46,7 +46,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer3D::map_get_cell_size);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer3D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer3D::map_get_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize"), &NavigationServer3D::map_get_path);
+ ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer3D::map_get_path, DEFVAL(1));
ClassDB::bind_method(D_METHOD("map_get_closest_point_to_segment", "map", "start", "end", "use_collision"), &NavigationServer3D::map_get_closest_point_to_segment, DEFVAL(false));
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer3D::map_get_closest_point);
ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal);
@@ -54,9 +54,14 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer3D::region_create);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer3D::region_set_map);
+ ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer3D::region_set_layers);
+ ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer3D::region_get_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_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);
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map);
@@ -75,9 +80,11 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_active", "active"), &NavigationServer3D::set_active);
ClassDB::bind_method(D_METHOD("process", "delta_time"), &NavigationServer3D::process);
+
+ ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
}
-const NavigationServer3D *NavigationServer3D::get_singleton() {
+NavigationServer3D *NavigationServer3D::get_singleton() {
return singleton;
}
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 3761c3871a..420f9c9c18 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -55,7 +55,7 @@ protected:
public:
/// Thread safe, can be used across many threads.
- static const NavigationServer3D *get_singleton();
+ static NavigationServer3D *get_singleton();
/// MUST be used in single thread!
static NavigationServer3D *get_singleton_mut();
@@ -88,7 +88,7 @@ public:
virtual real_t map_get_edge_connection_margin(RID p_map) const = 0;
/// Returns the navigation path to reach the destination from the origin.
- virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const = 0;
+ virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigable_layers = 1) const = 0;
virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const = 0;
virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const = 0;
@@ -101,15 +101,24 @@ public:
/// Set the map of this region.
virtual void region_set_map(RID p_region, RID p_map) const = 0;
+ /// Set the region's layers
+ virtual void region_set_layers(RID p_region, uint32_t p_layers) const = 0;
+ virtual uint32_t region_get_layers(RID p_region) const = 0;
+
/// Set the global transformation of this region.
virtual void region_set_transform(RID p_region, Transform 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;
- /// Bake the navigation mesh
+ /// Bake the navigation mesh.
virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_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;
+ virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const = 0;
+ virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const = 0;
+
/// Creates the agent.
virtual RID agent_create() const = 0;
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index feced36a2b..da70ac7d4b 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -221,11 +221,21 @@ real_t combine_friction(Body2DSW *A, Body2DSW *B) {
bool BodyPair2DSW::setup(real_t p_step) {
//cannot collide
- if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) {
+ if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
collided = false;
return false;
}
+ bool report_contacts_only = false;
+ if ((A->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC) && (B->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC)) {
+ if ((A->get_max_contacts_reported() > 0) || (B->get_max_contacts_reported() > 0)) {
+ report_contacts_only = true;
+ } else {
+ collided = false;
+ return false;
+ }
+ }
+
if (A->is_shape_set_as_disabled(shape_A) || B->is_shape_set_as_disabled(shape_B)) {
collided = false;
return false;
@@ -350,51 +360,44 @@ bool BodyPair2DSW::setup(real_t p_step) {
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
+ c.active = false;
+
Vector2 global_A = xform_Au.xform(c.local_A);
Vector2 global_B = xform_Bu.xform(c.local_B);
real_t depth = c.normal.dot(global_A - global_B);
if (depth <= 0 || !c.reused) {
- c.active = false;
continue;
}
- c.active = true;
#ifdef DEBUG_ENABLED
if (space->is_debugging_contacts()) {
space->add_debug_contact(global_A + offset_A);
space->add_debug_contact(global_B + offset_A);
}
#endif
- int gather_A = A->can_report_contacts();
- int gather_B = B->can_report_contacts();
c.rA = global_A;
c.rB = global_B - offset_B;
- if (gather_A | gather_B) {
- //Vector2 crB( -B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x );
-
- global_A += offset_A;
- global_B += offset_A;
+ if (A->can_report_contacts()) {
+ Vector2 crB(-B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x);
+ A->add_contact(global_A + offset_A, -c.normal, depth, shape_A, global_B + offset_A, shape_B, B->get_instance_id(), B->get_self(), crB + B->get_linear_velocity());
+ }
- if (gather_A) {
- Vector2 crB(-B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x);
- A->add_contact(global_A, -c.normal, depth, shape_A, global_B, shape_B, B->get_instance_id(), B->get_self(), crB + B->get_linear_velocity());
- }
- if (gather_B) {
- Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x);
- B->add_contact(global_B, c.normal, depth, shape_B, global_A, shape_A, A->get_instance_id(), A->get_self(), crA + A->get_linear_velocity());
- }
+ if (B->can_report_contacts()) {
+ Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x);
+ B->add_contact(global_B + offset_A, c.normal, depth, shape_B, global_A + offset_A, shape_A, A->get_instance_id(), A->get_self(), crA + A->get_linear_velocity());
}
- if ((A->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC)) {
- c.active = false;
+ if (report_contacts_only) {
collided = false;
continue;
}
+ c.active = true;
+
// Precompute normal mass, tangent mass, and bias.
real_t rnA = c.rA.dot(c.normal);
real_t rnB = c.rB.dot(c.normal);
diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp
index 3558848dac..c7b556deba 100644
--- a/servers/physics_2d/joints_2d_sw.cpp
+++ b/servers/physics_2d/joints_2d_sw.cpp
@@ -55,6 +55,14 @@
* SOFTWARE.
*/
+void Joint2DSW::copy_settings_from(Joint2DSW *p_joint) {
+ set_self(p_joint->get_self());
+ set_max_force(p_joint->get_max_force());
+ set_bias(p_joint->get_bias());
+ set_max_bias(p_joint->get_max_bias());
+ disable_collisions_between_bodies(p_joint->is_disabled_collisions_between_bodies());
+}
+
static inline real_t k_scalar(Body2DSW *a, Body2DSW *b, const Vector2 &rA, const Vector2 &rB, const Vector2 &n) {
real_t value = 0;
@@ -197,15 +205,6 @@ PinJoint2DSW::PinJoint2DSW(const Vector2 &p_pos, Body2DSW *p_body_a, Body2DSW *p
}
}
-PinJoint2DSW::~PinJoint2DSW() {
- if (A) {
- A->remove_constraint(this, 0);
- }
- if (B) {
- B->remove_constraint(this, 1);
- }
-}
-
//////////////////////////////////////////////
//////////////////////////////////////////////
//////////////////////////////////////////////
@@ -338,11 +337,6 @@ GrooveJoint2DSW::GrooveJoint2DSW(const Vector2 &p_a_groove1, const Vector2 &p_a_
B->add_constraint(this, 1);
}
-GrooveJoint2DSW::~GrooveJoint2DSW() {
- A->remove_constraint(this, 0);
- B->remove_constraint(this, 1);
-}
-
//////////////////////////////////////////////
//////////////////////////////////////////////
//////////////////////////////////////////////
@@ -434,8 +428,3 @@ DampedSpringJoint2DSW::DampedSpringJoint2DSW(const Vector2 &p_anchor_a, const Ve
A->add_constraint(this, 0);
B->add_constraint(this, 1);
}
-
-DampedSpringJoint2DSW::~DampedSpringJoint2DSW() {
- A->remove_constraint(this, 0);
- B->remove_constraint(this, 1);
-}
diff --git a/servers/physics_2d/joints_2d_sw.h b/servers/physics_2d/joints_2d_sw.h
index 53e436b539..628de972ae 100644
--- a/servers/physics_2d/joints_2d_sw.h
+++ b/servers/physics_2d/joints_2d_sw.h
@@ -49,12 +49,26 @@ public:
_FORCE_INLINE_ void set_max_bias(real_t p_bias) { max_bias = p_bias; }
_FORCE_INLINE_ real_t get_max_bias() const { return max_bias; }
- virtual PhysicsServer2D::JointType get_type() const = 0;
+ virtual bool setup(real_t p_step) { return false; }
+ virtual void solve(real_t p_step) {}
+
+ void copy_settings_from(Joint2DSW *p_joint);
+
+ virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_TYPE_MAX; }
Joint2DSW(Body2DSW **p_body_ptr = nullptr, int p_body_count = 0) :
Constraint2DSW(p_body_ptr, p_body_count) {
bias = 0;
max_force = max_bias = 3.40282e+38;
};
+
+ virtual ~Joint2DSW() {
+ for (int i = 0; i < get_body_count(); i++) {
+ Body2DSW *body = get_body_ptr()[i];
+ if (body) {
+ body->remove_constraint(this, i);
+ }
+ }
+ };
};
class PinJoint2DSW : public Joint2DSW {
@@ -76,7 +90,7 @@ class PinJoint2DSW : public Joint2DSW {
real_t softness;
public:
- virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_PIN; }
+ virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_TYPE_PIN; }
virtual bool setup(real_t p_step);
virtual void solve(real_t p_step);
@@ -85,7 +99,6 @@ public:
real_t get_param(PhysicsServer2D::PinJointParam p_param) const;
PinJoint2DSW(const Vector2 &p_pos, Body2DSW *p_body_a, Body2DSW *p_body_b = nullptr);
- ~PinJoint2DSW();
};
class GrooveJoint2DSW : public Joint2DSW {
@@ -113,13 +126,12 @@ class GrooveJoint2DSW : public Joint2DSW {
bool correct;
public:
- virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_GROOVE; }
+ virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_TYPE_GROOVE; }
virtual bool setup(real_t p_step);
virtual void solve(real_t p_step);
GrooveJoint2DSW(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, Body2DSW *p_body_a, Body2DSW *p_body_b);
- ~GrooveJoint2DSW();
};
class DampedSpringJoint2DSW : public Joint2DSW {
@@ -146,7 +158,7 @@ class DampedSpringJoint2DSW : public Joint2DSW {
real_t v_coef;
public:
- virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_DAMPED_SPRING; }
+ virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_TYPE_DAMPED_SPRING; }
virtual bool setup(real_t p_step);
virtual void solve(real_t p_step);
@@ -155,7 +167,6 @@ public:
real_t get_param(PhysicsServer2D::DampedSpringParam p_param) const;
DampedSpringJoint2DSW(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, Body2DSW *p_body_a, Body2DSW *p_body_b);
- ~DampedSpringJoint2DSW();
};
#endif // JOINTS_2D_SW_H
diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp
index 14fcf1520a..1040437ca7 100644
--- a/servers/physics_2d/physics_server_2d_sw.cpp
+++ b/servers/physics_2d/physics_server_2d_sw.cpp
@@ -985,6 +985,24 @@ PhysicsDirectBodyState2D *PhysicsServer2DSW::body_get_direct_state(RID p_body) {
/* JOINT API */
+RID PhysicsServer2DSW::joint_create() {
+ Joint2DSW *joint = memnew(Joint2DSW);
+ RID joint_rid = joint_owner.make_rid(joint);
+ joint->set_self(joint_rid);
+ return joint_rid;
+}
+
+void PhysicsServer2DSW::joint_clear(RID p_joint) {
+ Joint2DSW *joint = joint_owner.getornull(p_joint);
+ if (joint->get_type() != JOINT_TYPE_MAX) {
+ Joint2DSW *empty_joint = memnew(Joint2DSW);
+ empty_joint->copy_settings_from(joint);
+
+ joint_owner.replace(p_joint, empty_joint);
+ memdelete(joint);
+ }
+}
+
void PhysicsServer2DSW::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) {
Joint2DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
@@ -1048,52 +1066,63 @@ bool PhysicsServer2DSW::joint_is_disabled_collisions_between_bodies(RID p_joint)
return joint->is_disabled_collisions_between_bodies();
}
-RID PhysicsServer2DSW::pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b) {
+void PhysicsServer2DSW::joint_make_pin(RID p_joint, const Vector2 &p_pos, RID p_body_a, RID p_body_b) {
Body2DSW *A = body_owner.getornull(p_body_a);
- ERR_FAIL_COND_V(!A, RID());
+ ERR_FAIL_COND(!A);
Body2DSW *B = nullptr;
if (body_owner.owns(p_body_b)) {
B = body_owner.getornull(p_body_b);
- ERR_FAIL_COND_V(!B, RID());
+ ERR_FAIL_COND(!B);
}
+ Joint2DSW *prev_joint = joint_owner.getornull(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
+
Joint2DSW *joint = memnew(PinJoint2DSW(p_pos, A, B));
- RID self = joint_owner.make_rid(joint);
- joint->set_self(self);
- return self;
+ joint_owner.replace(p_joint, joint);
+ joint->copy_settings_from(prev_joint);
+ memdelete(prev_joint);
}
-RID PhysicsServer2DSW::groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) {
+void PhysicsServer2DSW::joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) {
Body2DSW *A = body_owner.getornull(p_body_a);
- ERR_FAIL_COND_V(!A, RID());
+ ERR_FAIL_COND(!A);
Body2DSW *B = body_owner.getornull(p_body_b);
- ERR_FAIL_COND_V(!B, RID());
+ ERR_FAIL_COND(!B);
+
+ Joint2DSW *prev_joint = joint_owner.getornull(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
Joint2DSW *joint = memnew(GrooveJoint2DSW(p_a_groove1, p_a_groove2, p_b_anchor, A, B));
- RID self = joint_owner.make_rid(joint);
- joint->set_self(self);
- return self;
+
+ joint_owner.replace(p_joint, joint);
+ joint->copy_settings_from(prev_joint);
+ memdelete(prev_joint);
}
-RID PhysicsServer2DSW::damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) {
+void PhysicsServer2DSW::joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) {
Body2DSW *A = body_owner.getornull(p_body_a);
- ERR_FAIL_COND_V(!A, RID());
+ ERR_FAIL_COND(!A);
Body2DSW *B = body_owner.getornull(p_body_b);
- ERR_FAIL_COND_V(!B, RID());
+ ERR_FAIL_COND(!B);
+
+ Joint2DSW *prev_joint = joint_owner.getornull(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
Joint2DSW *joint = memnew(DampedSpringJoint2DSW(p_anchor_a, p_anchor_b, A, B));
- RID self = joint_owner.make_rid(joint);
- joint->set_self(self);
- return self;
+
+ joint_owner.replace(p_joint, joint);
+ joint->copy_settings_from(prev_joint);
+ memdelete(prev_joint);
}
void PhysicsServer2DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
Joint2DSW *j = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!j);
- ERR_FAIL_COND(j->get_type() != JOINT_PIN);
+ ERR_FAIL_COND(j->get_type() != JOINT_TYPE_PIN);
PinJoint2DSW *pin_joint = static_cast<PinJoint2DSW *>(j);
pin_joint->set_param(p_param, p_value);
@@ -1102,7 +1131,7 @@ void PhysicsServer2DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param,
real_t PhysicsServer2DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
Joint2DSW *j = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!j, 0);
- ERR_FAIL_COND_V(j->get_type() != JOINT_PIN, 0);
+ ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_PIN, 0);
PinJoint2DSW *pin_joint = static_cast<PinJoint2DSW *>(j);
return pin_joint->get_param(p_param);
@@ -1111,7 +1140,7 @@ real_t PhysicsServer2DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param
void PhysicsServer2DSW::damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) {
Joint2DSW *j = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!j);
- ERR_FAIL_COND(j->get_type() != JOINT_DAMPED_SPRING);
+ ERR_FAIL_COND(j->get_type() != JOINT_TYPE_DAMPED_SPRING);
DampedSpringJoint2DSW *dsj = static_cast<DampedSpringJoint2DSW *>(j);
dsj->set_param(p_param, p_value);
@@ -1120,7 +1149,7 @@ void PhysicsServer2DSW::damped_spring_joint_set_param(RID p_joint, DampedSpringP
real_t PhysicsServer2DSW::damped_spring_joint_get_param(RID p_joint, DampedSpringParam p_param) const {
Joint2DSW *j = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!j, 0);
- ERR_FAIL_COND_V(j->get_type() != JOINT_DAMPED_SPRING, 0);
+ ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_DAMPED_SPRING, 0);
DampedSpringJoint2DSW *dsj = static_cast<DampedSpringJoint2DSW *>(j);
return dsj->get_param(p_param);
@@ -1128,7 +1157,7 @@ real_t PhysicsServer2DSW::damped_spring_joint_get_param(RID p_joint, DampedSprin
PhysicsServer2D::JointType PhysicsServer2DSW::joint_get_type(RID p_joint) const {
Joint2DSW *joint = joint_owner.getornull(p_joint);
- ERR_FAIL_COND_V(!joint, JOINT_PIN);
+ ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN);
return joint->get_type();
}
@@ -1325,7 +1354,7 @@ int PhysicsServer2DSW::get_process_info(ProcessInfo p_info) {
PhysicsServer2DSW *PhysicsServer2DSW::singletonsw = nullptr;
-PhysicsServer2DSW::PhysicsServer2DSW() {
+PhysicsServer2DSW::PhysicsServer2DSW(bool p_using_threads) {
singletonsw = this;
BroadPhase2DSW::create_func = BroadPhase2DHashGrid::_create;
//BroadPhase2DSW::create_func=BroadPhase2DBasic::_create;
@@ -1334,10 +1363,6 @@ PhysicsServer2DSW::PhysicsServer2DSW() {
island_count = 0;
active_objects = 0;
collision_pairs = 0;
-#ifdef NO_THREADS
- using_threads = false;
-#else
- using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2;
-#endif
+ using_threads = p_using_threads;
flushing_queries = false;
};
diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h
index 62ea30b3f6..65c5df0fce 100644
--- a/servers/physics_2d/physics_server_2d_sw.h
+++ b/servers/physics_2d/physics_server_2d_sw.h
@@ -61,11 +61,11 @@ class PhysicsServer2DSW : public PhysicsServer2D {
PhysicsDirectBodyState2DSW *direct_state;
- mutable RID_PtrOwner<Shape2DSW> shape_owner;
- mutable RID_PtrOwner<Space2DSW> space_owner;
- mutable RID_PtrOwner<Area2DSW> area_owner;
- mutable RID_PtrOwner<Body2DSW> body_owner;
- mutable RID_PtrOwner<Joint2DSW> joint_owner;
+ mutable RID_PtrOwner<Shape2DSW, true> shape_owner;
+ mutable RID_PtrOwner<Space2DSW, true> space_owner;
+ mutable RID_PtrOwner<Area2DSW, true> area_owner;
+ mutable RID_PtrOwner<Body2DSW, true> body_owner;
+ mutable RID_PtrOwner<Joint2DSW, true> joint_owner;
static PhysicsServer2DSW *singletonsw;
@@ -255,15 +255,20 @@ public:
/* JOINT API */
+ virtual RID joint_create() override;
+
+ virtual void joint_clear(RID p_joint) override;
+
virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value) override;
virtual real_t joint_get_param(RID p_joint, JointParam p_param) const override;
virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disabled) override;
virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const override;
- virtual RID pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b = RID()) override;
- virtual RID groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) override;
- virtual RID damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) override;
+ virtual void joint_make_pin(RID p_joint, const Vector2 &p_anchor, RID p_body_a, RID p_body_b = RID()) override;
+ virtual void joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) override;
+ virtual void joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) override;
+
virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) override;
virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const override;
virtual void damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) override;
@@ -287,7 +292,7 @@ public:
int get_process_info(ProcessInfo p_info) override;
- PhysicsServer2DSW();
+ PhysicsServer2DSW(bool p_using_threads = false);
~PhysicsServer2DSW() {}
};
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.cpp b/servers/physics_2d/physics_server_2d_wrap_mt.cpp
index 897724fe6f..790c87cc44 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.cpp
+++ b/servers/physics_2d/physics_server_2d_wrap_mt.cpp
@@ -33,7 +33,7 @@
#include "core/os/os.h"
void PhysicsServer2DWrapMT::thread_exit() {
- exit = true;
+ exit.set();
}
void PhysicsServer2DWrapMT::thread_step(real_t p_delta) {
@@ -52,9 +52,9 @@ void PhysicsServer2DWrapMT::thread_loop() {
physics_2d_server->init();
- exit = false;
- step_thread_up = true;
- while (!exit) {
+ exit.clear();
+ step_thread_up.set();
+ while (!exit.is_set()) {
// flush commands one by one, until exit is requested
command_queue.wait_and_flush_one();
}
@@ -98,7 +98,7 @@ void PhysicsServer2DWrapMT::init() {
if (create_thread) {
//OS::get_singleton()->release_rendering_thread();
thread.start(_thread_callback, this);
- while (!step_thread_up) {
+ while (!step_thread_up.is_set()) {
OS::get_singleton()->delay_usec(1000);
}
} else {
@@ -113,19 +113,6 @@ void PhysicsServer2DWrapMT::finish() {
} else {
physics_2d_server->finish();
}
-
- line_shape_free_cached_ids();
- ray_shape_free_cached_ids();
- segment_shape_free_cached_ids();
- circle_shape_free_cached_ids();
- rectangle_shape_free_cached_ids();
- capsule_shape_free_cached_ids();
- convex_polygon_shape_free_cached_ids();
- concave_polygon_shape_free_cached_ids();
-
- space_free_cached_ids();
- area_free_cached_ids();
- body_free_cached_ids();
}
PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) :
@@ -133,7 +120,6 @@ PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool
physics_2d_server = p_contained;
create_thread = p_create_thread;
step_pending = 0;
- step_thread_up = false;
pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h
index fbc5b1eaa1..3577f706de 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.h
+++ b/servers/physics_2d/physics_server_2d_wrap_mt.h
@@ -34,6 +34,7 @@
#include "core/config/project_settings.h"
#include "core/os/thread.h"
#include "core/templates/command_queue_mt.h"
+#include "core/templates/safe_refcount.h"
#include "servers/physics_server_2d.h"
#ifdef DEBUG_SYNC
@@ -52,9 +53,9 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D {
Thread::ID server_thread;
Thread::ID main_thread;
- volatile bool exit;
+ SafeFlag exit;
Thread thread;
- volatile bool step_thread_up;
+ SafeFlag step_thread_up;
bool create_thread;
Semaphore step_sem;
@@ -73,6 +74,8 @@ public:
#define ServerName PhysicsServer2D
#define ServerNameWrapMT PhysicsServer2DWrapMT
#define server_name physics_2d_server
+#define WRITE_ACTION
+
#include "servers/server_wrap_mt_common.h"
//FUNC1RID(shape,ShapeType); todo fix
@@ -93,7 +96,7 @@ public:
FUNC1RC(real_t, shape_get_custom_solver_bias, RID);
//these work well, but should be used from the main thread only
- bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) {
+ bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
return physics_2d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
}
@@ -108,18 +111,18 @@ public:
FUNC2RC(real_t, space_get_param, RID, SpaceParameter);
// this function only works on physics process, errors and returns null otherwise
- PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) {
+ PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
return physics_2d_server->space_get_direct_state(p_space);
}
FUNC2(space_set_debug_contacts, RID, int);
- virtual Vector<Vector2> space_get_contacts(RID p_space) const {
+ virtual Vector<Vector2> space_get_contacts(RID p_space) const override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector2>());
return physics_2d_server->space_get_contacts(p_space);
}
- virtual int space_get_contact_count(RID p_space) const {
+ virtual int space_get_contact_count(RID p_space) const override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0);
return physics_2d_server->space_get_contact_count(p_space);
}
@@ -244,30 +247,34 @@ public:
FUNC4(body_set_force_integration_callback, RID, Object *, const StringName &, const Variant &);
- bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) {
+ bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override {
return physics_2d_server->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count);
}
FUNC2(body_set_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) {
+ bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
}
- int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) {
+ int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
return physics_2d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
}
// this function only works on physics process, errors and returns null otherwise
- PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) {
+ PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
return physics_2d_server->body_get_direct_state(p_body);
}
/* JOINT API */
+ FUNCRID(joint)
+
+ FUNC1(joint_clear, RID)
+
FUNC3(joint_set_param, RID, JointParam, real_t);
FUNC2RC(real_t, joint_get_param, RID, JointParam);
@@ -280,9 +287,9 @@ public:
//TODO need to convert this to FUNCRID, but it's a hassle..
- FUNC3R(RID, pin_joint_create, const Vector2 &, RID, RID);
- FUNC5R(RID, groove_joint_create, const Vector2 &, const Vector2 &, const Vector2 &, RID, RID);
- FUNC4R(RID, damped_spring_joint_create, const Vector2 &, const Vector2 &, RID, RID);
+ FUNC4(joint_make_pin, RID, const Vector2 &, RID, RID);
+ FUNC6(joint_make_groove, RID, const Vector2 &, const Vector2 &, const Vector2 &, RID, RID);
+ FUNC5(joint_make_damped_spring, RID, const Vector2 &, const Vector2 &, RID, RID);
FUNC3(pin_joint_set_param, RID, PinJointParam, real_t);
FUNC2RC(real_t, pin_joint_get_param, RID, PinJointParam);
@@ -297,43 +304,28 @@ public:
FUNC1(free, RID);
FUNC1(set_active, bool);
- virtual void init();
- virtual void step(real_t p_step);
- virtual void sync();
- virtual void end_sync();
- virtual void flush_queries();
- virtual void finish();
+ virtual void init() override;
+ virtual void step(real_t p_step) override;
+ virtual void sync() override;
+ virtual void end_sync() override;
+ virtual void flush_queries() override;
+ virtual void finish() override;
- virtual bool is_flushing_queries() const {
+ virtual bool is_flushing_queries() const override {
return physics_2d_server->is_flushing_queries();
}
- int get_process_info(ProcessInfo p_info) {
+ int get_process_info(ProcessInfo p_info) override {
return physics_2d_server->get_process_info(p_info);
}
PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread);
~PhysicsServer2DWrapMT();
- template <class T>
- static PhysicsServer2D *init_server() {
-#ifdef NO_THREADS
- return memnew(T); // Always single unsafe when no threads are available.
-#else
- int tm = GLOBAL_DEF("physics/2d/thread_model", 1);
- if (tm == 0) { // single unsafe
- return memnew(T);
- } else if (tm == 1) { // single safe
- return memnew(PhysicsServer2DWrapMT(memnew(T), false));
- } else { // multi threaded
- return memnew(PhysicsServer2DWrapMT(memnew(T), true));
- }
-#endif
- }
-
#undef ServerNameWrapMT
#undef ServerName
#undef server_name
+#undef WRITE_ACTION
};
#ifdef DEBUG_SYNC
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 05136e2501..4f12248c3e 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -84,6 +84,10 @@ int PhysicsDirectSpaceState2DSW::_intersect_point_impl(const Vector2 &p_point, S
int shape_idx = space->intersection_query_subindex_results[i];
+ if (col_obj->is_shape_set_as_disabled(shape_idx)) {
+ continue;
+ }
+
Shape2DSW *shape = col_obj->get_shape(shape_idx);
Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_point);
@@ -229,6 +233,10 @@ int PhysicsDirectSpaceState2DSW::intersect_shape(const RID &p_shape, const Trans
const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
+ if (col_obj->is_shape_set_as_disabled(shape_idx)) {
+ continue;
+ }
+
if (!CollisionSolver2DSW::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), nullptr, nullptr, nullptr, p_margin)) {
continue;
}
@@ -272,6 +280,10 @@ bool PhysicsDirectSpaceState2DSW::cast_motion(const RID &p_shape, const Transfor
const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
+ if (col_obj->is_shape_set_as_disabled(shape_idx)) {
+ continue;
+ }
+
Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
if (!CollisionSolver2DSW::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) {
@@ -346,12 +358,17 @@ bool PhysicsDirectSpaceState2DSW::collide_shape(RID p_shape, const Transform2D &
}
const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
- int shape_idx = space->intersection_query_subindex_results[i];
if (p_exclude.has(col_obj->get_self())) {
continue;
}
+ int shape_idx = space->intersection_query_subindex_results[i];
+
+ if (col_obj->is_shape_set_as_disabled(shape_idx)) {
+ continue;
+ }
+
cbk.valid_dir = Vector2();
cbk.valid_depth = 0;
@@ -376,6 +393,7 @@ struct _RestCallbackData2D {
Vector2 best_normal;
real_t best_len;
Vector2 valid_dir;
+ real_t valid_depth;
real_t min_allowed_depth;
};
@@ -385,22 +403,24 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B,
Vector2 contact_rel = p_point_B - p_point_A;
real_t len = contact_rel.length();
- if (len == 0) {
+ if (len < rd->min_allowed_depth) {
return;
}
- Vector2 normal = contact_rel / len;
-
- if (rd->valid_dir != Vector2() && rd->valid_dir.dot(normal) > -CMP_EPSILON) {
+ if (len <= rd->best_len) {
return;
}
- if (len < rd->min_allowed_depth) {
- return;
- }
+ Vector2 normal = contact_rel / len;
- if (len <= rd->best_len) {
- return;
+ if (rd->valid_dir != Vector2()) {
+ if (len > rd->valid_depth) {
+ return;
+ }
+
+ if (rd->valid_dir.dot(normal) > -CMP_EPSILON) {
+ return;
+ }
}
rd->best_len = len;
@@ -433,12 +453,17 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh
}
const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
- int shape_idx = space->intersection_query_subindex_results[i];
if (p_exclude.has(col_obj->get_self())) {
continue;
}
+ int shape_idx = space->intersection_query_subindex_results[i];
+
+ if (col_obj->is_shape_set_as_disabled(shape_idx)) {
+ continue;
+ }
+
rcd.valid_dir = Vector2();
rcd.object = col_obj;
rcd.shape = shape_idx;
@@ -739,10 +764,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs];
int excluded_shape_pair_count = 0;
- real_t separation_margin = MIN(p_margin, MAX(0.0, p_motion.length() - CMP_EPSILON)); //don't separate by more than the intended motion
+ real_t motion_length = p_motion.length();
+ Vector2 motion_normal = p_motion / motion_length;
Transform2D body_transform = p_from;
+ bool recovered = false;
+
{
//STEP 1, FREE BODY IF STUCK
@@ -819,7 +847,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
bool did_collide = false;
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, separation_margin)) {
+ if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_margin)) {
did_collide = cbk.passed > current_passed; //more passed, so collision actually existed
}
@@ -845,11 +873,20 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
Vector2 recover_motion;
-
for (int i = 0; i < cbk.amount; i++) {
Vector2 a = sr[i * 2 + 0];
Vector2 b = sr[i * 2 + 1];
- recover_motion += (b - a) / cbk.amount;
+
+ // Compute plane on b towards a.
+ Vector2 n = (a - b).normalized();
+ real_t d = n.dot(b);
+
+ // Compute depth on recovered motion.
+ real_t depth = n.dot(a + recover_motion) - d;
+ if (depth > 0.0) {
+ // Only recover if there is penetration.
+ recover_motion -= n * depth * 0.4;
+ }
}
if (recover_motion == Vector2()) {
@@ -857,6 +894,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
break;
}
+ recovered = true;
+
body_transform.elements[2] += recover_motion;
body_aabb.position += recover_motion;
@@ -929,7 +968,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
//test initial overlap
if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) {
if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
- continue;
+ Vector2 direction = col_obj_shape_xform.get_axis(1).normalized();
+ if (motion_normal.dot(direction) < 0) {
+ continue;
+ }
}
stuck = true;
@@ -939,13 +981,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
//just do kinematic solving
real_t low = 0;
real_t hi = 1;
- Vector2 mnormal = p_motion.normalized();
for (int k = 0; k < 8; k++) { //steps should be customizable..
real_t ofs = (low + hi) * 0.5;
- Vector2 sep = mnormal; //important optimization for this to work fast enough
+ Vector2 sep = motion_normal; //important optimization for this to work fast enough
bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * ofs, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0);
if (collided) {
@@ -966,7 +1007,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
cbk.valid_depth = 10e20;
- Vector2 sep = mnormal; //important optimization for this to work fast enough
+ Vector2 sep = motion_normal; //important optimization for this to work fast enough
bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), PhysicsServer2DSW::_shape_col_cbk, &cbk, &sep, 0);
if (!collided || cbk.amount == 0) {
continue;
@@ -997,11 +1038,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
bool collided = false;
- if (safe >= 1) {
- best_shape = -1; //no best shape with cast, reset to -1
- }
- if (safe < 1) {
+ if (recovered || (safe < 1)) {
+ if (safe >= 1) {
+ best_shape = -1; //no best shape with cast, reset to -1
+ }
+
//it collided, let's get the rest info in unsafe advance
Transform2D ugt = body_transform;
ugt.elements[2] += p_motion * unsafe;
@@ -1010,9 +1052,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
rcd.best_len = 0;
rcd.best_object = nullptr;
rcd.best_shape = 0;
- rcd.min_allowed_depth = test_motion_min_contact_depth;
- //optimization
+ // Allowed depth can't be lower than motion length, in order to handle contacts at low speed.
+ rcd.min_allowed_depth = MIN(motion_length, test_motion_min_contact_depth);
+
int from_shape = best_shape != -1 ? best_shape : 0;
int to_shape = best_shape != -1 ? best_shape + 1 : p_body->get_shape_count();
@@ -1060,8 +1103,25 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
+
+ real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
+ rcd.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work
+
+ if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
+ const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
+ if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) {
+ //fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
+ Vector2 lv = b->get_linear_velocity();
+ //compute displacement from linear velocity
+ Vector2 motion = lv * PhysicsDirectBodyState2DSW::singleton->step;
+ real_t motion_len = motion.length();
+ motion.normalize();
+ rcd.valid_depth += motion_len * MAX(motion.dot(-rcd.valid_dir), 0.0);
+ }
+ }
} else {
rcd.valid_dir = Vector2();
+ rcd.valid_depth = 0;
}
rcd.object = col_obj;
diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/body_3d_sw.cpp
index 82356e77ef..64ba0cb09d 100644
--- a/servers/physics_3d/body_3d_sw.cpp
+++ b/servers/physics_3d/body_3d_sw.cpp
@@ -51,18 +51,18 @@ void Body3DSW::_update_transform_dependant() {
}
void Body3DSW::update_inertias() {
- //update shapes and motions
+ // Update shapes and motions.
switch (mode) {
case PhysicsServer3D::BODY_MODE_RIGID: {
- //update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet)
+ // Update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet)
real_t total_area = 0;
for (int i = 0; i < get_shape_count(); i++) {
total_area += get_shape_area(i);
}
- // We have to recompute the center of mass
+ // We have to recompute the center of mass.
center_of_mass_local.zero();
for (int i = 0; i < get_shape_count(); i++) {
@@ -70,21 +70,24 @@ void Body3DSW::update_inertias() {
real_t mass = area * this->mass / total_area;
- // NOTE: we assume that the shape origin is also its center of mass
+ // NOTE: we assume that the shape origin is also its center of mass.
center_of_mass_local += mass * get_shape_transform(i).origin;
}
center_of_mass_local /= mass;
- // Recompute the inertia tensor
+ // Recompute the inertia tensor.
Basis inertia_tensor;
inertia_tensor.set_zero();
+ bool inertia_set = false;
for (int i = 0; i < get_shape_count(); i++) {
if (is_shape_disabled(i)) {
continue;
}
+ inertia_set = true;
+
const Shape3DSW *shape = get_shape(i);
real_t area = get_shape_area(i);
@@ -102,7 +105,12 @@ void Body3DSW::update_inertias() {
inertia_tensor += shape_inertia_tensor + (Basis() * shape_origin.dot(shape_origin) - shape_origin.outer(shape_origin)) * mass;
}
- // Compute the principal axes of inertia
+ // Set the inertia to a valid value when there are no valid shapes.
+ if (!inertia_set) {
+ inertia_tensor.set_diagonal(Vector3(1.0, 1.0, 1.0));
+ }
+
+ // Compute the principal axes of inertia.
principal_inertia_axes_local = inertia_tensor.diagonalize().transposed();
_inv_inertia = inertia_tensor.get_main_diagonal().inverse();
@@ -493,20 +501,18 @@ void Body3DSW::integrate_forces(real_t p_step) {
if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC) {
//compute motion, angular and etc. velocities from prev transform
- linear_velocity = (new_transform.origin - get_transform().origin) / p_step;
+ motion = new_transform.origin - get_transform().origin;
+ do_motion = true;
+ linear_velocity = motion / p_step;
//compute a FAKE angular velocity, not so easy
- Basis rot = new_transform.basis.orthonormalized().transposed() * get_transform().basis.orthonormalized();
+ Basis rot = new_transform.basis.orthonormalized() * get_transform().basis.orthonormalized().transposed();
Vector3 axis;
real_t angle;
rot.get_axis_angle(axis, angle);
axis.normalize();
- angular_velocity = axis.normalized() * (angle / p_step);
-
- motion = new_transform.origin - get_transform().origin;
- do_motion = true;
-
+ angular_velocity = axis * (angle / p_step);
} else {
if (!omit_force_integration && !first_integration) {
//overridden by direct state query
diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h
index 8e21003a5f..e87ff2364b 100644
--- a/servers/physics_3d/body_3d_sw.h
+++ b/servers/physics_3d/body_3d_sw.h
@@ -290,10 +290,10 @@ public:
void update_inertias();
_FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; }
- _FORCE_INLINE_ Vector3 get_inv_inertia() const { return _inv_inertia; }
- _FORCE_INLINE_ Basis get_inv_inertia_tensor() const { return _inv_inertia_tensor; }
+ _FORCE_INLINE_ const Vector3 &get_inv_inertia() const { return _inv_inertia; }
+ _FORCE_INLINE_ const Basis &get_inv_inertia_tensor() const { return _inv_inertia_tensor; }
_FORCE_INLINE_ real_t get_friction() const { return friction; }
- _FORCE_INLINE_ Vector3 get_gravity() const { return gravity; }
+ _FORCE_INLINE_ const Vector3 &get_gravity() const { return gravity; }
_FORCE_INLINE_ real_t get_bounce() const { return bounce; }
void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock);
diff --git a/servers/physics_3d/body_pair_3d_sw.cpp b/servers/physics_3d/body_pair_3d_sw.cpp
index 6012ff1522..36114c0c91 100644
--- a/servers/physics_3d/body_pair_3d_sw.cpp
+++ b/servers/physics_3d/body_pair_3d_sw.cpp
@@ -49,12 +49,12 @@
#define MIN_VELOCITY 0.0001
#define MAX_BIAS_ROTATION (Math_PI / 8)
-void BodyPair3DSW::_contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) {
+void BodyPair3DSW::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
BodyPair3DSW *pair = (BodyPair3DSW *)p_userdata;
- pair->contact_added_callback(p_point_A, p_point_B);
+ pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B);
}
-void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B) {
+void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) {
// check if we already have the contact
//Vector3 local_A = A->get_inv_transform().xform(p_point_A);
@@ -73,6 +73,8 @@ void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, const Vector
contact.acc_bias_impulse = 0;
contact.acc_bias_impulse_center_of_mass = 0;
contact.acc_tangent_impulse = Vector3();
+ contact.index_A = p_index_A;
+ contact.index_B = p_index_B;
contact.local_A = local_A;
contact.local_B = local_B;
contact.normal = (p_point_A - p_point_B).normalized();
@@ -211,11 +213,21 @@ real_t combine_friction(Body3DSW *A, Body3DSW *B) {
bool BodyPair3DSW::setup(real_t p_step) {
//cannot collide
- if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) {
+ if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
collided = false;
return false;
}
+ bool report_contacts_only = false;
+ if ((A->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC) && (B->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC)) {
+ if ((A->get_max_contacts_reported() > 0) || (B->get_max_contacts_reported() > 0)) {
+ report_contacts_only = true;
+ } else {
+ collided = false;
+ return false;
+ }
+ }
+
if (A->is_shape_set_as_disabled(shape_A) || B->is_shape_set_as_disabled(shape_B)) {
collided = false;
return false;
@@ -279,12 +291,9 @@ bool BodyPair3DSW::setup(real_t p_step) {
real_t depth = c.normal.dot(global_A - global_B);
if (depth <= 0) {
- c.active = false;
continue;
}
- c.active = true;
-
#ifdef DEBUG_ENABLED
if (space->is_debugging_contacts()) {
@@ -308,6 +317,11 @@ bool BodyPair3DSW::setup(real_t p_step) {
B->add_contact(global_B, c.normal, depth, shape_B, global_A, shape_A, A->get_instance_id(), A->get_self(), crB);
}
+ if (report_contacts_only) {
+ collided = false;
+ continue;
+ }
+
c.active = true;
// Precompute normal mass, tangent mass, and bias.
@@ -456,7 +470,7 @@ void BodyPair3DSW::solve(real_t p_step) {
}
BodyPair3DSW::BodyPair3DSW(Body3DSW *p_A, int p_shape_A, Body3DSW *p_B, int p_shape_B) :
- Constraint3DSW(_arr, 2) {
+ BodyContact3DSW(_arr, 2) {
A = p_A;
B = p_B;
shape_A = p_shape_A;
@@ -472,3 +486,305 @@ BodyPair3DSW::~BodyPair3DSW() {
A->remove_constraint(this);
B->remove_constraint(this);
}
+
+void BodySoftBodyPair3DSW::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+ BodySoftBodyPair3DSW *pair = (BodySoftBodyPair3DSW *)p_userdata;
+ pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B);
+}
+
+void BodySoftBodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) {
+ Vector3 local_A = body->get_inv_transform().xform(p_point_A);
+ Vector3 local_B = p_point_B - soft_body->get_node_position(p_index_B);
+
+ Contact contact;
+ contact.index_A = p_index_A;
+ contact.index_B = p_index_B;
+ contact.acc_normal_impulse = 0;
+ contact.acc_bias_impulse = 0;
+ contact.acc_bias_impulse_center_of_mass = 0;
+ contact.acc_tangent_impulse = Vector3();
+ contact.local_A = local_A;
+ contact.local_B = local_B;
+ contact.normal = (p_point_A - p_point_B).normalized();
+ contact.mass_normal = 0;
+
+ // Attempt to determine if the contact will be reused.
+ real_t contact_recycle_radius = space->get_contact_recycle_radius();
+
+ uint32_t contact_count = contacts.size();
+ for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) {
+ Contact &c = contacts[contact_index];
+ if (c.index_B == p_index_B) {
+ if (c.local_A.distance_squared_to(local_A) < (contact_recycle_radius * contact_recycle_radius) &&
+ c.local_B.distance_squared_to(local_B) < (contact_recycle_radius * contact_recycle_radius)) {
+ contact.acc_normal_impulse = c.acc_normal_impulse;
+ contact.acc_bias_impulse = c.acc_bias_impulse;
+ contact.acc_bias_impulse_center_of_mass = c.acc_bias_impulse_center_of_mass;
+ contact.acc_tangent_impulse = c.acc_tangent_impulse;
+ }
+ c = contact;
+ return;
+ }
+ }
+
+ contacts.push_back(contact);
+}
+
+void BodySoftBodyPair3DSW::validate_contacts() {
+ // Make sure to erase contacts that are no longer valid.
+ const Transform &transform_A = body->get_transform();
+
+ real_t contact_max_separation = space->get_contact_max_separation();
+
+ uint32_t contact_count = contacts.size();
+ for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) {
+ Contact &c = contacts[contact_index];
+
+ Vector3 global_A = transform_A.xform(c.local_A);
+ Vector3 global_B = soft_body->get_node_position(c.index_B) + c.local_B;
+ Vector3 axis = global_A - global_B;
+ real_t depth = axis.dot(c.normal);
+
+ if (depth < -contact_max_separation || (global_B + c.normal * depth - global_A).length() > contact_max_separation) {
+ // Contact no longer needed, remove.
+ if ((contact_index + 1) < contact_count) {
+ // Swap with the last one.
+ SWAP(c, contacts[contact_count - 1]);
+ }
+
+ contact_index--;
+ contact_count--;
+ }
+ }
+
+ contacts.resize(contact_count);
+}
+
+bool BodySoftBodyPair3DSW::setup(real_t p_step) {
+ if (!body->test_collision_mask(soft_body) || body->has_exception(soft_body->get_self()) || soft_body->has_exception(body->get_self())) {
+ collided = false;
+ return false;
+ }
+
+ if (body->is_shape_set_as_disabled(body_shape)) {
+ collided = false;
+ return false;
+ }
+
+ const Transform &xform_Au = body->get_transform();
+ Transform xform_A = xform_Au * body->get_shape_transform(body_shape);
+
+ Transform xform_Bu = soft_body->get_transform();
+ Transform xform_B = xform_Bu * soft_body->get_shape_transform(0);
+
+ validate_contacts();
+
+ Shape3DSW *shape_A_ptr = body->get_shape(body_shape);
+ Shape3DSW *shape_B_ptr = soft_body->get_shape(0);
+
+ bool collided = CollisionSolver3DSW::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis);
+ this->collided = collided;
+
+ real_t max_penetration = space->get_contact_max_allowed_penetration();
+
+ real_t bias = (real_t)0.3;
+ if (shape_A_ptr->get_custom_bias()) {
+ bias = shape_A_ptr->get_custom_bias();
+ }
+
+ real_t inv_dt = 1.0 / p_step;
+
+ uint32_t contact_count = contacts.size();
+ for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) {
+ Contact &c = contacts[contact_index];
+ c.active = false;
+
+ real_t node_inv_mass = soft_body->get_node_inv_mass(c.index_B);
+ if (node_inv_mass == 0.0) {
+ continue;
+ }
+
+ Vector3 global_A = xform_Au.xform(c.local_A);
+ Vector3 global_B = soft_body->get_node_position(c.index_B) + c.local_B;
+
+ real_t depth = c.normal.dot(global_A - global_B);
+
+ if (depth <= 0) {
+ continue;
+ }
+
+ c.active = true;
+
+#ifdef DEBUG_ENABLED
+
+ if (space->is_debugging_contacts()) {
+ space->add_debug_contact(global_A);
+ space->add_debug_contact(global_B);
+ }
+#endif
+
+ c.rA = global_A - xform_Au.origin - body->get_center_of_mass();
+ c.rB = global_B;
+
+ if (body->can_report_contacts()) {
+ Vector3 crA = body->get_angular_velocity().cross(c.rA) + body->get_linear_velocity();
+ body->add_contact(global_A, -c.normal, depth, body_shape, global_B, 0, soft_body->get_instance_id(), soft_body->get_self(), crA);
+ }
+
+ if (body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) {
+ body->set_active(true);
+ }
+
+ // Precompute normal mass, tangent mass, and bias.
+ Vector3 inertia_A = body->get_inv_inertia_tensor().xform(c.rA.cross(c.normal));
+ real_t kNormal = body->get_inv_mass() + node_inv_mass;
+ kNormal += c.normal.dot(inertia_A.cross(c.rA));
+ c.mass_normal = 1.0f / kNormal;
+
+ c.bias = -bias * inv_dt * MIN(0.0f, -depth + max_penetration);
+ c.depth = depth;
+
+ Vector3 j_vec = c.normal * c.acc_normal_impulse + c.acc_tangent_impulse;
+ body->apply_impulse(c.rA + body->get_center_of_mass(), -j_vec);
+ soft_body->apply_node_impulse(c.index_B, j_vec);
+ c.acc_bias_impulse = 0;
+ c.acc_bias_impulse_center_of_mass = 0;
+
+ c.bounce = body->get_bounce();
+
+ if (c.bounce) {
+ Vector3 crA = body->get_angular_velocity().cross(c.rA);
+ Vector3 dv = soft_body->get_node_velocity(c.index_B) - body->get_linear_velocity() - crA;
+
+ // Normal impulse.
+ c.bounce = c.bounce * dv.dot(c.normal);
+ }
+ }
+
+ return true;
+}
+
+void BodySoftBodyPair3DSW::solve(real_t p_step) {
+ if (!collided) {
+ return;
+ }
+
+ uint32_t contact_count = contacts.size();
+ for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) {
+ Contact &c = contacts[contact_index];
+ if (!c.active) {
+ continue;
+ }
+
+ c.active = false;
+
+ // Bias impulse.
+ Vector3 crbA = body->get_biased_angular_velocity().cross(c.rA);
+ Vector3 dbv = soft_body->get_node_biased_velocity(c.index_B) - body->get_biased_linear_velocity() - crbA;
+
+ real_t vbn = dbv.dot(c.normal);
+
+ if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) {
+ real_t jbn = (-vbn + c.bias) * c.mass_normal;
+ real_t jbnOld = c.acc_bias_impulse;
+ c.acc_bias_impulse = MAX(jbnOld + jbn, 0.0f);
+
+ Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld);
+
+ body->apply_bias_impulse(c.rA + body->get_center_of_mass(), -jb, MAX_BIAS_ROTATION / p_step);
+ soft_body->apply_node_bias_impulse(c.index_B, jb);
+
+ crbA = body->get_biased_angular_velocity().cross(c.rA);
+ dbv = soft_body->get_node_biased_velocity(c.index_B) - body->get_biased_linear_velocity() - crbA;
+
+ vbn = dbv.dot(c.normal);
+
+ if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) {
+ real_t jbn_com = (-vbn + c.bias) / (body->get_inv_mass() + soft_body->get_node_inv_mass(c.index_B));
+ real_t jbnOld_com = c.acc_bias_impulse_center_of_mass;
+ c.acc_bias_impulse_center_of_mass = MAX(jbnOld_com + jbn_com, 0.0f);
+
+ Vector3 jb_com = c.normal * (c.acc_bias_impulse_center_of_mass - jbnOld_com);
+
+ body->apply_bias_impulse(body->get_center_of_mass(), -jb_com, 0.0f);
+ soft_body->apply_node_bias_impulse(c.index_B, -jb_com);
+ }
+
+ c.active = true;
+ }
+
+ Vector3 crA = body->get_angular_velocity().cross(c.rA);
+ Vector3 dv = soft_body->get_node_velocity(c.index_B) - body->get_linear_velocity() - crA;
+
+ // Normal impulse.
+ real_t vn = dv.dot(c.normal);
+
+ if (Math::abs(vn) > MIN_VELOCITY) {
+ real_t jn = -(c.bounce + vn) * c.mass_normal;
+ real_t jnOld = c.acc_normal_impulse;
+ c.acc_normal_impulse = MAX(jnOld + jn, 0.0f);
+
+ Vector3 j = c.normal * (c.acc_normal_impulse - jnOld);
+
+ body->apply_impulse(c.rA + body->get_center_of_mass(), -j);
+ soft_body->apply_node_impulse(c.index_B, j);
+
+ c.active = true;
+ }
+
+ // Friction impulse.
+ real_t friction = body->get_friction();
+
+ Vector3 lvA = body->get_linear_velocity() + body->get_angular_velocity().cross(c.rA);
+ Vector3 lvB = soft_body->get_node_velocity(c.index_B);
+ Vector3 dtv = lvB - lvA;
+
+ real_t tn = c.normal.dot(dtv);
+
+ // Tangential velocity.
+ Vector3 tv = dtv - c.normal * tn;
+ real_t tvl = tv.length();
+
+ if (tvl > MIN_VELOCITY) {
+ tv /= tvl;
+
+ Vector3 temp1 = body->get_inv_inertia_tensor().xform(c.rA.cross(tv));
+
+ real_t t = -tvl /
+ (body->get_inv_mass() + soft_body->get_node_inv_mass(c.index_B) + tv.dot(temp1.cross(c.rA)));
+
+ Vector3 jt = t * tv;
+
+ Vector3 jtOld = c.acc_tangent_impulse;
+ c.acc_tangent_impulse += jt;
+
+ real_t fi_len = c.acc_tangent_impulse.length();
+ real_t jtMax = c.acc_normal_impulse * friction;
+
+ if (fi_len > CMP_EPSILON && fi_len > jtMax) {
+ c.acc_tangent_impulse *= jtMax / fi_len;
+ }
+
+ jt = c.acc_tangent_impulse - jtOld;
+
+ body->apply_impulse(c.rA + body->get_center_of_mass(), -jt);
+ soft_body->apply_node_impulse(c.index_B, jt);
+
+ c.active = true;
+ }
+ }
+}
+
+BodySoftBodyPair3DSW::BodySoftBodyPair3DSW(Body3DSW *p_A, int p_shape_A, SoftBody3DSW *p_B) {
+ body = p_A;
+ soft_body = p_B;
+ body_shape = p_shape_A;
+ space = p_A->get_space();
+ body->add_constraint(this, 0);
+ soft_body->add_constraint(this);
+}
+
+BodySoftBodyPair3DSW::~BodySoftBodyPair3DSW() {
+ body->remove_constraint(this);
+ soft_body->remove_constraint(this);
+}
diff --git a/servers/physics_3d/body_pair_3d_sw.h b/servers/physics_3d/body_pair_3d_sw.h
index 4d049eafdc..74dddfa6aa 100644
--- a/servers/physics_3d/body_pair_3d_sw.h
+++ b/servers/physics_3d/body_pair_3d_sw.h
@@ -28,32 +28,20 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BODY_PAIR_SW_H
-#define BODY_PAIR_SW_H
+#ifndef BODY_PAIR_3D_SW_H
+#define BODY_PAIR_3D_SW_H
#include "body_3d_sw.h"
#include "constraint_3d_sw.h"
+#include "core/templates/local_vector.h"
+#include "soft_body_3d_sw.h"
-class BodyPair3DSW : public Constraint3DSW {
- enum {
- MAX_CONTACTS = 4
- };
-
- union {
- struct {
- Body3DSW *A;
- Body3DSW *B;
- };
-
- Body3DSW *_arr[2];
- };
-
- int shape_A;
- int shape_B;
-
+class BodyContact3DSW : public Constraint3DSW {
+protected:
struct Contact {
Vector3 position;
Vector3 normal;
+ int index_A, index_B;
Vector3 local_A, local_B;
real_t acc_normal_impulse; // accumulated normal impulse (Pn)
Vector3 acc_tangent_impulse; // accumulated tangent impulse (Pt)
@@ -68,22 +56,45 @@ class BodyPair3DSW : public Constraint3DSW {
Vector3 rA, rB; // Offset in world orientation with respect to center of mass
};
+ Vector3 sep_axis;
+ bool collided;
+
+ Space3DSW *space;
+
+ BodyContact3DSW(Body3DSW **p_body_ptr = nullptr, int p_body_count = 0) :
+ Constraint3DSW(p_body_ptr, p_body_count) {
+ }
+};
+
+class BodyPair3DSW : public BodyContact3DSW {
+ enum {
+ MAX_CONTACTS = 4
+ };
+
+ union {
+ struct {
+ Body3DSW *A;
+ Body3DSW *B;
+ };
+
+ Body3DSW *_arr[2];
+ };
+
+ int shape_A;
+ int shape_B;
+
Vector3 offset_B; //use local A coordinates to avoid numerical issues on collision detection
- Vector3 sep_axis;
Contact contacts[MAX_CONTACTS];
int contact_count;
- bool collided;
- static void _contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata);
+ static void _contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
- void contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B);
+ void contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B);
void validate_contacts();
bool _test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform &p_xform_B);
- Space3DSW *space;
-
public:
bool setup(real_t p_step);
void solve(real_t p_step);
@@ -92,4 +103,26 @@ public:
~BodyPair3DSW();
};
-#endif // BODY_PAIR__SW_H
+class BodySoftBodyPair3DSW : public BodyContact3DSW {
+ Body3DSW *body;
+ SoftBody3DSW *soft_body;
+
+ int body_shape;
+
+ LocalVector<Contact> contacts;
+
+ static void _contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
+
+ void contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B);
+
+ void validate_contacts();
+
+public:
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
+
+ BodySoftBodyPair3DSW(Body3DSW *p_A, int p_shape_A, SoftBody3DSW *p_B);
+ ~BodySoftBodyPair3DSW();
+};
+
+#endif // BODY_PAIR_3D_SW_H
diff --git a/servers/physics_3d/collision_object_3d_sw.cpp b/servers/physics_3d/collision_object_3d_sw.cpp
index b06ade5ed3..293a7e6606 100644
--- a/servers/physics_3d/collision_object_3d_sw.cpp
+++ b/servers/physics_3d/collision_object_3d_sw.cpp
@@ -43,7 +43,7 @@ void CollisionObject3DSW::add_shape(Shape3DSW *p_shape, const Transform &p_trans
p_shape->add_owner(this);
if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+ PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
//_update_shapes();
//_shapes_changed();
@@ -56,7 +56,7 @@ void CollisionObject3DSW::set_shape(int p_index, Shape3DSW *p_shape) {
p_shape->add_owner(this);
if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+ PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
//_update_shapes();
//_shapes_changed();
@@ -68,7 +68,7 @@ void CollisionObject3DSW::set_shape_transform(int p_index, const Transform &p_tr
shapes.write[p_index].xform = p_transform;
shapes.write[p_index].xform_inv = p_transform.affine_inverse();
if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+ PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
//_update_shapes();
//_shapes_changed();
@@ -77,7 +77,7 @@ void CollisionObject3DSW::set_shape_transform(int p_index, const Transform &p_tr
void CollisionObject3DSW::set_shape_as_disabled(int p_idx, bool p_enable) {
shapes.write[p_idx].disabled = p_enable;
if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+ PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
}
@@ -106,7 +106,7 @@ void CollisionObject3DSW::remove_shape(int p_index) {
shapes.remove(p_index);
if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+ PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
}
//_update_shapes();
//_shapes_changed();
diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/collision_object_3d_sw.h
index 3847b81381..85221b7746 100644
--- a/servers/physics_3d/collision_object_3d_sw.h
+++ b/servers/physics_3d/collision_object_3d_sw.h
@@ -48,7 +48,8 @@ class CollisionObject3DSW : public ShapeOwner3DSW {
public:
enum Type {
TYPE_AREA,
- TYPE_BODY
+ TYPE_BODY,
+ TYPE_SOFT_BODY,
};
private:
@@ -129,8 +130,8 @@ public:
_FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
_FORCE_INLINE_ real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; }
- _FORCE_INLINE_ Transform get_transform() const { return transform; }
- _FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; }
+ _FORCE_INLINE_ const Transform &get_transform() const { return transform; }
+ _FORCE_INLINE_ const Transform &get_inv_transform() const { return inv_transform; }
_FORCE_INLINE_ Space3DSW *get_space() const { return space; }
_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; }
diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp
index b8e056f1f4..9d5448dbfa 100644
--- a/servers/physics_3d/collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/collision_solver_3d_sat.cpp
@@ -31,7 +31,38 @@
#include "collision_solver_3d_sat.h"
#include "core/math/geometry_3d.h"
-#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.02
+#include "gjk_epa.h"
+
+#define fallback_collision_solver gjk_epa_calculate_penetration
+
+// Cylinder SAT analytic methods and face-circle contact points for cylinder-trimesh and cylinder-box collision are based on ODE colliders.
+
+/*
+ * Cylinder-trimesh and Cylinder-box colliders by Alen Ladavac
+ * Ported to ODE by Nguyen Binh
+ */
+
+/*************************************************************************
+ * *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
+ * All rights reserved. Email: russ@q12.org Web: www.q12.org *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of EITHER: *
+ * (1) The GNU Lesser General Public License as published by the Free *
+ * Software Foundation; either version 2.1 of the License, or (at *
+ * your option) any later version. The text of the GNU Lesser *
+ * General Public License is included with this library in the *
+ * file LICENSE.TXT. *
+ * (2) The BSD-style license that is included with this library in *
+ * the file LICENSE-BSD.TXT. *
+ * *
+ * This library 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 files *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
+ * *
+ *************************************************************************/
struct _CollectorCallback {
CollisionSolver3DSW::CallbackResult callback;
@@ -43,9 +74,9 @@ struct _CollectorCallback {
_FORCE_INLINE_ void call(const Vector3 &p_point_A, const Vector3 &p_point_B) {
if (swap) {
- callback(p_point_B, p_point_A, userdata);
+ callback(p_point_B, 0, p_point_A, 0, userdata);
} else {
- callback(p_point_A, p_point_B, userdata);
+ callback(p_point_A, 0, p_point_B, 0, userdata);
}
}
};
@@ -82,6 +113,17 @@ static void _generate_contacts_point_face(const Vector3 *p_points_A, int p_point
p_callback->call(*p_points_A, closest_B);
}
+static void _generate_contacts_point_circle(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(p_point_count_A != 1);
+ ERR_FAIL_COND(p_point_count_B != 3);
+#endif
+
+ Vector3 closest_B = Plane(p_points_B[0], p_points_B[1], p_points_B[2]).project(*p_points_A);
+
+ p_callback->call(*p_points_A, closest_B);
+}
+
static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND(p_point_count_A != 2);
@@ -128,6 +170,104 @@ static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_
p_callback->call(closest_A, closest_B);
}
+static void _generate_contacts_edge_circle(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(p_point_count_A != 2);
+ ERR_FAIL_COND(p_point_count_B != 3);
+#endif
+
+ const Vector3 &circle_B_pos = p_points_B[0];
+ Vector3 circle_B_line_1 = p_points_B[1] - circle_B_pos;
+ Vector3 circle_B_line_2 = p_points_B[2] - circle_B_pos;
+
+ real_t circle_B_radius = circle_B_line_1.length();
+ Vector3 circle_B_normal = circle_B_line_1.cross(circle_B_line_2).normalized();
+
+ Plane circle_plane(circle_B_pos, circle_B_normal);
+
+ static const int max_clip = 2;
+ Vector3 contact_points[max_clip];
+ int num_points = 0;
+
+ // Project edge point in circle plane.
+ const Vector3 &edge_A_1 = p_points_A[0];
+ Vector3 proj_point_1 = circle_plane.project(edge_A_1);
+
+ Vector3 dist_vec = proj_point_1 - circle_B_pos;
+ real_t dist_sq = dist_vec.length_squared();
+
+ // Point 1 is inside disk, add as contact point.
+ if (dist_sq <= circle_B_radius * circle_B_radius) {
+ contact_points[num_points] = edge_A_1;
+ ++num_points;
+ }
+
+ const Vector3 &edge_A_2 = p_points_A[1];
+ Vector3 proj_point_2 = circle_plane.project(edge_A_2);
+
+ Vector3 dist_vec_2 = proj_point_2 - circle_B_pos;
+ real_t dist_sq_2 = dist_vec_2.length_squared();
+
+ // Point 2 is inside disk, add as contact point.
+ if (dist_sq_2 <= circle_B_radius * circle_B_radius) {
+ contact_points[num_points] = edge_A_2;
+ ++num_points;
+ }
+
+ if (num_points < 2) {
+ Vector3 line_vec = proj_point_2 - proj_point_1;
+ real_t line_length_sq = line_vec.length_squared();
+
+ // Create a quadratic formula of the form ax^2 + bx + c = 0
+ real_t a, b, c;
+
+ a = line_length_sq;
+ b = 2.0 * dist_vec.dot(line_vec);
+ c = dist_sq - circle_B_radius * circle_B_radius;
+
+ // Solve for t.
+ real_t sqrtterm = b * b - 4.0 * a * c;
+
+ // If the term we intend to square root is less than 0 then the answer won't be real,
+ // so the line doesn't intersect.
+ if (sqrtterm >= 0) {
+ sqrtterm = Math::sqrt(sqrtterm);
+
+ Vector3 edge_dir = edge_A_2 - edge_A_1;
+
+ real_t fraction_1 = (-b - sqrtterm) / (2.0 * a);
+ if ((fraction_1 > 0.0) && (fraction_1 < 1.0)) {
+ Vector3 face_point_1 = edge_A_1 + fraction_1 * edge_dir;
+ ERR_FAIL_COND(num_points >= max_clip);
+ contact_points[num_points] = face_point_1;
+ ++num_points;
+ }
+
+ real_t fraction_2 = (-b + sqrtterm) / (2.0 * a);
+ if ((fraction_2 > 0.0) && (fraction_2 < 1.0) && !Math::is_equal_approx(fraction_1, fraction_2)) {
+ Vector3 face_point_2 = edge_A_1 + fraction_2 * edge_dir;
+ ERR_FAIL_COND(num_points >= max_clip);
+ contact_points[num_points] = face_point_2;
+ ++num_points;
+ }
+ }
+ }
+
+ // Generate contact points.
+ for (int i = 0; i < num_points; i++) {
+ const Vector3 &contact_point_A = contact_points[i];
+
+ real_t d = circle_plane.distance_to(contact_point_A);
+ Vector3 closest_B = contact_point_A - circle_plane.normal * d;
+
+ if (p_callback->normal.dot(contact_point_A) >= p_callback->normal.dot(closest_B)) {
+ continue;
+ }
+
+ p_callback->call(contact_point_A, closest_B);
+ }
+}
+
static void _generate_contacts_face_face(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND(p_point_count_A < 2);
@@ -217,36 +357,229 @@ static void _generate_contacts_face_face(const Vector3 *p_points_A, int p_point_
}
}
-static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
+static void _generate_contacts_face_circle(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(p_point_count_A < 3);
+ ERR_FAIL_COND(p_point_count_B != 3);
+#endif
+
+ const Vector3 &circle_B_pos = p_points_B[0];
+ Vector3 circle_B_line_1 = p_points_B[1] - circle_B_pos;
+ Vector3 circle_B_line_2 = p_points_B[2] - circle_B_pos;
+
+ // Clip face with circle segments.
+ static const int circle_segments = 8;
+ Vector3 circle_points[circle_segments];
+
+ real_t angle_delta = 2.0 * Math_PI / circle_segments;
+
+ for (int i = 0; i < circle_segments; ++i) {
+ Vector3 point_pos = circle_B_pos;
+ point_pos += circle_B_line_1 * Math::cos(i * angle_delta);
+ point_pos += circle_B_line_2 * Math::sin(i * angle_delta);
+ circle_points[i] = point_pos;
+ }
+
+ _generate_contacts_face_face(p_points_A, p_point_count_A, circle_points, circle_segments, p_callback);
+
+ // Clip face with circle plane.
+ Vector3 circle_B_normal = circle_B_line_1.cross(circle_B_line_2).normalized();
+
+ Plane circle_plane(circle_B_pos, circle_B_normal);
+
+ static const int max_clip = 32;
+ Vector3 contact_points[max_clip];
+ int num_points = 0;
+
+ for (int i = 0; i < p_point_count_A; i++) {
+ int i_n = (i + 1) % p_point_count_A;
+
+ const Vector3 &edge0_A = p_points_A[i];
+ const Vector3 &edge1_A = p_points_A[i_n];
+
+ real_t dist0 = circle_plane.distance_to(edge0_A);
+ real_t dist1 = circle_plane.distance_to(edge1_A);
+
+ // First point in front of plane, generate contact point.
+ if (dist0 * circle_plane.d >= 0) {
+ ERR_FAIL_COND(num_points >= max_clip);
+ contact_points[num_points] = edge0_A;
+ ++num_points;
+ }
+
+ // Points on different sides, generate contact point.
+ if (dist0 * dist1 < 0) {
+ // calculate intersection
+ Vector3 rel = edge1_A - edge0_A;
+ real_t den = circle_plane.normal.dot(rel);
+ real_t dist = -(circle_plane.normal.dot(edge0_A) - circle_plane.d) / den;
+ Vector3 inters = edge0_A + rel * dist;
+
+ ERR_FAIL_COND(num_points >= max_clip);
+ contact_points[num_points] = inters;
+ ++num_points;
+ }
+ }
+
+ // Generate contact points.
+ for (int i = 0; i < num_points; i++) {
+ const Vector3 &contact_point_A = contact_points[i];
+
+ real_t d = circle_plane.distance_to(contact_point_A);
+ Vector3 closest_B = contact_point_A - circle_plane.normal * d;
+
+ if (p_callback->normal.dot(contact_point_A) >= p_callback->normal.dot(closest_B)) {
+ continue;
+ }
+
+ p_callback->call(contact_point_A, closest_B);
+ }
+}
+
+static void _generate_contacts_circle_circle(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(p_point_count_A != 3);
+ ERR_FAIL_COND(p_point_count_B != 3);
+#endif
+
+ const Vector3 &circle_A_pos = p_points_A[0];
+ Vector3 circle_A_line_1 = p_points_A[1] - circle_A_pos;
+ Vector3 circle_A_line_2 = p_points_A[2] - circle_A_pos;
+
+ real_t circle_A_radius = circle_A_line_1.length();
+ Vector3 circle_A_normal = circle_A_line_1.cross(circle_A_line_2).normalized();
+
+ const Vector3 &circle_B_pos = p_points_B[0];
+ Vector3 circle_B_line_1 = p_points_B[1] - circle_B_pos;
+ Vector3 circle_B_line_2 = p_points_B[2] - circle_B_pos;
+
+ real_t circle_B_radius = circle_B_line_1.length();
+ Vector3 circle_B_normal = circle_B_line_1.cross(circle_B_line_2).normalized();
+
+ static const int max_clip = 4;
+ Vector3 contact_points[max_clip];
+ int num_points = 0;
+
+ Vector3 centers_diff = circle_B_pos - circle_A_pos;
+ Vector3 norm_proj = circle_A_normal.dot(centers_diff) * circle_A_normal;
+ Vector3 comp_proj = centers_diff - norm_proj;
+ real_t proj_dist = comp_proj.length();
+ if (!Math::is_zero_approx(proj_dist)) {
+ comp_proj /= proj_dist;
+ if ((proj_dist > circle_A_radius - circle_B_radius) && (proj_dist > circle_B_radius - circle_A_radius)) {
+ // Circles are overlapping, use the 2 points of intersection as contacts.
+ real_t radius_a_sqr = circle_A_radius * circle_A_radius;
+ real_t radius_b_sqr = circle_B_radius * circle_B_radius;
+ real_t d_sqr = proj_dist * proj_dist;
+ real_t s = (1.0 + (radius_a_sqr - radius_b_sqr) / d_sqr) * 0.5;
+ real_t h = Math::sqrt(MAX(radius_a_sqr - d_sqr * s * s, 0.0));
+ Vector3 midpoint = circle_A_pos + s * comp_proj * proj_dist;
+ Vector3 h_vec = h * circle_A_normal.cross(comp_proj);
+
+ Vector3 point_A = midpoint + h_vec;
+ contact_points[num_points] = point_A;
+ ++num_points;
+
+ point_A = midpoint - h_vec;
+ contact_points[num_points] = point_A;
+ ++num_points;
+
+ // Add 2 points from circle A and B along the line between the centers.
+ point_A = circle_A_pos + comp_proj * circle_A_radius;
+ contact_points[num_points] = point_A;
+ ++num_points;
+
+ point_A = circle_B_pos - comp_proj * circle_B_radius - norm_proj;
+ contact_points[num_points] = point_A;
+ ++num_points;
+ } // Otherwise one circle is inside the other one, use 3 arbitrary equidistant points.
+ } // Otherwise circles are concentric, use 3 arbitrary equidistant points.
+
+ if (num_points == 0) {
+ // Generate equidistant points.
+ if (circle_A_radius < circle_B_radius) {
+ // Circle A inside circle B.
+ for (int i = 0; i < 3; ++i) {
+ Vector3 circle_A_point = circle_A_pos;
+ circle_A_point += circle_A_line_1 * Math::cos(2.0 * Math_PI * i / 3.0);
+ circle_A_point += circle_A_line_2 * Math::sin(2.0 * Math_PI * i / 3.0);
+
+ contact_points[num_points] = circle_A_point;
+ ++num_points;
+ }
+ } else {
+ // Circle B inside circle A.
+ for (int i = 0; i < 3; ++i) {
+ Vector3 circle_B_point = circle_B_pos;
+ circle_B_point += circle_B_line_1 * Math::cos(2.0 * Math_PI * i / 3.0);
+ circle_B_point += circle_B_line_2 * Math::sin(2.0 * Math_PI * i / 3.0);
+
+ Vector3 circle_A_point = circle_B_point - norm_proj;
+
+ contact_points[num_points] = circle_A_point;
+ ++num_points;
+ }
+ }
+ }
+
+ Plane circle_B_plane(circle_B_pos, circle_B_normal);
+
+ // Generate contact points.
+ for (int i = 0; i < num_points; i++) {
+ const Vector3 &contact_point_A = contact_points[i];
+
+ real_t d = circle_B_plane.distance_to(contact_point_A);
+ Vector3 closest_B = contact_point_A - circle_B_plane.normal * d;
+
+ if (p_callback->normal.dot(contact_point_A) >= p_callback->normal.dot(closest_B)) {
+ continue;
+ }
+
+ p_callback->call(contact_point_A, closest_B);
+ }
+}
+
+static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_point_count_A, Shape3DSW::FeatureType p_feature_type_A, const Vector3 *p_points_B, int p_point_count_B, Shape3DSW::FeatureType p_feature_type_B, _CollectorCallback *p_callback) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND(p_point_count_A < 1);
ERR_FAIL_COND(p_point_count_B < 1);
#endif
- static const GenerateContactsFunc generate_contacts_func_table[3][3] = {
+ static const GenerateContactsFunc generate_contacts_func_table[4][4] = {
{
_generate_contacts_point_point,
_generate_contacts_point_edge,
_generate_contacts_point_face,
+ _generate_contacts_point_circle,
},
{
nullptr,
_generate_contacts_edge_edge,
_generate_contacts_face_face,
+ _generate_contacts_edge_circle,
},
{
nullptr,
nullptr,
_generate_contacts_face_face,
- }
+ _generate_contacts_face_circle,
+ },
+ {
+ nullptr,
+ nullptr,
+ nullptr,
+ _generate_contacts_circle_circle,
+ },
};
int pointcount_B;
int pointcount_A;
const Vector3 *points_A;
const Vector3 *points_B;
+ int version_A;
+ int version_B;
- if (p_point_count_A > p_point_count_B) {
+ if (p_feature_type_A > p_feature_type_B) {
//swap
p_callback->swap = !p_callback->swap;
p_callback->normal = -p_callback->normal;
@@ -255,16 +588,17 @@ static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_po
pointcount_A = p_point_count_B;
points_A = p_points_B;
points_B = p_points_A;
+ version_A = p_feature_type_B;
+ version_B = p_feature_type_A;
} else {
pointcount_B = p_point_count_B;
pointcount_A = p_point_count_A;
points_A = p_points_A;
points_B = p_points_B;
+ version_A = p_feature_type_A;
+ version_B = p_feature_type_B;
}
- int version_A = (pointcount_A > 3 ? 3 : pointcount_A) - 1;
- int version_B = (pointcount_B > 3 ? 3 : pointcount_B) - 1;
-
GenerateContactsFunc contacts_func = generate_contacts_func_table[version_A][version_B];
ERR_FAIL_COND(!contacts_func);
contacts_func(points_A, pointcount_A, points_B, pointcount_B, p_callback);
@@ -292,7 +626,7 @@ public:
}
}
- _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis) {
+ _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis, bool p_directional = false) {
Vector3 axis = p_axis;
if (Math::abs(axis.x) < CMP_EPSILON &&
@@ -328,7 +662,12 @@ public:
//use the smallest depth
if (min_B < 0.0) { // could be +0.0, we don't want it to become -0.0
- min_B = -min_B;
+ if (p_directional) {
+ min_B = max_B;
+ axis = -axis;
+ } else {
+ min_B = -min_B;
+ }
}
if (max_B < min_B) {
@@ -346,6 +685,17 @@ public:
return true;
}
+ static _FORCE_INLINE_ void test_contact_points(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+ SeparatorAxisTest<ShapeA, ShapeB, withMargin> *separator = (SeparatorAxisTest<ShapeA, ShapeB, withMargin> *)p_userdata;
+ Vector3 axis = (p_point_B - p_point_A);
+ real_t depth = axis.length();
+
+ // Filter out bogus directions with a treshold and re-testing axis.
+ if (separator->best_depth - depth > 0.001) {
+ separator->test_axis(axis / depth);
+ }
+ }
+
_FORCE_INLINE_ void generate_contacts() {
// nothing to do, don't generate
if (best_axis == Vector3(0.0, 0.0, 0.0)) {
@@ -365,7 +715,8 @@ public:
Vector3 supports_A[max_supports];
int support_count_A;
- shape_A->get_supports(transform_A->basis.xform_inv(-best_axis).normalized(), max_supports, supports_A, support_count_A);
+ Shape3DSW::FeatureType support_type_A;
+ shape_A->get_supports(transform_A->basis.xform_inv(-best_axis).normalized(), max_supports, supports_A, support_count_A, support_type_A);
for (int i = 0; i < support_count_A; i++) {
supports_A[i] = transform_A->xform(supports_A[i]);
}
@@ -378,7 +729,8 @@ public:
Vector3 supports_B[max_supports];
int support_count_B;
- shape_B->get_supports(transform_B->basis.xform_inv(best_axis).normalized(), max_supports, supports_B, support_count_B);
+ Shape3DSW::FeatureType support_type_B;
+ shape_B->get_supports(transform_B->basis.xform_inv(best_axis).normalized(), max_supports, supports_B, support_count_B, support_type_B);
for (int i = 0; i < support_count_B; i++) {
supports_B[i] = transform_B->xform(supports_B[i]);
}
@@ -393,7 +745,7 @@ public:
if (callback->prev_axis) {
*callback->prev_axis = best_axis;
}
- _generate_contacts_from_supports(supports_A, support_count_A, supports_B, support_count_B, callback);
+ _generate_contacts_from_supports(supports_A, support_count_A, support_type_A, supports_B, support_count_B, support_type_B, callback);
callback->collided = true;
}
@@ -498,7 +850,7 @@ static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform &p_t
//capsule sphere 1, sphere
- Vector3 capsule_axis = p_transform_b.basis.get_axis(2) * (capsule_B->get_height() * 0.5);
+ Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5);
Vector3 capsule_ball_1 = p_transform_b.origin + capsule_axis;
@@ -529,6 +881,61 @@ static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform &p_t
template <bool withMargin>
static void _collision_sphere_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
+ const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
+
+ SeparatorAxisTest<SphereShape3DSW, CylinderShape3DSW, withMargin> separator(sphere_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+
+ if (!separator.test_previous_axis()) {
+ return;
+ }
+
+ // Cylinder B end caps.
+ Vector3 cylinder_B_axis = p_transform_b.basis.get_axis(1).normalized();
+ if (!separator.test_axis(cylinder_B_axis)) {
+ return;
+ }
+
+ Vector3 cylinder_diff = p_transform_b.origin - p_transform_a.origin;
+
+ // Cylinder B lateral surface.
+ if (!separator.test_axis(cylinder_B_axis.cross(cylinder_diff).cross(cylinder_B_axis).normalized())) {
+ return;
+ }
+
+ // Closest point to cylinder caps.
+ const Vector3 &sphere_center = p_transform_a.origin;
+ Vector3 cyl_axis = p_transform_b.basis.get_axis(1);
+ Vector3 cap_axis = p_transform_b.basis.get_axis(0);
+ real_t height_scale = cyl_axis.length();
+ real_t cap_dist = cylinder_B->get_height() * 0.5 * height_scale;
+ cyl_axis /= height_scale;
+ real_t radius_scale = cap_axis.length();
+ real_t cap_radius = cylinder_B->get_radius() * radius_scale;
+
+ for (int i = 0; i < 2; i++) {
+ Vector3 cap_dir = ((i == 0) ? cyl_axis : -cyl_axis);
+ Vector3 cap_pos = p_transform_b.origin + cap_dir * cap_dist;
+
+ Vector3 closest_point;
+
+ Vector3 diff = sphere_center - cap_pos;
+ Vector3 proj = diff - cap_dir.dot(diff) * cap_dir;
+
+ real_t proj_len = proj.length();
+ if (Math::is_zero_approx(proj_len)) {
+ // Point is equidistant to all circle points.
+ continue;
+ }
+
+ closest_point = cap_pos + (cap_radius / proj_len) * proj;
+
+ if (!separator.test_axis((closest_point - sphere_center).normalized())) {
+ return;
+ }
+ }
+
+ separator.generate_contacts();
}
template <bool withMargin>
@@ -604,23 +1011,31 @@ static void _collision_sphere_face(const Shape3DSW *p_a, const Transform &p_tran
p_transform_b.xform(face_B->vertex[2]),
};
- if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) {
+ Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
+
+ if (!separator.test_axis(normal, !face_B->backface_collision)) {
return;
}
// edges and points of B
for (int i = 0; i < 3; i++) {
Vector3 n1 = vertex[i] - p_transform_a.origin;
+ if (n1.dot(normal) < 0.0) {
+ n1 *= -1.0;
+ }
- if (!separator.test_axis(n1.normalized())) {
+ if (!separator.test_axis(n1.normalized(), !face_B->backface_collision)) {
return;
}
Vector3 n2 = vertex[(i + 1) % 3] - vertex[i];
Vector3 axis = n1.cross(n2).cross(n2).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
- if (!separator.test_axis(axis)) {
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
return;
}
}
@@ -739,14 +1154,14 @@ static void _collision_box_capsule(const Shape3DSW *p_a, const Transform &p_tran
// faces of A
for (int i = 0; i < 3; i++) {
- Vector3 axis = p_transform_a.basis.get_axis(i);
+ Vector3 axis = p_transform_a.basis.get_axis(i).normalized();
if (!separator.test_axis(axis)) {
return;
}
}
- Vector3 cyl_axis = p_transform_b.basis.get_axis(2).normalized();
+ Vector3 cyl_axis = p_transform_b.basis.get_axis(1).normalized();
// edges of A, capsule cylinder
@@ -791,7 +1206,7 @@ static void _collision_box_capsule(const Shape3DSW *p_a, const Transform &p_tran
// capsule balls, edges of A
for (int i = 0; i < 2; i++) {
- Vector3 capsule_axis = p_transform_b.basis.get_axis(2) * (capsule_B->get_height() * 0.5);
+ Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5);
Vector3 sphere_pos = p_transform_b.origin + ((i == 0) ? capsule_axis : -capsule_axis);
@@ -826,6 +1241,115 @@ static void _collision_box_capsule(const Shape3DSW *p_a, const Transform &p_tran
template <bool withMargin>
static void _collision_box_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a);
+ const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
+
+ SeparatorAxisTest<BoxShape3DSW, CylinderShape3DSW, withMargin> separator(box_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+
+ if (!separator.test_previous_axis()) {
+ return;
+ }
+
+ // Faces of A.
+ for (int i = 0; i < 3; i++) {
+ Vector3 axis = p_transform_a.basis.get_axis(i).normalized();
+
+ if (!separator.test_axis(axis)) {
+ return;
+ }
+ }
+
+ Vector3 cyl_axis = p_transform_b.basis.get_axis(1).normalized();
+
+ // Cylinder end caps.
+ {
+ if (!separator.test_axis(cyl_axis)) {
+ return;
+ }
+ }
+
+ // Edges of A, cylinder lateral surface.
+ for (int i = 0; i < 3; i++) {
+ Vector3 box_axis = p_transform_a.basis.get_axis(i);
+ Vector3 axis = box_axis.cross(cyl_axis);
+ if (Math::is_zero_approx(axis.length_squared())) {
+ continue;
+ }
+
+ if (!separator.test_axis(axis.normalized())) {
+ return;
+ }
+ }
+
+ // Gather points of A.
+ Vector3 vertices_A[8];
+ Vector3 box_extent = box_A->get_half_extents();
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ for (int k = 0; k < 2; k++) {
+ Vector3 extent = box_extent;
+ extent.x *= (i * 2 - 1);
+ extent.y *= (j * 2 - 1);
+ extent.z *= (k * 2 - 1);
+ Vector3 &point = vertices_A[i * 2 * 2 + j * 2 + k];
+ point = p_transform_a.origin;
+ for (int l = 0; l < 3; l++) {
+ point += p_transform_a.basis.get_axis(l) * extent[l];
+ }
+ }
+ }
+ }
+
+ // Points of A, cylinder lateral surface.
+ for (int i = 0; i < 8; i++) {
+ const Vector3 &point = vertices_A[i];
+ Vector3 axis = Plane(cyl_axis, 0).project(point).normalized();
+
+ if (!separator.test_axis(axis)) {
+ return;
+ }
+ }
+
+ // Edges of A, cylinder end caps rim.
+ int edges_start_A[12] = { 0, 2, 4, 6, 0, 1, 4, 5, 0, 1, 2, 3 };
+ int edges_end_A[12] = { 1, 3, 5, 7, 2, 3, 6, 7, 4, 5, 6, 7 };
+
+ Vector3 cap_axis = cyl_axis * (cylinder_B->get_height() * 0.5);
+
+ for (int i = 0; i < 2; i++) {
+ Vector3 cap_pos = p_transform_b.origin + ((i == 0) ? cap_axis : -cap_axis);
+
+ for (int e = 0; e < 12; e++) {
+ const Vector3 &edge_start = vertices_A[edges_start_A[e]];
+ const Vector3 &edge_end = vertices_A[edges_end_A[e]];
+
+ Vector3 edge_dir = (edge_end - edge_start);
+ edge_dir.normalize();
+
+ real_t edge_dot = edge_dir.dot(cyl_axis);
+ if (Math::is_zero_approx(edge_dot)) {
+ // Edge is perpendicular to cylinder axis.
+ continue;
+ }
+
+ // Calculate intersection between edge and circle plane.
+ Vector3 edge_diff = cap_pos - edge_start;
+ real_t diff_dot = edge_diff.dot(cyl_axis);
+ Vector3 intersection = edge_start + edge_dir * diff_dot / edge_dot;
+
+ // Calculate tangent that touches intersection.
+ Vector3 tangent = (cap_pos - intersection).cross(cyl_axis);
+
+ // Axis is orthogonal both to tangent and edge direction.
+ Vector3 axis = tangent.cross(edge_dir);
+
+ if (!separator.test_axis(axis.normalized())) {
+ return;
+ }
+ }
+ }
+
+ separator.generate_contacts();
}
template <bool withMargin>
@@ -956,15 +1480,20 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo
p_transform_b.xform(face_B->vertex[2]),
};
- if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) {
+ Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
+
+ if (!separator.test_axis(normal, !face_B->backface_collision)) {
return;
}
// faces of A
for (int i = 0; i < 3; i++) {
Vector3 axis = p_transform_a.basis.get_axis(i).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
- if (!separator.test_axis(axis)) {
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
return;
}
}
@@ -975,9 +1504,12 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo
Vector3 e = vertex[i] - vertex[(i + 1) % 3];
for (int j = 0; j < 3; j++) {
- Vector3 axis = p_transform_a.basis.get_axis(j);
+ Vector3 axis = e.cross(p_transform_a.basis.get_axis(j)).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
- if (!separator.test_axis(e.cross(axis).normalized())) {
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
return;
}
}
@@ -997,8 +1529,11 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo
(cnormal_a.z < 0) ? -box_A->get_half_extents().z : box_A->get_half_extents().z));
Vector3 axis_ab = support_a - vertex[v];
+ if (axis_ab.dot(normal) < 0.0) {
+ axis_ab *= -1.0;
+ }
- if (!separator.test_axis(axis_ab.normalized())) {
+ if (!separator.test_axis(axis_ab.normalized(), !face_B->backface_collision)) {
return;
}
@@ -1008,7 +1543,12 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo
//a ->b
Vector3 axis_a = p_transform_a.basis.get_axis(i);
- if (!separator.test_axis(axis_ab.cross(axis_a).cross(axis_a).normalized())) {
+ Vector3 axis = axis_ab.cross(axis_a).cross(axis_a).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
+
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
return;
}
}
@@ -1033,7 +1573,12 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo
Vector3 n = (p2 - p1);
- if (!separator.test_axis((point - p2).cross(n).cross(n).normalized())) {
+ Vector3 axis = (point - p2).cross(n).cross(n).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
+
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
return;
}
}
@@ -1058,8 +1603,8 @@ static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform &p_
// some values
- Vector3 capsule_A_axis = p_transform_a.basis.get_axis(2) * (capsule_A->get_height() * 0.5);
- Vector3 capsule_B_axis = p_transform_b.basis.get_axis(2) * (capsule_B->get_height() * 0.5);
+ Vector3 capsule_A_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5);
+ Vector3 capsule_B_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5);
Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis;
Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis;
@@ -1111,6 +1656,64 @@ static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform &p_
template <bool withMargin>
static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a);
+ const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
+
+ SeparatorAxisTest<CapsuleShape3DSW, CylinderShape3DSW, withMargin> separator(capsule_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+
+ if (!separator.test_previous_axis()) {
+ return;
+ }
+
+ // Cylinder B end caps.
+ Vector3 cylinder_B_axis = p_transform_b.basis.get_axis(1).normalized();
+ if (!separator.test_axis(cylinder_B_axis)) {
+ return;
+ }
+
+ // Cylinder edge against capsule balls.
+
+ Vector3 capsule_A_axis = p_transform_a.basis.get_axis(1);
+
+ Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis * (capsule_A->get_height() * 0.5);
+ Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis * (capsule_A->get_height() * 0.5);
+
+ if (!separator.test_axis((p_transform_b.origin - capsule_A_ball_1).cross(cylinder_B_axis).cross(cylinder_B_axis).normalized())) {
+ return;
+ }
+
+ if (!separator.test_axis((p_transform_b.origin - capsule_A_ball_2).cross(cylinder_B_axis).cross(cylinder_B_axis).normalized())) {
+ return;
+ }
+
+ // Cylinder edge against capsule edge.
+
+ Vector3 center_diff = p_transform_b.origin - p_transform_a.origin;
+
+ if (!separator.test_axis(capsule_A_axis.cross(center_diff).cross(capsule_A_axis).normalized())) {
+ return;
+ }
+
+ if (!separator.test_axis(cylinder_B_axis.cross(center_diff).cross(cylinder_B_axis).normalized())) {
+ return;
+ }
+
+ real_t proj = capsule_A_axis.cross(cylinder_B_axis).cross(cylinder_B_axis).dot(capsule_A_axis);
+ if (Math::is_zero_approx(proj)) {
+ // Parallel capsule and cylinder axes, handle with specific axes only.
+ // Note: GJKEPA with no margin can lead to degenerate cases in this situation.
+ separator.generate_contacts();
+ return;
+ }
+
+ CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CapsuleShape3DSW, CylinderShape3DSW, withMargin>::test_contact_points;
+
+ // Fallback to generic algorithm to find the best separating axis.
+ if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) {
+ return;
+ }
+
+ separator.generate_contacts();
}
template <bool withMargin>
@@ -1146,7 +1749,7 @@ static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transf
for (int i = 0; i < edge_count; i++) {
// cylinder
Vector3 edge_axis = p_transform_b.basis.xform(vertices[edges[i].a]) - p_transform_b.basis.xform(vertices[edges[i].b]);
- Vector3 axis = edge_axis.cross(p_transform_a.basis.get_axis(2)).normalized();
+ Vector3 axis = edge_axis.cross(p_transform_a.basis.get_axis(1)).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1158,7 +1761,7 @@ static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transf
for (int i = 0; i < 2; i++) {
// edges of B, capsule cylinder
- Vector3 capsule_axis = p_transform_a.basis.get_axis(2) * (capsule_A->get_height() * 0.5);
+ Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5);
Vector3 sphere_pos = p_transform_a.origin + ((i == 0) ? capsule_axis : -capsule_axis);
@@ -1190,24 +1793,35 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_tra
p_transform_b.xform(face_B->vertex[2]),
};
- if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) {
+ Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
+
+ if (!separator.test_axis(normal, !face_B->backface_collision)) {
return;
}
// edges of B, capsule cylinder
- Vector3 capsule_axis = p_transform_a.basis.get_axis(2) * (capsule_A->get_height() * 0.5);
+ Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5);
for (int i = 0; i < 3; i++) {
// edge-cylinder
Vector3 edge_axis = vertex[i] - vertex[(i + 1) % 3];
+
Vector3 axis = edge_axis.cross(capsule_axis).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
- if (!separator.test_axis(axis)) {
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
return;
}
- if (!separator.test_axis((p_transform_a.origin - vertex[i]).cross(capsule_axis).cross(capsule_axis).normalized())) {
+ Vector3 dir_axis = (p_transform_a.origin - vertex[i]).cross(capsule_axis).cross(capsule_axis).normalized();
+ if (dir_axis.dot(normal) < 0.0) {
+ dir_axis *= -1.0;
+ }
+
+ if (!separator.test_axis(dir_axis, !face_B->backface_collision)) {
return;
}
@@ -1216,16 +1830,22 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_tra
Vector3 sphere_pos = p_transform_a.origin + ((j == 0) ? capsule_axis : -capsule_axis);
Vector3 n1 = sphere_pos - vertex[i];
+ if (n1.dot(normal) < 0.0) {
+ n1 *= -1.0;
+ }
- if (!separator.test_axis(n1.normalized())) {
+ if (!separator.test_axis(n1.normalized(), !face_B->backface_collision)) {
return;
}
Vector3 n2 = edge_axis;
axis = n1.cross(n2).cross(n2);
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
- if (!separator.test_axis(axis.normalized())) {
+ if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) {
return;
}
}
@@ -1236,14 +1856,178 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_tra
template <bool withMargin>
static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a);
+ const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
+
+ SeparatorAxisTest<CylinderShape3DSW, CylinderShape3DSW, withMargin> separator(cylinder_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+
+ Vector3 cylinder_A_axis = p_transform_a.basis.get_axis(1);
+ Vector3 cylinder_B_axis = p_transform_b.basis.get_axis(1);
+
+ if (!separator.test_previous_axis()) {
+ return;
+ }
+
+ // Cylinder A end caps.
+ if (!separator.test_axis(cylinder_A_axis.normalized())) {
+ return;
+ }
+
+ // Cylinder B end caps.
+ if (!separator.test_axis(cylinder_A_axis.normalized())) {
+ return;
+ }
+
+ Vector3 cylinder_diff = p_transform_b.origin - p_transform_a.origin;
+
+ // Cylinder A lateral surface.
+ if (!separator.test_axis(cylinder_A_axis.cross(cylinder_diff).cross(cylinder_A_axis).normalized())) {
+ return;
+ }
+
+ // Cylinder B lateral surface.
+ if (!separator.test_axis(cylinder_B_axis.cross(cylinder_diff).cross(cylinder_B_axis).normalized())) {
+ return;
+ }
+
+ real_t proj = cylinder_A_axis.cross(cylinder_B_axis).cross(cylinder_B_axis).dot(cylinder_A_axis);
+ if (Math::is_zero_approx(proj)) {
+ // Parallel cylinders, handle with specific axes only.
+ // Note: GJKEPA with no margin can lead to degenerate cases in this situation.
+ separator.generate_contacts();
+ return;
+ }
+
+ CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CylinderShape3DSW, CylinderShape3DSW, withMargin>::test_contact_points;
+
+ // Fallback to generic algorithm to find the best separating axis.
+ if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) {
+ return;
+ }
+
+ separator.generate_contacts();
}
template <bool withMargin>
static void _collision_cylinder_convex_polygon(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a);
+ const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b);
+
+ SeparatorAxisTest<CylinderShape3DSW, ConvexPolygonShape3DSW, withMargin> separator(cylinder_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+
+ CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CylinderShape3DSW, ConvexPolygonShape3DSW, withMargin>::test_contact_points;
+
+ // Fallback to generic algorithm to find the best separating axis.
+ if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) {
+ return;
+ }
+
+ separator.generate_contacts();
}
template <bool withMargin>
static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a);
+ const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b);
+
+ SeparatorAxisTest<CylinderShape3DSW, FaceShape3DSW, withMargin> separator(cylinder_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+
+ if (!separator.test_previous_axis()) {
+ return;
+ }
+
+ Vector3 vertex[3] = {
+ p_transform_b.xform(face_B->vertex[0]),
+ p_transform_b.xform(face_B->vertex[1]),
+ p_transform_b.xform(face_B->vertex[2]),
+ };
+
+ Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
+
+ // Face B normal.
+ if (!separator.test_axis(normal, !face_B->backface_collision)) {
+ return;
+ }
+
+ Vector3 cyl_axis = p_transform_a.basis.get_axis(1).normalized();
+ if (cyl_axis.dot(normal) < 0.0) {
+ cyl_axis *= -1.0;
+ }
+
+ // Cylinder end caps.
+ if (!separator.test_axis(cyl_axis, !face_B->backface_collision)) {
+ return;
+ }
+
+ // Edges of B, cylinder lateral surface.
+ for (int i = 0; i < 3; i++) {
+ Vector3 edge_axis = vertex[i] - vertex[(i + 1) % 3];
+ Vector3 axis = edge_axis.cross(cyl_axis);
+ if (Math::is_zero_approx(axis.length_squared())) {
+ continue;
+ }
+
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
+
+ if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) {
+ return;
+ }
+ }
+
+ // Points of B, cylinder lateral surface.
+ for (int i = 0; i < 3; i++) {
+ const Vector3 &point = vertex[i];
+ Vector3 axis = Plane(cyl_axis, 0).project(point).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
+
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
+ return;
+ }
+ }
+
+ // Edges of B, cylinder end caps rim.
+ Vector3 cap_axis = cyl_axis * (cylinder_A->get_height() * 0.5);
+
+ for (int i = 0; i < 2; i++) {
+ Vector3 cap_pos = p_transform_a.origin + ((i == 0) ? cap_axis : -cap_axis);
+
+ for (int j = 0; j < 3; j++) {
+ const Vector3 &edge_start = vertex[j];
+ const Vector3 &edge_end = vertex[(j + 1) % 3];
+ Vector3 edge_dir = edge_end - edge_start;
+ edge_dir.normalize();
+
+ real_t edge_dot = edge_dir.dot(cyl_axis);
+ if (Math::is_zero_approx(edge_dot)) {
+ // Edge is perpendicular to cylinder axis.
+ continue;
+ }
+
+ // Calculate intersection between edge and circle plane.
+ Vector3 edge_diff = cap_pos - edge_start;
+ real_t diff_dot = edge_diff.dot(cyl_axis);
+ Vector3 intersection = edge_start + edge_dir * diff_dot / edge_dot;
+
+ // Calculate tangent that touches intersection.
+ Vector3 tangent = (cap_pos - intersection).cross(cyl_axis);
+
+ // Axis is orthogonal both to tangent and edge direction.
+ Vector3 axis = tangent.cross(edge_dir);
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
+
+ if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) {
+ return;
+ }
+ }
+ }
+
+ separator.generate_contacts();
}
template <bool withMargin>
@@ -1377,7 +2161,9 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
p_transform_b.xform(face_B->vertex[2]),
};
- if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) {
+ Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
+
+ if (!separator.test_axis(normal, !face_B->backface_collision)) {
return;
}
@@ -1385,8 +2171,11 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
for (int i = 0; i < face_count; i++) {
//Vector3 axis = p_transform_a.xform( faces[i].plane ).normal;
Vector3 axis = p_transform_a.basis.xform(faces[i].plane.normal).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
- if (!separator.test_axis(axis)) {
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
return;
}
}
@@ -1399,8 +2188,11 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
Vector3 e2 = vertex[j] - vertex[(j + 1) % 3];
Vector3 axis = e1.cross(e2).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
- if (!separator.test_axis(axis)) {
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
return;
}
}
@@ -1412,7 +2204,12 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
Vector3 va = p_transform_a.xform(vertices[i]);
for (int j = 0; j < 3; j++) {
- if (!separator.test_axis((va - vertex[j]).normalized())) {
+ Vector3 axis = (va - vertex[j]).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
+
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
return;
}
}
@@ -1427,7 +2224,12 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
for (int j = 0; j < 3; j++) {
Vector3 e3 = vertex[j];
- if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) {
+ Vector3 axis = (e1 - e3).cross(n).cross(n).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
+
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
return;
}
}
@@ -1441,7 +2243,12 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
for (int j = 0; j < vertex_count; j++) {
Vector3 e3 = p_transform_a.xform(vertices[j]);
- if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) {
+ Vector3 axis = (e1 - e3).cross(n).cross(n).normalized();
+ if (axis.dot(normal) < 0.0) {
+ axis *= -1.0;
+ }
+
+ if (!separator.test_axis(axis, !face_B->backface_collision)) {
return;
}
}
diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/collision_solver_3d_sw.cpp
index 1150696b84..f655c4626c 100644
--- a/servers/physics_3d/collision_solver_3d_sw.cpp
+++ b/servers/physics_3d/collision_solver_3d_sw.cpp
@@ -30,6 +30,7 @@
#include "collision_solver_3d_sw.h"
#include "collision_solver_3d_sat.h"
+#include "soft_body_3d_sw.h"
#include "gjk_epa.h"
@@ -46,8 +47,24 @@ bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const T
static const int max_supports = 16;
Vector3 supports[max_supports];
int support_count;
-
- p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count);
+ Shape3DSW::FeatureType support_type;
+ p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count, support_type);
+
+ if (support_type == Shape3DSW::FEATURE_CIRCLE) {
+ ERR_FAIL_COND_V(support_count != 3, false);
+
+ Vector3 circle_pos = supports[0];
+ Vector3 circle_axis_1 = supports[1] - circle_pos;
+ Vector3 circle_axis_2 = supports[2] - circle_pos;
+
+ // Use 3 equidistant points on the circle.
+ for (int i = 0; i < 3; ++i) {
+ Vector3 vertex_pos = circle_pos;
+ vertex_pos += circle_axis_1 * Math::cos(2.0 * Math_PI * i / 3.0);
+ vertex_pos += circle_axis_2 * Math::sin(2.0 * Math_PI * i / 3.0);
+ supports[i] = vertex_pos;
+ }
+ }
bool found = false;
@@ -62,9 +79,9 @@ bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const T
if (p_result_callback) {
if (p_swap_result) {
- p_result_callback(supports[i], support_A, p_userdata);
+ p_result_callback(supports[i], 0, support_A, 0, p_userdata);
} else {
- p_result_callback(support_A, supports[i], p_userdata);
+ p_result_callback(support_A, 0, supports[i], 0, p_userdata);
}
}
}
@@ -97,14 +114,148 @@ bool CollisionSolver3DSW::solve_ray(const Shape3DSW *p_shape_A, const Transform
if (p_result_callback) {
if (p_swap_result) {
- p_result_callback(support_B, support_A, p_userdata);
+ p_result_callback(support_B, 0, support_A, 0, p_userdata);
} else {
- p_result_callback(support_A, support_B, p_userdata);
+ p_result_callback(support_A, 0, support_B, 0, p_userdata);
}
}
return true;
}
+struct _SoftBodyContactCollisionInfo {
+ int node_index = 0;
+ CollisionSolver3DSW::CallbackResult result_callback = nullptr;
+ void *userdata = nullptr;
+ bool swap_result = false;
+ int contact_count = 0;
+};
+
+void CollisionSolver3DSW::soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+ _SoftBodyContactCollisionInfo &cinfo = *(_SoftBodyContactCollisionInfo *)(p_userdata);
+
+ ++cinfo.contact_count;
+
+ if (cinfo.swap_result) {
+ cinfo.result_callback(p_point_B, cinfo.node_index, p_point_A, p_index_A, cinfo.userdata);
+ } else {
+ cinfo.result_callback(p_point_A, p_index_A, p_point_B, cinfo.node_index, cinfo.userdata);
+ }
+}
+
+struct _SoftBodyQueryInfo {
+ SoftBody3DSW *soft_body = nullptr;
+ const Shape3DSW *shape_A = nullptr;
+ const Shape3DSW *shape_B = nullptr;
+ Transform transform_A;
+ Transform node_transform;
+ _SoftBodyContactCollisionInfo contact_info;
+#ifdef DEBUG_ENABLED
+ int node_query_count = 0;
+ int convex_query_count = 0;
+#endif
+};
+
+bool CollisionSolver3DSW::soft_body_query_callback(uint32_t p_node_index, void *p_userdata) {
+ _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata);
+
+ Vector3 node_position = query_cinfo.soft_body->get_node_position(p_node_index);
+
+ Transform transform_B;
+ transform_B.origin = query_cinfo.node_transform.xform(node_position);
+
+ query_cinfo.contact_info.node_index = p_node_index;
+ solve_static(query_cinfo.shape_A, query_cinfo.transform_A, query_cinfo.shape_B, transform_B, soft_body_contact_callback, &query_cinfo.contact_info);
+
+#ifdef DEBUG_ENABLED
+ ++query_cinfo.node_query_count;
+#endif
+
+ // Continue with the query.
+ return false;
+}
+
+void CollisionSolver3DSW::soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex) {
+ _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata);
+
+ query_cinfo.shape_A = p_convex;
+
+ // Calculate AABB for internal soft body query (in world space).
+ AABB shape_aabb;
+ for (int i = 0; i < 3; i++) {
+ Vector3 axis;
+ axis[i] = 1.0;
+
+ real_t smin, smax;
+ p_convex->project_range(axis, query_cinfo.transform_A, smin, smax);
+
+ shape_aabb.position[i] = smin;
+ shape_aabb.size[i] = smax - smin;
+ }
+
+ shape_aabb.grow_by(query_cinfo.soft_body->get_collision_margin());
+
+ query_cinfo.soft_body->query_aabb(shape_aabb, soft_body_query_callback, &query_cinfo);
+
+#ifdef DEBUG_ENABLED
+ ++query_cinfo.convex_query_count;
+#endif
+}
+
+bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+ const SoftBodyShape3DSW *soft_body_shape_B = static_cast<const SoftBodyShape3DSW *>(p_shape_B);
+
+ SoftBody3DSW *soft_body = soft_body_shape_B->get_soft_body();
+ const Transform &world_to_local = soft_body->get_inv_transform();
+
+ const real_t collision_margin = soft_body->get_collision_margin();
+
+ SphereShape3DSW sphere_shape;
+ sphere_shape.set_data(collision_margin);
+
+ _SoftBodyQueryInfo query_cinfo;
+ query_cinfo.contact_info.result_callback = p_result_callback;
+ query_cinfo.contact_info.userdata = p_userdata;
+ query_cinfo.contact_info.swap_result = p_swap_result;
+ query_cinfo.soft_body = soft_body;
+ query_cinfo.node_transform = p_transform_B * world_to_local;
+ query_cinfo.shape_A = p_shape_A;
+ query_cinfo.transform_A = p_transform_A;
+ query_cinfo.shape_B = &sphere_shape;
+
+ if (p_shape_A->is_concave()) {
+ // In case of concave shape, query convex shapes first.
+ const ConcaveShape3DSW *concave_shape_A = static_cast<const ConcaveShape3DSW *>(p_shape_A);
+
+ AABB soft_body_aabb = soft_body->get_bounds();
+ soft_body_aabb.grow_by(collision_margin);
+
+ // Calculate AABB for internal concave shape query (in local space).
+ AABB local_aabb;
+ for (int i = 0; i < 3; i++) {
+ Vector3 axis(p_transform_A.basis.get_axis(i));
+ real_t axis_scale = 1.0 / axis.length();
+
+ real_t smin = soft_body_aabb.position[i];
+ real_t smax = smin + soft_body_aabb.size[i];
+
+ smin *= axis_scale;
+ smax *= axis_scale;
+
+ local_aabb.position[i] = smin;
+ local_aabb.size[i] = smax - smin;
+ }
+
+ concave_shape_A->cull(local_aabb, soft_body_concave_callback, &query_cinfo);
+ } else {
+ AABB shape_aabb = p_transform_A.xform(p_shape_A->get_aabb());
+ shape_aabb.grow_by(collision_margin);
+
+ soft_body->query_aabb(shape_aabb, soft_body_query_callback, &query_cinfo);
+ }
+
+ return (query_cinfo.contact_info.contact_count > 0);
+}
+
struct _ConcaveCollisionInfo {
const Transform *transform_A;
const Shape3DSW *shape_A;
@@ -199,6 +350,9 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo
if (type_B == PhysicsServer3D::SHAPE_RAY) {
return false;
}
+ if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) {
+ return false;
+ }
if (swap) {
return solve_static_plane(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
@@ -217,6 +371,18 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo
return solve_ray(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
}
+ } else if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) {
+ if (type_A == PhysicsServer3D::SHAPE_SOFT_BODY) {
+ // Soft Body / Soft Body not supported.
+ return false;
+ }
+
+ if (swap) {
+ return solve_soft_body(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
+ } else {
+ return solve_soft_body(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
+ }
+
} else if (concave_B) {
if (concave_A) {
return false;
@@ -265,8 +431,25 @@ bool CollisionSolver3DSW::solve_distance_plane(const Shape3DSW *p_shape_A, const
static const int max_supports = 16;
Vector3 supports[max_supports];
int support_count;
+ Shape3DSW::FeatureType support_type;
+
+ p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count, support_type);
- p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count);
+ if (support_type == Shape3DSW::FEATURE_CIRCLE) {
+ ERR_FAIL_COND_V(support_count != 3, false);
+
+ Vector3 circle_pos = supports[0];
+ Vector3 circle_axis_1 = supports[1] - circle_pos;
+ Vector3 circle_axis_2 = supports[2] - circle_pos;
+
+ // Use 3 equidistant points on the circle.
+ for (int i = 0; i < 3; ++i) {
+ Vector3 vertex_pos = circle_pos;
+ vertex_pos += circle_axis_1 * Math::cos(2.0 * Math_PI * i / 3.0);
+ vertex_pos += circle_axis_2 * Math::sin(2.0 * Math_PI * i / 3.0);
+ supports[i] = vertex_pos;
+ }
+ }
bool collided = false;
Vector3 closest;
diff --git a/servers/physics_3d/collision_solver_3d_sw.h b/servers/physics_3d/collision_solver_3d_sw.h
index 81d87e9773..34ac2c6d3f 100644
--- a/servers/physics_3d/collision_solver_3d_sw.h
+++ b/servers/physics_3d/collision_solver_3d_sw.h
@@ -35,12 +35,16 @@
class CollisionSolver3DSW {
public:
- typedef void (*CallbackResult)(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata);
+ typedef void (*CallbackResult)(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
private:
+ static bool soft_body_query_callback(uint32_t p_node_index, void *p_userdata);
+ static void soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
+ static void soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex);
static void concave_callback(void *p_userdata, Shape3DSW *p_convex);
static bool solve_static_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
static bool solve_ray(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool solve_soft_body(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
static bool solve_concave(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0);
static void concave_distance_callback(void *p_userdata, Shape3DSW *p_convex);
static bool solve_distance_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B);
diff --git a/servers/physics_3d/gjk_epa.cpp b/servers/physics_3d/gjk_epa.cpp
index dafd2feb8b..1a8c7f704f 100644
--- a/servers/physics_3d/gjk_epa.cpp
+++ b/servers/physics_3d/gjk_epa.cpp
@@ -64,7 +64,7 @@ GJK-EPA collision solver by Nathanael Presson, 2008
/* GJK */
#define GJK_MAX_ITERATIONS 128
-#define GJK_ACCURARY ((real_t)0.0001)
+#define GJK_ACCURACY ((real_t)0.0001)
#define GJK_MIN_DISTANCE ((real_t)0.0001)
#define GJK_DUPLICATED_EPS ((real_t)0.0001)
#define GJK_SIMPLEX2_EPS ((real_t)0.0)
@@ -72,10 +72,13 @@ GJK-EPA collision solver by Nathanael Presson, 2008
#define GJK_SIMPLEX4_EPS ((real_t)0.0)
/* EPA */
-#define EPA_MAX_VERTICES 64
+#define EPA_MAX_VERTICES 128
#define EPA_MAX_FACES (EPA_MAX_VERTICES*2)
#define EPA_MAX_ITERATIONS 255
-#define EPA_ACCURACY ((real_t)0.0001)
+// -- GODOT start --
+//#define EPA_ACCURACY ((real_t)0.0001)
+#define EPA_ACCURACY ((real_t)0.00001)
+// -- GODOT end --
#define EPA_FALLBACK (10*EPA_ACCURACY)
#define EPA_PLANE_EPS ((real_t)0.00001)
#define EPA_INSIDE_EPS ((real_t)0.01)
@@ -107,26 +110,60 @@ struct MinkowskiDiff {
Transform transform_A;
Transform transform_B;
+ real_t margin_A = 0.0;
+ real_t margin_B = 0.0;
+
+ Vector3 (*get_support)(const Shape3DSW*, const Vector3&, real_t);
+
+ void Initialize(const Shape3DSW* shape0, const Transform& wtrs0, const real_t margin0,
+ const Shape3DSW* shape1, const Transform& wtrs1, const real_t margin1) {
+ m_shapes[0] = shape0;
+ m_shapes[1] = shape1;
+ transform_A = wtrs0;
+ transform_B = wtrs1;
+ margin_A = margin0;
+ margin_B = margin1;
+
+ if ((margin0 > 0.0) || (margin1 > 0.0)) {
+ get_support = get_support_with_margin;
+ } else {
+ get_support = get_support_without_margin;
+ }
+ }
+
+ static Vector3 get_support_without_margin(const Shape3DSW* p_shape, const Vector3& p_dir, real_t p_margin) {
+ return p_shape->get_support(p_dir.normalized());
+ }
+
+ static Vector3 get_support_with_margin(const Shape3DSW* p_shape, const Vector3& p_dir, real_t p_margin) {
+ Vector3 local_dir_norm = p_dir;
+ if (local_dir_norm.length_squared() < CMP_EPSILON2) {
+ local_dir_norm = Vector3(-1.0, -1.0, -1.0);
+ }
+ local_dir_norm.normalize();
+
+ return p_shape->get_support(local_dir_norm) + p_margin * local_dir_norm;
+ }
+
// i wonder how this could be sped up... if it can
- _FORCE_INLINE_ Vector3 Support0 ( const Vector3& d ) const {
- return transform_A.xform( m_shapes[0]->get_support( transform_A.basis.xform_inv(d).normalized() ) );
+ _FORCE_INLINE_ Vector3 Support0(const Vector3& d) const {
+ return transform_A.xform(get_support(m_shapes[0], transform_A.basis.xform_inv(d), margin_A));
}
- _FORCE_INLINE_ Vector3 Support1 ( const Vector3& d ) const {
- return transform_B.xform( m_shapes[1]->get_support( transform_B.basis.xform_inv(d).normalized() ) );
+ _FORCE_INLINE_ Vector3 Support1(const Vector3& d) const {
+ return transform_B.xform(get_support(m_shapes[1], transform_B.basis.xform_inv(d), margin_B));
}
- _FORCE_INLINE_ Vector3 Support ( const Vector3& d ) const {
- return ( Support0 ( d )-Support1 ( -d ) );
+ _FORCE_INLINE_ Vector3 Support (const Vector3& d) const {
+ return (Support0(d) - Support1(-d));
}
- _FORCE_INLINE_ Vector3 Support ( const Vector3& d,U index ) const
- {
- if ( index ) {
- return ( Support1 ( d ) );
+ _FORCE_INLINE_ Vector3 Support(const Vector3& d, U index) const {
+ if (index) {
+ return Support1(d);
} else {
- return ( Support0 ( d ) );
-}
+ return Support0(d);
+ }
}
};
@@ -237,7 +274,7 @@ struct GJK
/* Check for termination */
const real_t omega=vec3_dot(m_ray,w)/rl;
alpha=MAX(omega,alpha);
- if(((rl-alpha)-(GJK_ACCURARY*rl))<=0)
+ if(((rl-alpha)-(GJK_ACCURACY*rl))<=0)
{/* Return old simplex */
removevertice(m_simplices[m_current]);
break;
@@ -466,7 +503,7 @@ struct GJK
if(ng&&(Math::abs(vl)>GJK_SIMPLEX4_EPS))
{
real_t mindist=-1;
- real_t subw[3];
+ real_t subw[3] = {0.f, 0.f, 0.f};
U subm=0;
for(U i=0;i<3;++i)
{
@@ -512,7 +549,6 @@ struct GJK
{
Vector3 n;
real_t d;
- real_t p;
sSV* c[3];
sFace* f[3];
sFace* l[2];
@@ -661,8 +697,7 @@ struct GJK
remove(m_hull,best);
append(m_stock,best);
best=findbest();
- if(best->p>=outer.p) { outer=*best;
-}
+ outer=*best;
} else { m_status=eStatus::InvalidHull;break; }
} else { m_status=eStatus::AccuraryReached;break; }
} else { m_status=eStatus::OutOfVertices;break; }
@@ -688,24 +723,54 @@ struct GJK
}
}
/* Fallback */
- m_status = eStatus::FallBack;
- m_normal = -guess;
- const real_t nl=m_normal.length();
- if(nl>0) {
- m_normal = m_normal/nl;
+ m_status = eStatus::FallBack;
+ m_normal = -guess;
+ const real_t nl = m_normal.length();
+ if (nl > 0) {
+ m_normal = m_normal/nl;
} else {
- m_normal = Vector3(1,0,0);
-}
+ m_normal = Vector3(1,0,0);
+ }
m_depth = 0;
m_result.rank=1;
m_result.c[0]=simplex.c[0];
m_result.p[0]=1;
return(m_status);
}
+
+ bool getedgedist(sFace* face, sSV* a, sSV* b, real_t& dist)
+ {
+ const Vector3 ba = b->w - a->w;
+ const Vector3 n_ab = vec3_cross(ba, face->n); // Outward facing edge normal direction, on triangle plane
+ const real_t a_dot_nab = vec3_dot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
+
+ if (a_dot_nab < 0) {
+ // Outside of edge a->b
+ const real_t ba_l2 = ba.length_squared();
+ const real_t a_dot_ba = vec3_dot(a->w, ba);
+ const real_t b_dot_ba = vec3_dot(b->w, ba);
+
+ if (a_dot_ba > 0) {
+ // Pick distance vertex a
+ dist = a->w.length();
+ } else if (b_dot_ba < 0) {
+ // Pick distance vertex b
+ dist = b->w.length();
+ } else {
+ // Pick distance to edge a->b
+ const real_t a_dot_b = vec3_dot(a->w, b->w);
+ dist = Math::sqrt(MAX((a->w.length_squared() * b->w.length_squared() - a_dot_b * a_dot_b) / ba_l2, 0.0));
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
sFace* newface(sSV* a,sSV* b,sSV* c,bool forced)
{
- if(m_stock.root)
- {
+ if (m_stock.root) {
sFace* face=m_stock.root;
remove(m_stock,face);
append(m_hull,face);
@@ -716,23 +781,23 @@ struct GJK
face->n = vec3_cross(b->w-a->w,c->w-a->w);
const real_t l=face->n.length();
const bool v=l>EPA_ACCURACY;
- face->p = MIN(MIN(
- vec3_dot(a->w,vec3_cross(face->n,a->w-b->w)),
- vec3_dot(b->w,vec3_cross(face->n,b->w-c->w))),
- vec3_dot(c->w,vec3_cross(face->n,c->w-a->w))) /
- (v?l:1);
- face->p = face->p>=-EPA_INSIDE_EPS?0:face->p;
- if(v)
- {
- face->d = vec3_dot(a->w,face->n)/l;
+ if (v) {
+ if (!(getedgedist(face, a, b, face->d) ||
+ getedgedist(face, b, c, face->d) ||
+ getedgedist(face, c, a, face->d))) {
+ // Origin projects to the interior of the triangle
+ // Use distance to triangle plane
+ face->d = vec3_dot(a->w, face->n) / l;
+ }
face->n /= l;
- if(forced||(face->d>=-EPA_PLANE_EPS))
- {
+ if (forced||(face->d>=-EPA_PLANE_EPS)) {
return(face);
- } else { m_status=eStatus::NonConvex;
-}
- } else { m_status=eStatus::Degenerated;
-}
+ } else {
+ m_status=eStatus::NonConvex;
+ }
+ } else {
+ m_status=eStatus::Degenerated;
+ }
remove(m_hull,face);
append(m_stock,face);
return(nullptr);
@@ -747,15 +812,13 @@ struct GJK
{
sFace* minf=m_hull.root;
real_t mind=minf->d*minf->d;
- real_t maxp=minf->p;
for(sFace* f=minf->l[1];f;f=f->l[1])
{
const real_t sqd=f->d*f->d;
- if((f->p>=maxp)&&(sqd<mind))
+ if(sqd<mind)
{
minf=f;
mind=sqd;
- maxp=f->p;
}
}
return(minf);
@@ -799,22 +862,17 @@ struct GJK
};
//
- static void Initialize( const Shape3DSW* shape0,const Transform& wtrs0,
- const Shape3DSW* shape1,const Transform& wtrs1,
+ static void Initialize( const Shape3DSW* shape0, const Transform& wtrs0, real_t margin0,
+ const Shape3DSW* shape1, const Transform& wtrs1, real_t margin1,
sResults& results,
- tShape& shape,
- bool withmargins)
+ tShape& shape)
{
/* Results */
- results.witnesses[0] =
- results.witnesses[1] = Vector3(0,0,0);
+ results.witnesses[0] = Vector3(0,0,0);
+ results.witnesses[1] = Vector3(0,0,0);
results.status = sResults::Separated;
/* Shape */
- shape.m_shapes[0] = shape0;
- shape.m_shapes[1] = shape1;
- shape.transform_A = wtrs0;
- shape.transform_B = wtrs1;
-
+ shape.Initialize(shape0, wtrs0, margin0, shape1, wtrs1, margin1);
}
@@ -828,13 +886,15 @@ struct GJK
//
bool Distance( const Shape3DSW* shape0,
const Transform& wtrs0,
- const Shape3DSW* shape1,
+ real_t margin0,
+ const Shape3DSW* shape1,
const Transform& wtrs1,
+ real_t margin1,
const Vector3& guess,
sResults& results)
{
tShape shape;
- Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false);
+ Initialize(shape0, wtrs0, margin0, shape1, wtrs1, margin1, results, shape);
GJK gjk;
GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess);
if(gjk_status==GJK::eStatus::Valid)
@@ -867,14 +927,16 @@ bool Distance( const Shape3DSW* shape0,
//
bool Penetration( const Shape3DSW* shape0,
const Transform& wtrs0,
- const Shape3DSW* shape1,
+ real_t margin0,
+ const Shape3DSW* shape1,
const Transform& wtrs1,
- const Vector3& guess,
+ real_t margin1,
+ const Vector3& guess,
sResults& results
)
{
tShape shape;
- Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false);
+ Initialize(shape0, wtrs0, margin0, shape1, wtrs1, margin1, results, shape);
GJK gjk;
GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess);
switch(gjk_status)
@@ -934,7 +996,7 @@ bool Penetration( const Shape3DSW* shape0,
bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B) {
GjkEpa2::sResults res;
- if (GjkEpa2::Distance(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_transform_B.origin - p_transform_A.origin, res)) {
+ if (GjkEpa2::Distance(p_shape_A, p_transform_A, 0.0, p_shape_B, p_transform_B, 0.0, p_transform_B.origin - p_transform_A.origin, res)) {
r_result_A = res.witnesses[0];
r_result_B = res.witnesses[1];
return true;
@@ -943,15 +1005,15 @@ bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform &p_t
return false;
}
-bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap) {
+bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, real_t p_margin_A, real_t p_margin_B) {
GjkEpa2::sResults res;
- if (GjkEpa2::Penetration(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_transform_B.origin - p_transform_A.origin, res)) {
+ if (GjkEpa2::Penetration(p_shape_A, p_transform_A, p_margin_A, p_shape_B, p_transform_B, p_margin_B, p_transform_B.origin - p_transform_A.origin, res)) {
if (p_result_callback) {
if (p_swap) {
- p_result_callback(res.witnesses[1], res.witnesses[0], p_userdata);
+ p_result_callback(res.witnesses[1], 0, res.witnesses[0], 0, p_userdata);
} else {
- p_result_callback(res.witnesses[0], res.witnesses[1], p_userdata);
+ p_result_callback(res.witnesses[0], 0, res.witnesses[1], 0, p_userdata);
}
}
return true;
diff --git a/servers/physics_3d/gjk_epa.h b/servers/physics_3d/gjk_epa.h
index be3ba4e664..a7e2e1719e 100644
--- a/servers/physics_3d/gjk_epa.h
+++ b/servers/physics_3d/gjk_epa.h
@@ -34,7 +34,7 @@
#include "collision_solver_3d_sw.h"
#include "shape_3d_sw.h"
-bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false);
+bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0);
bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B);
#endif
diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.h b/servers/physics_3d/joints/cone_twist_joint_3d_sw.h
index c38edc5737..4e4d4e7f0c 100644
--- a/servers/physics_3d/joints/cone_twist_joint_3d_sw.h
+++ b/servers/physics_3d/joints/cone_twist_joint_3d_sw.h
@@ -102,7 +102,7 @@ public:
bool m_solveSwingLimit;
public:
- virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_CONE_TWIST; }
+ virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_CONE_TWIST; }
virtual bool setup(real_t p_timestep);
virtual void solve(real_t p_timestep);
diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
index 2ae6fe85fa..d61a033231 100644
--- a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
+++ b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
@@ -234,7 +234,7 @@ protected:
public:
Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA);
- virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_6DOF; }
+ virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_6DOF; }
virtual bool setup(real_t p_timestep);
virtual void solve(real_t p_timestep);
diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.h b/servers/physics_3d/joints/hinge_joint_3d_sw.h
index 028a8b8c72..b6117aa0bc 100644
--- a/servers/physics_3d/joints/hinge_joint_3d_sw.h
+++ b/servers/physics_3d/joints/hinge_joint_3d_sw.h
@@ -96,7 +96,7 @@ class HingeJoint3DSW : public Joint3DSW {
real_t m_appliedImpulse;
public:
- virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_HINGE; }
+ virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_HINGE; }
virtual bool setup(real_t p_step);
virtual void solve(real_t p_step);
diff --git a/servers/physics_3d/joints/pin_joint_3d_sw.h b/servers/physics_3d/joints/pin_joint_3d_sw.h
index e28fbec6cd..1875983527 100644
--- a/servers/physics_3d/joints/pin_joint_3d_sw.h
+++ b/servers/physics_3d/joints/pin_joint_3d_sw.h
@@ -74,7 +74,7 @@ class PinJoint3DSW : public Joint3DSW {
Vector3 m_pivotInB;
public:
- virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_PIN; }
+ virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_PIN; }
virtual bool setup(real_t p_step);
virtual void solve(real_t p_step);
diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.h b/servers/physics_3d/joints/slider_joint_3d_sw.h
index 196e60d19d..f52f6ace27 100644
--- a/servers/physics_3d/joints/slider_joint_3d_sw.h
+++ b/servers/physics_3d/joints/slider_joint_3d_sw.h
@@ -243,7 +243,7 @@ public:
bool setup(real_t p_step);
void solve(real_t p_step);
- virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_SLIDER; }
+ virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_SLIDER; }
};
#endif // SLIDER_JOINT_SW_H
diff --git a/servers/physics_3d/joints_3d_sw.h b/servers/physics_3d/joints_3d_sw.h
index cad05b6702..225a71aca9 100644
--- a/servers/physics_3d/joints_3d_sw.h
+++ b/servers/physics_3d/joints_3d_sw.h
@@ -36,10 +36,28 @@
class Joint3DSW : public Constraint3DSW {
public:
- virtual PhysicsServer3D::JointType get_type() const = 0;
+ virtual bool setup(real_t p_step) { return false; }
+ virtual void solve(real_t p_step) {}
+
+ void copy_settings_from(Joint3DSW *p_joint) {
+ set_self(p_joint->get_self());
+ set_priority(p_joint->get_priority());
+ disable_collisions_between_bodies(p_joint->is_disabled_collisions_between_bodies());
+ }
+
+ virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_MAX; }
_FORCE_INLINE_ Joint3DSW(Body3DSW **p_body_ptr = nullptr, int p_body_count = 0) :
Constraint3DSW(p_body_ptr, p_body_count) {
}
+
+ virtual ~Joint3DSW() {
+ for (int i = 0; i < get_body_count(); i++) {
+ Body3DSW *body = get_body_ptr()[i];
+ if (body) {
+ body->remove_constraint(this);
+ }
+ }
+ }
};
#endif // JOINTS_SW_H
diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp
index b554a23bf2..3d0063b0fa 100644
--- a/servers/physics_3d/physics_server_3d_sw.cpp
+++ b/servers/physics_3d/physics_server_3d_sw.cpp
@@ -43,47 +43,63 @@
#define FLUSH_QUERY_CHECK(m_object) \
ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.");
-RID PhysicsServer3DSW::shape_create(ShapeType p_shape) {
- Shape3DSW *shape = nullptr;
- switch (p_shape) {
- case SHAPE_PLANE: {
- shape = memnew(PlaneShape3DSW);
- } break;
- case SHAPE_RAY: {
- shape = memnew(RayShape3DSW);
- } break;
- case SHAPE_SPHERE: {
- shape = memnew(SphereShape3DSW);
- } break;
- case SHAPE_BOX: {
- shape = memnew(BoxShape3DSW);
- } break;
- case SHAPE_CAPSULE: {
- shape = memnew(CapsuleShape3DSW);
- } break;
- case SHAPE_CYLINDER: {
- ERR_FAIL_V_MSG(RID(), "CylinderShape3D is not supported in GodotPhysics3D. Please switch to Bullet in the Project Settings.");
- } break;
- case SHAPE_CONVEX_POLYGON: {
- shape = memnew(ConvexPolygonShape3DSW);
- } break;
- case SHAPE_CONCAVE_POLYGON: {
- shape = memnew(ConcavePolygonShape3DSW);
- } break;
- case SHAPE_HEIGHTMAP: {
- shape = memnew(HeightMapShape3DSW);
- } break;
- case SHAPE_CUSTOM: {
- ERR_FAIL_V(RID());
-
- } break;
- }
-
- RID id = shape_owner.make_rid(shape);
- shape->set_self(id);
-
- return id;
-};
+RID PhysicsServer3DSW::plane_shape_create() {
+ Shape3DSW *shape = memnew(PlaneShape3DSW);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID PhysicsServer3DSW::ray_shape_create() {
+ Shape3DSW *shape = memnew(RayShape3DSW);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID PhysicsServer3DSW::sphere_shape_create() {
+ Shape3DSW *shape = memnew(SphereShape3DSW);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID PhysicsServer3DSW::box_shape_create() {
+ Shape3DSW *shape = memnew(BoxShape3DSW);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID PhysicsServer3DSW::capsule_shape_create() {
+ Shape3DSW *shape = memnew(CapsuleShape3DSW);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID PhysicsServer3DSW::cylinder_shape_create() {
+ Shape3DSW *shape = memnew(CylinderShape3DSW);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID PhysicsServer3DSW::convex_polygon_shape_create() {
+ Shape3DSW *shape = memnew(ConvexPolygonShape3DSW);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID PhysicsServer3DSW::concave_polygon_shape_create() {
+ Shape3DSW *shape = memnew(ConcavePolygonShape3DSW);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID PhysicsServer3DSW::heightmap_shape_create() {
+ Shape3DSW *shape = memnew(HeightMapShape3DSW);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID PhysicsServer3DSW::custom_shape_create() {
+ ERR_FAIL_V(RID());
+}
void PhysicsServer3DSW::shape_set_data(RID p_shape, const Variant &p_data) {
Shape3DSW *shape = shape_owner.getornull(p_shape);
@@ -174,7 +190,7 @@ real_t PhysicsServer3DSW::space_get_param(RID p_space, SpaceParameter p_param) c
PhysicsDirectSpaceState3D *PhysicsServer3DSW::space_get_direct_state(RID p_space) {
Space3DSW *space = space_owner.getornull(p_space);
ERR_FAIL_COND_V(!space, nullptr);
- ERR_FAIL_COND_V_MSG(space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification.");
+ ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification.");
return space->get_direct_state();
}
@@ -413,13 +429,6 @@ void PhysicsServer3DSW::area_set_ray_pickable(RID p_area, bool p_enable) {
area->set_ray_pickable(p_enable);
}
-bool PhysicsServer3DSW::area_is_ray_pickable(RID p_area) const {
- Area3DSW *area = area_owner.getornull(p_area);
- ERR_FAIL_COND_V(!area, false);
-
- return area->is_ray_pickable();
-}
-
void PhysicsServer3DSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
Area3DSW *area = area_owner.getornull(p_area);
ERR_FAIL_COND(!area);
@@ -429,14 +438,8 @@ void PhysicsServer3DSW::area_set_area_monitor_callback(RID p_area, Object *p_rec
/* BODY API */
-RID PhysicsServer3DSW::body_create(BodyMode p_mode, bool p_init_sleeping) {
+RID PhysicsServer3DSW::body_create() {
Body3DSW *body = memnew(Body3DSW);
- if (p_mode != BODY_MODE_RIGID) {
- body->set_mode(p_mode);
- }
- if (p_init_sleeping) {
- body->set_state(BODY_STATE_SLEEPING, p_init_sleeping);
- }
RID rid = body_owner.make_rid(body);
body->set_self(rid);
return rid;
@@ -608,9 +611,18 @@ uint32_t PhysicsServer3DSW::body_get_collision_mask(RID p_body) const {
void PhysicsServer3DSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) {
Body3DSW *body = body_owner.getornull(p_body);
- ERR_FAIL_COND(!body);
+ if (body) {
+ body->set_instance_id(p_id);
+ return;
+ }
- body->set_instance_id(p_id);
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ if (soft_body) {
+ soft_body->set_instance_id(p_id);
+ return;
+ }
+
+ ERR_FAIL_MSG("Invalid ID.");
};
ObjectID PhysicsServer3DSW::body_get_object_instance_id(RID p_body) const {
@@ -857,12 +869,6 @@ void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) {
body->set_ray_pickable(p_enable);
}
-bool PhysicsServer3DSW::body_is_ray_pickable(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, false);
- return body->is_ray_pickable();
-}
-
bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) {
Body3DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, false);
@@ -886,6 +892,8 @@ int PhysicsServer3DSW::body_test_ray_separation(RID p_body, const Transform &p_t
}
PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) {
+ ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
+
Body3DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, nullptr);
ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
@@ -894,32 +902,314 @@ PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) {
return direct_state;
}
+/* SOFT BODY */
+
+RID PhysicsServer3DSW::soft_body_create() {
+ SoftBody3DSW *soft_body = memnew(SoftBody3DSW);
+ RID rid = soft_body_owner.make_rid(soft_body);
+ soft_body->set_self(rid);
+ return rid;
+}
+
+void PhysicsServer3DSW::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->update_rendering_server(p_rendering_server_handler);
+}
+
+void PhysicsServer3DSW::soft_body_set_space(RID p_body, RID p_space) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ Space3DSW *space = nullptr;
+ if (p_space.is_valid()) {
+ space = space_owner.getornull(p_space);
+ ERR_FAIL_COND(!space);
+ }
+
+ if (soft_body->get_space() == space) {
+ return;
+ }
+
+ soft_body->set_space(space);
+}
+
+RID PhysicsServer3DSW::soft_body_get_space(RID p_body) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, RID());
+
+ Space3DSW *space = soft_body->get_space();
+ if (!space) {
+ return RID();
+ }
+ return space->get_self();
+}
+
+void PhysicsServer3DSW::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_collision_layer(p_layer);
+}
+
+uint32_t PhysicsServer3DSW::soft_body_get_collision_layer(RID p_body) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0);
+
+ return soft_body->get_collision_layer();
+}
+
+void PhysicsServer3DSW::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_collision_mask(p_mask);
+}
+
+uint32_t PhysicsServer3DSW::soft_body_get_collision_mask(RID p_body) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0);
+
+ return soft_body->get_collision_mask();
+}
+
+void PhysicsServer3DSW::soft_body_add_collision_exception(RID p_body, RID p_body_b) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->add_exception(p_body_b);
+}
+
+void PhysicsServer3DSW::soft_body_remove_collision_exception(RID p_body, RID p_body_b) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->remove_exception(p_body_b);
+}
+
+void PhysicsServer3DSW::soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ for (int i = 0; i < soft_body->get_exceptions().size(); i++) {
+ p_exceptions->push_back(soft_body->get_exceptions()[i]);
+ }
+}
+
+void PhysicsServer3DSW::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_state(p_state, p_variant);
+}
+
+Variant PhysicsServer3DSW::soft_body_get_state(RID p_body, BodyState p_state) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, Variant());
+
+ return soft_body->get_state(p_state);
+}
+
+void PhysicsServer3DSW::soft_body_set_transform(RID p_body, const Transform &p_transform) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_state(BODY_STATE_TRANSFORM, p_transform);
+}
+
+void PhysicsServer3DSW::soft_body_set_ray_pickable(RID p_body, bool p_enable) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_ray_pickable(p_enable);
+}
+
+void PhysicsServer3DSW::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_iteration_count(p_simulation_precision);
+}
+
+int PhysicsServer3DSW::soft_body_get_simulation_precision(RID p_body) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_iteration_count();
+}
+
+void PhysicsServer3DSW::soft_body_set_total_mass(RID p_body, real_t p_total_mass) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_total_mass(p_total_mass);
+}
+
+real_t PhysicsServer3DSW::soft_body_get_total_mass(RID p_body) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_total_mass();
+}
+
+void PhysicsServer3DSW::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_linear_stiffness(p_stiffness);
+}
+
+real_t PhysicsServer3DSW::soft_body_get_linear_stiffness(RID p_body) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_linear_stiffness();
+}
+
+void PhysicsServer3DSW::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_pressure_coefficient(p_pressure_coefficient);
+}
+
+real_t PhysicsServer3DSW::soft_body_get_pressure_coefficient(RID p_body) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_pressure_coefficient();
+}
+
+void PhysicsServer3DSW::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_damping_coefficient(p_damping_coefficient);
+}
+
+real_t PhysicsServer3DSW::soft_body_get_damping_coefficient(RID p_body) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_damping_coefficient();
+}
+
+void PhysicsServer3DSW::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_drag_coefficient(p_drag_coefficient);
+}
+
+real_t PhysicsServer3DSW::soft_body_get_drag_coefficient(RID p_body) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_drag_coefficient();
+}
+
+void PhysicsServer3DSW::soft_body_set_mesh(RID p_body, const REF &p_mesh) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_mesh(p_mesh);
+}
+
+AABB PhysicsServer3DSW::soft_body_get_bounds(RID p_body) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, AABB());
+
+ return soft_body->get_bounds();
+}
+
+void PhysicsServer3DSW::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_vertex_position(p_point_index, p_global_position);
+}
+
+Vector3 PhysicsServer3DSW::soft_body_get_point_global_position(RID p_body, int p_point_index) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, Vector3());
+
+ return soft_body->get_vertex_position(p_point_index);
+}
+
+void PhysicsServer3DSW::soft_body_remove_all_pinned_points(RID p_body) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->unpin_all_vertices();
+}
+
+void PhysicsServer3DSW::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ if (p_pin) {
+ soft_body->pin_vertex(p_point_index);
+ } else {
+ soft_body->unpin_vertex(p_point_index);
+ }
+}
+
+bool PhysicsServer3DSW::soft_body_is_point_pinned(RID p_body, int p_point_index) const {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ ERR_FAIL_COND_V(!soft_body, false);
+
+ return soft_body->is_vertex_pinned(p_point_index);
+}
+
/* JOINT API */
-RID PhysicsServer3DSW::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) {
+RID PhysicsServer3DSW::joint_create() {
+ Joint3DSW *joint = memnew(Joint3DSW);
+ RID rid = joint_owner.make_rid(joint);
+ joint->set_self(rid);
+ return rid;
+}
+
+void PhysicsServer3DSW::joint_clear(RID p_joint) {
+ Joint3DSW *joint = joint_owner.getornull(p_joint);
+ if (joint->get_type() != JOINT_TYPE_MAX) {
+ Joint3DSW *empty_joint = memnew(Joint3DSW);
+ empty_joint->copy_settings_from(joint);
+
+ joint_owner.replace(p_joint, empty_joint);
+ memdelete(joint);
+ }
+}
+
+void PhysicsServer3DSW::joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) {
Body3DSW *body_A = body_owner.getornull(p_body_A);
- ERR_FAIL_COND_V(!body_A, RID());
+ ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND_V(!body_A->get_space(), RID());
+ ERR_FAIL_COND(!body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
Body3DSW *body_B = body_owner.getornull(p_body_B);
- ERR_FAIL_COND_V(!body_B, RID());
+ ERR_FAIL_COND(!body_B);
+
+ ERR_FAIL_COND(body_A == body_B);
- ERR_FAIL_COND_V(body_A == body_B, RID());
+ Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(PinJoint3DSW(body_A, p_local_A, body_B, p_local_B));
- RID rid = joint_owner.make_rid(joint);
- joint->set_self(rid);
- return rid;
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
}
void PhysicsServer3DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_PIN);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
pin_joint->set_param(p_param, p_value);
}
@@ -927,7 +1217,7 @@ void PhysicsServer3DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param,
real_t PhysicsServer3DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, 0);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0);
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
return pin_joint->get_param(p_param);
}
@@ -935,7 +1225,7 @@ real_t PhysicsServer3DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param
void PhysicsServer3DSW::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_PIN);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
pin_joint->set_pos_a(p_A);
}
@@ -943,7 +1233,7 @@ void PhysicsServer3DSW::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) {
Vector3 PhysicsServer3DSW::pin_joint_get_local_a(RID p_joint) const {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, Vector3());
- ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3());
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3());
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
return pin_joint->get_position_a();
}
@@ -951,7 +1241,7 @@ Vector3 PhysicsServer3DSW::pin_joint_get_local_a(RID p_joint) const {
void PhysicsServer3DSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_PIN);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
pin_joint->set_pos_b(p_B);
}
@@ -959,55 +1249,63 @@ void PhysicsServer3DSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) {
Vector3 PhysicsServer3DSW::pin_joint_get_local_b(RID p_joint) const {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, Vector3());
- ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3());
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3());
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
return pin_joint->get_position_b();
}
-RID PhysicsServer3DSW::joint_create_hinge(RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) {
+void PhysicsServer3DSW::joint_make_hinge(RID p_joint, RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) {
Body3DSW *body_A = body_owner.getornull(p_body_A);
- ERR_FAIL_COND_V(!body_A, RID());
+ ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND_V(!body_A->get_space(), RID());
+ ERR_FAIL_COND(!body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
Body3DSW *body_B = body_owner.getornull(p_body_B);
- ERR_FAIL_COND_V(!body_B, RID());
+ ERR_FAIL_COND(!body_B);
+
+ ERR_FAIL_COND(body_A == body_B);
- ERR_FAIL_COND_V(body_A == body_B, RID());
+ Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_frame_A, p_frame_B));
- RID rid = joint_owner.make_rid(joint);
- joint->set_self(rid);
- return rid;
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
}
-RID PhysicsServer3DSW::joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) {
+void PhysicsServer3DSW::joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) {
Body3DSW *body_A = body_owner.getornull(p_body_A);
- ERR_FAIL_COND_V(!body_A, RID());
+ ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND_V(!body_A->get_space(), RID());
+ ERR_FAIL_COND(!body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
Body3DSW *body_B = body_owner.getornull(p_body_B);
- ERR_FAIL_COND_V(!body_B, RID());
+ ERR_FAIL_COND(!body_B);
- ERR_FAIL_COND_V(body_A == body_B, RID());
+ ERR_FAIL_COND(body_A == body_B);
+
+ Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B));
- RID rid = joint_owner.make_rid(joint);
- joint->set_self(rid);
- return rid;
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
}
void PhysicsServer3DSW::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_HINGE);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE);
HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
hinge_joint->set_param(p_param, p_value);
}
@@ -1015,7 +1313,7 @@ void PhysicsServer3DSW::hinge_joint_set_param(RID p_joint, HingeJointParam p_par
real_t PhysicsServer3DSW::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, 0);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, 0);
HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
return hinge_joint->get_param(p_param);
}
@@ -1023,7 +1321,7 @@ real_t PhysicsServer3DSW::hinge_joint_get_param(RID p_joint, HingeJointParam p_p
void PhysicsServer3DSW::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_HINGE);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE);
HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
hinge_joint->set_flag(p_flag, p_value);
}
@@ -1031,7 +1329,7 @@ void PhysicsServer3DSW::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag,
bool PhysicsServer3DSW::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, false);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, false);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, false);
HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
return hinge_joint->get_flag(p_flag);
}
@@ -1077,34 +1375,38 @@ bool PhysicsServer3DSW::joint_is_disabled_collisions_between_bodies(RID p_joint)
PhysicsServer3DSW::JointType PhysicsServer3DSW::joint_get_type(RID p_joint) const {
Joint3DSW *joint = joint_owner.getornull(p_joint);
- ERR_FAIL_COND_V(!joint, JOINT_PIN);
+ ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN);
return joint->get_type();
}
-RID PhysicsServer3DSW::joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+void PhysicsServer3DSW::joint_make_slider(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
Body3DSW *body_A = body_owner.getornull(p_body_A);
- ERR_FAIL_COND_V(!body_A, RID());
+ ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND_V(!body_A->get_space(), RID());
+ ERR_FAIL_COND(!body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
Body3DSW *body_B = body_owner.getornull(p_body_B);
- ERR_FAIL_COND_V(!body_B, RID());
+ ERR_FAIL_COND(!body_B);
+
+ ERR_FAIL_COND(body_A == body_B);
- ERR_FAIL_COND_V(body_A == body_B, RID());
+ Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(SliderJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B));
- RID rid = joint_owner.make_rid(joint);
- joint->set_self(rid);
- return rid;
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
}
void PhysicsServer3DSW::slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_SLIDER);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_SLIDER);
SliderJoint3DSW *slider_joint = static_cast<SliderJoint3DSW *>(joint);
slider_joint->set_param(p_param, p_value);
}
@@ -1112,35 +1414,39 @@ void PhysicsServer3DSW::slider_joint_set_param(RID p_joint, SliderJointParam p_p
real_t PhysicsServer3DSW::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, 0);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0);
SliderJoint3DSW *slider_joint = static_cast<SliderJoint3DSW *>(joint);
return slider_joint->get_param(p_param);
}
-RID PhysicsServer3DSW::joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+void PhysicsServer3DSW::joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
Body3DSW *body_A = body_owner.getornull(p_body_A);
- ERR_FAIL_COND_V(!body_A, RID());
+ ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND_V(!body_A->get_space(), RID());
+ ERR_FAIL_COND(!body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
Body3DSW *body_B = body_owner.getornull(p_body_B);
- ERR_FAIL_COND_V(!body_B, RID());
+ ERR_FAIL_COND(!body_B);
+
+ ERR_FAIL_COND(body_A == body_B);
- ERR_FAIL_COND_V(body_A == body_B, RID());
+ Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(ConeTwistJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B));
- RID rid = joint_owner.make_rid(joint);
- joint->set_self(rid);
- return rid;
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
}
void PhysicsServer3DSW::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_CONE_TWIST);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_CONE_TWIST);
ConeTwistJoint3DSW *cone_twist_joint = static_cast<ConeTwistJoint3DSW *>(joint);
cone_twist_joint->set_param(p_param, p_value);
}
@@ -1148,43 +1454,47 @@ void PhysicsServer3DSW::cone_twist_joint_set_param(RID p_joint, ConeTwistJointPa
real_t PhysicsServer3DSW::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, 0);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0);
ConeTwistJoint3DSW *cone_twist_joint = static_cast<ConeTwistJoint3DSW *>(joint);
return cone_twist_joint->get_param(p_param);
}
-RID PhysicsServer3DSW::joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+void PhysicsServer3DSW::joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
Body3DSW *body_A = body_owner.getornull(p_body_A);
- ERR_FAIL_COND_V(!body_A, RID());
+ ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND_V(!body_A->get_space(), RID());
+ ERR_FAIL_COND(!body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
Body3DSW *body_B = body_owner.getornull(p_body_B);
- ERR_FAIL_COND_V(!body_B, RID());
+ ERR_FAIL_COND(!body_B);
+
+ ERR_FAIL_COND(body_A == body_B);
- ERR_FAIL_COND_V(body_A == body_B, RID());
+ Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(Generic6DOFJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B, true));
- RID rid = joint_owner.make_rid(joint);
- joint->set_self(rid);
- return rid;
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
}
void PhysicsServer3DSW::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_6DOF);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF);
Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
generic_6dof_joint->set_param(p_axis, p_param, p_value);
}
-real_t PhysicsServer3DSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) {
+real_t PhysicsServer3DSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) const {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, 0);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, 0);
Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
return generic_6dof_joint->get_param(p_axis, p_param);
}
@@ -1192,15 +1502,15 @@ real_t PhysicsServer3DSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axi
void PhysicsServer3DSW::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_6DOF);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF);
Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
generic_6dof_joint->set_flag(p_axis, p_flag, p_enable);
}
-bool PhysicsServer3DSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) {
+bool PhysicsServer3DSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) const {
Joint3DSW *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, false);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, false);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, false);
Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
return generic_6dof_joint->get_flag(p_axis, p_flag);
}
@@ -1237,7 +1547,13 @@ void PhysicsServer3DSW::free(RID p_rid) {
body_owner.free(p_rid);
memdelete(body);
+ } else if (soft_body_owner.owns(p_rid)) {
+ SoftBody3DSW *soft_body = soft_body_owner.getornull(p_rid);
+
+ soft_body->set_space(nullptr);
+ soft_body_owner.free(p_rid);
+ memdelete(soft_body);
} else if (area_owner.owns(p_rid)) {
Area3DSW *area = area_owner.getornull(p_rid);
@@ -1271,9 +1587,6 @@ void PhysicsServer3DSW::free(RID p_rid) {
} else if (joint_owner.owns(p_rid)) {
Joint3DSW *joint = joint_owner.getornull(p_rid);
- for (int i = 0; i < joint->get_body_count(); i++) {
- joint->get_body_ptr()[i]->remove_constraint(joint);
- }
joint_owner.free(p_rid);
memdelete(joint);
@@ -1317,6 +1630,10 @@ void PhysicsServer3DSW::step(real_t p_step) {
#endif
}
+void PhysicsServer3DSW::sync() {
+ doing_sync = true;
+};
+
void PhysicsServer3DSW::flush_queries() {
#ifndef _3D_DISABLED
@@ -1370,6 +1687,10 @@ void PhysicsServer3DSW::flush_queries() {
#endif
};
+void PhysicsServer3DSW::end_sync() {
+ doing_sync = false;
+};
+
void PhysicsServer3DSW::finish() {
memdelete(stepper);
memdelete(direct_state);
@@ -1398,7 +1719,7 @@ void PhysicsServer3DSW::_update_shapes() {
}
}
-void PhysicsServer3DSW::_shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) {
+void PhysicsServer3DSW::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
CollCbkData *cbk = (CollCbkData *)p_userdata;
if (cbk->max == 0) {
@@ -1431,14 +1752,15 @@ void PhysicsServer3DSW::_shape_col_cbk(const Vector3 &p_point_A, const Vector3 &
}
}
-PhysicsServer3DSW *PhysicsServer3DSW::singleton = nullptr;
-PhysicsServer3DSW::PhysicsServer3DSW() {
- singleton = this;
+PhysicsServer3DSW *PhysicsServer3DSW::singletonsw = nullptr;
+PhysicsServer3DSW::PhysicsServer3DSW(bool p_using_threads) {
+ singletonsw = this;
BroadPhase3DSW::create_func = BroadPhaseOctree::_create;
island_count = 0;
active_objects = 0;
collision_pairs = 0;
-
+ using_threads = p_using_threads;
active = true;
flushing_queries = false;
+ doing_sync = false;
};
diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h
index c48db81d97..f92652bfad 100644
--- a/servers/physics_3d/physics_server_3d_sw.h
+++ b/servers/physics_3d/physics_server_3d_sw.h
@@ -50,6 +50,8 @@ class PhysicsServer3DSW : public PhysicsServer3D {
int active_objects;
int collision_pairs;
+ bool using_threads;
+ bool doing_sync;
bool flushing_queries;
Step3DSW *stepper;
@@ -57,29 +59,40 @@ class PhysicsServer3DSW : public PhysicsServer3D {
PhysicsDirectBodyState3DSW *direct_state;
- mutable RID_PtrOwner<Shape3DSW> shape_owner;
- mutable RID_PtrOwner<Space3DSW> space_owner;
- mutable RID_PtrOwner<Area3DSW> area_owner;
- mutable RID_PtrOwner<Body3DSW> body_owner;
- mutable RID_PtrOwner<Joint3DSW> joint_owner;
+ mutable RID_PtrOwner<Shape3DSW, true> shape_owner;
+ mutable RID_PtrOwner<Space3DSW, true> space_owner;
+ mutable RID_PtrOwner<Area3DSW, true> area_owner;
+ mutable RID_PtrOwner<Body3DSW, true> body_owner;
+ mutable RID_PtrOwner<SoftBody3DSW, true> soft_body_owner;
+ mutable RID_PtrOwner<Joint3DSW, true> joint_owner;
//void _clear_query(QuerySW *p_query);
friend class CollisionObject3DSW;
SelfList<CollisionObject3DSW>::List pending_shape_update_list;
void _update_shapes();
-public:
- static PhysicsServer3DSW *singleton;
+ static PhysicsServer3DSW *singletonsw;
+public:
struct CollCbkData {
int max;
int amount;
Vector3 *ptr;
};
- static void _shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata);
+ static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
+
+ virtual RID plane_shape_create() override;
+ virtual RID ray_shape_create() override;
+ virtual RID sphere_shape_create() override;
+ virtual RID box_shape_create() override;
+ virtual RID capsule_shape_create() override;
+ virtual RID cylinder_shape_create() override;
+ virtual RID convex_polygon_shape_create() override;
+ virtual RID concave_polygon_shape_create() override;
+ virtual RID heightmap_shape_create() override;
+ virtual RID custom_shape_create() override;
- virtual RID shape_create(ShapeType p_shape) override;
virtual void shape_set_data(RID p_shape, const Variant &p_data) override;
virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias) override;
@@ -140,7 +153,6 @@ public:
virtual Transform area_get_transform(RID p_area) const override;
virtual void area_set_ray_pickable(RID p_area, bool p_enable) override;
- virtual bool area_is_ray_pickable(RID p_area) const override;
virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) override;
virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) override;
@@ -153,7 +165,7 @@ public:
/* BODY API */
// create a body of a given type
- virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false) override;
+ virtual RID body_create() override;
virtual void body_set_space(RID p_body, RID p_space) override;
virtual RID body_get_space(RID p_body) const override;
@@ -232,7 +244,6 @@ public:
virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) override;
virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
- virtual bool body_is_ray_pickable(RID p_body) const override;
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
@@ -242,73 +253,66 @@ public:
/* SOFT BODY */
- virtual RID soft_body_create(bool p_init_sleeping = false) override { return RID(); }
+ virtual RID soft_body_create() override;
- virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) override {}
+ virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) override;
- virtual void soft_body_set_space(RID p_body, RID p_space) override {}
- virtual RID soft_body_get_space(RID p_body) const override { return RID(); }
+ virtual void soft_body_set_space(RID p_body, RID p_space) override;
+ virtual RID soft_body_get_space(RID p_body) const override;
- virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) override {}
- virtual uint32_t soft_body_get_collision_layer(RID p_body) const override { return 0; }
+ virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) override;
+ virtual uint32_t soft_body_get_collision_layer(RID p_body) const override;
- virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask) override {}
- virtual uint32_t soft_body_get_collision_mask(RID p_body) const override { return 0; }
+ virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask) override;
+ virtual uint32_t soft_body_get_collision_mask(RID p_body) const override;
- virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b) override {}
- virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b) override {}
- virtual void soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) override {}
+ virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b) override;
+ virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b) override;
+ virtual void soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) override;
- virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override {}
- virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const override { return Variant(); }
+ virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override;
+ virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const override;
- virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) override {}
- virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const override { return Vector3(); }
+ virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) override;
- virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) override {}
- virtual bool soft_body_is_ray_pickable(RID p_body) const override { return false; }
+ virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) override;
- virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) override {}
- virtual int soft_body_get_simulation_precision(RID p_body) override { return 0; }
+ virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) override;
+ virtual int soft_body_get_simulation_precision(RID p_body) const override;
- virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) override {}
- virtual real_t soft_body_get_total_mass(RID p_body) override { return 0.; }
+ virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) override;
+ virtual real_t soft_body_get_total_mass(RID p_body) const override;
- virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) override {}
- virtual real_t soft_body_get_linear_stiffness(RID p_body) override { return 0.; }
+ virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) override;
+ virtual real_t soft_body_get_linear_stiffness(RID p_body) const override;
- virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) override {}
- virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) override { return 0.; }
+ virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) override;
+ virtual real_t soft_body_get_pressure_coefficient(RID p_body) const override;
- virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) override {}
- virtual real_t soft_body_get_volume_stiffness(RID p_body) override { return 0.; }
+ virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) override;
+ virtual real_t soft_body_get_damping_coefficient(RID p_body) const override;
- virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) override {}
- virtual real_t soft_body_get_pressure_coefficient(RID p_body) override { return 0.; }
+ virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) override;
+ virtual real_t soft_body_get_drag_coefficient(RID p_body) const override;
- virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) override {}
- virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) override { return 0.; }
+ virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) override;
- virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) override {}
- virtual real_t soft_body_get_damping_coefficient(RID p_body) override { return 0.; }
+ virtual AABB soft_body_get_bounds(RID p_body) const override;
- virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) override {}
- virtual real_t soft_body_get_drag_coefficient(RID p_body) override { return 0.; }
+ virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) override;
+ virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) const override;
- virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) override {}
+ virtual void soft_body_remove_all_pinned_points(RID p_body) override;
+ virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) override;
+ virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) const override;
- virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) override {}
- virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) override { return Vector3(); }
-
- virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const override { return Vector3(); }
+ /* JOINT API */
- virtual void soft_body_remove_all_pinned_points(RID p_body) override {}
- virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) override {}
- virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) override { return false; }
+ virtual RID joint_create() override;
- /* JOINT API */
+ virtual void joint_clear(RID p_joint) override; //resets type
- virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) override;
+ virtual void joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) override;
virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) override;
virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const override;
@@ -319,8 +323,8 @@ public:
virtual void pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) override;
virtual Vector3 pin_joint_get_local_b(RID p_joint) const override;
- virtual RID joint_create_hinge(RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) override;
- virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) override;
+ virtual void joint_make_hinge(RID p_joint, RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) override;
+ virtual void joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) override;
virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) override;
virtual real_t hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const override;
@@ -328,23 +332,23 @@ public:
virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) override;
virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const override;
- virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
+ virtual void joint_make_slider(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) override;
virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const override;
- virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
+ virtual void joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) override;
virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const override;
- virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
+ virtual void joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, real_t p_value) override;
- virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) override;
+ virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) const override;
virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable) override;
- virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) override;
+ virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) const override;
virtual JointType joint_get_type(RID p_joint) const override;
@@ -361,14 +365,16 @@ public:
virtual void set_active(bool p_active) override;
virtual void init() override;
virtual void step(real_t p_step) override;
+ virtual void sync() override;
virtual void flush_queries() override;
+ virtual void end_sync() override;
virtual void finish() override;
virtual bool is_flushing_queries() const override { return flushing_queries; }
int get_process_info(ProcessInfo p_info) override;
- PhysicsServer3DSW();
+ PhysicsServer3DSW(bool p_using_threads = false);
~PhysicsServer3DSW() {}
};
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.cpp b/servers/physics_3d/physics_server_3d_wrap_mt.cpp
new file mode 100644
index 0000000000..f73f67a756
--- /dev/null
+++ b/servers/physics_3d/physics_server_3d_wrap_mt.cpp
@@ -0,0 +1,140 @@
+/*************************************************************************/
+/* physics_server_3d_wrap_mt.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "physics_server_3d_wrap_mt.h"
+
+#include "core/os/os.h"
+
+void PhysicsServer3DWrapMT::thread_exit() {
+ exit = true;
+}
+
+void PhysicsServer3DWrapMT::thread_step(real_t p_delta) {
+ physics_3d_server->step(p_delta);
+ step_sem.post();
+}
+
+void PhysicsServer3DWrapMT::_thread_callback(void *_instance) {
+ PhysicsServer3DWrapMT *vsmt = reinterpret_cast<PhysicsServer3DWrapMT *>(_instance);
+
+ vsmt->thread_loop();
+}
+
+void PhysicsServer3DWrapMT::thread_loop() {
+ server_thread = Thread::get_caller_id();
+
+ physics_3d_server->init();
+
+ exit = false;
+ step_thread_up = true;
+ while (!exit) {
+ // flush commands one by one, until exit is requested
+ command_queue.wait_and_flush_one();
+ }
+
+ command_queue.flush_all(); // flush all
+
+ physics_3d_server->finish();
+}
+
+/* EVENT QUEUING */
+
+void PhysicsServer3DWrapMT::step(real_t p_step) {
+ if (create_thread) {
+ command_queue.push(this, &PhysicsServer3DWrapMT::thread_step, p_step);
+ } else {
+ command_queue.flush_all(); //flush all pending from other threads
+ physics_3d_server->step(p_step);
+ }
+}
+
+void PhysicsServer3DWrapMT::sync() {
+ if (create_thread) {
+ if (first_frame) {
+ first_frame = false;
+ } else {
+ step_sem.wait(); //must not wait if a step was not issued
+ }
+ }
+ physics_3d_server->sync();
+}
+
+void PhysicsServer3DWrapMT::flush_queries() {
+ physics_3d_server->flush_queries();
+}
+
+void PhysicsServer3DWrapMT::end_sync() {
+ physics_3d_server->end_sync();
+}
+
+void PhysicsServer3DWrapMT::init() {
+ if (create_thread) {
+ //OS::get_singleton()->release_rendering_thread();
+ thread.start(_thread_callback, this);
+ while (!step_thread_up) {
+ OS::get_singleton()->delay_usec(1000);
+ }
+ } else {
+ physics_3d_server->init();
+ }
+}
+
+void PhysicsServer3DWrapMT::finish() {
+ if (thread.is_started()) {
+ command_queue.push(this, &PhysicsServer3DWrapMT::thread_exit);
+ thread.wait_to_finish();
+ } else {
+ physics_3d_server->finish();
+ }
+}
+
+PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) :
+ command_queue(p_create_thread) {
+ physics_3d_server = p_contained;
+ create_thread = p_create_thread;
+ step_pending = 0;
+ step_thread_up = false;
+
+ pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
+
+ if (!p_create_thread) {
+ server_thread = Thread::get_caller_id();
+ } else {
+ server_thread = 0;
+ }
+
+ main_thread = Thread::get_caller_id();
+ first_frame = true;
+}
+
+PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() {
+ memdelete(physics_3d_server);
+ //finish();
+}
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h
new file mode 100644
index 0000000000..49ae60db92
--- /dev/null
+++ b/servers/physics_3d/physics_server_3d_wrap_mt.h
@@ -0,0 +1,413 @@
+/*************************************************************************/
+/* physics_server_3d_wrap_mt.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 PHYSICS3DSERVERWRAPMT_H
+#define PHYSICS3DSERVERWRAPMT_H
+
+#include "core/config/project_settings.h"
+#include "core/os/thread.h"
+#include "core/templates/command_queue_mt.h"
+#include "servers/physics_server_3d.h"
+
+#ifdef DEBUG_SYNC
+#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__));
+#else
+#define SYNC_DEBUG
+#endif
+
+class PhysicsServer3DWrapMT : public PhysicsServer3D {
+ mutable PhysicsServer3D *physics_3d_server;
+
+ mutable CommandQueueMT command_queue;
+
+ static void _thread_callback(void *_instance);
+ void thread_loop();
+
+ Thread::ID server_thread;
+ Thread::ID main_thread;
+ volatile bool exit = false;
+ Thread thread;
+ volatile bool step_thread_up = false;
+ bool create_thread = false;
+
+ Semaphore step_sem;
+ int step_pending;
+ void thread_step(real_t p_delta);
+ void thread_flush();
+
+ void thread_exit();
+
+ bool first_frame = true;
+
+ Mutex alloc_mutex;
+ int pool_max_size = 0;
+
+public:
+#define ServerName PhysicsServer3D
+#define ServerNameWrapMT PhysicsServer3DWrapMT
+#define server_name physics_3d_server
+#define WRITE_ACTION
+
+#include "servers/server_wrap_mt_common.h"
+
+ //FUNC1RID(shape,ShapeType); todo fix
+ FUNCRID(plane_shape)
+ FUNCRID(ray_shape)
+ FUNCRID(sphere_shape)
+ FUNCRID(box_shape)
+ FUNCRID(capsule_shape)
+ FUNCRID(cylinder_shape)
+ FUNCRID(convex_polygon_shape)
+ FUNCRID(concave_polygon_shape)
+ FUNCRID(heightmap_shape)
+ FUNCRID(custom_shape)
+
+ FUNC2(shape_set_data, RID, const Variant &);
+ FUNC2(shape_set_custom_solver_bias, RID, real_t);
+
+ FUNC2(shape_set_margin, RID, real_t)
+ FUNC1RC(real_t, shape_get_margin, RID)
+
+ FUNC1RC(ShapeType, shape_get_type, RID);
+ FUNC1RC(Variant, shape_get_data, RID);
+ FUNC1RC(real_t, shape_get_custom_solver_bias, RID);
+#if 0
+ //these work well, but should be used from the main thread only
+ bool shape_collide(RID p_shape_A, const Transform &p_xform_A, const Vector3 &p_motion_A, RID p_shape_B, const Transform &p_xform_B, const Vector3 &p_motion_B, Vector3 *r_results, int p_result_max, int &r_result_count) {
+ ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
+ return physics_3d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
+ }
+#endif
+ /* SPACE API */
+
+ FUNCRID(space);
+ FUNC2(space_set_active, RID, bool);
+ FUNC1RC(bool, space_is_active, RID);
+
+ FUNC3(space_set_param, RID, SpaceParameter, real_t);
+ FUNC2RC(real_t, space_get_param, RID, SpaceParameter);
+
+ // this function only works on physics process, errors and returns null otherwise
+ PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space) override {
+ ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
+ return physics_3d_server->space_get_direct_state(p_space);
+ }
+
+ FUNC2(space_set_debug_contacts, RID, int);
+ virtual Vector<Vector3> space_get_contacts(RID p_space) const override {
+ ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector3>());
+ return physics_3d_server->space_get_contacts(p_space);
+ }
+
+ virtual int space_get_contact_count(RID p_space) const override {
+ ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0);
+ return physics_3d_server->space_get_contact_count(p_space);
+ }
+
+ /* AREA API */
+
+ //FUNC0RID(area);
+ FUNCRID(area);
+
+ FUNC2(area_set_space, RID, RID);
+ FUNC1RC(RID, area_get_space, RID);
+
+ FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode);
+ FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID);
+
+ FUNC4(area_add_shape, RID, RID, const Transform &, bool);
+ FUNC3(area_set_shape, RID, int, RID);
+ FUNC3(area_set_shape_transform, RID, int, const Transform &);
+ FUNC3(area_set_shape_disabled, RID, int, bool);
+
+ FUNC1RC(int, area_get_shape_count, RID);
+ FUNC2RC(RID, area_get_shape, RID, int);
+ FUNC2RC(Transform, area_get_shape_transform, RID, int);
+ FUNC2(area_remove_shape, RID, int);
+ FUNC1(area_clear_shapes, RID);
+
+ FUNC2(area_attach_object_instance_id, RID, ObjectID);
+ FUNC1RC(ObjectID, area_get_object_instance_id, RID);
+
+ FUNC3(area_set_param, RID, AreaParameter, const Variant &);
+ FUNC2(area_set_transform, RID, const Transform &);
+
+ FUNC2RC(Variant, area_get_param, RID, AreaParameter);
+ FUNC1RC(Transform, area_get_transform, RID);
+
+ FUNC2(area_set_collision_mask, RID, uint32_t);
+ FUNC2(area_set_collision_layer, RID, uint32_t);
+
+ FUNC2(area_set_monitorable, RID, bool);
+ FUNC2(area_set_ray_pickable, RID, bool);
+
+ FUNC3(area_set_monitor_callback, RID, Object *, const StringName &);
+ FUNC3(area_set_area_monitor_callback, RID, Object *, const StringName &);
+
+ /* BODY API */
+
+ //FUNC2RID(body,BodyMode,bool);
+ FUNCRID(body)
+
+ FUNC2(body_set_space, RID, RID);
+ FUNC1RC(RID, body_get_space, RID);
+
+ FUNC2(body_set_mode, RID, BodyMode);
+ FUNC1RC(BodyMode, body_get_mode, RID);
+
+ FUNC4(body_add_shape, RID, RID, const Transform &, bool);
+ FUNC3(body_set_shape, RID, int, RID);
+ FUNC3(body_set_shape_transform, RID, int, const Transform &);
+
+ FUNC1RC(int, body_get_shape_count, RID);
+ FUNC2RC(Transform, body_get_shape_transform, RID, int);
+ FUNC2RC(RID, body_get_shape, RID, int);
+
+ FUNC3(body_set_shape_disabled, RID, int, bool);
+
+ FUNC2(body_remove_shape, RID, int);
+ FUNC1(body_clear_shapes, RID);
+
+ FUNC2(body_attach_object_instance_id, RID, ObjectID);
+ FUNC1RC(ObjectID, body_get_object_instance_id, RID);
+
+ FUNC2(body_set_enable_continuous_collision_detection, RID, bool);
+ FUNC1RC(bool, body_is_continuous_collision_detection_enabled, RID);
+
+ FUNC2(body_set_collision_layer, RID, uint32_t);
+ FUNC1RC(uint32_t, body_get_collision_layer, RID);
+
+ FUNC2(body_set_collision_mask, RID, uint32_t);
+ FUNC1RC(uint32_t, body_get_collision_mask, RID);
+
+ FUNC2(body_set_user_flags, RID, uint32_t);
+ FUNC1RC(uint32_t, body_get_user_flags, RID);
+
+ FUNC3(body_set_param, RID, BodyParameter, real_t);
+ FUNC2RC(real_t, body_get_param, RID, BodyParameter);
+
+ FUNC2(body_set_kinematic_safe_margin, RID, real_t);
+ FUNC1RC(real_t, body_get_kinematic_safe_margin, RID);
+
+ FUNC3(body_set_state, RID, BodyState, const Variant &);
+ FUNC2RC(Variant, body_get_state, RID, BodyState);
+
+ FUNC2(body_set_applied_force, RID, const Vector3 &);
+ FUNC1RC(Vector3, body_get_applied_force, RID);
+
+ FUNC2(body_set_applied_torque, RID, const Vector3 &);
+ FUNC1RC(Vector3, body_get_applied_torque, RID);
+
+ FUNC2(body_add_central_force, RID, const Vector3 &);
+ FUNC3(body_add_force, RID, const Vector3 &, const Vector3 &);
+ FUNC2(body_add_torque, RID, const Vector3 &);
+ FUNC2(body_apply_torque_impulse, RID, const Vector3 &);
+ FUNC2(body_apply_central_impulse, RID, const Vector3 &);
+ FUNC3(body_apply_impulse, RID, const Vector3 &, const Vector3 &);
+ FUNC2(body_set_axis_velocity, RID, const Vector3 &);
+
+ FUNC3(body_set_axis_lock, RID, BodyAxis, bool);
+ FUNC2RC(bool, body_is_axis_locked, RID, BodyAxis);
+
+ FUNC2(body_add_collision_exception, RID, RID);
+ FUNC2(body_remove_collision_exception, RID, RID);
+ FUNC2S(body_get_collision_exceptions, RID, List<RID> *);
+
+ FUNC2(body_set_max_contacts_reported, RID, int);
+ FUNC1RC(int, body_get_max_contacts_reported, RID);
+
+ FUNC2(body_set_contacts_reported_depth_threshold, RID, real_t);
+ FUNC1RC(real_t, body_get_contacts_reported_depth_threshold, RID);
+
+ FUNC2(body_set_omit_force_integration, RID, bool);
+ FUNC1RC(bool, body_is_omitting_force_integration, RID);
+
+ FUNC4(body_set_force_integration_callback, RID, Object *, const StringName &, const Variant &);
+
+ FUNC2(body_set_ray_pickable, RID, bool);
+
+ bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override {
+ ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
+ return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, r_result, p_exclude_raycast_shapes);
+ }
+
+ int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override {
+ ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
+ return physics_3d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
+ }
+
+ // this function only works on physics process, errors and returns null otherwise
+ PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override {
+ ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
+ return physics_3d_server->body_get_direct_state(p_body);
+ }
+
+ /* SOFT BODY API */
+
+ FUNCRID(soft_body)
+
+ FUNC2(soft_body_update_rendering_server, RID, class RenderingServerHandler *)
+
+ FUNC2(soft_body_set_space, RID, RID)
+ FUNC1RC(RID, soft_body_get_space, RID)
+
+ FUNC2(soft_body_set_ray_pickable, RID, bool);
+
+ FUNC2(soft_body_set_collision_layer, RID, uint32_t)
+ FUNC1RC(uint32_t, soft_body_get_collision_layer, RID)
+
+ FUNC2(soft_body_set_collision_mask, RID, uint32_t)
+ FUNC1RC(uint32_t, soft_body_get_collision_mask, RID)
+
+ FUNC2(soft_body_add_collision_exception, RID, RID)
+ FUNC2(soft_body_remove_collision_exception, RID, RID)
+ FUNC2S(soft_body_get_collision_exceptions, RID, List<RID> *)
+
+ FUNC3(soft_body_set_state, RID, BodyState, const Variant &);
+ FUNC2RC(Variant, soft_body_get_state, RID, BodyState);
+
+ FUNC2(soft_body_set_transform, RID, const Transform &);
+
+ FUNC2(soft_body_set_simulation_precision, RID, int);
+ FUNC1RC(int, soft_body_get_simulation_precision, RID);
+
+ FUNC2(soft_body_set_total_mass, RID, real_t);
+ FUNC1RC(real_t, soft_body_get_total_mass, RID);
+
+ FUNC2(soft_body_set_linear_stiffness, RID, real_t);
+ FUNC1RC(real_t, soft_body_get_linear_stiffness, RID);
+
+ FUNC2(soft_body_set_pressure_coefficient, RID, real_t);
+ FUNC1RC(real_t, soft_body_get_pressure_coefficient, RID);
+
+ FUNC2(soft_body_set_damping_coefficient, RID, real_t);
+ FUNC1RC(real_t, soft_body_get_damping_coefficient, RID);
+
+ FUNC2(soft_body_set_drag_coefficient, RID, real_t);
+ FUNC1RC(real_t, soft_body_get_drag_coefficient, RID);
+
+ FUNC2(soft_body_set_mesh, RID, const REF &);
+
+ FUNC1RC(AABB, soft_body_get_bounds, RID);
+
+ FUNC3(soft_body_move_point, RID, int, const Vector3 &);
+ FUNC2RC(Vector3, soft_body_get_point_global_position, RID, int);
+
+ FUNC1(soft_body_remove_all_pinned_points, RID);
+ FUNC3(soft_body_pin_point, RID, int, bool);
+ FUNC2RC(bool, soft_body_is_point_pinned, RID, int);
+
+ /* JOINT API */
+
+ FUNCRID(joint)
+
+ FUNC1(joint_clear, RID)
+
+ FUNC5(joint_make_pin, RID, RID, const Vector3 &, RID, const Vector3 &)
+
+ FUNC3(pin_joint_set_param, RID, PinJointParam, real_t)
+ FUNC2RC(real_t, pin_joint_get_param, RID, PinJointParam)
+
+ FUNC2(pin_joint_set_local_a, RID, const Vector3 &)
+ FUNC1RC(Vector3, pin_joint_get_local_a, RID)
+
+ FUNC2(pin_joint_set_local_b, RID, const Vector3 &)
+ FUNC1RC(Vector3, pin_joint_get_local_b, RID)
+
+ FUNC5(joint_make_hinge, RID, RID, const Transform &, RID, const Transform &)
+ FUNC7(joint_make_hinge_simple, RID, RID, const Vector3 &, const Vector3 &, RID, const Vector3 &, const Vector3 &)
+
+ FUNC3(hinge_joint_set_param, RID, HingeJointParam, real_t)
+ FUNC2RC(real_t, hinge_joint_get_param, RID, HingeJointParam)
+
+ FUNC3(hinge_joint_set_flag, RID, HingeJointFlag, bool)
+ FUNC2RC(bool, hinge_joint_get_flag, RID, HingeJointFlag)
+
+ FUNC5(joint_make_slider, RID, RID, const Transform &, RID, const Transform &)
+
+ FUNC3(slider_joint_set_param, RID, SliderJointParam, real_t)
+ FUNC2RC(real_t, slider_joint_get_param, RID, SliderJointParam)
+
+ FUNC5(joint_make_cone_twist, RID, RID, const Transform &, RID, const Transform &)
+
+ FUNC3(cone_twist_joint_set_param, RID, ConeTwistJointParam, real_t)
+ FUNC2RC(real_t, cone_twist_joint_get_param, RID, ConeTwistJointParam)
+
+ FUNC5(joint_make_generic_6dof, RID, RID, const Transform &, RID, const Transform &)
+
+ FUNC4(generic_6dof_joint_set_param, RID, Vector3::Axis, G6DOFJointAxisParam, real_t)
+ FUNC3RC(real_t, generic_6dof_joint_get_param, RID, Vector3::Axis, G6DOFJointAxisParam)
+
+ FUNC4(generic_6dof_joint_set_flag, RID, Vector3::Axis, G6DOFJointAxisFlag, bool)
+ FUNC3RC(bool, generic_6dof_joint_get_flag, RID, Vector3::Axis, G6DOFJointAxisFlag)
+
+ FUNC1RC(JointType, joint_get_type, RID);
+
+ FUNC2(joint_set_solver_priority, RID, int);
+ FUNC1RC(int, joint_get_solver_priority, RID);
+
+ FUNC2(joint_disable_collisions_between_bodies, RID, const bool);
+ FUNC1RC(bool, joint_is_disabled_collisions_between_bodies, RID);
+
+ /* MISC */
+
+ FUNC1(free, RID);
+ FUNC1(set_active, bool);
+
+ virtual void init() override;
+ virtual void step(real_t p_step) override;
+ virtual void sync() override;
+ virtual void end_sync() override;
+ virtual void flush_queries() override;
+ virtual void finish() override;
+
+ virtual bool is_flushing_queries() const override {
+ return physics_3d_server->is_flushing_queries();
+ }
+
+ int get_process_info(ProcessInfo p_info) override {
+ return physics_3d_server->get_process_info(p_info);
+ }
+
+ PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread);
+ ~PhysicsServer3DWrapMT();
+
+#undef ServerNameWrapMT
+#undef ServerName
+#undef server_name
+#undef WRITE_ACTION
+};
+
+#ifdef DEBUG_SYNC
+#undef DEBUG_SYNC
+#endif
+#undef SYNC_DEBUG
+
+#endif // PHYSICS3DSERVERWRAPMT_H
diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp
index 9c37060bea..bf0946a0e2 100644
--- a/servers/physics_3d/shape_3d_sw.cpp
+++ b/servers/physics_3d/shape_3d_sw.cpp
@@ -34,10 +34,12 @@
#include "core/math/quick_hull.h"
#include "core/templates/sort_array.h"
-#define _POINT_SNAP 0.001953125
#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.0002
#define _FACE_IS_VALID_SUPPORT_THRESHOLD 0.9998
+#define _CYLINDER_EDGE_IS_VALID_SUPPORT_THRESHOLD 0.002
+#define _CYLINDER_FACE_IS_VALID_SUPPORT_THRESHOLD 0.999
+
void Shape3DSW::configure(const AABB &p_aabb) {
aabb = p_aabb;
configured = true;
@@ -50,7 +52,8 @@ void Shape3DSW::configure(const AABB &p_aabb) {
Vector3 Shape3DSW::get_support(const Vector3 &p_normal) const {
Vector3 res;
int amnt;
- get_supports(p_normal, 1, &res, amnt);
+ FeatureType type;
+ get_supports(p_normal, 1, &res, amnt, type);
return res;
}
@@ -167,16 +170,19 @@ Vector3 RayShape3DSW::get_support(const Vector3 &p_normal) const {
}
}
-void RayShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const {
+void RayShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
if (Math::abs(p_normal.z) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) {
r_amount = 2;
+ r_type = FEATURE_EDGE;
r_supports[0] = Vector3(0, 0, 0);
r_supports[1] = Vector3(0, 0, length);
} else if (p_normal.z > 0) {
r_amount = 1;
+ r_type = FEATURE_POINT;
*r_supports = Vector3(0, 0, length);
} else {
r_amount = 1;
+ r_type = FEATURE_POINT;
*r_supports = Vector3(0, 0, 0);
}
}
@@ -246,9 +252,10 @@ Vector3 SphereShape3DSW::get_support(const Vector3 &p_normal) const {
return p_normal * radius;
}
-void SphereShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const {
+void SphereShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
*r_supports = p_normal * radius;
r_amount = 1;
+ r_type = FEATURE_POINT;
}
bool SphereShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
@@ -312,7 +319,7 @@ Vector3 BoxShape3DSW::get_support(const Vector3 &p_normal) const {
return point;
}
-void BoxShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const {
+void BoxShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
static const int next[3] = { 1, 2, 0 };
static const int next2[3] = { 2, 0, 1 };
@@ -325,6 +332,7 @@ void BoxShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_s
bool neg = dot < 0;
r_amount = 4;
+ r_type = FEATURE_FACE;
Vector3 point;
point[i] = half_extents[i];
@@ -362,6 +370,7 @@ void BoxShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_s
if (Math::abs(p_normal.dot(axis)) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) {
r_amount = 2;
+ r_type = FEATURE_EDGE;
int i_n = next[i];
int i_n2 = next2[i];
@@ -389,6 +398,7 @@ void BoxShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_s
(p_normal.z < 0) ? -half_extents.z : half_extents.z);
r_amount = 1;
+ r_type = FEATURE_POINT;
r_supports[0] = point;
}
@@ -481,10 +491,10 @@ BoxShape3DSW::BoxShape3DSW() {
void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
Vector3 n = p_transform.basis.xform_inv(p_normal).normalized();
- real_t h = (n.z > 0) ? height : -height;
+ real_t h = (n.y > 0) ? height : -height;
n *= radius;
- n.z += h * 0.5;
+ n.y += h * 0.5;
r_max = p_normal.dot(p_transform.xform(n));
r_min = p_normal.dot(p_transform.xform(-n));
@@ -493,36 +503,38 @@ void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform &p
Vector3 CapsuleShape3DSW::get_support(const Vector3 &p_normal) const {
Vector3 n = p_normal;
- real_t h = (n.z > 0) ? height : -height;
+ real_t h = (n.y > 0) ? height : -height;
n *= radius;
- n.z += h * 0.5;
+ n.y += h * 0.5;
return n;
}
-void CapsuleShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const {
+void CapsuleShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
Vector3 n = p_normal;
- real_t d = n.z;
+ real_t d = n.y;
if (Math::abs(d) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) {
// make it flat
- n.z = 0.0;
+ n.y = 0.0;
n.normalize();
n *= radius;
r_amount = 2;
+ r_type = FEATURE_EDGE;
r_supports[0] = n;
- r_supports[0].z += height * 0.5;
+ r_supports[0].y += height * 0.5;
r_supports[1] = n;
- r_supports[1].z -= height * 0.5;
+ r_supports[1].y -= height * 0.5;
} else {
real_t h = (d > 0) ? height : -height;
n *= radius;
- n.z += h * 0.5;
+ n.y += h * 0.5;
r_amount = 1;
+ r_type = FEATURE_POINT;
*r_supports = n;
}
}
@@ -539,7 +551,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
// test against cylinder and spheres :-|
- collided = Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &auxres, &auxn);
+ collided = Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &auxres, &auxn, 1);
if (collided) {
real_t d = norm.dot(auxres);
@@ -551,7 +563,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
}
}
- collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, 0, height * 0.5), radius, &auxres, &auxn);
+ collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, height * 0.5, 0), radius, &auxres, &auxn);
if (collided) {
real_t d = norm.dot(auxres);
@@ -563,7 +575,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
}
}
- collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, 0, height * -0.5), radius, &auxres, &auxn);
+ collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, height * -0.5, 0), radius, &auxres, &auxn);
if (collided) {
real_t d = norm.dot(auxres);
@@ -584,19 +596,19 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
}
bool CapsuleShape3DSW::intersect_point(const Vector3 &p_point) const {
- if (Math::abs(p_point.z) < height * 0.5) {
- return Vector3(p_point.x, p_point.y, 0).length() < radius;
+ if (Math::abs(p_point.y) < height * 0.5) {
+ return Vector3(p_point.x, 0, p_point.z).length() < radius;
} else {
Vector3 p = p_point;
- p.z = Math::abs(p.z) - height * 0.5;
+ p.y = Math::abs(p.y) - height * 0.5;
return p.length() < radius;
}
}
Vector3 CapsuleShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
Vector3 s[2] = {
- Vector3(0, 0, -height * 0.5),
- Vector3(0, 0, height * 0.5),
+ Vector3(0, -height * 0.5, 0),
+ Vector3(0, height * 0.5, 0),
};
Vector3 p = Geometry3D::get_closest_point_to_segment(p_point, s);
@@ -615,13 +627,13 @@ Vector3 CapsuleShape3DSW::get_moment_of_inertia(real_t p_mass) const {
return Vector3(
(p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z),
(p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z),
- (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y));
+ (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
void CapsuleShape3DSW::_setup(real_t p_height, real_t p_radius) {
height = p_height;
radius = p_radius;
- configure(AABB(Vector3(-radius, -radius, -height * 0.5 - radius), Vector3(radius * 2, radius * 2, height + radius * 2.0)));
+ configure(AABB(Vector3(-radius, -height * 0.5 - radius, -radius), Vector3(radius * 2, height + radius * 2.0, radius * 2)));
}
void CapsuleShape3DSW::set_data(const Variant &p_data) {
@@ -642,6 +654,186 @@ CapsuleShape3DSW::CapsuleShape3DSW() {
height = radius = 0;
}
+/********** CYLINDER *************/
+
+void CylinderShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
+ Vector3 cylinder_axis = p_transform.basis.get_axis(1).normalized();
+ real_t axis_dot = cylinder_axis.dot(p_normal);
+
+ Vector3 local_normal = p_transform.basis.xform_inv(p_normal);
+ real_t scale = local_normal.length();
+ real_t scaled_radius = radius * scale;
+ real_t scaled_height = height * scale;
+
+ real_t length;
+ if (Math::abs(axis_dot) > 1.0) {
+ length = scaled_height * 0.5;
+ } else {
+ length = Math::abs(axis_dot * scaled_height * 0.5) + scaled_radius * Math::sqrt(1.0 - axis_dot * axis_dot);
+ }
+
+ real_t distance = p_normal.dot(p_transform.origin);
+
+ r_min = distance - length;
+ r_max = distance + length;
+}
+
+Vector3 CylinderShape3DSW::get_support(const Vector3 &p_normal) const {
+ Vector3 n = p_normal;
+ real_t h = (n.y > 0) ? height : -height;
+ real_t s = Math::sqrt(n.x * n.x + n.z * n.z);
+ if (Math::is_zero_approx(s)) {
+ n.x = radius;
+ n.y = h * 0.5;
+ n.z = 0.0;
+ } else {
+ real_t d = radius / s;
+ n.x = n.x * d;
+ n.y = h * 0.5;
+ n.z = n.z * d;
+ }
+
+ return n;
+}
+
+void CylinderShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
+ real_t d = p_normal.y;
+ if (Math::abs(d) > _CYLINDER_FACE_IS_VALID_SUPPORT_THRESHOLD) {
+ real_t h = (d > 0) ? height : -height;
+
+ Vector3 n = p_normal;
+ n.x = 0.0;
+ n.z = 0.0;
+ n.y = h * 0.5;
+
+ r_amount = 3;
+ r_type = FEATURE_CIRCLE;
+ r_supports[0] = n;
+ r_supports[1] = n;
+ r_supports[1].x += radius;
+ r_supports[2] = n;
+ r_supports[2].z += radius;
+ } else if (Math::abs(d) < _CYLINDER_EDGE_IS_VALID_SUPPORT_THRESHOLD) {
+ // make it flat
+ Vector3 n = p_normal;
+ n.y = 0.0;
+ n.normalize();
+ n *= radius;
+
+ r_amount = 2;
+ r_type = FEATURE_EDGE;
+ r_supports[0] = n;
+ r_supports[0].y += height * 0.5;
+ r_supports[1] = n;
+ r_supports[1].y -= height * 0.5;
+ } else {
+ r_amount = 1;
+ r_type = FEATURE_POINT;
+ r_supports[0] = get_support(p_normal);
+ return;
+
+ Vector3 n = p_normal;
+ real_t h = n.y * Math::sqrt(0.25 * height * height + radius * radius);
+ if (Math::abs(h) > 1.0) {
+ // Top or bottom surface.
+ n.y = (n.y > 0.0) ? height * 0.5 : -height * 0.5;
+ } else {
+ // Lateral surface.
+ n.y = height * 0.5 * h;
+ }
+
+ real_t s = Math::sqrt(n.x * n.x + n.z * n.z);
+ if (Math::is_zero_approx(s)) {
+ n.x = 0.0;
+ n.z = 0.0;
+ } else {
+ real_t scaled_radius = radius / s;
+ n.x = n.x * scaled_radius;
+ n.z = n.z * scaled_radius;
+ }
+
+ r_supports[0] = n;
+ }
+}
+
+bool CylinderShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+ return Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &r_result, &r_normal, 1);
+}
+
+bool CylinderShape3DSW::intersect_point(const Vector3 &p_point) const {
+ if (Math::abs(p_point.y) < height * 0.5) {
+ return Vector3(p_point.x, 0, p_point.z).length() < radius;
+ }
+ return false;
+}
+
+Vector3 CylinderShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+ if (Math::absf(p_point.y) > height * 0.5) {
+ // Project point to top disk.
+ real_t dir = p_point.y > 0.0 ? 1.0 : -1.0;
+ Vector3 circle_pos(0.0, dir * height * 0.5, 0.0);
+ Plane circle_plane(circle_pos, Vector3(0.0, dir, 0.0));
+ Vector3 proj_point = circle_plane.project(p_point);
+
+ // Clip position.
+ Vector3 delta_point_1 = proj_point - circle_pos;
+ real_t dist_point_1 = delta_point_1.length_squared();
+ if (!Math::is_zero_approx(dist_point_1)) {
+ dist_point_1 = Math::sqrt(dist_point_1);
+ proj_point = circle_pos + delta_point_1 * MIN(dist_point_1, radius) / dist_point_1;
+ }
+
+ return proj_point;
+ } else {
+ Vector3 s[2] = {
+ Vector3(0, -height * 0.5, 0),
+ Vector3(0, height * 0.5, 0),
+ };
+
+ Vector3 p = Geometry3D::get_closest_point_to_segment(p_point, s);
+
+ if (p.distance_to(p_point) < radius) {
+ return p_point;
+ }
+
+ return p + (p_point - p).normalized() * radius;
+ }
+}
+
+Vector3 CylinderShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+ // use bad AABB approximation
+ Vector3 extents = get_aabb().size * 0.5;
+
+ return Vector3(
+ (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z),
+ (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z),
+ (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
+}
+
+void CylinderShape3DSW::_setup(real_t p_height, real_t p_radius) {
+ height = p_height;
+ radius = p_radius;
+ configure(AABB(Vector3(-radius, -height * 0.5, -radius), Vector3(radius * 2.0, height, radius * 2.0)));
+}
+
+void CylinderShape3DSW::set_data(const Variant &p_data) {
+ Dictionary d = p_data;
+ ERR_FAIL_COND(!d.has("radius"));
+ ERR_FAIL_COND(!d.has("height"));
+ _setup(d["height"], d["radius"]);
+}
+
+Variant CylinderShape3DSW::get_data() const {
+ Dictionary d;
+ d["radius"] = radius;
+ d["height"] = height;
+ return d;
+}
+
+CylinderShape3DSW::CylinderShape3DSW() {
+ height = radius = 0;
+}
+
/********** CONVEX POLYGON *************/
void ConvexPolygonShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
@@ -689,7 +881,7 @@ Vector3 ConvexPolygonShape3DSW::get_support(const Vector3 &p_normal) const {
return vrts[vert_support_idx];
}
-void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const {
+void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
int fc = mesh.faces.size();
@@ -734,6 +926,7 @@ void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Ve
r_supports[j] = vertices[ind[j]];
}
r_amount = m;
+ r_type = FEATURE_FACE;
return;
}
}
@@ -743,6 +936,7 @@ void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Ve
dot = ABS(dot);
if (dot < _EDGE_IS_VALID_SUPPORT_THRESHOLD && (edges[i].a == vtx || edges[i].b == vtx)) {
r_amount = 2;
+ r_type = FEATURE_EDGE;
r_supports[0] = vertices[edges[i].a];
r_supports[1] = vertices[edges[i].b];
return;
@@ -751,6 +945,7 @@ void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Ve
r_supports[0] = vertices[vtx];
r_amount = 1;
+ r_type = FEATURE_POINT;
}
bool ConvexPolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
@@ -869,7 +1064,7 @@ Vector3 ConvexPolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const {
return Vector3(
(p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z),
(p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z),
- (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y));
+ (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
void ConvexPolygonShape3DSW::_setup(const Vector<Vector3> &p_vertices) {
@@ -935,12 +1130,13 @@ Vector3 FaceShape3DSW::get_support(const Vector3 &p_normal) const {
return vertex[vert_support_idx];
}
-void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const {
+void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
Vector3 n = p_normal;
/** TEST FACE AS SUPPORT **/
- if (normal.dot(n) > _FACE_IS_VALID_SUPPORT_THRESHOLD) {
+ if (Math::abs(normal.dot(n)) > _FACE_IS_VALID_SUPPORT_THRESHOLD) {
r_amount = 3;
+ r_type = FEATURE_FACE;
for (int i = 0; i < 3; i++) {
r_supports[i] = vertex[i];
}
@@ -974,6 +1170,7 @@ void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_
dot = ABS(dot);
if (dot < _EDGE_IS_VALID_SUPPORT_THRESHOLD) {
r_amount = 2;
+ r_type = FEATURE_EDGE;
r_supports[0] = vertex[i];
r_supports[1] = vertex[nx];
return;
@@ -981,6 +1178,7 @@ void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_
}
r_amount = 1;
+ r_type = FEATURE_POINT;
r_supports[0] = vertex[vert_support_idx];
}
@@ -989,7 +1187,11 @@ bool FaceShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_e
if (c) {
r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal;
if (r_normal.dot(p_end - p_begin) > 0) {
- r_normal = -r_normal;
+ if (backface_collision) {
+ r_normal = -r_normal;
+ } else {
+ c = false;
+ }
}
}
@@ -1087,30 +1289,24 @@ void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_par
}
if (bvh->face_index >= 0) {
- Vector3 res;
- Vector3 vertices[3] = {
- p_params->vertices[p_params->faces[bvh->face_index].indices[0]],
- p_params->vertices[p_params->faces[bvh->face_index].indices[1]],
- p_params->vertices[p_params->faces[bvh->face_index].indices[2]]
- };
+ const Face *f = &p_params->faces[bvh->face_index];
+ FaceShape3DSW *face = p_params->face;
+ face->normal = f->normal;
+ face->vertex[0] = p_params->vertices[f->indices[0]];
+ face->vertex[1] = p_params->vertices[f->indices[1]];
+ face->vertex[2] = p_params->vertices[f->indices[2]];
- if (Geometry3D::segment_intersects_triangle(
- p_params->from,
- p_params->to,
- vertices[0],
- vertices[1],
- vertices[2],
- &res)) {
+ Vector3 res;
+ Vector3 normal;
+ if (face->intersect_segment(p_params->from, p_params->to, res, normal)) {
real_t d = p_params->dir.dot(res) - p_params->dir.dot(p_params->from);
- //TODO, seems segmen/triangle intersection is broken :(
- if (d > 0 && d < p_params->min_d) {
+ if ((d > 0) && (d < p_params->min_d)) {
p_params->min_d = d;
p_params->result = res;
- p_params->normal = Plane(vertices[0], vertices[1], vertices[2]).normal;
+ p_params->normal = normal;
p_params->collisions++;
}
}
-
} else {
if (bvh->left >= 0) {
_cull_segment(bvh->left, p_params);
@@ -1131,17 +1327,20 @@ bool ConcavePolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Ve
const Vector3 *vr = vertices.ptr();
const BVH *br = bvh.ptr();
+ FaceShape3DSW face;
+ face.backface_collision = backface_collision;
+
_SegmentCullParams params;
params.from = p_begin;
params.to = p_end;
- params.collisions = 0;
params.dir = (p_end - p_begin).normalized();
params.faces = fr;
params.vertices = vr;
params.bvh = br;
- params.min_d = 1e20;
+ params.face = &face;
+
// cull
_cull_segment(0, &params);
@@ -1203,6 +1402,7 @@ void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, Callback p_callback
const BVH *br = bvh.ptr();
FaceShape3DSW face; // use this to send in the callback
+ face.backface_collision = backface_collision;
_CullParams params;
params.aabb = local_aabb;
@@ -1224,7 +1424,7 @@ Vector3 ConcavePolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const {
return Vector3(
(p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z),
(p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z),
- (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y));
+ (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
struct _VolumeSW_BVH_Element {
@@ -1334,7 +1534,7 @@ void ConcavePolygonShape3DSW::_fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_ar
memdelete(p_bvh_tree);
}
-void ConcavePolygonShape3DSW::_setup(Vector<Vector3> p_faces) {
+void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_backface_collision) {
int src_face_count = p_faces.size();
if (src_face_count == 0) {
configure(AABB());
@@ -1389,15 +1589,24 @@ void ConcavePolygonShape3DSW::_setup(Vector<Vector3> p_faces) {
int idx = 0;
_fill_bvh(bvh_tree, bvh_arrayw2, idx);
+ backface_collision = p_backface_collision;
+
configure(_aabb); // this type of shape has no margin
}
void ConcavePolygonShape3DSW::set_data(const Variant &p_data) {
- _setup(p_data);
+ Dictionary d = p_data;
+ ERR_FAIL_COND(!d.has("faces"));
+
+ _setup(d["faces"], d["backface_collision"]);
}
Variant ConcavePolygonShape3DSW::get_data() const {
- return get_faces();
+ Dictionary d;
+ d["faces"] = get_faces();
+ d["backface_collision"] = backface_collision;
+
+ return d;
}
ConcavePolygonShape3DSW::ConcavePolygonShape3DSW() {
@@ -1453,7 +1662,7 @@ Vector3 HeightMapShape3DSW::get_moment_of_inertia(real_t p_mass) const {
return Vector3(
(p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z),
(p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z),
- (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y));
+ (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
void HeightMapShape3DSW::_setup(Vector<real_t> p_heights, int p_width, int p_depth, real_t p_cell_size) {
diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h
index 851c0d9443..988e76c699 100644
--- a/servers/physics_3d/shape_3d_sw.h
+++ b/servers/physics_3d/shape_3d_sw.h
@@ -67,8 +67,11 @@ protected:
void configure(const AABB &p_aabb);
public:
- enum {
- MAX_SUPPORTS = 8
+ enum FeatureType {
+ FEATURE_POINT,
+ FEATURE_EDGE,
+ FEATURE_FACE,
+ FEATURE_CIRCLE,
};
virtual real_t get_area() const { return aabb.get_area(); }
@@ -85,7 +88,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const = 0;
virtual Vector3 get_support(const Vector3 &p_normal) const;
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const = 0;
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const = 0;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const = 0;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const = 0;
virtual bool intersect_point(const Vector3 &p_point) const = 0;
@@ -110,7 +113,7 @@ class ConcaveShape3DSW : public Shape3DSW {
public:
virtual bool is_concave() const { return true; }
typedef void (*Callback)(void *p_userdata, Shape3DSW *p_convex);
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; }
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; }
virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const = 0;
@@ -129,7 +132,7 @@ public:
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_PLANE; }
virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; }
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; }
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
virtual bool intersect_point(const Vector3 &p_point) const;
@@ -156,7 +159,7 @@ public:
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_RAY; }
virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
virtual bool intersect_point(const Vector3 &p_point) const;
@@ -184,7 +187,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
virtual bool intersect_point(const Vector3 &p_point) const;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
@@ -209,7 +212,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
virtual bool intersect_point(const Vector3 &p_point) const;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
@@ -238,7 +241,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
virtual bool intersect_point(const Vector3 &p_point) const;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
@@ -251,6 +254,35 @@ public:
CapsuleShape3DSW();
};
+class CylinderShape3DSW : public Shape3DSW {
+ real_t height;
+ real_t radius;
+
+ void _setup(real_t p_height, real_t p_radius);
+
+public:
+ _FORCE_INLINE_ real_t get_height() const { return height; }
+ _FORCE_INLINE_ real_t get_radius() const { return radius; }
+
+ virtual real_t get_area() const { return 4.0 / 3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; }
+
+ virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CYLINDER; }
+
+ virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
+ virtual Vector3 get_support(const Vector3 &p_normal) const;
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
+ virtual bool intersect_point(const Vector3 &p_point) const;
+ virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
+
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
+
+ virtual void set_data(const Variant &p_data);
+ virtual Variant get_data() const;
+
+ CylinderShape3DSW();
+};
+
struct ConvexPolygonShape3DSW : public Shape3DSW {
Geometry3D::MeshData mesh;
@@ -263,7 +295,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
virtual bool intersect_point(const Vector3 &p_point) const;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
@@ -302,34 +334,37 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW {
struct _CullParams {
AABB aabb;
- Callback callback;
- void *userdata;
- const Face *faces;
- const Vector3 *vertices;
- const BVH *bvh;
- FaceShape3DSW *face;
+ Callback callback = nullptr;
+ void *userdata = nullptr;
+ const Face *faces = nullptr;
+ const Vector3 *vertices = nullptr;
+ const BVH *bvh = nullptr;
+ FaceShape3DSW *face = nullptr;
};
struct _SegmentCullParams {
Vector3 from;
Vector3 to;
- const Face *faces;
- const Vector3 *vertices;
- const BVH *bvh;
Vector3 dir;
+ const Face *faces = nullptr;
+ const Vector3 *vertices = nullptr;
+ const BVH *bvh = nullptr;
+ FaceShape3DSW *face = nullptr;
Vector3 result;
Vector3 normal;
- real_t min_d;
- int collisions;
+ real_t min_d = 1e20;
+ int collisions = 0;
};
+ bool backface_collision = false;
+
void _cull_segment(int p_idx, _SegmentCullParams *p_params) const;
void _cull(int p_idx, _CullParams *p_params) const;
void _fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx);
- void _setup(Vector<Vector3> p_faces);
+ void _setup(const Vector<Vector3> &p_faces, bool p_backface_collision);
public:
Vector<Vector3> get_faces() const;
@@ -392,6 +427,7 @@ public:
struct FaceShape3DSW : public Shape3DSW {
Vector3 normal; //cache
Vector3 vertex[3];
+ bool backface_collision = false;
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; }
@@ -399,7 +435,7 @@ struct FaceShape3DSW : public Shape3DSW {
void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
Vector3 get_support(const Vector3 &p_normal) const;
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
virtual bool intersect_point(const Vector3 &p_point) const;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
@@ -437,7 +473,7 @@ struct MotionShape3DSW : public Shape3DSW {
}
return support;
}
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; }
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; }
bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { return false; }
virtual bool intersect_point(const Vector3 &p_point) const { return false; }
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const { return p_point; }
diff --git a/servers/physics_3d/soft_body_3d_sw.cpp b/servers/physics_3d/soft_body_3d_sw.cpp
new file mode 100644
index 0000000000..f63a470cbe
--- /dev/null
+++ b/servers/physics_3d/soft_body_3d_sw.cpp
@@ -0,0 +1,1221 @@
+/*************************************************************************/
+/* soft_body_3d_sw.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "soft_body_3d_sw.h"
+#include "space_3d_sw.h"
+
+#include "core/math/geometry_3d.h"
+#include "core/templates/map.h"
+
+// Based on Bullet soft body.
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btSoftBody implementation by Nathanael Presson
+
+SoftBody3DSW::SoftBody3DSW() :
+ CollisionObject3DSW(TYPE_SOFT_BODY),
+ active_list(this) {
+ _set_static(false);
+}
+
+void SoftBody3DSW::_shapes_changed() {
+}
+
+void SoftBody3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) {
+ switch (p_state) {
+ case PhysicsServer3D::BODY_STATE_TRANSFORM: {
+ _set_transform(p_variant);
+ _set_inv_transform(get_transform().inverse());
+
+ apply_nodes_transform(get_transform());
+
+ } break;
+ case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: {
+ // Not supported.
+ ERR_FAIL_MSG("Linear velocity is not supported for Soft bodies.");
+ } break;
+ case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: {
+ ERR_FAIL_MSG("Angular velocity is not supported for Soft bodies.");
+ } break;
+ case PhysicsServer3D::BODY_STATE_SLEEPING: {
+ ERR_FAIL_MSG("Sleeping state is not supported for Soft bodies.");
+ } break;
+ case PhysicsServer3D::BODY_STATE_CAN_SLEEP: {
+ ERR_FAIL_MSG("Sleeping state is not supported for Soft bodies.");
+ } break;
+ }
+}
+
+Variant SoftBody3DSW::get_state(PhysicsServer3D::BodyState p_state) const {
+ switch (p_state) {
+ case PhysicsServer3D::BODY_STATE_TRANSFORM: {
+ return get_transform();
+ } break;
+ case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: {
+ ERR_FAIL_V_MSG(Vector3(), "Linear velocity is not supported for Soft bodies.");
+ } break;
+ case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: {
+ ERR_FAIL_V_MSG(Vector3(), "Angular velocity is not supported for Soft bodies.");
+ return Vector3();
+ } break;
+ case PhysicsServer3D::BODY_STATE_SLEEPING: {
+ ERR_FAIL_V_MSG(false, "Sleeping state is not supported for Soft bodies.");
+ } break;
+ case PhysicsServer3D::BODY_STATE_CAN_SLEEP: {
+ ERR_FAIL_V_MSG(false, "Sleeping state is not supported for Soft bodies.");
+ } break;
+ }
+
+ return Variant();
+}
+
+void SoftBody3DSW::set_space(Space3DSW *p_space) {
+ if (get_space()) {
+ get_space()->soft_body_remove_from_active_list(&active_list);
+
+ deinitialize_shape();
+ }
+
+ _set_space(p_space);
+
+ if (get_space()) {
+ get_space()->soft_body_add_to_active_list(&active_list);
+
+ if (bounds != AABB()) {
+ initialize_shape(true);
+ }
+ }
+}
+
+void SoftBody3DSW::set_mesh(const Ref<Mesh> &p_mesh) {
+ destroy();
+
+ soft_mesh = p_mesh;
+
+ if (soft_mesh.is_null()) {
+ return;
+ }
+
+ Array arrays = soft_mesh->surface_get_arrays(0);
+ ERR_FAIL_COND(!(soft_mesh->surface_get_format(0) & RS::ARRAY_FORMAT_INDEX));
+
+ bool success = create_from_trimesh(arrays[RS::ARRAY_INDEX], arrays[RS::ARRAY_VERTEX]);
+ if (!success) {
+ destroy();
+ soft_mesh = Ref<Mesh>();
+ }
+}
+
+void SoftBody3DSW::update_rendering_server(RenderingServerHandler *p_rendering_server_handler) {
+ if (soft_mesh.is_null()) {
+ return;
+ }
+
+ const uint32_t vertex_count = map_visual_to_physics.size();
+ for (uint32_t i = 0; i < vertex_count; ++i) {
+ const uint32_t node_index = map_visual_to_physics[i];
+ const Node &node = nodes[node_index];
+ const Vector3 &vertex_position = node.x;
+ const Vector3 &vertex_normal = node.n;
+
+ p_rendering_server_handler->set_vertex(i, &vertex_position);
+ p_rendering_server_handler->set_normal(i, &vertex_normal);
+ }
+
+ p_rendering_server_handler->set_aabb(bounds);
+}
+
+void SoftBody3DSW::update_normals() {
+ uint32_t i, ni;
+
+ for (i = 0, ni = nodes.size(); i < ni; ++i) {
+ nodes[i].n = Vector3();
+ }
+
+ for (i = 0, ni = faces.size(); i < ni; ++i) {
+ Face &face = faces[i];
+ const Vector3 n = vec3_cross(face.n[0]->x - face.n[2]->x, face.n[0]->x - face.n[1]->x);
+ face.n[0]->n += n;
+ face.n[1]->n += n;
+ face.n[2]->n += n;
+ face.normal = n;
+ face.normal.normalize();
+ }
+
+ for (i = 0, ni = nodes.size(); i < ni; ++i) {
+ Node &node = nodes[i];
+ real_t len = node.n.length();
+ if (len > CMP_EPSILON) {
+ node.n /= len;
+ }
+ }
+}
+
+void SoftBody3DSW::update_bounds() {
+ AABB prev_bounds = bounds;
+ prev_bounds.grow_by(collision_margin);
+
+ bounds = AABB();
+
+ const uint32_t nodes_count = nodes.size();
+ if (nodes_count == 0) {
+ deinitialize_shape();
+ return;
+ }
+
+ bool first = true;
+ bool moved = false;
+ for (uint32_t node_index = 0; node_index < nodes_count; ++node_index) {
+ const Node &node = nodes[node_index];
+ if (!prev_bounds.has_point(node.x)) {
+ moved = true;
+ }
+ if (first) {
+ bounds.position = node.x;
+ first = false;
+ } else {
+ bounds.expand_to(node.x);
+ }
+ }
+
+ if (get_space()) {
+ initialize_shape(moved);
+ }
+}
+
+void SoftBody3DSW::update_constants() {
+ reset_link_rest_lengths();
+ update_link_constants();
+ update_area();
+}
+
+void SoftBody3DSW::update_area() {
+ int i, ni;
+
+ // Face area.
+ for (i = 0, ni = faces.size(); i < ni; ++i) {
+ Face &face = faces[i];
+
+ const Vector3 &x0 = face.n[0]->x;
+ const Vector3 &x1 = face.n[1]->x;
+ const Vector3 &x2 = face.n[2]->x;
+
+ const Vector3 a = x1 - x0;
+ const Vector3 b = x2 - x0;
+ const Vector3 cr = vec3_cross(a, b);
+ face.ra = cr.length();
+ }
+
+ // Node area.
+ LocalVector<int> counts;
+ counts.resize(nodes.size());
+ memset(counts.ptr(), 0, counts.size() * sizeof(int));
+
+ for (i = 0, ni = nodes.size(); i < ni; ++i) {
+ nodes[i].area = 0.0;
+ }
+
+ for (i = 0, ni = faces.size(); i < ni; ++i) {
+ const Face &face = faces[i];
+ for (int j = 0; j < 3; ++j) {
+ const int index = (int)(face.n[j] - &nodes[0]);
+ counts[index]++;
+ face.n[j]->area += Math::abs(face.ra);
+ }
+ }
+
+ for (i = 0, ni = nodes.size(); i < ni; ++i) {
+ if (counts[i] > 0) {
+ nodes[i].area /= (real_t)counts[i];
+ } else {
+ nodes[i].area = 0.0;
+ }
+ }
+}
+
+void SoftBody3DSW::reset_link_rest_lengths() {
+ for (uint32_t i = 0, ni = links.size(); i < ni; ++i) {
+ Link &link = links[i];
+ link.rl = (link.n[0]->x - link.n[1]->x).length();
+ link.c1 = link.rl * link.rl;
+ }
+}
+
+void SoftBody3DSW::update_link_constants() {
+ real_t inv_linear_stiffness = 1.0 / linear_stiffness;
+ for (uint32_t i = 0, ni = links.size(); i < ni; ++i) {
+ Link &link = links[i];
+ link.c0 = (link.n[0]->im + link.n[1]->im) * inv_linear_stiffness;
+ }
+}
+
+void SoftBody3DSW::apply_nodes_transform(const Transform &p_transform) {
+ if (soft_mesh.is_null()) {
+ return;
+ }
+
+ uint32_t node_count = nodes.size();
+ Vector3 leaf_size = Vector3(collision_margin, collision_margin, collision_margin) * 2.0;
+ for (uint32_t node_index = 0; node_index < node_count; ++node_index) {
+ Node &node = nodes[node_index];
+
+ node.x = p_transform.xform(node.x);
+ node.q = node.x;
+ node.v = Vector3();
+ node.bv = Vector3();
+
+ AABB node_aabb(node.x, leaf_size);
+ node_tree.update(node.leaf, node_aabb);
+ }
+
+ face_tree.clear();
+
+ update_normals();
+ update_bounds();
+ update_constants();
+}
+
+Vector3 SoftBody3DSW::get_vertex_position(int p_index) const {
+ if (soft_mesh.is_null()) {
+ return Vector3();
+ }
+
+ ERR_FAIL_INDEX_V(p_index, (int)map_visual_to_physics.size(), Vector3());
+ uint32_t node_index = map_visual_to_physics[p_index];
+
+ ERR_FAIL_COND_V(node_index >= nodes.size(), Vector3());
+ return nodes[node_index].x;
+}
+
+void SoftBody3DSW::set_vertex_position(int p_index, const Vector3 &p_position) {
+ if (soft_mesh.is_null()) {
+ return;
+ }
+
+ ERR_FAIL_INDEX(p_index, (int)map_visual_to_physics.size());
+ uint32_t node_index = map_visual_to_physics[p_index];
+
+ ERR_FAIL_COND(node_index >= nodes.size());
+ Node &node = nodes[node_index];
+ node.q = node.x;
+ node.x = p_position;
+}
+
+void SoftBody3DSW::pin_vertex(int p_index) {
+ if (is_vertex_pinned(p_index)) {
+ return;
+ }
+
+ pinned_vertices.push_back(p_index);
+
+ if (!soft_mesh.is_null()) {
+ ERR_FAIL_INDEX(p_index, (int)map_visual_to_physics.size());
+ uint32_t node_index = map_visual_to_physics[p_index];
+
+ ERR_FAIL_COND(node_index >= nodes.size());
+ Node &node = nodes[node_index];
+ node.im = 0.0;
+ }
+}
+
+void SoftBody3DSW::unpin_vertex(int p_index) {
+ uint32_t pinned_count = pinned_vertices.size();
+ for (uint32_t i = 0; i < pinned_count; ++i) {
+ if (p_index == pinned_vertices[i]) {
+ pinned_vertices.remove(i);
+
+ if (!soft_mesh.is_null()) {
+ ERR_FAIL_INDEX(p_index, (int)map_visual_to_physics.size());
+ uint32_t node_index = map_visual_to_physics[p_index];
+
+ ERR_FAIL_COND(node_index >= nodes.size());
+ real_t inv_node_mass = nodes.size() * inv_total_mass;
+
+ Node &node = nodes[node_index];
+ node.im = inv_node_mass;
+ }
+
+ return;
+ }
+ }
+}
+
+void SoftBody3DSW::unpin_all_vertices() {
+ if (!soft_mesh.is_null()) {
+ real_t inv_node_mass = nodes.size() * inv_total_mass;
+ uint32_t pinned_count = pinned_vertices.size();
+ for (uint32_t i = 0; i < pinned_count; ++i) {
+ uint32_t vertex_index = pinned_vertices[i];
+
+ ERR_CONTINUE(vertex_index >= map_visual_to_physics.size());
+ uint32_t node_index = map_visual_to_physics[vertex_index];
+
+ ERR_CONTINUE(node_index >= nodes.size());
+ Node &node = nodes[node_index];
+ node.im = inv_node_mass;
+ }
+ }
+
+ pinned_vertices.clear();
+}
+
+bool SoftBody3DSW::is_vertex_pinned(int p_index) const {
+ uint32_t pinned_count = pinned_vertices.size();
+ for (uint32_t i = 0; i < pinned_count; ++i) {
+ if (p_index == pinned_vertices[i]) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+uint32_t SoftBody3DSW::get_node_count() const {
+ return nodes.size();
+}
+
+real_t SoftBody3DSW::get_node_inv_mass(uint32_t p_node_index) const {
+ ERR_FAIL_COND_V(p_node_index >= nodes.size(), 0.0);
+ return nodes[p_node_index].im;
+}
+
+Vector3 SoftBody3DSW::get_node_position(uint32_t p_node_index) const {
+ ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3());
+ return nodes[p_node_index].x;
+}
+
+Vector3 SoftBody3DSW::get_node_velocity(uint32_t p_node_index) const {
+ ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3());
+ return nodes[p_node_index].v;
+}
+
+Vector3 SoftBody3DSW::get_node_biased_velocity(uint32_t p_node_index) const {
+ ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3());
+ return nodes[p_node_index].bv;
+}
+
+void SoftBody3DSW::apply_node_impulse(uint32_t p_node_index, const Vector3 &p_impulse) {
+ ERR_FAIL_COND(p_node_index >= nodes.size());
+ Node &node = nodes[p_node_index];
+ node.v += p_impulse * node.im;
+}
+
+void SoftBody3DSW::apply_node_bias_impulse(uint32_t p_node_index, const Vector3 &p_impulse) {
+ ERR_FAIL_COND(p_node_index >= nodes.size());
+ Node &node = nodes[p_node_index];
+ node.bv += p_impulse * node.im;
+}
+
+uint32_t SoftBody3DSW::get_face_count() const {
+ return faces.size();
+}
+
+void SoftBody3DSW::get_face_points(uint32_t p_face_index, Vector3 &r_point_1, Vector3 &r_point_2, Vector3 &r_point_3) const {
+ ERR_FAIL_COND(p_face_index >= faces.size());
+ const Face &face = faces[p_face_index];
+ r_point_1 = face.n[0]->x;
+ r_point_2 = face.n[1]->x;
+ r_point_3 = face.n[2]->x;
+}
+
+Vector3 SoftBody3DSW::get_face_normal(uint32_t p_face_index) const {
+ ERR_FAIL_COND_V(p_face_index >= faces.size(), Vector3());
+ return faces[p_face_index].normal;
+}
+
+bool SoftBody3DSW::create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices) {
+ uint32_t node_count = 0;
+ LocalVector<Vector3> vertices;
+ const int visual_vertex_count(p_vertices.size());
+
+ LocalVector<int> triangles;
+ const uint32_t triangle_count(p_indices.size() / 3);
+ triangles.resize(triangle_count * 3);
+
+ // Merge all overlapping vertices and create a map of physical vertices to visual vertices.
+ {
+ // Process vertices.
+ {
+ uint32_t vertex_count = 0;
+ Map<Vector3, uint32_t> unique_vertices;
+
+ vertices.resize(visual_vertex_count);
+ map_visual_to_physics.resize(visual_vertex_count);
+
+ for (int visual_vertex_index = 0; visual_vertex_index < visual_vertex_count; ++visual_vertex_index) {
+ const Vector3 &vertex = p_vertices[visual_vertex_index];
+
+ Map<Vector3, uint32_t>::Element *e = unique_vertices.find(vertex);
+ uint32_t vertex_id;
+ if (e) {
+ // Already existing.
+ vertex_id = e->value();
+ } else {
+ // Create new one.
+ vertex_id = vertex_count++;
+ unique_vertices[vertex] = vertex_id;
+ vertices[vertex_id] = vertex;
+ }
+
+ map_visual_to_physics[visual_vertex_index] = vertex_id;
+ }
+
+ vertices.resize(vertex_count);
+ }
+
+ // Process triangles.
+ {
+ for (uint32_t triangle_index = 0; triangle_index < triangle_count; ++triangle_index) {
+ for (int i = 0; i < 3; ++i) {
+ int visual_index = 3 * triangle_index + i;
+ int physics_index = map_visual_to_physics[p_indices[visual_index]];
+ triangles[visual_index] = physics_index;
+ node_count = MAX((int)node_count, physics_index);
+ }
+ }
+ }
+ }
+
+ ++node_count;
+
+ // Create nodes from vertices.
+ nodes.resize(node_count);
+ real_t inv_node_mass = node_count * inv_total_mass;
+ Vector3 leaf_size = Vector3(collision_margin, collision_margin, collision_margin) * 2.0;
+ for (uint32_t i = 0; i < node_count; ++i) {
+ Node &node = nodes[i];
+ node.s = vertices[i];
+ node.x = node.s;
+ node.q = node.s;
+ node.im = inv_node_mass;
+
+ AABB node_aabb(node.x, leaf_size);
+ node.leaf = node_tree.insert(node_aabb, &node);
+
+ node.index = i;
+ }
+
+ // Create links and faces from triangles.
+ LocalVector<bool> chks;
+ chks.resize(node_count * node_count);
+ memset(chks.ptr(), 0, chks.size() * sizeof(bool));
+
+ for (uint32_t i = 0; i < triangle_count * 3; i += 3) {
+ const int idx[] = { triangles[i], triangles[i + 1], triangles[i + 2] };
+
+ for (int j = 2, k = 0; k < 3; j = k++) {
+ int chk = idx[k] * node_count + idx[j];
+ if (!chks[chk]) {
+ chks[chk] = true;
+ int inv_chk = idx[j] * node_count + idx[k];
+ chks[inv_chk] = true;
+
+ append_link(idx[j], idx[k]);
+ }
+ }
+
+ append_face(idx[0], idx[1], idx[2]);
+ }
+
+ // Set pinned nodes.
+ uint32_t pinned_count = pinned_vertices.size();
+ for (uint32_t i = 0; i < pinned_count; ++i) {
+ int pinned_vertex = pinned_vertices[i];
+
+ ERR_CONTINUE(pinned_vertex >= visual_vertex_count);
+ uint32_t node_index = map_visual_to_physics[pinned_vertex];
+
+ ERR_CONTINUE(node_index >= node_count);
+ Node &node = nodes[node_index];
+ node.im = 0.0;
+ }
+
+ generate_bending_constraints(2);
+ reoptimize_link_order();
+
+ update_constants();
+ update_normals();
+ update_bounds();
+
+ return true;
+}
+
+void SoftBody3DSW::generate_bending_constraints(int p_distance) {
+ uint32_t i, j;
+
+ if (p_distance > 1) {
+ // Build graph.
+ const uint32_t n = nodes.size();
+ const unsigned inf = (~(unsigned)0) >> 1;
+ const uint32_t adj_size = n * n;
+ unsigned *adj = memnew_arr(unsigned, adj_size);
+
+#define IDX(_x_, _y_) ((_y_)*n + (_x_))
+ for (j = 0; j < n; ++j) {
+ for (i = 0; i < n; ++i) {
+ int idx_ij = j * n + i;
+ int idx_ji = i * n + j;
+ if (i != j) {
+ adj[idx_ij] = adj[idx_ji] = inf;
+ } else {
+ adj[idx_ij] = adj[idx_ji] = 0;
+ }
+ }
+ }
+ for (i = 0; i < links.size(); ++i) {
+ const int ia = (int)(links[i].n[0] - &nodes[0]);
+ const int ib = (int)(links[i].n[1] - &nodes[0]);
+ int idx = ib * n + ia;
+ int idx_inv = ia * n + ib;
+ adj[idx] = 1;
+ adj[idx_inv] = 1;
+ }
+
+ // Special optimized case for distance == 2.
+ if (p_distance == 2) {
+ LocalVector<LocalVector<int>> node_links;
+
+ // Build node links.
+ node_links.resize(nodes.size());
+
+ for (i = 0; i < links.size(); ++i) {
+ const int ia = (int)(links[i].n[0] - &nodes[0]);
+ const int ib = (int)(links[i].n[1] - &nodes[0]);
+ if (node_links[ia].find(ib) == -1) {
+ node_links[ia].push_back(ib);
+ }
+
+ if (node_links[ib].find(ia) == -1) {
+ node_links[ib].push_back(ia);
+ }
+ }
+ for (uint32_t ii = 0; ii < node_links.size(); ii++) {
+ for (uint32_t jj = 0; jj < node_links[ii].size(); jj++) {
+ int k = node_links[ii][jj];
+ for (uint32_t kk = 0; kk < node_links[k].size(); kk++) {
+ int l = node_links[k][kk];
+ if ((int)ii != l) {
+ int idx_ik = k * n + ii;
+ int idx_kj = l * n + k;
+ const unsigned sum = adj[idx_ik] + adj[idx_kj];
+ ERR_FAIL_COND(sum != 2);
+ int idx_ij = l * n + ii;
+ if (adj[idx_ij] > sum) {
+ int idx_ji = l * n + ii;
+ adj[idx_ij] = adj[idx_ji] = sum;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // Generic Floyd's algorithm.
+ for (uint32_t k = 0; k < n; ++k) {
+ for (j = 0; j < n; ++j) {
+ for (i = j + 1; i < n; ++i) {
+ int idx_ik = k * n + i;
+ int idx_kj = j * n + k;
+ const unsigned sum = adj[idx_ik] + adj[idx_kj];
+ int idx_ij = j * n + i;
+ if (adj[idx_ij] > sum) {
+ int idx_ji = j * n + i;
+ adj[idx_ij] = adj[idx_ji] = sum;
+ }
+ }
+ }
+ }
+ }
+
+ // Build links.
+ for (j = 0; j < n; ++j) {
+ for (i = j + 1; i < n; ++i) {
+ int idx_ij = j * n + i;
+ if (adj[idx_ij] == (unsigned)p_distance) {
+ append_link(i, j);
+ }
+ }
+ }
+ memdelete_arr(adj);
+ }
+}
+
+//===================================================================
+//
+//
+// This function takes in a list of interdependent Links and tries
+// to maximize the distance between calculation
+// of dependent links. This increases the amount of parallelism that can
+// be exploited by out-of-order instruction processors with large but
+// (inevitably) finite instruction windows.
+//
+//===================================================================
+
+// A small structure to track lists of dependent link calculations.
+class LinkDeps {
+public:
+ int value; // A link calculation that is dependent on this one
+ // Positive values = "input A" while negative values = "input B"
+ LinkDeps *next; // Next dependence in the list
+};
+typedef LinkDeps *LinkDepsPtr;
+
+void SoftBody3DSW::reoptimize_link_order() {
+ const int reop_not_dependent = -1;
+ const int reop_node_complete = -2;
+
+ uint32_t i, link_count = links.size(), node_count = nodes.size();
+ Link *lr;
+ int ar, br;
+ Node *node0 = &(nodes[0]);
+ Node *node1 = &(nodes[1]);
+ LinkDepsPtr link_dep;
+ int ready_list_head, ready_list_tail, link_num, link_dep_frees, dep_link;
+
+ // Allocate temporary buffers.
+ int *node_written_at = memnew_arr(int, node_count + 1); // What link calculation produced this node's current values?
+ int *link_dep_A = memnew_arr(int, link_count); // Link calculation input is dependent upon prior calculation #N
+ int *link_dep_B = memnew_arr(int, link_count);
+ int *ready_list = memnew_arr(int, link_count); // List of ready-to-process link calculations (# of links, maximum)
+ LinkDeps *link_dep_free_list = memnew_arr(LinkDeps, 2 * link_count); // Dependent-on-me list elements (2x# of links, maximum)
+ LinkDepsPtr *link_dep_list_starts = memnew_arr(LinkDepsPtr, link_count); // Start nodes of dependent-on-me lists, one for each link
+
+ // Copy the original, unsorted links to a side buffer.
+ Link *link_buffer = memnew_arr(Link, link_count);
+ memcpy(link_buffer, &(links[0]), sizeof(Link) * link_count);
+
+ // Clear out the node setup and ready list.
+ for (i = 0; i < node_count + 1; i++) {
+ node_written_at[i] = reop_not_dependent;
+ }
+ for (i = 0; i < link_count; i++) {
+ link_dep_list_starts[i] = nullptr;
+ }
+ ready_list_head = ready_list_tail = link_dep_frees = 0;
+
+ // Initial link analysis to set up data structures.
+ for (i = 0; i < link_count; i++) {
+ // Note which prior link calculations we are dependent upon & build up dependence lists.
+ lr = &(links[i]);
+ ar = (lr->n[0] - node0) / (node1 - node0);
+ br = (lr->n[1] - node0) / (node1 - node0);
+ if (node_written_at[ar] > reop_not_dependent) {
+ link_dep_A[i] = node_written_at[ar];
+ link_dep = &link_dep_free_list[link_dep_frees++];
+ link_dep->value = i;
+ link_dep->next = link_dep_list_starts[node_written_at[ar]];
+ link_dep_list_starts[node_written_at[ar]] = link_dep;
+ } else {
+ link_dep_A[i] = reop_not_dependent;
+ }
+ if (node_written_at[br] > reop_not_dependent) {
+ link_dep_B[i] = node_written_at[br];
+ link_dep = &link_dep_free_list[link_dep_frees++];
+ link_dep->value = -(int)(i + 1);
+ link_dep->next = link_dep_list_starts[node_written_at[br]];
+ link_dep_list_starts[node_written_at[br]] = link_dep;
+ } else {
+ link_dep_B[i] = reop_not_dependent;
+ }
+
+ // Add this link to the initial ready list, if it is not dependent on any other links.
+ if ((link_dep_A[i] == reop_not_dependent) && (link_dep_B[i] == reop_not_dependent)) {
+ ready_list[ready_list_tail++] = i;
+ link_dep_A[i] = link_dep_B[i] = reop_node_complete; // Probably not needed now.
+ }
+
+ // Update the nodes to mark which ones are calculated by this link.
+ node_written_at[ar] = node_written_at[br] = i;
+ }
+
+ // Process the ready list and create the sorted list of links:
+ // -- By treating the ready list as a queue, we maximize the distance between any
+ // inter-dependent node calculations.
+ // -- All other (non-related) nodes in the ready list will automatically be inserted
+ // in between each set of inter-dependent link calculations by this loop.
+ i = 0;
+ while (ready_list_head != ready_list_tail) {
+ // Use ready list to select the next link to process.
+ link_num = ready_list[ready_list_head++];
+ // Copy the next-to-calculate link back into the original link array.
+ links[i++] = link_buffer[link_num];
+
+ // Free up any link inputs that are dependent on this one.
+ link_dep = link_dep_list_starts[link_num];
+ while (link_dep) {
+ dep_link = link_dep->value;
+ if (dep_link >= 0) {
+ link_dep_A[dep_link] = reop_not_dependent;
+ } else {
+ dep_link = -dep_link - 1;
+ link_dep_B[dep_link] = reop_not_dependent;
+ }
+ // Add this dependent link calculation to the ready list if *both* inputs are clear.
+ if ((link_dep_A[dep_link] == reop_not_dependent) && (link_dep_B[dep_link] == reop_not_dependent)) {
+ ready_list[ready_list_tail++] = dep_link;
+ link_dep_A[dep_link] = link_dep_B[dep_link] = reop_node_complete; // Probably not needed now.
+ }
+ link_dep = link_dep->next;
+ }
+ }
+
+ // Delete the temporary buffers.
+ memdelete_arr(node_written_at);
+ memdelete_arr(link_dep_A);
+ memdelete_arr(link_dep_B);
+ memdelete_arr(ready_list);
+ memdelete_arr(link_dep_free_list);
+ memdelete_arr(link_dep_list_starts);
+ memdelete_arr(link_buffer);
+}
+
+void SoftBody3DSW::append_link(uint32_t p_node1, uint32_t p_node2) {
+ if (p_node1 == p_node2) {
+ return;
+ }
+
+ Node *node1 = &nodes[p_node1];
+ Node *node2 = &nodes[p_node2];
+
+ Link link;
+ link.n[0] = node1;
+ link.n[1] = node2;
+ link.rl = (node1->x - node2->x).length();
+
+ links.push_back(link);
+}
+
+void SoftBody3DSW::append_face(uint32_t p_node1, uint32_t p_node2, uint32_t p_node3) {
+ if (p_node1 == p_node2) {
+ return;
+ }
+ if (p_node1 == p_node3) {
+ return;
+ }
+ if (p_node2 == p_node3) {
+ return;
+ }
+
+ Node *node1 = &nodes[p_node1];
+ Node *node2 = &nodes[p_node2];
+ Node *node3 = &nodes[p_node3];
+
+ Face face;
+ face.n[0] = node1;
+ face.n[1] = node2;
+ face.n[2] = node3;
+
+ face.index = faces.size();
+
+ faces.push_back(face);
+}
+
+void SoftBody3DSW::set_iteration_count(int p_val) {
+ iteration_count = p_val;
+}
+
+void SoftBody3DSW::set_total_mass(real_t p_val) {
+ ERR_FAIL_COND(p_val < 0.0);
+
+ inv_total_mass = 1.0 / p_val;
+ real_t mass_factor = total_mass * inv_total_mass;
+ total_mass = p_val;
+
+ uint32_t node_count = nodes.size();
+ for (uint32_t node_index = 0; node_index < node_count; ++node_index) {
+ Node &node = nodes[node_index];
+ node.im *= mass_factor;
+ }
+
+ update_constants();
+}
+
+void SoftBody3DSW::set_collision_margin(real_t p_val) {
+ collision_margin = p_val;
+}
+
+void SoftBody3DSW::set_linear_stiffness(real_t p_val) {
+ linear_stiffness = p_val;
+}
+
+void SoftBody3DSW::set_pressure_coefficient(real_t p_val) {
+ pressure_coefficient = p_val;
+}
+
+void SoftBody3DSW::set_damping_coefficient(real_t p_val) {
+ damping_coefficient = p_val;
+}
+
+void SoftBody3DSW::set_drag_coefficient(real_t p_val) {
+ drag_coefficient = p_val;
+}
+
+void SoftBody3DSW::add_velocity(const Vector3 &p_velocity) {
+ for (uint32_t i = 0, ni = nodes.size(); i < ni; ++i) {
+ Node &node = nodes[i];
+ if (node.im > 0) {
+ node.v += p_velocity;
+ }
+ }
+}
+
+void SoftBody3DSW::apply_forces() {
+ if (pressure_coefficient < CMP_EPSILON) {
+ return;
+ }
+
+ if (nodes.is_empty()) {
+ return;
+ }
+
+ uint32_t i, ni;
+
+ // Calculate volume.
+ real_t volume = 0.0;
+ const Vector3 &org = nodes[0].x;
+ for (i = 0, ni = faces.size(); i < ni; ++i) {
+ const Face &face = faces[i];
+ volume += vec3_dot(face.n[0]->x - org, vec3_cross(face.n[1]->x - org, face.n[2]->x - org));
+ }
+ volume /= 6.0;
+
+ // Apply per node forces.
+ real_t ivolumetp = 1.0 / Math::abs(volume) * pressure_coefficient;
+ for (i = 0, ni = nodes.size(); i < ni; ++i) {
+ Node &node = nodes[i];
+ if (node.im > 0) {
+ node.f += node.n * (node.area * ivolumetp);
+ }
+ }
+}
+
+void SoftBody3DSW::predict_motion(real_t p_delta) {
+ const real_t inv_delta = 1.0 / p_delta;
+
+ ERR_FAIL_COND(!get_space());
+
+ Area3DSW *def_area = get_space()->get_default_area();
+ ERR_FAIL_COND(!def_area);
+
+ // Apply forces.
+ Vector3 gravity = def_area->get_gravity_vector() * def_area->get_gravity();
+ add_velocity(gravity * p_delta);
+ apply_forces();
+
+ // Avoid soft body from 'exploding' so use some upper threshold of maximum motion
+ // that a node can travel per frame.
+ const real_t max_displacement = 1000.0;
+ real_t clamp_delta_v = max_displacement * inv_delta;
+
+ // Integrate.
+ uint32_t i, ni;
+ for (i = 0, ni = nodes.size(); i < ni; ++i) {
+ Node &node = nodes[i];
+ node.q = node.x;
+ Vector3 delta_v = node.f * node.im * p_delta;
+ for (int c = 0; c < 3; c++) {
+ delta_v[c] = CLAMP(delta_v[c], -clamp_delta_v, clamp_delta_v);
+ }
+ node.v += delta_v;
+ node.x += node.v * p_delta;
+ node.f = Vector3();
+ }
+
+ // Bounds and tree update.
+ update_bounds();
+
+ // Node tree update.
+ for (i = 0, ni = nodes.size(); i < ni; ++i) {
+ const Node &node = nodes[i];
+
+ AABB node_aabb(node.x, Vector3());
+ node_aabb.expand_to(node.x + node.v * p_delta);
+ node_aabb.grow_by(collision_margin);
+
+ node_tree.update(node.leaf, node_aabb);
+ }
+
+ // Face tree update.
+ if (!face_tree.is_empty()) {
+ update_face_tree(p_delta);
+ }
+
+ // Optimize node tree.
+ node_tree.optimize_incremental(1);
+ face_tree.optimize_incremental(1);
+}
+
+void SoftBody3DSW::solve_constraints(real_t p_delta) {
+ const real_t inv_delta = 1.0 / p_delta;
+
+ uint32_t i, ni;
+
+ for (i = 0, ni = links.size(); i < ni; ++i) {
+ Link &link = links[i];
+ link.c3 = link.n[1]->q - link.n[0]->q;
+ link.c2 = 1 / (link.c3.length_squared() * link.c0);
+ }
+
+ // Solve velocities.
+ for (i = 0, ni = nodes.size(); i < ni; ++i) {
+ Node &node = nodes[i];
+ node.x = node.q + node.v * p_delta;
+ }
+
+ // Solve positions.
+ for (int isolve = 0; isolve < iteration_count; ++isolve) {
+ const real_t ti = isolve / (real_t)iteration_count;
+ solve_links(1.0, ti);
+ }
+ const real_t vc = (1.0 - damping_coefficient) * inv_delta;
+ for (i = 0, ni = nodes.size(); i < ni; ++i) {
+ Node &node = nodes[i];
+
+ node.x += node.bv * p_delta;
+ node.bv = Vector3();
+
+ node.v = (node.x - node.q) * vc;
+
+ node.q = node.x;
+ }
+
+ update_normals();
+}
+
+void SoftBody3DSW::solve_links(real_t kst, real_t ti) {
+ for (uint32_t i = 0, ni = links.size(); i < ni; ++i) {
+ Link &link = links[i];
+ if (link.c0 > 0) {
+ Node &node_a = *link.n[0];
+ Node &node_b = *link.n[1];
+ const Vector3 del = node_b.x - node_a.x;
+ const real_t len = del.length_squared();
+ if (link.c1 + len > CMP_EPSILON) {
+ const real_t k = ((link.c1 - len) / (link.c0 * (link.c1 + len))) * kst;
+ node_a.x -= del * (k * node_a.im);
+ node_b.x += del * (k * node_b.im);
+ }
+ }
+ }
+}
+
+struct AABBQueryResult {
+ const SoftBody3DSW *soft_body = nullptr;
+ void *userdata = nullptr;
+ SoftBody3DSW::QueryResultCallback result_callback = nullptr;
+
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ return result_callback(soft_body->get_node_index(p_data), userdata);
+ };
+};
+
+void SoftBody3DSW::query_aabb(const AABB &p_aabb, SoftBody3DSW::QueryResultCallback p_result_callback, void *p_userdata) {
+ AABBQueryResult query_result;
+ query_result.soft_body = this;
+ query_result.result_callback = p_result_callback;
+ query_result.userdata = p_userdata;
+
+ node_tree.aabb_query(p_aabb, query_result);
+}
+
+struct RayQueryResult {
+ const SoftBody3DSW *soft_body = nullptr;
+ void *userdata = nullptr;
+ SoftBody3DSW::QueryResultCallback result_callback = nullptr;
+
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ return result_callback(soft_body->get_face_index(p_data), userdata);
+ };
+};
+
+void SoftBody3DSW::query_ray(const Vector3 &p_from, const Vector3 &p_to, SoftBody3DSW::QueryResultCallback p_result_callback, void *p_userdata) {
+ if (face_tree.is_empty()) {
+ initialize_face_tree();
+ }
+
+ RayQueryResult query_result;
+ query_result.soft_body = this;
+ query_result.result_callback = p_result_callback;
+ query_result.userdata = p_userdata;
+
+ face_tree.ray_query(p_from, p_to, query_result);
+}
+
+void SoftBody3DSW::initialize_face_tree() {
+ face_tree.clear();
+ for (uint32_t i = 0; i < faces.size(); ++i) {
+ Face &face = faces[i];
+
+ AABB face_aabb;
+
+ face_aabb.position = face.n[0]->x;
+ face_aabb.expand_to(face.n[1]->x);
+ face_aabb.expand_to(face.n[2]->x);
+
+ face_aabb.grow_by(collision_margin);
+
+ face.leaf = face_tree.insert(face_aabb, &face);
+ }
+}
+
+void SoftBody3DSW::update_face_tree(real_t p_delta) {
+ for (uint32_t i = 0; i < faces.size(); ++i) {
+ const Face &face = faces[i];
+
+ AABB face_aabb;
+
+ const Node *node0 = face.n[0];
+ face_aabb.position = node0->x;
+ face_aabb.expand_to(node0->x + node0->v * p_delta);
+
+ const Node *node1 = face.n[1];
+ face_aabb.expand_to(node1->x);
+ face_aabb.expand_to(node1->x + node1->v * p_delta);
+
+ const Node *node2 = face.n[2];
+ face_aabb.expand_to(node2->x);
+ face_aabb.expand_to(node2->x + node2->v * p_delta);
+
+ face_aabb.grow_by(collision_margin);
+
+ face_tree.update(face.leaf, face_aabb);
+ }
+}
+
+void SoftBody3DSW::initialize_shape(bool p_force_move) {
+ if (get_shape_count() == 0) {
+ SoftBodyShape3DSW *soft_body_shape = memnew(SoftBodyShape3DSW(this));
+ add_shape(soft_body_shape);
+ } else if (p_force_move) {
+ SoftBodyShape3DSW *soft_body_shape = static_cast<SoftBodyShape3DSW *>(get_shape(0));
+ soft_body_shape->update_bounds();
+ }
+}
+
+void SoftBody3DSW::deinitialize_shape() {
+ if (get_shape_count() > 0) {
+ Shape3DSW *shape = get_shape(0);
+ remove_shape(shape);
+ memdelete(shape);
+ }
+}
+
+void SoftBody3DSW::destroy() {
+ map_visual_to_physics.clear();
+
+ node_tree.clear();
+ face_tree.clear();
+
+ nodes.clear();
+ links.clear();
+ faces.clear();
+
+ bounds = AABB();
+ deinitialize_shape();
+}
+
+void SoftBodyShape3DSW::update_bounds() {
+ ERR_FAIL_COND(!soft_body);
+
+ AABB collision_aabb = soft_body->get_bounds();
+ collision_aabb.grow_by(soft_body->get_collision_margin());
+ configure(collision_aabb);
+}
+
+SoftBodyShape3DSW::SoftBodyShape3DSW(SoftBody3DSW *p_soft_body) {
+ soft_body = p_soft_body;
+ update_bounds();
+}
+
+struct _SoftBodyIntersectSegmentInfo {
+ const SoftBody3DSW *soft_body = nullptr;
+ Vector3 from;
+ Vector3 dir;
+ Vector3 hit_position;
+ uint32_t hit_face_index = -1;
+ real_t hit_dist_sq = Math_INF;
+
+ static bool process_hit(uint32_t p_face_index, void *p_userdata) {
+ _SoftBodyIntersectSegmentInfo &query_info = *(_SoftBodyIntersectSegmentInfo *)(p_userdata);
+
+ Vector3 points[3];
+ query_info.soft_body->get_face_points(p_face_index, points[0], points[1], points[2]);
+
+ Vector3 result;
+ if (Geometry3D::ray_intersects_triangle(query_info.from, query_info.dir, points[0], points[1], points[2], &result)) {
+ real_t dist_sq = query_info.from.distance_squared_to(result);
+ if (dist_sq < query_info.hit_dist_sq) {
+ query_info.hit_dist_sq = dist_sq;
+ query_info.hit_position = result;
+ query_info.hit_face_index = p_face_index;
+ }
+ }
+
+ // Continue with the query.
+ return false;
+ }
+};
+
+bool SoftBodyShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+ _SoftBodyIntersectSegmentInfo query_info;
+ query_info.soft_body = soft_body;
+ query_info.from = p_begin;
+ query_info.dir = (p_end - p_begin).normalized();
+
+ soft_body->query_ray(p_begin, p_end, _SoftBodyIntersectSegmentInfo::process_hit, &query_info);
+
+ if (query_info.hit_dist_sq != Math_INF) {
+ r_result = query_info.hit_position;
+ r_normal = soft_body->get_face_normal(query_info.hit_face_index);
+ return true;
+ }
+
+ return false;
+}
+
+bool SoftBodyShape3DSW::intersect_point(const Vector3 &p_point) const {
+ return false;
+}
+
+Vector3 SoftBodyShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+ ERR_FAIL_V_MSG(Vector3(), "Get closest point is not supported for soft bodies.");
+}
diff --git a/servers/physics_3d/soft_body_3d_sw.h b/servers/physics_3d/soft_body_3d_sw.h
new file mode 100644
index 0000000000..6c0451ff45
--- /dev/null
+++ b/servers/physics_3d/soft_body_3d_sw.h
@@ -0,0 +1,247 @@
+/*************************************************************************/
+/* soft_body_3d_sw.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 SOFT_BODY_3D_SW_H
+#define SOFT_BODY_3D_SW_H
+
+#include "collision_object_3d_sw.h"
+
+#include "core/math/aabb.h"
+#include "core/math/dynamic_bvh.h"
+#include "core/math/vector3.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/set.h"
+#include "core/templates/vset.h"
+#include "scene/resources/mesh.h"
+
+class Constraint3DSW;
+
+class SoftBody3DSW : public CollisionObject3DSW {
+ Ref<Mesh> soft_mesh;
+
+ struct Node {
+ Vector3 s; // Source position
+ Vector3 x; // Position
+ Vector3 q; // Previous step position/Test position
+ Vector3 f; // Force accumulator
+ Vector3 v; // Velocity
+ Vector3 bv; // Biased Velocity
+ Vector3 n; // Normal
+ real_t area = 0.0; // Area
+ real_t im = 0.0; // 1/mass
+ DynamicBVH::ID leaf; // Leaf data
+ uint32_t index = 0;
+ };
+
+ struct Link {
+ Vector3 c3; // gradient
+ Node *n[2] = { nullptr, nullptr }; // Node pointers
+ real_t rl = 0.0; // Rest length
+ real_t c0 = 0.0; // (ima+imb)*kLST
+ real_t c1 = 0.0; // rl^2
+ real_t c2 = 0.0; // |gradient|^2/c0
+ };
+
+ struct Face {
+ Node *n[3] = { nullptr, nullptr, nullptr }; // Node pointers
+ Vector3 normal; // Normal
+ real_t ra = 0.0; // Rest area
+ DynamicBVH::ID leaf; // Leaf data
+ uint32_t index = 0;
+ };
+
+ LocalVector<Node> nodes;
+ LocalVector<Link> links;
+ LocalVector<Face> faces;
+
+ DynamicBVH node_tree;
+ DynamicBVH face_tree;
+
+ LocalVector<uint32_t> map_visual_to_physics;
+
+ AABB bounds;
+
+ real_t collision_margin = 0.05;
+
+ real_t total_mass = 1.0;
+ real_t inv_total_mass = 1.0;
+
+ int iteration_count = 5;
+ real_t linear_stiffness = 0.5; // [0,1]
+ real_t pressure_coefficient = 0.0; // [-inf,+inf]
+ real_t damping_coefficient = 0.01; // [0,1]
+ real_t drag_coefficient = 0.0; // [0,1]
+ LocalVector<int> pinned_vertices;
+
+ SelfList<SoftBody3DSW> active_list;
+
+ Set<Constraint3DSW *> constraints;
+
+ VSet<RID> exceptions;
+
+public:
+ SoftBody3DSW();
+
+ const AABB &get_bounds() const { return bounds; }
+
+ void set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant);
+ Variant get_state(PhysicsServer3D::BodyState p_state) const;
+
+ _FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint) { constraints.insert(p_constraint); }
+ _FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraints.erase(p_constraint); }
+ _FORCE_INLINE_ const Set<Constraint3DSW *> &get_constraints() const { return constraints; }
+ _FORCE_INLINE_ void clear_constraints() { constraints.clear(); }
+
+ _FORCE_INLINE_ void add_exception(const RID &p_exception) { exceptions.insert(p_exception); }
+ _FORCE_INLINE_ void remove_exception(const RID &p_exception) { exceptions.erase(p_exception); }
+ _FORCE_INLINE_ bool has_exception(const RID &p_exception) const { return exceptions.has(p_exception); }
+ _FORCE_INLINE_ const VSet<RID> &get_exceptions() const { return exceptions; }
+
+ virtual void set_space(Space3DSW *p_space);
+
+ void set_mesh(const Ref<Mesh> &p_mesh);
+
+ void update_rendering_server(RenderingServerHandler *p_rendering_server_handler);
+
+ Vector3 get_vertex_position(int p_index) const;
+ void set_vertex_position(int p_index, const Vector3 &p_position);
+
+ void pin_vertex(int p_index);
+ void unpin_vertex(int p_index);
+ void unpin_all_vertices();
+ bool is_vertex_pinned(int p_index) const;
+
+ uint32_t get_node_count() const;
+ real_t get_node_inv_mass(uint32_t p_node_index) const;
+ Vector3 get_node_position(uint32_t p_node_index) const;
+ Vector3 get_node_velocity(uint32_t p_node_index) const;
+ Vector3 get_node_biased_velocity(uint32_t p_node_index) const;
+ void apply_node_impulse(uint32_t p_node_index, const Vector3 &p_impulse);
+ void apply_node_bias_impulse(uint32_t p_node_index, const Vector3 &p_impulse);
+
+ uint32_t get_face_count() const;
+ void get_face_points(uint32_t p_face_index, Vector3 &r_point_1, Vector3 &r_point_2, Vector3 &r_point_3) const;
+ Vector3 get_face_normal(uint32_t p_face_index) const;
+
+ void set_iteration_count(int p_val);
+ _FORCE_INLINE_ real_t get_iteration_count() const { return iteration_count; }
+
+ void set_total_mass(real_t p_val);
+ _FORCE_INLINE_ real_t get_total_mass() const { return total_mass; }
+ _FORCE_INLINE_ real_t get_total_inv_mass() const { return inv_total_mass; }
+
+ void set_collision_margin(real_t p_val);
+ _FORCE_INLINE_ real_t get_collision_margin() const { return collision_margin; }
+
+ void set_linear_stiffness(real_t p_val);
+ _FORCE_INLINE_ real_t get_linear_stiffness() const { return linear_stiffness; }
+
+ void set_pressure_coefficient(real_t p_val);
+ _FORCE_INLINE_ real_t get_pressure_coefficient() const { return pressure_coefficient; }
+
+ void set_damping_coefficient(real_t p_val);
+ _FORCE_INLINE_ real_t get_damping_coefficient() const { return damping_coefficient; }
+
+ void set_drag_coefficient(real_t p_val);
+ _FORCE_INLINE_ real_t get_drag_coefficient() const { return drag_coefficient; }
+
+ void predict_motion(real_t p_delta);
+ void solve_constraints(real_t p_delta);
+
+ _FORCE_INLINE_ uint32_t get_node_index(void *p_node) const { return ((Node *)p_node)->index; }
+ _FORCE_INLINE_ uint32_t get_face_index(void *p_face) const { return ((Face *)p_face)->index; }
+
+ // Return true to stop the query.
+ // p_index is the node index for AABB query, face index for Ray query.
+ typedef bool (*QueryResultCallback)(uint32_t p_index, void *p_userdata);
+
+ void query_aabb(const AABB &p_aabb, QueryResultCallback p_result_callback, void *p_userdata);
+ void query_ray(const Vector3 &p_from, const Vector3 &p_to, QueryResultCallback p_result_callback, void *p_userdata);
+
+protected:
+ virtual void _shapes_changed();
+
+private:
+ void update_normals();
+ void update_bounds();
+ void update_constants();
+ void update_area();
+ void reset_link_rest_lengths();
+ void update_link_constants();
+
+ void apply_nodes_transform(const Transform &p_transform);
+
+ void add_velocity(const Vector3 &p_velocity);
+
+ void apply_forces();
+
+ bool create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices);
+ void generate_bending_constraints(int p_distance);
+ void reoptimize_link_order();
+ void append_link(uint32_t p_node1, uint32_t p_node2);
+ void append_face(uint32_t p_node1, uint32_t p_node2, uint32_t p_node3);
+
+ void solve_links(real_t kst, real_t ti);
+
+ void initialize_face_tree();
+ void update_face_tree(real_t p_delta);
+
+ void initialize_shape(bool p_force_move = true);
+ void deinitialize_shape();
+
+ void destroy();
+};
+
+class SoftBodyShape3DSW : public Shape3DSW {
+ SoftBody3DSW *soft_body = nullptr;
+
+public:
+ SoftBody3DSW *get_soft_body() const { return soft_body; }
+
+ virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_SOFT_BODY; }
+ virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { r_min = r_max = 0.0; }
+ virtual Vector3 get_support(const Vector3 &p_normal) const { return Vector3(); }
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; }
+
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
+ virtual bool intersect_point(const Vector3 &p_point) const;
+ virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const { return Vector3(); }
+
+ virtual void set_data(const Variant &p_data) {}
+ virtual Variant get_data() const { return Variant(); }
+
+ void update_bounds();
+
+ SoftBodyShape3DSW(SoftBody3DSW *p_soft_body);
+ ~SoftBodyShape3DSW() {}
+};
+
+#endif // SOFT_BODY_3D_SW_H
diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp
index 43cc032120..2df824b320 100644
--- a/servers/physics_3d/space_3d_sw.cpp
+++ b/servers/physics_3d/space_3d_sw.cpp
@@ -47,6 +47,10 @@ _FORCE_INLINE_ static bool _can_collide_with(CollisionObject3DSW *p_object, uint
return false;
}
+ if (p_object->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY && !p_collide_with_bodies) {
+ return false;
+ }
+
return true;
}
@@ -181,7 +185,7 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
return 0;
}
- Shape3DSW *shape = static_cast<PhysicsServer3DSW *>(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape);
+ Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
ERR_FAIL_COND_V(!shape, 0);
AABB aabb = p_xform.xform(shape->get_aabb());
@@ -210,6 +214,10 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
+ if (col_obj->is_shape_set_as_disabled(shape_idx)) {
+ continue;
+ }
+
if (!CollisionSolver3DSW::solve_static(shape, p_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), nullptr, nullptr, nullptr, p_margin, 0)) {
continue;
}
@@ -232,7 +240,7 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
}
bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
- Shape3DSW *shape = static_cast<PhysicsServer3DSW *>(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape);
+ Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
ERR_FAIL_COND_V(!shape, false);
AABB aabb = p_xform.xform(shape->get_aabb());
@@ -265,6 +273,10 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
+ if (col_obj->is_shape_set_as_disabled(shape_idx)) {
+ continue;
+ }
+
Vector3 point_A, point_B;
Vector3 sep_axis = p_motion.normalized();
@@ -324,7 +336,8 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
best_first = false;
if (col_obj->get_type() == CollisionObject3DSW::TYPE_BODY) {
const Body3DSW *body = static_cast<const Body3DSW *>(col_obj);
- r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - closest_B);
+ Vector3 rel_vec = closest_B - (body->get_transform().origin + body->get_center_of_mass());
+ r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
}
}
}
@@ -340,7 +353,7 @@ bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform &p_
return false;
}
- Shape3DSW *shape = static_cast<PhysicsServer3DSW *>(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape);
+ Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
ERR_FAIL_COND_V(!shape, 0);
AABB aabb = p_shape_xform.xform(shape->get_aabb());
@@ -365,12 +378,17 @@ bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform &p_
}
const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
- int shape_idx = space->intersection_query_subindex_results[i];
if (p_exclude.has(col_obj->get_self())) {
continue;
}
+ int shape_idx = space->intersection_query_subindex_results[i];
+
+ if (col_obj->is_shape_set_as_disabled(shape_idx)) {
+ continue;
+ }
+
if (CollisionSolver3DSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) {
collided = true;
}
@@ -384,6 +402,8 @@ bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform &p_
struct _RestCallbackData {
const CollisionObject3DSW *object;
const CollisionObject3DSW *best_object;
+ int local_shape;
+ int best_local_shape;
int shape;
int best_shape;
Vector3 best_contact;
@@ -392,7 +412,7 @@ struct _RestCallbackData {
real_t min_allowed_depth;
};
-static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) {
+static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
_RestCallbackData *rd = (_RestCallbackData *)p_userdata;
Vector3 contact_rel = p_point_B - p_point_A;
@@ -409,10 +429,11 @@ static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B,
rd->best_normal = contact_rel / len;
rd->best_object = rd->object;
rd->best_shape = rd->shape;
+ rd->best_local_shape = rd->local_shape;
}
bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
- Shape3DSW *shape = static_cast<PhysicsServer3DSW *>(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape);
+ Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
ERR_FAIL_COND_V(!shape, 0);
AABB aabb = p_shape_xform.xform(shape->get_aabb());
@@ -432,12 +453,17 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform &p_shap
}
const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
- int shape_idx = space->intersection_query_subindex_results[i];
if (p_exclude.has(col_obj->get_self())) {
continue;
}
+ int shape_idx = space->intersection_query_subindex_results[i];
+
+ if (col_obj->is_shape_set_as_disabled(shape_idx)) {
+ continue;
+ }
+
rcd.object = col_obj;
rcd.shape = shape_idx;
bool sc = CollisionSolver3DSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin);
@@ -457,8 +483,8 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform &p_shap
r_info->rid = rcd.best_object->get_self();
if (rcd.best_object->get_type() == CollisionObject3DSW::TYPE_BODY) {
const Body3DSW *body = static_cast<const Body3DSW *>(rcd.best_object);
- r_info->linear_velocity = body->get_linear_velocity() +
- (body->get_angular_velocity()).cross(body->get_transform().origin - rcd.best_contact); // * mPos);
+ Vector3 rel_vec = rcd.best_contact - (body->get_transform().origin + body->get_center_of_mass());
+ r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
} else {
r_info->linear_velocity = Vector3();
@@ -468,9 +494,9 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform &p_shap
}
Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const {
- CollisionObject3DSW *obj = PhysicsServer3DSW::singleton->area_owner.getornull(p_object);
+ CollisionObject3DSW *obj = PhysicsServer3DSW::singletonsw->area_owner.getornull(p_object);
if (!obj) {
- obj = PhysicsServer3DSW::singleton->body_owner.getornull(p_object);
+ obj = PhysicsServer3DSW::singletonsw->body_owner.getornull(p_object);
}
ERR_FAIL_COND_V(!obj, Vector3());
@@ -523,6 +549,8 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) {
keep = false;
} else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_AREA) {
keep = false;
+ } else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY) {
+ keep = false;
} else if ((static_cast<Body3DSW *>(intersection_query_results[i])->test_collision_mask(p_body)) == 0) {
keep = false;
} else if (static_cast<Body3DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
@@ -663,10 +691,8 @@ int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform &p_tra
//result.collider_metadata = col_obj->get_shape_metadata(shape_idx);
if (col_obj->get_type() == CollisionObject3DSW::TYPE_BODY) {
Body3DSW *body = (Body3DSW *)col_obj;
-
- Vector3 rel_vec = b - body->get_transform().get_origin();
- //result.collider_velocity = Vector3(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity();
- result.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - rel_vec); // * mPos);
+ Vector3 rel_vec = b - (body->get_transform().origin + body->get_center_of_mass());
+ result.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
}
}
}
@@ -739,8 +765,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb));
body_aabb = body_aabb.grow(p_margin);
+ real_t motion_length = p_motion.length();
+ Vector3 motion_normal = p_motion / motion_length;
+
Transform body_transform = p_from;
+ bool recovered = false;
+
{
//STEP 1, FREE BODY IF STUCK
@@ -791,7 +822,17 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
for (int i = 0; i < cbk.amount; i++) {
Vector3 a = sr[i * 2 + 0];
Vector3 b = sr[i * 2 + 1];
- recover_motion += (b - a) / cbk.amount;
+
+ // Compute plane on b towards a.
+ Vector3 n = (a - b).normalized();
+ real_t d = n.dot(b);
+
+ // Compute depth on recovered motion.
+ real_t depth = n.dot(a + recover_motion) - d;
+ if (depth > 0.0) {
+ // Only recover if there is penetration.
+ recover_motion -= n * depth * 0.4;
+ }
}
if (recover_motion == Vector3()) {
@@ -799,6 +840,8 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
break;
}
+ recovered = true;
+
body_transform.origin += recover_motion;
body_aabb.position += recover_motion;
@@ -848,14 +891,14 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
//test initial overlap, does it collide if going all the way?
Vector3 point_A, point_B;
- Vector3 sep_axis = p_motion.normalized();
+ Vector3 sep_axis = motion_normal;
Transform col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
if (CollisionSolver3DSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) {
continue;
}
- sep_axis = p_motion.normalized();
+ sep_axis = motion_normal;
if (!CollisionSolver3DSW::solve_distance(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) {
stuck = true;
@@ -865,13 +908,12 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
//just do kinematic solving
real_t low = 0;
real_t hi = 1;
- Vector3 mnormal = p_motion.normalized();
for (int k = 0; k < 8; k++) { //steps should be customizable..
real_t ofs = (low + hi) * 0.5;
- Vector3 sep = mnormal; //important optimization for this to work fast enough
+ Vector3 sep = motion_normal; //important optimization for this to work fast enough
mshape.motion = body_shape_xform_inv.basis.xform(p_motion * ofs);
@@ -912,16 +954,11 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
}
bool collided = false;
- if (safe >= 1) {
- //not collided
- collided = false;
- if (r_result) {
- r_result->motion = p_motion;
- r_result->remainder = Vector3();
- r_result->motion += (body_transform.get_origin() - p_from.get_origin());
+ if (recovered || (safe < 1)) {
+ if (safe >= 1) {
+ best_shape = -1; //no best shape with cast, reset to -1
}
- } else {
//it collided, let's get the rest info in unsafe advance
Transform ugt = body_transform;
ugt.origin += p_motion * unsafe;
@@ -930,25 +967,40 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
rcd.best_len = 0;
rcd.best_object = nullptr;
rcd.best_shape = 0;
- rcd.min_allowed_depth = test_motion_min_contact_depth;
- Transform body_shape_xform = ugt * p_body->get_shape_transform(best_shape);
- Shape3DSW *body_shape = p_body->get_shape(best_shape);
+ // Allowed depth can't be lower than motion length, in order to handle contacts at low speed.
+ rcd.min_allowed_depth = MIN(motion_length, test_motion_min_contact_depth);
- body_aabb.position += p_motion * unsafe;
+ int from_shape = best_shape != -1 ? best_shape : 0;
+ int to_shape = best_shape != -1 ? best_shape + 1 : p_body->get_shape_count();
- int amount = _cull_aabb_for_body(p_body, body_aabb);
+ for (int j = from_shape; j < to_shape; j++) {
+ if (p_body->is_shape_set_as_disabled(j)) {
+ continue;
+ }
- for (int i = 0; i < amount; i++) {
- const CollisionObject3DSW *col_obj = intersection_query_results[i];
- int shape_idx = intersection_query_subindex_results[i];
+ Transform body_shape_xform = ugt * p_body->get_shape_transform(j);
+ Shape3DSW *body_shape = p_body->get_shape(j);
- rcd.object = col_obj;
- rcd.shape = shape_idx;
- bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin);
- if (!sc) {
+ if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer3D::SHAPE_RAY) {
continue;
}
+
+ body_aabb.position += p_motion * unsafe;
+
+ int amount = _cull_aabb_for_body(p_body, body_aabb);
+
+ for (int i = 0; i < amount; i++) {
+ const CollisionObject3DSW *col_obj = intersection_query_results[i];
+ int shape_idx = intersection_query_subindex_results[i];
+
+ rcd.object = col_obj;
+ rcd.shape = shape_idx;
+ bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin);
+ if (!sc) {
+ continue;
+ }
+ }
}
if (rcd.best_len != 0) {
@@ -956,15 +1008,15 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
r_result->collider = rcd.best_object->get_self();
r_result->collider_id = rcd.best_object->get_instance_id();
r_result->collider_shape = rcd.best_shape;
- r_result->collision_local_shape = best_shape;
+ r_result->collision_local_shape = rcd.best_local_shape;
r_result->collision_normal = rcd.best_normal;
r_result->collision_point = rcd.best_contact;
//r_result->collider_metadata = rcd.best_object->get_shape_metadata(rcd.best_shape);
const Body3DSW *body = static_cast<const Body3DSW *>(rcd.best_object);
- //Vector3 rel_vec = r_result->collision_point - body->get_transform().get_origin();
- // r_result->collider_velocity = Vector3(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity();
- r_result->collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - rcd.best_contact); // * mPos);
+
+ Vector3 rel_vec = rcd.best_contact - (body->get_transform().origin + body->get_center_of_mass());
+ r_result->collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
r_result->motion = safe * p_motion;
r_result->remainder = p_motion - safe * p_motion;
@@ -972,17 +1024,15 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
}
collided = true;
- } else {
- if (r_result) {
- r_result->motion = p_motion;
- r_result->remainder = Vector3();
- r_result->motion += (body_transform.get_origin() - p_from.get_origin());
- }
-
- collided = false;
}
}
+ if (!collided && r_result) {
+ r_result->motion = p_motion;
+ r_result->remainder = Vector3();
+ r_result->motion += (body_transform.get_origin() - p_from.get_origin());
+ }
+
return collided;
}
@@ -1009,14 +1059,23 @@ void *Space3DSW::_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, Coll
Area3DSW *area_b = static_cast<Area3DSW *>(B);
Area2Pair3DSW *area2_pair = memnew(Area2Pair3DSW(area_b, p_subindex_B, area, p_subindex_A));
return area2_pair;
+ } else if (type_B == CollisionObject3DSW::TYPE_SOFT_BODY) {
+ // Area/Soft Body, not supported.
} else {
Body3DSW *body = static_cast<Body3DSW *>(B);
AreaPair3DSW *area_pair = memnew(AreaPair3DSW(body, p_subindex_B, area, p_subindex_A));
return area_pair;
}
+ } else if (type_A == CollisionObject3DSW::TYPE_BODY) {
+ if (type_B == CollisionObject3DSW::TYPE_SOFT_BODY) {
+ BodySoftBodyPair3DSW *soft_pair = memnew(BodySoftBodyPair3DSW((Body3DSW *)A, p_subindex_A, (SoftBody3DSW *)B));
+ return soft_pair;
+ } else {
+ BodyPair3DSW *b = memnew(BodyPair3DSW((Body3DSW *)A, p_subindex_A, (Body3DSW *)B, p_subindex_B));
+ return b;
+ }
} else {
- BodyPair3DSW *b = memnew(BodyPair3DSW((Body3DSW *)A, p_subindex_A, (Body3DSW *)B, p_subindex_B));
- return b;
+ // Soft Body/Soft Body, not supported.
}
return nullptr;
@@ -1099,6 +1158,18 @@ const SelfList<Area3DSW>::List &Space3DSW::get_moved_area_list() const {
return area_moved_list;
}
+const SelfList<SoftBody3DSW>::List &Space3DSW::get_active_soft_body_list() const {
+ return active_soft_body_list;
+}
+
+void Space3DSW::soft_body_add_to_active_list(SelfList<SoftBody3DSW> *p_soft_body) {
+ active_soft_body_list.add(p_soft_body);
+}
+
+void Space3DSW::soft_body_remove_from_active_list(SelfList<SoftBody3DSW> *p_soft_body) {
+ active_soft_body_list.remove(p_soft_body);
+}
+
void Space3DSW::call_queries() {
while (state_query_list.first()) {
Body3DSW *b = state_query_list.first()->self();
diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h
index eed3d86a72..3a8f452e54 100644
--- a/servers/physics_3d/space_3d_sw.h
+++ b/servers/physics_3d/space_3d_sw.h
@@ -40,6 +40,7 @@
#include "core/config/project_settings.h"
#include "core/templates/hash_map.h"
#include "core/typedefs.h"
+#include "soft_body_3d_sw.h"
class PhysicsDirectSpaceState3DSW : public PhysicsDirectSpaceState3D {
GDCLASS(PhysicsDirectSpaceState3DSW, PhysicsDirectSpaceState3D);
@@ -82,6 +83,7 @@ private:
SelfList<Body3DSW>::List state_query_list;
SelfList<Area3DSW>::List monitor_query_list;
SelfList<Area3DSW>::List area_moved_list;
+ SelfList<SoftBody3DSW>::List active_soft_body_list;
static void *_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_self);
static void _broadphase_unpair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_self);
@@ -145,6 +147,10 @@ public:
void area_remove_from_moved_list(SelfList<Area3DSW> *p_area);
const SelfList<Area3DSW>::List &get_moved_area_list() const;
+ const SelfList<SoftBody3DSW>::List &get_active_soft_body_list() const;
+ void soft_body_add_to_active_list(SelfList<SoftBody3DSW> *p_soft_body);
+ void soft_body_remove_from_active_list(SelfList<SoftBody3DSW> *p_soft_body);
+
BroadPhase3DSW *get_broadphase();
void add_object(CollisionObject3DSW *p_object);
diff --git a/servers/physics_3d/step_3d_sw.cpp b/servers/physics_3d/step_3d_sw.cpp
index d9370de6a3..9a73e11562 100644
--- a/servers/physics_3d/step_3d_sw.cpp
+++ b/servers/physics_3d/step_3d_sw.cpp
@@ -146,6 +146,8 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
const SelfList<Body3DSW>::List *body_list = &p_space->get_active_body_list();
+ const SelfList<SoftBody3DSW>::List *soft_body_list = &p_space->get_active_soft_body_list();
+
/* INTEGRATE FORCES */
uint64_t profile_begtime = OS::get_singleton()->get_ticks_usec();
@@ -160,6 +162,15 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
active_count++;
}
+ /* UPDATE SOFT BODY MOTION */
+
+ const SelfList<SoftBody3DSW> *sb = soft_body_list->first();
+ while (sb) {
+ sb->self()->predict_motion(p_delta);
+ sb = sb->next();
+ active_count++;
+ }
+
p_space->set_active_objects(active_count);
{ //profile
@@ -214,6 +225,20 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
p_space->area_remove_from_moved_list((SelfList<Area3DSW> *)aml.first()); //faster to remove here
}
+ sb = soft_body_list->first();
+ while (sb) {
+ for (const Set<Constraint3DSW *>::Element *E = sb->self()->get_constraints().front(); E; E = E->next()) {
+ Constraint3DSW *c = E->get();
+ if (c->get_island_step() == _step)
+ continue;
+ c->set_island_step(_step);
+ c->set_island_next(NULL);
+ c->set_island_list_next(constraint_island_list);
+ constraint_island_list = c;
+ }
+ sb = sb->next();
+ }
+
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime);
@@ -272,6 +297,14 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
}
}
+ /* UPDATE SOFT BODY CONSTRAINTS */
+
+ sb = soft_body_list->first();
+ while (sb) {
+ sb->self()->solve_constraints(p_delta);
+ sb = sb->next();
+ }
+
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime);
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index 7c36229e9f..83ebc0c55b 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -655,12 +655,16 @@ void PhysicsServer2D::_bind_methods() {
/* JOINT API */
+ ClassDB::bind_method(D_METHOD("joint_create"), &PhysicsServer2D::joint_create);
+
+ ClassDB::bind_method(D_METHOD("joint_clear", "joint"), &PhysicsServer2D::joint_clear);
+
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("pin_joint_create", "anchor", "body_a", "body_b"), &PhysicsServer2D::pin_joint_create, DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("groove_joint_create", "groove1_a", "groove2_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::groove_joint_create, DEFVAL(RID()), DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("damped_spring_joint_create", "anchor_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::damped_spring_joint_create, DEFVAL(RID()));
+ 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()));
ClassDB::bind_method(D_METHOD("damped_spring_joint_set_param", "joint", "param", "value"), &PhysicsServer2D::damped_spring_joint_set_param);
ClassDB::bind_method(D_METHOD("damped_spring_joint_get_param", "joint", "param"), &PhysicsServer2D::damped_spring_joint_get_param);
@@ -727,9 +731,10 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_STATE_SLEEPING);
BIND_ENUM_CONSTANT(BODY_STATE_CAN_SLEEP);
- BIND_ENUM_CONSTANT(JOINT_PIN);
- BIND_ENUM_CONSTANT(JOINT_GROOVE);
- BIND_ENUM_CONSTANT(JOINT_DAMPED_SPRING);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_PIN);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_GROOVE);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_DAMPED_SPRING);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_MAX);
BIND_ENUM_CONSTANT(JOINT_PARAM_BIAS);
BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_BIAS);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index 710eecfdec..28f22ce06b 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -524,10 +524,15 @@ public:
/* JOINT API */
+ virtual RID joint_create() = 0;
+
+ virtual void joint_clear(RID p_joint) = 0;
+
enum JointType {
- JOINT_PIN,
- JOINT_GROOVE,
- JOINT_DAMPED_SPRING
+ JOINT_TYPE_PIN,
+ JOINT_TYPE_GROOVE,
+ JOINT_TYPE_DAMPED_SPRING,
+ JOINT_TYPE_MAX
};
enum JointParam {
@@ -542,9 +547,9 @@ public:
virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0;
virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0;
- virtual RID pin_joint_create(const Vector2 &p_anchor, RID p_body_a, RID p_body_b = RID()) = 0;
- virtual RID groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) = 0;
- virtual RID damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) = 0;
+ virtual void joint_make_pin(RID p_joint, const Vector2 &p_anchor, RID p_body_a, RID p_body_b = RID()) = 0;
+ virtual void joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) = 0;
+ virtual void joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) = 0;
enum PinJointParam {
PIN_JOINT_SOFTNESS
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index a4dc80b0a6..586845de99 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -398,10 +398,47 @@ void PhysicsShapeQueryResult3D::_bind_methods() {
///////////////////////////////////////
+RID PhysicsServer3D::shape_create(ShapeType p_shape) {
+ switch (p_shape) {
+ case SHAPE_PLANE:
+ return plane_shape_create();
+ case SHAPE_RAY:
+ return ray_shape_create();
+ case SHAPE_SPHERE:
+ return sphere_shape_create();
+ case SHAPE_BOX:
+ return box_shape_create();
+ case SHAPE_CAPSULE:
+ return capsule_shape_create();
+ case SHAPE_CYLINDER:
+ return cylinder_shape_create();
+ case SHAPE_CONVEX_POLYGON:
+ return convex_polygon_shape_create();
+ case SHAPE_CONCAVE_POLYGON:
+ return concave_polygon_shape_create();
+ case SHAPE_HEIGHTMAP:
+ return heightmap_shape_create();
+ case SHAPE_CUSTOM:
+ return custom_shape_create();
+ default:
+ return RID();
+ }
+}
+
void PhysicsServer3D::_bind_methods() {
#ifndef _3D_DISABLED
- ClassDB::bind_method(D_METHOD("shape_create", "type"), &PhysicsServer3D::shape_create);
+ ClassDB::bind_method(D_METHOD("plane_shape_create"), &PhysicsServer3D::plane_shape_create);
+ ClassDB::bind_method(D_METHOD("ray_shape_create"), &PhysicsServer3D::ray_shape_create);
+ ClassDB::bind_method(D_METHOD("sphere_shape_create"), &PhysicsServer3D::sphere_shape_create);
+ ClassDB::bind_method(D_METHOD("box_shape_create"), &PhysicsServer3D::box_shape_create);
+ ClassDB::bind_method(D_METHOD("capsule_shape_create"), &PhysicsServer3D::capsule_shape_create);
+ ClassDB::bind_method(D_METHOD("cylinder_shape_create"), &PhysicsServer3D::cylinder_shape_create);
+ ClassDB::bind_method(D_METHOD("convex_polygon_shape_create"), &PhysicsServer3D::convex_polygon_shape_create);
+ ClassDB::bind_method(D_METHOD("concave_polygon_shape_create"), &PhysicsServer3D::concave_polygon_shape_create);
+ ClassDB::bind_method(D_METHOD("heightmap_shape_create"), &PhysicsServer3D::heightmap_shape_create);
+ ClassDB::bind_method(D_METHOD("custom_shape_create"), &PhysicsServer3D::custom_shape_create);
+
ClassDB::bind_method(D_METHOD("shape_set_data", "shape", "data"), &PhysicsServer3D::shape_set_data);
ClassDB::bind_method(D_METHOD("shape_get_type", "shape"), &PhysicsServer3D::shape_get_type);
@@ -450,9 +487,8 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &PhysicsServer3D::area_set_monitorable);
ClassDB::bind_method(D_METHOD("area_set_ray_pickable", "area", "enable"), &PhysicsServer3D::area_set_ray_pickable);
- ClassDB::bind_method(D_METHOD("area_is_ray_pickable", "area"), &PhysicsServer3D::area_is_ray_pickable);
- ClassDB::bind_method(D_METHOD("body_create", "mode", "init_sleeping"), &PhysicsServer3D::body_create, DEFVAL(BODY_MODE_RIGID), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("body_create"), &PhysicsServer3D::body_create);
ClassDB::bind_method(D_METHOD("body_set_space", "body", "space"), &PhysicsServer3D::body_set_space);
ClassDB::bind_method(D_METHOD("body_get_space", "body"), &PhysicsServer3D::body_get_space);
@@ -517,19 +553,26 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &PhysicsServer3D::body_set_force_integration_callback, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable);
- ClassDB::bind_method(D_METHOD("body_is_ray_pickable", "body"), &PhysicsServer3D::body_is_ray_pickable);
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer3D::body_get_direct_state);
+ /* SOFT BODY API */
+
+ ClassDB::bind_method(D_METHOD("soft_body_get_bounds", "body"), &PhysicsServer3D::soft_body_get_bounds);
+
/* JOINT API */
- BIND_ENUM_CONSTANT(JOINT_PIN);
- BIND_ENUM_CONSTANT(JOINT_HINGE);
- BIND_ENUM_CONSTANT(JOINT_SLIDER);
- BIND_ENUM_CONSTANT(JOINT_CONE_TWIST);
- BIND_ENUM_CONSTANT(JOINT_6DOF);
+ ClassDB::bind_method(D_METHOD("joint_create"), &PhysicsServer3D::joint_create);
+ ClassDB::bind_method(D_METHOD("joint_clear", "joint"), &PhysicsServer3D::joint_clear);
+
+ BIND_ENUM_CONSTANT(JOINT_TYPE_PIN);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_HINGE);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_SLIDER);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_CONE_TWIST);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_6DOF);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_MAX);
- ClassDB::bind_method(D_METHOD("joint_create_pin", "body_A", "local_A", "body_B", "local_B"), &PhysicsServer3D::joint_create_pin);
+ ClassDB::bind_method(D_METHOD("joint_make_pin", "joint", "body_A", "local_A", "body_B", "local_B"), &PhysicsServer3D::joint_make_pin);
ClassDB::bind_method(D_METHOD("pin_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::pin_joint_set_param);
ClassDB::bind_method(D_METHOD("pin_joint_get_param", "joint", "param"), &PhysicsServer3D::pin_joint_get_param);
@@ -555,7 +598,7 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(HINGE_JOINT_FLAG_USE_LIMIT);
BIND_ENUM_CONSTANT(HINGE_JOINT_FLAG_ENABLE_MOTOR);
- ClassDB::bind_method(D_METHOD("joint_create_hinge", "body_A", "hinge_A", "body_B", "hinge_B"), &PhysicsServer3D::joint_create_hinge);
+ ClassDB::bind_method(D_METHOD("joint_make_hinge", "joint", "body_A", "hinge_A", "body_B", "hinge_B"), &PhysicsServer3D::joint_make_hinge);
ClassDB::bind_method(D_METHOD("hinge_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::hinge_joint_set_param);
ClassDB::bind_method(D_METHOD("hinge_joint_get_param", "joint", "param"), &PhysicsServer3D::hinge_joint_get_param);
@@ -563,7 +606,7 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("hinge_joint_set_flag", "joint", "flag", "enabled"), &PhysicsServer3D::hinge_joint_set_flag);
ClassDB::bind_method(D_METHOD("hinge_joint_get_flag", "joint", "flag"), &PhysicsServer3D::hinge_joint_get_flag);
- ClassDB::bind_method(D_METHOD("joint_create_slider", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_create_slider);
+ ClassDB::bind_method(D_METHOD("joint_make_slider", "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_make_slider);
ClassDB::bind_method(D_METHOD("slider_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::slider_joint_set_param);
ClassDB::bind_method(D_METHOD("slider_joint_get_param", "joint", "param"), &PhysicsServer3D::slider_joint_get_param);
@@ -593,7 +636,7 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING);
BIND_ENUM_CONSTANT(SLIDER_JOINT_MAX);
- ClassDB::bind_method(D_METHOD("joint_create_cone_twist", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_create_cone_twist);
+ ClassDB::bind_method(D_METHOD("joint_make_cone_twist", "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_make_cone_twist);
ClassDB::bind_method(D_METHOD("cone_twist_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::cone_twist_joint_set_param);
ClassDB::bind_method(D_METHOD("cone_twist_joint_get_param", "joint", "param"), &PhysicsServer3D::cone_twist_joint_get_param);
@@ -631,7 +674,7 @@ 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_create_generic_6dof", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_create_generic_6dof);
+ 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);
ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_param", "joint", "axis", "param"), &PhysicsServer3D::generic_6dof_joint_get_param);
@@ -654,6 +697,7 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(SHAPE_CONVEX_POLYGON);
BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON);
BIND_ENUM_CONSTANT(SHAPE_HEIGHTMAP);
+ BIND_ENUM_CONSTANT(SHAPE_SOFT_BODY);
BIND_ENUM_CONSTANT(SHAPE_CUSTOM);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY);
@@ -718,7 +762,6 @@ void PhysicsServer3D::_bind_methods() {
}
PhysicsServer3D::PhysicsServer3D() {
- ERR_FAIL_COND(singleton != nullptr);
singleton = this;
}
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index 1349e0e033..69f5c1c0ad 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -216,6 +216,15 @@ public:
PhysicsShapeQueryResult3D();
};
+class RenderingServerHandler {
+public:
+ virtual void set_vertex(int p_vertex_id, const void *p_vector3) = 0;
+ virtual void set_normal(int p_vertex_id, const void *p_vector3) = 0;
+ virtual void set_aabb(const AABB &p_aabb) = 0;
+
+ virtual ~RenderingServerHandler() {}
+};
+
class PhysicsServer3D : public Object {
GDCLASS(PhysicsServer3D, Object);
@@ -237,10 +246,23 @@ public:
SHAPE_CONVEX_POLYGON, ///< array of planes:"planes"
SHAPE_CONCAVE_POLYGON, ///< vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array)
SHAPE_HEIGHTMAP, ///< dict( int:"width", int:"depth",float:"cell_size", float_array:"heights"
+ SHAPE_SOFT_BODY, ///< Used internally, can't be created from the physics server.
SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error
};
- virtual RID shape_create(ShapeType p_shape) = 0;
+ RID shape_create(ShapeType p_shape);
+
+ virtual RID plane_shape_create() = 0;
+ virtual RID ray_shape_create() = 0;
+ virtual RID sphere_shape_create() = 0;
+ virtual RID box_shape_create() = 0;
+ virtual RID capsule_shape_create() = 0;
+ virtual RID cylinder_shape_create() = 0;
+ virtual RID convex_polygon_shape_create() = 0;
+ virtual RID concave_polygon_shape_create() = 0;
+ virtual RID heightmap_shape_create() = 0;
+ virtual RID custom_shape_create() = 0;
+
virtual void shape_set_data(RID p_shape, const Variant &p_data) = 0;
virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias) = 0;
@@ -344,7 +366,6 @@ public:
virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0;
virtual void area_set_ray_pickable(RID p_area, bool p_enable) = 0;
- virtual bool area_is_ray_pickable(RID p_area) const = 0;
/* BODY API */
@@ -357,7 +378,7 @@ public:
BODY_MODE_CHARACTER
};
- virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false) = 0;
+ virtual RID body_create() = 0;
virtual void body_set_space(RID p_body, RID p_space) = 0;
virtual RID body_get_space(RID p_body) const = 0;
@@ -468,7 +489,6 @@ public:
virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0;
virtual void body_set_ray_pickable(RID p_body, bool p_enable) = 0;
- virtual bool body_is_ray_pickable(RID p_body) const = 0;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) = 0;
@@ -510,15 +530,17 @@ public:
/* SOFT BODY */
- virtual RID soft_body_create(bool p_init_sleeping = false) = 0;
+ virtual RID soft_body_create() = 0;
- virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) = 0;
+ virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) = 0;
virtual void soft_body_set_space(RID p_body, RID p_space) = 0;
virtual RID soft_body_get_space(RID p_body) const = 0;
virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) = 0;
+ virtual AABB soft_body_get_bounds(RID p_body) const = 0;
+
virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) = 0;
virtual uint32_t soft_body_get_collision_layer(RID p_body) const = 0;
@@ -533,58 +555,50 @@ public:
virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const = 0;
virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) = 0;
- virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const = 0;
virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) = 0;
- virtual bool soft_body_is_ray_pickable(RID p_body) const = 0;
virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) = 0;
- virtual int soft_body_get_simulation_precision(RID p_body) = 0;
+ virtual int soft_body_get_simulation_precision(RID p_body) const = 0;
virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) = 0;
- virtual real_t soft_body_get_total_mass(RID p_body) = 0;
+ virtual real_t soft_body_get_total_mass(RID p_body) const = 0;
virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) = 0;
- virtual real_t soft_body_get_linear_stiffness(RID p_body) = 0;
-
- virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) = 0;
- virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) = 0;
-
- virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) = 0;
- virtual real_t soft_body_get_volume_stiffness(RID p_body) = 0;
+ virtual real_t soft_body_get_linear_stiffness(RID p_body) const = 0;
virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) = 0;
- virtual real_t soft_body_get_pressure_coefficient(RID p_body) = 0;
-
- virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) = 0;
- virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) = 0;
+ virtual real_t soft_body_get_pressure_coefficient(RID p_body) const = 0;
virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) = 0;
- virtual real_t soft_body_get_damping_coefficient(RID p_body) = 0;
+ virtual real_t soft_body_get_damping_coefficient(RID p_body) const = 0;
virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) = 0;
- virtual real_t soft_body_get_drag_coefficient(RID p_body) = 0;
+ virtual real_t soft_body_get_drag_coefficient(RID p_body) const = 0;
virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) = 0;
- virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) = 0;
-
- virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const = 0;
+ virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) const = 0;
virtual void soft_body_remove_all_pinned_points(RID p_body) = 0;
virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) = 0;
- virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) = 0;
+ virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) const = 0;
/* JOINT API */
enum JointType {
- JOINT_PIN,
- JOINT_HINGE,
- JOINT_SLIDER,
- JOINT_CONE_TWIST,
- JOINT_6DOF
+ JOINT_TYPE_PIN,
+ JOINT_TYPE_HINGE,
+ JOINT_TYPE_SLIDER,
+ JOINT_TYPE_CONE_TWIST,
+ JOINT_TYPE_6DOF,
+ JOINT_TYPE_MAX,
};
+ virtual RID joint_create() = 0;
+
+ virtual void joint_clear(RID p_joint) = 0;
+
virtual JointType joint_get_type(RID p_joint) const = 0;
virtual void joint_set_solver_priority(RID p_joint, int p_priority) = 0;
@@ -593,7 +607,7 @@ public:
virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0;
virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0;
- virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) = 0;
+ virtual void joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) = 0;
enum PinJointParam {
PIN_JOINT_BIAS,
@@ -628,8 +642,8 @@ public:
HINGE_JOINT_FLAG_MAX
};
- virtual RID joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) = 0;
- virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) = 0;
+ virtual void joint_make_hinge(RID p_joint, RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) = 0;
+ virtual void joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) = 0;
virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) = 0;
virtual real_t hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const = 0;
@@ -665,7 +679,7 @@ public:
};
- virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
+ virtual void joint_make_slider(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) = 0;
virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const = 0;
@@ -679,7 +693,7 @@ public:
CONE_TWIST_MAX
};
- virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
+ virtual void joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) = 0;
virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const = 0;
@@ -720,13 +734,13 @@ public:
G6DOF_JOINT_FLAG_MAX
};
- virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
+ virtual void joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, real_t p_value) = 0;
- virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) = 0;
+ virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) const = 0;
virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable) = 0;
- virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) = 0;
+ virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) const = 0;
/* QUERY API */
@@ -742,7 +756,9 @@ public:
virtual void set_active(bool p_active) = 0;
virtual void init() = 0;
virtual void step(real_t p_step) = 0;
+ virtual void sync() = 0;
virtual void flush_queries() = 0;
+ virtual void end_sync() = 0;
virtual void finish() = 0;
virtual bool is_flushing_queries() const = 0;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 50efd7c554..deb230c4fb 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -61,6 +61,7 @@
#include "physics_2d/physics_server_2d_sw.h"
#include "physics_2d/physics_server_2d_wrap_mt.h"
#include "physics_3d/physics_server_3d_sw.h"
+#include "physics_3d/physics_server_3d_wrap_mt.h"
#include "physics_server_2d.h"
#include "physics_server_3d.h"
#include "rendering/renderer_compositor.h"
@@ -76,11 +77,19 @@
ShaderTypes *shader_types = nullptr;
PhysicsServer3D *_createGodotPhysics3DCallback() {
- return memnew(PhysicsServer3DSW);
+ bool using_threads = GLOBAL_GET("physics/3d/run_on_thread");
+
+ PhysicsServer3D *physics_server = memnew(PhysicsServer3DSW(using_threads));
+
+ return memnew(PhysicsServer3DWrapMT(physics_server, using_threads));
}
PhysicsServer2D *_createGodotPhysics2DCallback() {
- return PhysicsServer2DWrapMT::init_server<PhysicsServer2DSW>();
+ bool using_threads = GLOBAL_GET("physics/2d/run_on_thread");
+
+ PhysicsServer2D *physics_server = memnew(PhysicsServer2DSW(using_threads));
+
+ return memnew(PhysicsServer2DWrapMT(physics_server, using_threads));
}
static bool has_server_feature_callback(const String &p_feature) {
@@ -95,6 +104,16 @@ static bool has_server_feature_callback(const String &p_feature) {
void preregister_server_types() {
shader_types = memnew(ShaderTypes);
+
+ GLOBAL_DEF("internationalization/rendering/text_driver", "");
+ String text_driver_options;
+ for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
+ if (i > 0) {
+ text_driver_options += ",";
+ }
+ text_driver_options += TextServerManager::get_interface_name(i);
+ }
+ ProjectSettings::get_singleton()->set_custom_property_info("internationalization/rendering/text_driver", PropertyInfo(Variant::STRING, "internationalization/rendering/text_driver", PROPERTY_HINT_ENUM, text_driver_options));
}
void register_server_types() {
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index e1ce52661c..7f3fc2f8f4 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -97,7 +97,7 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
}
}
-void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_PtrOwner<RendererCanvasCull::Item> &canvas_item_owner) {
+void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_PtrOwner<RendererCanvasCull::Item, true> &canvas_item_owner) {
do {
ysort_owner->ysort_children_count = -1;
ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.getornull(ysort_owner->parent) : nullptr;
@@ -148,6 +148,8 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
} else {
ci->final_clip_rect = global_rect;
}
+ ci->final_clip_rect.position = ci->final_clip_rect.position.round();
+ ci->final_clip_rect.size = ci->final_clip_rect.size.round();
ci->final_clip_owner = ci;
} else {
@@ -356,12 +358,12 @@ bool RendererCanvasCull::was_sdf_used() {
return sdf_used;
}
-RID RendererCanvasCull::canvas_create() {
+RID RendererCanvasCull::canvas_allocate() {
+ return canvas_owner.allocate_rid();
+}
+void RendererCanvasCull::canvas_initialize(RID p_rid) {
Canvas *canvas = memnew(Canvas);
- ERR_FAIL_COND_V(!canvas, RID());
- RID rid = canvas_owner.make_rid(canvas);
-
- return rid;
+ canvas_owner.initialize_rid(p_rid, canvas);
}
void RendererCanvasCull::canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) {
@@ -393,11 +395,12 @@ void RendererCanvasCull::canvas_set_parent(RID p_canvas, RID p_parent, float p_s
canvas->parent_scale = p_scale;
}
-RID RendererCanvasCull::canvas_item_create() {
+RID RendererCanvasCull::canvas_item_allocate() {
+ return canvas_item_owner.allocate_rid();
+}
+void RendererCanvasCull::canvas_item_initialize(RID p_rid) {
Item *canvas_item = memnew(Item);
- ERR_FAIL_COND_V(!canvas_item, RID());
-
- return canvas_item_owner.make_rid(canvas_item);
+ canvas_item_owner.initialize_rid(p_rid, canvas_item);
}
void RendererCanvasCull::canvas_item_set_parent(RID p_item, RID p_parent) {
@@ -524,11 +527,11 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
Item::CommandPrimitive *line = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!line);
if (p_width > 1.001) {
- Vector2 t = (p_from - p_to).orthogonal().normalized();
- line->points[0] = p_from + t * p_width;
- line->points[1] = p_from - t * p_width;
- line->points[2] = p_to - t * p_width;
- line->points[3] = p_to + t * p_width;
+ Vector2 t = (p_from - p_to).orthogonal().normalized() * p_width * 0.5;
+ line->points[0] = p_from + t;
+ line->points[1] = p_from - t;
+ line->points[2] = p_to - t;
+ line->points[3] = p_to + t;
line->point_count = 4;
} else {
line->point_count = 2;
@@ -1075,10 +1078,13 @@ void RendererCanvasCull::canvas_item_set_canvas_group_mode(RID p_item, RS::Canva
}
}
-RID RendererCanvasCull::canvas_light_create() {
+RID RendererCanvasCull::canvas_light_allocate() {
+ return canvas_light_owner.allocate_rid();
+}
+void RendererCanvasCull::canvas_light_initialize(RID p_rid) {
RendererCanvasRender::Light *clight = memnew(RendererCanvasRender::Light);
clight->light_internal = RSG::canvas_render->light_create();
- return canvas_light_owner.make_rid(clight);
+ return canvas_light_owner.initialize_rid(p_rid, clight);
}
void RendererCanvasCull::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) {
@@ -1268,10 +1274,13 @@ void RendererCanvasCull::canvas_light_set_shadow_smooth(RID p_light, float p_smo
clight->shadow_smooth = p_smooth;
}
-RID RendererCanvasCull::canvas_light_occluder_create() {
+RID RendererCanvasCull::canvas_light_occluder_allocate() {
+ return canvas_light_occluder_owner.allocate_rid();
+}
+void RendererCanvasCull::canvas_light_occluder_initialize(RID p_rid) {
RendererCanvasRender::LightOccluderInstance *occluder = memnew(RendererCanvasRender::LightOccluderInstance);
- return canvas_light_occluder_owner.make_rid(occluder);
+ return canvas_light_occluder_owner.initialize_rid(p_rid, occluder);
}
void RendererCanvasCull::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) {
@@ -1349,10 +1358,13 @@ void RendererCanvasCull::canvas_light_occluder_set_light_mask(RID p_occluder, in
occluder->light_mask = p_mask;
}
-RID RendererCanvasCull::canvas_occluder_polygon_create() {
+RID RendererCanvasCull::canvas_occluder_polygon_allocate() {
+ return canvas_light_occluder_polygon_owner.allocate_rid();
+}
+void RendererCanvasCull::canvas_occluder_polygon_initialize(RID p_rid) {
LightOccluderPolygon *occluder_poly = memnew(LightOccluderPolygon);
occluder_poly->occluder = RSG::canvas_render->occluder_polygon_create();
- return canvas_light_occluder_polygon_owner.make_rid(occluder_poly);
+ return canvas_light_occluder_polygon_owner.initialize_rid(p_rid, occluder_poly);
}
void RendererCanvasCull::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) {
@@ -1393,8 +1405,11 @@ void RendererCanvasCull::canvas_set_shadow_texture_size(int p_size) {
RSG::canvas_render->set_shadow_texture_size(p_size);
}
-RID RendererCanvasCull::canvas_texture_create() {
- return RSG::storage->canvas_texture_create();
+RID RendererCanvasCull::canvas_texture_allocate() {
+ return RSG::storage->canvas_texture_allocate();
+}
+void RendererCanvasCull::canvas_texture_initialize(RID p_rid) {
+ RSG::storage->canvas_texture_initialize(p_rid);
}
void RendererCanvasCull::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 7496a413ee..b71f8e5a9a 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -101,9 +101,9 @@ public:
}
};
- RID_PtrOwner<LightOccluderPolygon> canvas_light_occluder_polygon_owner;
+ RID_PtrOwner<LightOccluderPolygon, true> canvas_light_occluder_polygon_owner;
- RID_PtrOwner<RendererCanvasRender::LightOccluderInstance> canvas_light_occluder_owner;
+ RID_PtrOwner<RendererCanvasRender::LightOccluderInstance, true> canvas_light_occluder_owner;
struct Canvas : public RendererViewport::CanvasBase {
Set<RID> viewports;
@@ -148,9 +148,9 @@ public:
}
};
- mutable RID_PtrOwner<Canvas> canvas_owner;
- RID_PtrOwner<Item> canvas_item_owner;
- RID_PtrOwner<RendererCanvasRender::Light> canvas_light_owner;
+ mutable RID_PtrOwner<Canvas, true> canvas_owner;
+ RID_PtrOwner<Item, true> canvas_item_owner;
+ RID_PtrOwner<RendererCanvasRender::Light, true> canvas_light_owner;
bool disable_scale;
bool sdf_used = false;
@@ -168,13 +168,17 @@ public:
bool was_sdf_used();
- RID canvas_create();
+ RID canvas_allocate();
+ void canvas_initialize(RID p_rid);
+
void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring);
void canvas_set_modulate(RID p_canvas, const Color &p_color);
void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale);
void canvas_set_disable_scale(bool p_disable);
- RID canvas_item_create();
+ RID canvas_item_allocate();
+ void canvas_item_initialize(RID p_rid);
+
void canvas_item_set_parent(RID p_item, RID p_parent);
void canvas_item_set_visible(RID p_item, bool p_visible);
@@ -222,7 +226,9 @@ public:
void canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false);
- RID canvas_light_create();
+ RID canvas_light_allocate();
+ void canvas_light_initialize(RID p_rid);
+
void canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode);
void canvas_light_attach_to_canvas(RID p_light, RID p_canvas);
void canvas_light_set_enabled(RID p_light, bool p_enabled);
@@ -246,7 +252,9 @@ public:
void canvas_light_set_shadow_color(RID p_light, const Color &p_color);
void canvas_light_set_shadow_smooth(RID p_light, float p_smooth);
- RID canvas_light_occluder_create();
+ RID canvas_light_occluder_allocate();
+ void canvas_light_occluder_initialize(RID p_rid);
+
void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas);
void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled);
void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon);
@@ -254,14 +262,18 @@ public:
void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform);
void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask);
- RID canvas_occluder_polygon_create();
+ RID canvas_occluder_polygon_allocate();
+ void canvas_occluder_polygon_initialize(RID p_rid);
+
void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed);
void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode);
void canvas_set_shadow_texture_size(int p_size);
- RID canvas_texture_create();
+ RID canvas_texture_allocate();
+ void canvas_texture_initialize(RID p_rid);
+
void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture);
void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess);
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index c35e5e1730..0fdd864d47 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -400,12 +400,14 @@ void ClusterBuilderRD::begin(const Transform &p_view_transform, const CameraMatr
void ClusterBuilderRD::bake_cluster() {
RENDER_TIMESTAMP(">Bake Cluster");
+ RD::get_singleton()->draw_command_begin_label("Bake Light Cluster");
+
//clear cluster buffer
- RD::get_singleton()->buffer_clear(cluster_buffer, 0, cluster_buffer_size);
+ RD::get_singleton()->buffer_clear(cluster_buffer, 0, cluster_buffer_size, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
if (render_element_count > 0) {
//clear render buffer
- RD::get_singleton()->buffer_clear(cluster_render_buffer, 0, cluster_render_buffer_size);
+ RD::get_singleton()->buffer_clear(cluster_render_buffer, 0, cluster_render_buffer_size, RD::BARRIER_MASK_RASTER);
{ //fill state uniform
@@ -420,12 +422,12 @@ void ClusterBuilderRD::bake_cluster() {
state.cluster_depth_offset = (render_element_max / 32);
state.cluster_data_size = state.cluster_depth_offset + render_element_max;
- RD::get_singleton()->buffer_update(state_uniform, 0, sizeof(StateUniform), &state);
+ RD::get_singleton()->buffer_update(state_uniform, 0, sizeof(StateUniform), &state, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
}
//update instances
- RD::get_singleton()->buffer_update(element_buffer, 0, sizeof(RenderElementData) * render_element_count, render_elements);
+ RD::get_singleton()->buffer_update(element_buffer, 0, sizeof(RenderElementData) * render_element_count, render_elements, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
RENDER_TIMESTAMP("Render Elements");
@@ -469,7 +471,7 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->draw_list_draw(draw_list, true, instances);
i += instances;
}
- RD::get_singleton()->draw_list_end();
+ RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_COMPUTE);
}
//store elements
RENDER_TIMESTAMP("Pack Elements");
@@ -491,12 +493,15 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterStore::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, cluster_screen_size.x, cluster_screen_size.y, 1, 8, 8, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, cluster_screen_size.x, cluster_screen_size.y, 1);
- RD::get_singleton()->compute_list_end();
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
}
+ } else {
+ RD::get_singleton()->barrier(RD::BARRIER_MASK_TRANSFER, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
}
RENDER_TIMESTAMP("<Bake Cluster");
+ RD::get_singleton()->draw_command_end_label();
}
void ClusterBuilderRD::debug(ElementType p_element) {
@@ -519,7 +524,7 @@ void ClusterBuilderRD::debug(ElementType p_element) {
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterDebug::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, screen_size.x, screen_size.y, 1, 8, 8, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, screen_size.x, screen_size.y, 1);
RD::get_singleton()->compute_list_end();
}
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index f1bab19445..bc304aedd8 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -299,15 +299,12 @@ void EffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const
copy.push_constant.target[0] = p_rect.position.x;
copy.push_constant.target[1] = p_rect.position.y;
- int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
- int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
-
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
RD::get_singleton()->compute_list_end();
}
@@ -322,15 +319,12 @@ void EffectsRD::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama,
copy.push_constant.target[1] = 0;
copy.push_constant.camera_z_far = p_lod;
- int32_t x_groups = (p_panorama_size.width - 1) / 8 + 1;
- int32_t y_groups = (p_panorama_size.height - 1) / 8 + 1;
-
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cube), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_panorama), 3);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_panorama_size.width, p_panorama_size.height, 1);
RD::get_singleton()->compute_list_end();
}
@@ -349,15 +343,12 @@ void EffectsRD::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_
copy.push_constant.camera_z_far = p_z_far;
copy.push_constant.camera_z_near = p_z_near;
- int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
- int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
-
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_LINEARIZE_DEPTH]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
RD::get_singleton()->compute_list_end();
}
@@ -374,15 +365,12 @@ void EffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture,
copy.push_constant.target[0] = p_rect.position.x;
copy.push_constant.target[1] = p_rect.position.y;
- int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
- int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
-
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_SIMPLY_COPY_DEPTH]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
RD::get_singleton()->compute_list_end();
}
@@ -400,14 +388,11 @@ void EffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i
copy.push_constant.set_color[2] = p_color.b;
copy.push_constant.set_color[3] = p_color.a;
- int32_t x_groups = (p_region.size.width - 1) / 8 + 1;
- int32_t y_groups = (p_region.size.height - 1) / 8 + 1;
-
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
RD::get_singleton()->compute_list_end();
}
@@ -420,8 +405,6 @@ void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back
copy.push_constant.section[2] = p_region.size.width;
copy.push_constant.section[3] = p_region.size.height;
- int32_t x_groups = (p_region.size.width - 1) / 8 + 1;
- int32_t y_groups = (p_region.size.height - 1) / 8 + 1;
//HORIZONTAL
RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY]);
@@ -431,7 +414,7 @@ void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back
copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
@@ -442,7 +425,7 @@ void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back
copy.push_constant.flags = base_flags;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
RD::get_singleton()->compute_list_end();
}
@@ -452,9 +435,6 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW;
uint32_t base_flags = 0;
- int32_t x_groups = (p_size.width + 7) / 8;
- int32_t y_groups = (p_size.height + 7) / 8;
-
copy.push_constant.section[2] = p_size.x;
copy.push_constant.section[3] = p_size.y;
@@ -479,16 +459,13 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
RD::get_singleton()->compute_list_end();
}
void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) {
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- int32_t x_groups = (p_screen_size.width - 1) / 8 + 1;
- int32_t y_groups = (p_screen_size.height - 1) / 8 + 1;
-
{ //scale color and depth to half
ssr_scale.push_constant.camera_z_far = p_camera.get_z_far();
ssr_scale.push_constant.camera_z_near = p_camera.get_z_near();
@@ -506,7 +483,7 @@ void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, R
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_scale.push_constant, sizeof(ScreenSpaceReflectionScalePushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
}
@@ -547,7 +524,7 @@ void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, R
}
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 2);
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
}
if (p_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED) {
@@ -585,7 +562,7 @@ void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, R
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
@@ -600,7 +577,7 @@ void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, R
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
}
RD::get_singleton()->compute_list_end();
@@ -609,9 +586,6 @@ void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, R
void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- int32_t x_groups = (p_screen_size.width - 1) / 8 + 1;
- int32_t y_groups = (p_screen_size.height - 1) / 8 + 1;
-
Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
p.normal /= p.d;
float unit_size = p.normal.x;
@@ -635,7 +609,7 @@ void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_dept
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
@@ -646,7 +620,7 @@ void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_dept
sss.push_constant.vertical = true;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
RD::get_singleton()->compute_list_end();
}
@@ -690,15 +664,12 @@ void EffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const S
copy.push_constant.section[2] = p_size.width;
copy.push_constant.section[3] = p_size.height;
- int32_t x_groups = (p_size.width - 1) / 8 + 1;
- int32_t y_groups = (p_size.height - 1) / 8 + 1;
-
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_MIPMAP]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
RD::get_singleton()->compute_list_end();
}
@@ -719,7 +690,7 @@ void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffe
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
+ RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_TRANSFER);
}
void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) {
@@ -804,10 +775,7 @@ void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_
RD::get_singleton()->compute_list_set_push_constant(compute_list, &luminance_reduce.push_constant, sizeof(LuminanceReducePushConstant));
- int32_t x_groups = (luminance_reduce.push_constant.source_size[0] - 1) / 8 + 1;
- int32_t y_groups = (luminance_reduce.push_constant.source_size[1] - 1) / 8 + 1;
-
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, luminance_reduce.push_constant.source_size[0], luminance_reduce.push_constant.source_size[1], 1);
luminance_reduce.push_constant.source_size[0] = MAX(luminance_reduce.push_constant.source_size[0] / 8, 1);
luminance_reduce.push_constant.source_size[1] = MAX(luminance_reduce.push_constant.source_size[1] / 8, 1);
@@ -848,14 +816,12 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_texture), 1);
- int32_t x_groups = (p_base_texture_size.x - 1) / 8 + 1;
- int32_t y_groups = (p_base_texture_size.y - 1) / 8 + 1;
bokeh.push_constant.size[0] = p_base_texture_size.x;
bokeh.push_constant.size[1] = p_base_texture_size.y;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_base_texture_size.x, p_base_texture_size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
@@ -872,8 +838,6 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture1), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1);
- x_groups = ((p_base_texture_size.x >> 1) - 1) / 8 + 1;
- y_groups = ((p_base_texture_size.y >> 1) - 1) / 8 + 1;
bokeh.push_constant.size[0] = p_base_texture_size.x >> 1;
bokeh.push_constant.size[1] = p_base_texture_size.y >> 1;
bokeh.push_constant.half_size = true;
@@ -887,7 +851,7 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
//third pass
@@ -903,7 +867,7 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
@@ -914,8 +878,6 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture2), 1);
- x_groups = (p_base_texture_size.x - 1) / 8 + 1;
- y_groups = (p_base_texture_size.y - 1) / 8 + 1;
bokeh.push_constant.size[0] = p_base_texture_size.x;
bokeh.push_constant.size[1] = p_base_texture_size.y;
bokeh.push_constant.half_size = false;
@@ -923,7 +885,7 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_base_texture_size.x, p_base_texture_size.y, 1);
}
} else {
//circle
@@ -941,15 +903,13 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture1), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1);
- x_groups = ((p_base_texture_size.x >> 1) - 1) / 8 + 1;
- y_groups = ((p_base_texture_size.y >> 1) - 1) / 8 + 1;
bokeh.push_constant.size[0] = p_base_texture_size.x >> 1;
bokeh.push_constant.size[1] = p_base_texture_size.y >> 1;
bokeh.push_constant.half_size = true;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
//circle is just one pass, then upscale
@@ -961,8 +921,6 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture1), 1);
- x_groups = (p_base_texture_size.x - 1) / 8 + 1;
- y_groups = (p_base_texture_size.y - 1) / 8 + 1;
bokeh.push_constant.size[0] = p_base_texture_size.x;
bokeh.push_constant.size[1] = p_base_texture_size.y;
bokeh.push_constant.half_size = false;
@@ -970,7 +928,7 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_base_texture_size.x, p_base_texture_size.y, 1);
}
RD::get_singleton()->compute_list_end();
@@ -995,10 +953,9 @@ void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID>
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 2);
RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));
- int x_groups = ((p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
- int y_groups = ((p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
+ Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
- RD::get_singleton()->compute_list_dispatch(p_compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
}
RD::get_singleton()->compute_list_add_barrier(p_compute_list);
}
@@ -1072,10 +1029,9 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.downsample_push_constant, sizeof(SSAODownsamplePushConstant));
- int x_groups = (MAX(1, p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
- int y_groups = (MAX(1, p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
+ Size2i size(MAX(1, p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)), MAX(1, p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
RD::get_singleton()->draw_command_end_label(); // Downsample SSAO
}
@@ -1193,21 +1149,19 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
gather_ssao(compute_list, p_ao_pong_slices, p_settings, true);
//generate importance map
- int x_groups = (p_settings.quarter_screen_size.x - 1) / 8 + 1;
- int y_groups = (p_settings.quarter_screen_size.y - 1) / 8 + 1;
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
//process importance map A
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
//process Importance Map B
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]);
@@ -1215,7 +1169,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]);
@@ -1272,10 +1226,8 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
- int x_groups = ((p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
- int y_groups = ((p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
-
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ Size2i size(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
}
if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
@@ -1313,18 +1265,15 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));
- int x_groups = (p_settings.full_screen_size.x - 1) / 8 + 1;
- int y_groups = (p_settings.full_screen_size.y - 1) / 8 + 1;
-
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
RD::get_singleton()->draw_command_end_label(); // Interleave
}
RD::get_singleton()->draw_command_end_label(); //SSAO
- RD::get_singleton()->compute_list_end();
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_TRANSFER); //wait for upcoming transfer
int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
+ RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
}
void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) {
@@ -1337,12 +1286,9 @@ void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_normal), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_roughness), 1);
- int x_groups = (p_size.x - 1) / 8 + 1;
- int y_groups = (p_size.y - 1) / 8 + 1;
-
RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness_limiter.push_constant, sizeof(RoughnessLimiterPushConstant)); //not used but set anyway
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.x, p_size.y, 1);
RD::get_singleton()->compute_list_end();
}
@@ -1455,7 +1401,7 @@ void EffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_
RD::get_singleton()->draw_list_draw(draw_list, true);
}
-void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples) {
+void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
ResolvePushConstant push_constant;
push_constant.screen_size[0] = p_screen_size.x;
push_constant.screen_size[1] = p_screen_size.y;
@@ -1472,54 +1418,9 @@ void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RI
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1, 8, 8, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::reduce_shadow(RID p_source_shadow, RID p_dest_shadow, const Size2i &p_source_size, const Rect2i &p_source_rect, int p_shrink_limit, RD::ComputeListID compute_list) {
- uint32_t push_constant[8] = { (uint32_t)p_source_size.x, (uint32_t)p_source_size.y, (uint32_t)p_source_rect.position.x, (uint32_t)p_source_rect.position.y, (uint32_t)p_shrink_limit, 0, 0, 0 };
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shadow_reduce.pipelines[SHADOW_REDUCE_REDUCE]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_source_shadow, p_dest_shadow), 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(uint32_t) * 8);
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_source_rect.size.width, p_source_rect.size.height, 1, 8, 8, 1);
-}
-void EffectsRD::filter_shadow(RID p_shadow, RID p_backing_shadow, const Size2i &p_source_size, const Rect2i &p_source_rect, RenderingServer::EnvVolumetricFogShadowFilter p_filter, RD::ComputeListID compute_list, bool p_vertical, bool p_horizontal) {
- uint32_t push_constant[8] = { (uint32_t)p_source_size.x, (uint32_t)p_source_size.y, (uint32_t)p_source_rect.position.x, (uint32_t)p_source_rect.position.y, 0, 0, 0, 0 };
-
- switch (p_filter) {
- case RS::ENV_VOLUMETRIC_FOG_SHADOW_FILTER_DISABLED:
- case RS::ENV_VOLUMETRIC_FOG_SHADOW_FILTER_LOW: {
- push_constant[5] = 0;
- } break;
- case RS::ENV_VOLUMETRIC_FOG_SHADOW_FILTER_MEDIUM: {
- push_constant[5] = 9;
- } break;
- case RS::ENV_VOLUMETRIC_FOG_SHADOW_FILTER_HIGH: {
- push_constant[5] = 18;
- } break;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shadow_reduce.pipelines[SHADOW_REDUCE_FILTER]);
- if (p_vertical) {
- push_constant[6] = 1;
- push_constant[7] = 0;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_shadow, p_backing_shadow), 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(uint32_t) * 8);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_source_rect.size.width, p_source_rect.size.height, 1, 8, 8, 1);
- }
- if (p_vertical && p_horizontal) {
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
- if (p_horizontal) {
- push_constant[6] = 0;
- push_constant[7] = 1;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_backing_shadow, p_shadow), 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(uint32_t) * 8);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_source_rect.size.width, p_source_rect.size.height, 1, 8, 8, 1);
- }
+ RD::get_singleton()->compute_list_end(p_barrier);
}
void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
@@ -1880,7 +1781,7 @@ EffectsRD::EffectsRD() {
{
// Initialize cubemap filter
- filter.use_high_quality = GLOBAL_GET("rendering/quality/reflections/fast_filter_high_quality");
+ filter.use_high_quality = GLOBAL_GET("rendering/reflections/sky_reflections/fast_filter_high_quality");
Vector<String> cubemap_filter_modes;
cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n");
@@ -2018,20 +1919,6 @@ EffectsRD::EffectsRD() {
}
{
- Vector<String> shadow_reduce_modes;
- shadow_reduce_modes.push_back("\n#define MODE_REDUCE\n");
- shadow_reduce_modes.push_back("\n#define MODE_FILTER\n");
-
- shadow_reduce.shader.initialize(shadow_reduce_modes);
-
- shadow_reduce.shader_version = shadow_reduce.shader.version_create();
-
- for (int i = 0; i < SHADOW_REDUCE_MAX; i++) {
- shadow_reduce.pipelines[i] = RD::get_singleton()->compute_pipeline_create(shadow_reduce.shader.version_get_shader(shadow_reduce.shader_version, i));
- }
- }
-
- {
Vector<String> sort_modes;
sort_modes.push_back("\n#define MODE_SORT_BLOCK\n");
sort_modes.push_back("\n#define MODE_SORT_STEP\n");
@@ -2119,5 +2006,4 @@ EffectsRD::~EffectsRD() {
ssr_scale.shader.version_free(ssr_scale.shader_version);
sss.shader.version_free(sss.shader_version);
tonemap.shader.version_free(tonemap.shader_version);
- shadow_reduce.shader.version_free(shadow_reduce.shader_version);
}
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 00309b4d0f..1ba25e301b 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -46,7 +46,6 @@
#include "servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/shadow_reduce.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/specular_merge.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/ssao.glsl.gen.h"
@@ -597,18 +596,6 @@ class EffectsRD {
RID pipelines[RESOLVE_MODE_MAX]; //3 quality levels
} resolve;
- enum ShadowReduceMode {
- SHADOW_REDUCE_REDUCE,
- SHADOW_REDUCE_FILTER,
- SHADOW_REDUCE_MAX
- };
-
- struct ShadowReduce {
- ShadowReduceShaderRD shader;
- RID shader_version;
- RID pipelines[SHADOW_REDUCE_MAX];
- } shadow_reduce;
-
enum SortMode {
SORT_MODE_BLOCK,
SORT_MODE_STEP,
@@ -763,10 +750,7 @@ public:
void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
- void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples);
-
- void reduce_shadow(RID p_source_shadow, RID p_dest_shadow, const Size2i &p_source_size, const Rect2i &p_source_rect, int p_shrink_limit, RenderingDevice::ComputeListID compute_list);
- void filter_shadow(RID p_shadow, RID p_backing_shadow, const Size2i &p_source_size, const Rect2i &p_source_rect, RS::EnvVolumetricFogShadowFilter p_filter, RenderingDevice::ComputeListID compute_list, bool p_vertical = true, bool p_horizontal = true);
+ void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
void sort_buffer(RID p_uniform_set, int p_size);
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 2a1a4efe48..7d6e2fa8e4 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -2695,9 +2695,10 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
state.default_transforms_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
}
- default_canvas_texture = storage->canvas_texture_create();
+ default_canvas_texture = storage->canvas_texture_allocate();
+ storage->canvas_texture_initialize(default_canvas_texture);
- state.shadow_texture_size = GLOBAL_GET("rendering/quality/2d_shadow_atlas/size");
+ state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
//create functions for shader and material
storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_shader_funcs);
@@ -2706,9 +2707,14 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
state.time = 0;
{
- default_canvas_group_shader = storage->shader_create();
+ default_canvas_group_shader = storage->shader_allocate();
+ storage->shader_initialize(default_canvas_group_shader);
+
storage->shader_set_code(default_canvas_group_shader, "shader_type canvas_item; \nvoid fragment() {\n\tvec4 c = textureLod(SCREEN_TEXTURE,SCREEN_UV,0.0); if (c.a > 0.0001) c.rgb/=c.a; COLOR *= c; \n}\n");
- default_canvas_group_material = storage->material_create();
+
+ default_canvas_group_material = storage->material_allocate();
+ storage->material_initialize(default_canvas_group_material);
+
storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
}
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index be2552bd32..d5ac05d1d1 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -175,5 +175,5 @@ RendererCompositorRD::RendererCompositorRD() {
storage = memnew(RendererStorageRD);
canvas = memnew(RendererCanvasRenderRD(storage));
- scene = memnew(RendererSceneRenderForward(storage));
+ scene = memnew(RendererSceneRenderForwardClustered(storage));
}
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index cb85fc79e0..67a843452b 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -35,14 +35,14 @@
#include "core/templates/thread_work_pool.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_scene_render_forward.h"
+#include "servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
class RendererCompositorRD : public RendererCompositor {
protected:
RendererCanvasRenderRD *canvas;
RendererStorageRD *storage;
- RendererSceneRenderForward *scene;
+ RendererSceneRenderRD *scene;
RID copy_viewports_rd_shader;
RID copy_viewports_rd_pipeline;
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
new file mode 100644
index 0000000000..d631cb4bac
--- /dev/null
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
@@ -0,0 +1,126 @@
+/*************************************************************************/
+/* renderer_scene_environment_rd.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
+
+uint64_t RendererSceneEnvironmentRD::auto_exposure_counter = 2;
+
+void RendererSceneEnvironmentRD::set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color) {
+ ambient_light = p_color;
+ ambient_source = p_ambient;
+ ambient_light_energy = p_energy;
+ ambient_sky_contribution = p_sky_contribution;
+ reflection_source = p_reflection_source;
+ ao_color = p_ao_color;
+}
+
+void RendererSceneEnvironmentRD::set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
+ exposure = p_exposure;
+ tone_mapper = p_tone_mapper;
+ if (!auto_exposure && p_auto_exposure) {
+ auto_exposure_version = ++auto_exposure_counter;
+ }
+ auto_exposure = p_auto_exposure;
+ white = p_white;
+ min_luminance = p_min_luminance;
+ max_luminance = p_max_luminance;
+ auto_exp_speed = p_auto_exp_speed;
+ auto_exp_scale = p_auto_exp_scale;
+}
+
+void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) {
+ ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
+ glow_enabled = p_enable;
+ glow_levels = p_levels;
+ glow_intensity = p_intensity;
+ glow_strength = p_strength;
+ glow_mix = p_mix;
+ glow_bloom = p_bloom_threshold;
+ glow_blend_mode = p_blend_mode;
+ glow_hdr_bleed_threshold = p_hdr_bleed_threshold;
+ glow_hdr_bleed_scale = p_hdr_bleed_scale;
+ glow_hdr_luminance_cap = p_hdr_luminance_cap;
+}
+
+void RendererSceneEnvironmentRD::set_sdfgi(bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
+ sdfgi_enabled = p_enable;
+ sdfgi_cascades = p_cascades;
+ sdfgi_min_cell_size = p_min_cell_size;
+ sdfgi_use_occlusion = p_use_occlusion;
+ sdfgi_bounce_feedback = p_bounce_feedback;
+ sdfgi_read_sky_light = p_read_sky;
+ sdfgi_energy = p_energy;
+ sdfgi_normal_bias = p_normal_bias;
+ sdfgi_probe_bias = p_probe_bias;
+ sdfgi_y_scale = p_y_scale;
+}
+
+void RendererSceneEnvironmentRD::set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) {
+ fog_enabled = p_enable;
+ fog_light_color = p_light_color;
+ fog_light_energy = p_light_energy;
+ fog_sun_scatter = p_sun_scatter;
+ fog_density = p_density;
+ fog_height = p_height;
+ fog_height_density = p_height_density;
+ fog_aerial_perspective = p_fog_aerial_perspective;
+}
+
+void RendererSceneEnvironmentRD::set_volumetric_fog(bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) {
+ volumetric_fog_enabled = p_enable;
+ volumetric_fog_density = p_density;
+ volumetric_fog_light = p_light;
+ volumetric_fog_light_energy = p_light_energy;
+ volumetric_fog_length = p_length;
+ volumetric_fog_detail_spread = p_detail_spread;
+ volumetric_fog_gi_inject = p_gi_inject;
+ volumetric_fog_temporal_reprojection = p_temporal_reprojection;
+ volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount;
+}
+
+void RendererSceneEnvironmentRD::set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
+ ssr_enabled = p_enable;
+ ssr_max_steps = p_max_steps;
+ ssr_fade_in = p_fade_int;
+ ssr_fade_out = p_fade_out;
+ ssr_depth_tolerance = p_depth_tolerance;
+}
+
+void RendererSceneEnvironmentRD::set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
+ ssao_enabled = p_enable;
+ ssao_radius = p_radius;
+ ssao_intensity = p_intensity;
+ ssao_power = p_power;
+ ssao_detail = p_detail;
+ ssao_horizon = p_horizon;
+ ssao_sharpness = p_sharpness;
+ ssao_direct_light_affect = p_light_affect;
+ ssao_ao_channel_affect = p_ao_channel_affect;
+}
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
new file mode 100644
index 0000000000..992c4bf471
--- /dev/null
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
@@ -0,0 +1,155 @@
+/*************************************************************************/
+/* renderer_scene_environment_rd.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H
+#define RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H
+
+#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering/rendering_device.h"
+
+class RendererSceneEnvironmentRD {
+private:
+ static uint64_t auto_exposure_counter;
+
+public:
+ // BG
+ RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR;
+ RID sky;
+ float sky_custom_fov = 0.0;
+ Basis sky_orientation;
+ Color bg_color;
+ float bg_energy = 1.0;
+ int canvas_max_layer = 0;
+ RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG;
+ Color ambient_light;
+ float ambient_light_energy = 1.0;
+ float ambient_sky_contribution = 1.0;
+ RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG;
+ Color ao_color;
+
+ /// Tonemap
+
+ RS::EnvironmentToneMapper tone_mapper;
+ float exposure = 1.0;
+ float white = 1.0;
+ bool auto_exposure = false;
+ float min_luminance = 0.2;
+ float max_luminance = 8.0;
+ float auto_exp_speed = 0.2;
+ float auto_exp_scale = 0.5;
+ uint64_t auto_exposure_version = 0;
+
+ // Fog
+ bool fog_enabled = false;
+ Color fog_light_color = Color(0.5, 0.6, 0.7);
+ float fog_light_energy = 1.0;
+ float fog_sun_scatter = 0.0;
+ float fog_density = 0.001;
+ float fog_height = 0.0;
+ float fog_height_density = 0.0; //can be negative to invert effect
+ float fog_aerial_perspective = 0.0;
+
+ /// Volumetric Fog
+ ///
+ bool volumetric_fog_enabled = false;
+ float volumetric_fog_density = 0.01;
+ Color volumetric_fog_light = Color(0, 0, 0);
+ float volumetric_fog_light_energy = 0.0;
+ float volumetric_fog_length = 64.0;
+ float volumetric_fog_detail_spread = 2.0;
+ float volumetric_fog_gi_inject = 0.0;
+ bool volumetric_fog_temporal_reprojection = true;
+ float volumetric_fog_temporal_reprojection_amount = 0.9;
+
+ /// Glow
+
+ bool glow_enabled = false;
+ Vector<float> glow_levels;
+ float glow_intensity = 0.8;
+ float glow_strength = 1.0;
+ float glow_bloom = 0.0;
+ float glow_mix = 0.01;
+ RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT;
+ float glow_hdr_bleed_threshold = 1.0;
+ float glow_hdr_luminance_cap = 12.0;
+ float glow_hdr_bleed_scale = 2.0;
+
+ /// SSAO
+
+ bool ssao_enabled = false;
+ float ssao_radius = 1.0;
+ float ssao_intensity = 2.0;
+ float ssao_power = 1.5;
+ float ssao_detail = 0.5;
+ float ssao_horizon = 0.06;
+ float ssao_sharpness = 0.98;
+ float ssao_direct_light_affect = 0.0;
+ float ssao_ao_channel_affect = 0.0;
+
+ /// SSR
+ ///
+ bool ssr_enabled = false;
+ int ssr_max_steps = 64;
+ float ssr_fade_in = 0.15;
+ float ssr_fade_out = 2.0;
+ float ssr_depth_tolerance = 0.2;
+
+ /// SDFGI
+ bool sdfgi_enabled = false;
+ RS::EnvironmentSDFGICascades sdfgi_cascades;
+ float sdfgi_min_cell_size = 0.2;
+ bool sdfgi_use_occlusion = false;
+ float sdfgi_bounce_feedback = 0.0;
+ bool sdfgi_read_sky_light = false;
+ float sdfgi_energy = 1.0;
+ float sdfgi_normal_bias = 1.1;
+ float sdfgi_probe_bias = 1.1;
+ RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_DISABLED;
+
+ /// Adjustments
+
+ bool adjustments_enabled = false;
+ float adjustments_brightness = 1.0f;
+ float adjustments_contrast = 1.0f;
+ float adjustments_saturation = 1.0f;
+ bool use_1d_color_correction = false;
+ RID color_correction = RID();
+
+ void set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color);
+ void set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
+ void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap);
+ void set_sdfgi(bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
+ void set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective);
+ void set_volumetric_fog(bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount);
+ void set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
+ void set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
+};
+
+#endif /* !RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H */
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
new file mode 100644
index 0000000000..4e4e553605
--- /dev/null
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
@@ -0,0 +1,3403 @@
+/*************************************************************************/
+/* renderer_scene_gi_rd.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "renderer_scene_gi_rd.h"
+
+#include "core/config/project_settings.h"
+#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
+#include "servers/rendering/rendering_server_default.h"
+
+const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF);
+
+////////////////////////////////////////////////////////////////////////////////
+// SDFGI
+
+void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) {
+ storage = p_gi->storage;
+ gi = p_gi;
+ cascade_mode = p_env->sdfgi_cascades;
+ min_cell_size = p_env->sdfgi_min_cell_size;
+ uses_occlusion = p_env->sdfgi_use_occlusion;
+ y_scale_mode = p_env->sdfgi_y_scale;
+ static const float y_scale[3] = { 1.0, 1.5, 2.0 };
+ y_mult = y_scale[y_scale_mode];
+ static const int cascasde_size[3] = { 4, 6, 8 };
+ cascades.resize(cascasde_size[cascade_mode]);
+ probe_axis_count = SDFGI::PROBE_DIVISOR + 1;
+ solid_cell_ratio = gi->sdfgi_solid_cell_ratio;
+ solid_cell_count = uint32_t(float(cascade_size * cascade_size * cascade_size) * solid_cell_ratio);
+
+ float base_cell_size = min_cell_size;
+
+ RD::TextureFormat tf_sdf;
+ tf_sdf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf_sdf.width = cascade_size; // Always 64x64
+ tf_sdf.height = cascade_size;
+ tf_sdf.depth = cascade_size;
+ tf_sdf.texture_type = RD::TEXTURE_TYPE_3D;
+ tf_sdf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+
+ {
+ RD::TextureFormat tf_render = tf_sdf;
+ tf_render.format = RD::DATA_FORMAT_R16_UINT;
+ render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ tf_render.format = RD::DATA_FORMAT_R32_UINT;
+ render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+
+ tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize
+
+ for (int i = 0; i < 8; i++) {
+ render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ }
+
+ tf_render.format = RD::DATA_FORMAT_R32_UINT;
+ render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+
+ tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
+ render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+
+ tf_render.width /= 2;
+ tf_render.height /= 2;
+ tf_render.depth /= 2;
+
+ render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ }
+
+ RD::TextureFormat tf_occlusion = tf_sdf;
+ tf_occlusion.format = RD::DATA_FORMAT_R16_UINT;
+ tf_occlusion.shareable_formats.push_back(RD::DATA_FORMAT_R16_UINT);
+ tf_occlusion.shareable_formats.push_back(RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16);
+ tf_occlusion.depth *= cascades.size(); //use depth for occlusion slices
+ tf_occlusion.width *= 2; //use width for the other half
+
+ RD::TextureFormat tf_light = tf_sdf;
+ tf_light.format = RD::DATA_FORMAT_R32_UINT;
+ tf_light.shareable_formats.push_back(RD::DATA_FORMAT_R32_UINT);
+ tf_light.shareable_formats.push_back(RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32);
+
+ RD::TextureFormat tf_aniso0 = tf_sdf;
+ tf_aniso0.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ RD::TextureFormat tf_aniso1 = tf_sdf;
+ tf_aniso1.format = RD::DATA_FORMAT_R8G8_UNORM;
+
+ int passes = nearest_shift(cascade_size) - 1;
+
+ //store lightprobe SH
+ RD::TextureFormat tf_probes;
+ tf_probes.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf_probes.width = probe_axis_count * probe_axis_count;
+ tf_probes.height = probe_axis_count * SDFGI::SH_SIZE;
+ tf_probes.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ tf_probes.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+
+ history_size = p_requested_history_size;
+
+ RD::TextureFormat tf_probe_history = tf_probes;
+ tf_probe_history.format = RD::DATA_FORMAT_R16G16B16A16_SINT; //signed integer because SH are signed
+ tf_probe_history.array_layers = history_size;
+
+ RD::TextureFormat tf_probe_average = tf_probes;
+ tf_probe_average.format = RD::DATA_FORMAT_R32G32B32A32_SINT; //signed integer because SH are signed
+ tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D;
+
+ lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
+ lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
+
+ {
+ //octahedral lightprobes
+ RD::TextureFormat tf_octprobes = tf_probes;
+ tf_octprobes.array_layers = cascades.size() * 2;
+ tf_octprobes.format = RD::DATA_FORMAT_R32_UINT; //pack well with RGBE
+ tf_octprobes.width = probe_axis_count * probe_axis_count * (SDFGI::LIGHTPROBE_OCT_SIZE + 2);
+ tf_octprobes.height = probe_axis_count * (SDFGI::LIGHTPROBE_OCT_SIZE + 2);
+ tf_octprobes.shareable_formats.push_back(RD::DATA_FORMAT_R32_UINT);
+ tf_octprobes.shareable_formats.push_back(RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32);
+ //lightprobe texture is an octahedral texture
+
+ lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView());
+ RD::TextureView tv;
+ tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
+ lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, lightprobe_data);
+
+ //texture handling ambient data, to integrate with volumetric foc
+ RD::TextureFormat tf_ambient = tf_probes;
+ tf_ambient.array_layers = cascades.size();
+ tf_ambient.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; //pack well with RGBE
+ tf_ambient.width = probe_axis_count * probe_axis_count;
+ tf_ambient.height = probe_axis_count;
+ tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ //lightprobe texture is an octahedral texture
+ ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView());
+ }
+
+ cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES);
+
+ occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView());
+ {
+ RD::TextureView tv;
+ tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16;
+ occlusion_texture = RD::get_singleton()->texture_create_shared(tv, occlusion_data);
+ }
+
+ for (uint32_t i = 0; i < cascades.size(); i++) {
+ SDFGI::Cascade &cascade = cascades[i];
+
+ /* 3D Textures */
+
+ cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView());
+
+ cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView());
+
+ cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView());
+ cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView());
+
+ {
+ RD::TextureView tv;
+ tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
+ cascade.light_tex = RD::get_singleton()->texture_create_shared(tv, cascade.light_data);
+
+ RD::get_singleton()->texture_clear(cascade.light_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ RD::get_singleton()->texture_clear(cascade.light_aniso_0_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ RD::get_singleton()->texture_clear(cascade.light_aniso_1_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ }
+
+ cascade.cell_size = base_cell_size;
+ Vector3 world_position = p_world_position;
+ world_position.y *= y_mult;
+ int32_t probe_cells = cascade_size / SDFGI::PROBE_DIVISOR;
+ Vector3 probe_size = Vector3(1, 1, 1) * cascade.cell_size * probe_cells;
+ Vector3i probe_pos = Vector3i((world_position / probe_size + Vector3(0.5, 0.5, 0.5)).floor());
+ cascade.position = probe_pos * probe_cells;
+
+ cascade.dirty_regions = SDFGI::Cascade::DIRTY_ALL;
+
+ base_cell_size *= 2.0;
+
+ /* Probe History */
+
+ cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
+ RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work
+
+ cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
+ RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work
+
+ /* Buffers */
+
+ cascade.solid_cell_buffer = RD::get_singleton()->storage_buffer_create(sizeof(SDFGI::Cascade::SolidCell) * solid_cell_count);
+ cascade.solid_cell_dispatch_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4, Vector<uint8_t>(), RD::STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT);
+ cascade.lights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(SDFGIShader::Light) * MAX(SDFGI::MAX_STATIC_LIGHTS, SDFGI::MAX_DYNAMIC_LIGHTS));
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(render_sdf[(passes & 1) ? 1 : 0]); //if passes are even, we read from buffer 0, else we read from buffer 1
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.ids.push_back(render_albedo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ for (int j = 0; j < 8; j++) {
+ u.ids.push_back(render_occlusion[j]);
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 4;
+ u.ids.push_back(render_emission);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 5;
+ u.ids.push_back(render_emission_aniso);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 6;
+ u.ids.push_back(render_geom_facing);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 7;
+ u.ids.push_back(cascade.sdf_tex);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 8;
+ u.ids.push_back(occlusion_data);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 10;
+ u.ids.push_back(cascade.solid_cell_dispatch_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 11;
+ u.ids.push_back(cascade.solid_cell_buffer);
+ uniforms.push_back(u);
+ }
+
+ cascade.sdf_store_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_STORE), 0);
+ }
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(render_albedo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.ids.push_back(render_geom_facing);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ u.ids.push_back(render_emission);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 4;
+ u.ids.push_back(render_emission_aniso);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 5;
+ u.ids.push_back(cascade.solid_cell_dispatch_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 6;
+ u.ids.push_back(cascade.solid_cell_buffer);
+ uniforms.push_back(u);
+ }
+
+ cascade.scroll_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_SCROLL), 0);
+ }
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ for (int j = 0; j < 8; j++) {
+ u.ids.push_back(render_occlusion[j]);
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.ids.push_back(occlusion_data);
+ uniforms.push_back(u);
+ }
+
+ cascade.scroll_occlusion_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_SCROLL_OCCLUSION), 0);
+ }
+ }
+
+ //direct light
+ for (uint32_t i = 0; i < cascades.size(); i++) {
+ SDFGI::Cascade &cascade = cascades[i];
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (j < cascades.size()) {
+ u.ids.push_back(cascades[j].sdf_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 3;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(cascade.solid_cell_dispatch_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(cascade.solid_cell_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 5;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.ids.push_back(cascade.light_data);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 6;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.ids.push_back(cascade.light_aniso_0_tex);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 7;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.ids.push_back(cascade.light_aniso_1_tex);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 8;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.ids.push_back(cascades_ubo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 9;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(cascade.lights_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 10;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.push_back(lightprobe_texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 11;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.push_back(occlusion_texture);
+ uniforms.push_back(u);
+ }
+
+ cascade.sdf_direct_light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, 0), 0);
+ }
+
+ //preprocess initialize uniform set
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(render_albedo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.ids.push_back(render_sdf[0]);
+ uniforms.push_back(u);
+ }
+
+ sdf_initialize_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE), 0);
+ }
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(render_albedo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.ids.push_back(render_sdf_half[0]);
+ uniforms.push_back(u);
+ }
+
+ sdf_initialize_half_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF), 0);
+ }
+
+ //jump flood uniform set
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(render_sdf[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.ids.push_back(render_sdf[1]);
+ uniforms.push_back(u);
+ }
+
+ jump_flood_uniform_set[0] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
+ SWAP(uniforms.write[0].ids.write[0], uniforms.write[1].ids.write[0]);
+ jump_flood_uniform_set[1] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
+ }
+ //jump flood half uniform set
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(render_sdf_half[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.ids.push_back(render_sdf_half[1]);
+ uniforms.push_back(u);
+ }
+
+ jump_flood_half_uniform_set[0] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
+ SWAP(uniforms.write[0].ids.write[0], uniforms.write[1].ids.write[0]);
+ jump_flood_half_uniform_set[1] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
+ }
+
+ //upscale half size sdf
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(render_albedo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.ids.push_back(render_sdf_half[(passes & 1) ? 0 : 1]); //reverse pass order because half size
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ u.ids.push_back(render_sdf[(passes & 1) ? 0 : 1]); //reverse pass order because it needs an extra JFA pass
+ uniforms.push_back(u);
+ }
+
+ upscale_jfa_uniform_set_index = (passes & 1) ? 0 : 1;
+ sdf_upscale_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD_UPSCALE), 0);
+ }
+
+ //occlusion uniform set
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(render_albedo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ for (int i = 0; i < 8; i++) {
+ u.ids.push_back(render_occlusion[i]);
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ u.ids.push_back(render_geom_facing);
+ uniforms.push_back(u);
+ }
+
+ occlusion_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_OCCLUSION), 0);
+ }
+
+ for (uint32_t i = 0; i < cascades.size(); i++) {
+ //integrate uniform
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (j < cascades.size()) {
+ u.ids.push_back(cascades[j].sdf_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (j < cascades.size()) {
+ u.ids.push_back(cascades[j].light_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 3;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (j < cascades.size()) {
+ u.ids.push_back(cascades[j].light_aniso_0_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (j < cascades.size()) {
+ u.ids.push_back(cascades[j].light_aniso_1_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 6;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 7;
+ u.ids.push_back(cascades_ubo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 8;
+ u.ids.push_back(lightprobe_data);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 9;
+ u.ids.push_back(cascades[i].lightprobe_history_tex);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 10;
+ u.ids.push_back(cascades[i].lightprobe_average_tex);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 11;
+ u.ids.push_back(lightprobe_history_scroll);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 12;
+ u.ids.push_back(lightprobe_average_scroll);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 13;
+ RID parent_average;
+ if (i < cascades.size() - 1) {
+ parent_average = cascades[i + 1].lightprobe_average_tex;
+ } else {
+ parent_average = cascades[i - 1].lightprobe_average_tex; //to use something, but it won't be used
+ }
+ u.ids.push_back(parent_average);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 14;
+ u.ids.push_back(ambient_texture);
+ uniforms.push_back(u);
+ }
+
+ cascades[i].integrate_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.integrate.version_get_shader(gi->sdfgi_shader.integrate_shader, 0), 0);
+ }
+
+ bounce_feedback = p_env->sdfgi_bounce_feedback;
+ energy = p_env->sdfgi_energy;
+ normal_bias = p_env->sdfgi_normal_bias;
+ probe_bias = p_env->sdfgi_probe_bias;
+ reads_sky = p_env->sdfgi_read_sky_light;
+}
+
+void RendererSceneGIRD::SDFGI::erase() {
+ for (uint32_t i = 0; i < cascades.size(); i++) {
+ const SDFGI::Cascade &c = cascades[i];
+ RD::get_singleton()->free(c.light_data);
+ RD::get_singleton()->free(c.light_aniso_0_tex);
+ RD::get_singleton()->free(c.light_aniso_1_tex);
+ RD::get_singleton()->free(c.sdf_tex);
+ RD::get_singleton()->free(c.solid_cell_dispatch_buffer);
+ RD::get_singleton()->free(c.solid_cell_buffer);
+ RD::get_singleton()->free(c.lightprobe_history_tex);
+ RD::get_singleton()->free(c.lightprobe_average_tex);
+ RD::get_singleton()->free(c.lights_buffer);
+ }
+
+ RD::get_singleton()->free(render_albedo);
+ RD::get_singleton()->free(render_emission);
+ RD::get_singleton()->free(render_emission_aniso);
+
+ RD::get_singleton()->free(render_sdf[0]);
+ RD::get_singleton()->free(render_sdf[1]);
+
+ RD::get_singleton()->free(render_sdf_half[0]);
+ RD::get_singleton()->free(render_sdf_half[1]);
+
+ for (int i = 0; i < 8; i++) {
+ RD::get_singleton()->free(render_occlusion[i]);
+ }
+
+ RD::get_singleton()->free(render_geom_facing);
+
+ RD::get_singleton()->free(lightprobe_data);
+ RD::get_singleton()->free(lightprobe_history_scroll);
+ RD::get_singleton()->free(occlusion_data);
+ RD::get_singleton()->free(ambient_texture);
+
+ RD::get_singleton()->free(cascades_ubo);
+}
+
+void RendererSceneGIRD::SDFGI::update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position) {
+ bounce_feedback = p_env->sdfgi_bounce_feedback;
+ energy = p_env->sdfgi_energy;
+ normal_bias = p_env->sdfgi_normal_bias;
+ probe_bias = p_env->sdfgi_probe_bias;
+ reads_sky = p_env->sdfgi_read_sky_light;
+
+ int32_t drag_margin = (cascade_size / SDFGI::PROBE_DIVISOR) / 2;
+
+ for (uint32_t i = 0; i < cascades.size(); i++) {
+ SDFGI::Cascade &cascade = cascades[i];
+ cascade.dirty_regions = Vector3i();
+
+ Vector3 probe_half_size = Vector3(1, 1, 1) * cascade.cell_size * float(cascade_size / SDFGI::PROBE_DIVISOR) * 0.5;
+ probe_half_size = Vector3(0, 0, 0);
+
+ Vector3 world_position = p_world_position;
+ world_position.y *= y_mult;
+ Vector3i pos_in_cascade = Vector3i((world_position + probe_half_size) / cascade.cell_size);
+
+ for (int j = 0; j < 3; j++) {
+ if (pos_in_cascade[j] < cascade.position[j]) {
+ while (pos_in_cascade[j] < (cascade.position[j] - drag_margin)) {
+ cascade.position[j] -= drag_margin * 2;
+ cascade.dirty_regions[j] += drag_margin * 2;
+ }
+ } else if (pos_in_cascade[j] > cascade.position[j]) {
+ while (pos_in_cascade[j] > (cascade.position[j] + drag_margin)) {
+ cascade.position[j] += drag_margin * 2;
+ cascade.dirty_regions[j] -= drag_margin * 2;
+ }
+ }
+
+ if (cascade.dirty_regions[j] == 0) {
+ continue; // not dirty
+ } else if (uint32_t(ABS(cascade.dirty_regions[j])) >= cascade_size) {
+ //moved too much, just redraw everything (make all dirty)
+ cascade.dirty_regions = SDFGI::Cascade::DIRTY_ALL;
+ break;
+ }
+ }
+
+ if (cascade.dirty_regions != Vector3i() && cascade.dirty_regions != SDFGI::Cascade::DIRTY_ALL) {
+ //see how much the total dirty volume represents from the total volume
+ uint32_t total_volume = cascade_size * cascade_size * cascade_size;
+ uint32_t safe_volume = 1;
+ for (int j = 0; j < 3; j++) {
+ safe_volume *= cascade_size - ABS(cascade.dirty_regions[j]);
+ }
+ uint32_t dirty_volume = total_volume - safe_volume;
+ if (dirty_volume > (safe_volume / 2)) {
+ //more than half the volume is dirty, make all dirty so its only rendered once
+ cascade.dirty_regions = SDFGI::Cascade::DIRTY_ALL;
+ }
+ }
+ }
+}
+
+void RendererSceneGIRD::SDFGI::update_light() {
+ RD::get_singleton()->draw_command_begin_label("SDFGI Update dynamic Light");
+
+ /* Update dynamic light */
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.direct_light_pipeline[SDFGIShader::DIRECT_LIGHT_MODE_DYNAMIC]);
+
+ SDFGIShader::DirectLightPushConstant push_constant;
+
+ push_constant.grid_size[0] = cascade_size;
+ push_constant.grid_size[1] = cascade_size;
+ push_constant.grid_size[2] = cascade_size;
+ push_constant.max_cascades = cascades.size();
+ push_constant.probe_axis_size = probe_axis_count;
+ push_constant.bounce_feedback = bounce_feedback;
+ push_constant.y_mult = y_mult;
+ push_constant.use_occlusion = uses_occlusion;
+
+ for (uint32_t i = 0; i < cascades.size(); i++) {
+ SDFGI::Cascade &cascade = cascades[i];
+ push_constant.light_count = cascade_dynamic_light_count[i];
+ push_constant.cascade = i;
+
+ if (cascades[i].all_dynamic_lights_dirty || gi->sdfgi_frames_to_update_light == RS::ENV_SDFGI_UPDATE_LIGHT_IN_1_FRAME) {
+ push_constant.process_offset = 0;
+ push_constant.process_increment = 1;
+ } else {
+ static uint32_t frames_to_update_table[RS::ENV_SDFGI_UPDATE_LIGHT_MAX] = {
+ 1, 2, 4, 8, 16
+ };
+
+ uint32_t frames_to_update = frames_to_update_table[gi->sdfgi_frames_to_update_light];
+
+ push_constant.process_offset = RSG::rasterizer->get_frame_number() % frames_to_update;
+ push_constant.process_increment = frames_to_update;
+ }
+ cascades[i].all_dynamic_lights_dirty = false;
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_uniform_set, 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DirectLightPushConstant));
+ RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer, 0);
+ }
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE);
+ RD::get_singleton()->draw_command_end_label();
+}
+
+void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky) {
+ RD::get_singleton()->draw_command_begin_label("SDFGI Update Probes");
+
+ SDFGIShader::IntegratePushConstant push_constant;
+ push_constant.grid_size[1] = cascade_size;
+ push_constant.grid_size[2] = cascade_size;
+ push_constant.grid_size[0] = cascade_size;
+ push_constant.max_cascades = cascades.size();
+ push_constant.probe_axis_size = probe_axis_count;
+ push_constant.history_index = render_pass % history_size;
+ push_constant.history_size = history_size;
+ static const uint32_t ray_count[RS::ENV_SDFGI_RAY_COUNT_MAX] = { 4, 8, 16, 32, 64, 96, 128 };
+ push_constant.ray_count = ray_count[gi->sdfgi_ray_count];
+ push_constant.ray_bias = probe_bias;
+ push_constant.image_size[0] = probe_axis_count * probe_axis_count;
+ push_constant.image_size[1] = probe_axis_count;
+ push_constant.store_ambient_texture = p_env->volumetric_fog_enabled;
+
+ RID sky_uniform_set = gi->sdfgi_shader.integrate_default_sky_uniform_set;
+ push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_DISABLED;
+ push_constant.y_mult = y_mult;
+
+ if (reads_sky && p_env) {
+ push_constant.sky_energy = p_env->bg_energy;
+
+ if (p_env->background == RS::ENV_BG_CLEAR_COLOR) {
+ push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
+ Color c = storage->get_default_clear_color().to_linear();
+ push_constant.sky_color[0] = c.r;
+ push_constant.sky_color[1] = c.g;
+ push_constant.sky_color[2] = c.b;
+ } else if (p_env->background == RS::ENV_BG_COLOR) {
+ push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
+ Color c = p_env->bg_color;
+ push_constant.sky_color[0] = c.r;
+ push_constant.sky_color[1] = c.g;
+ push_constant.sky_color[2] = c.b;
+
+ } else if (p_env->background == RS::ENV_BG_SKY) {
+ if (p_sky && p_sky->radiance.is_valid()) {
+ if (integrate_sky_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(integrate_sky_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 0;
+ u.ids.push_back(p_sky->radiance);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 1;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+
+ integrate_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.integrate.version_get_shader(gi->sdfgi_shader.integrate_shader, 0), 1);
+ }
+ sky_uniform_set = integrate_sky_uniform_set;
+ push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_SKY;
+ }
+ }
+ }
+
+ render_pass++;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_PROCESS]);
+
+ int32_t probe_divisor = cascade_size / SDFGI::PROBE_DIVISOR;
+ for (uint32_t i = 0; i < cascades.size(); i++) {
+ push_constant.cascade = i;
+ push_constant.world_offset[0] = cascades[i].position.x / probe_divisor;
+ push_constant.world_offset[1] = cascades[i].position.y / probe_divisor;
+ push_constant.world_offset[2] = cascades[i].position.z / probe_divisor;
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[i].integrate_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sky_uniform_set, 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::IntegratePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, probe_axis_count * probe_axis_count, probe_axis_count, 1);
+ }
+
+ //end later after raster to avoid barriering on layout changes
+ //RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER);
+
+ RD::get_singleton()->draw_command_end_label();
+}
+
+void RendererSceneGIRD::SDFGI::store_probes() {
+ RD::get_singleton()->barrier(RD::BARRIER_MASK_COMPUTE, RD::BARRIER_MASK_COMPUTE);
+ RD::get_singleton()->draw_command_begin_label("SDFGI Store Probes");
+
+ SDFGIShader::IntegratePushConstant push_constant;
+ push_constant.grid_size[1] = cascade_size;
+ push_constant.grid_size[2] = cascade_size;
+ push_constant.grid_size[0] = cascade_size;
+ push_constant.max_cascades = cascades.size();
+ push_constant.probe_axis_size = probe_axis_count;
+ push_constant.history_index = render_pass % history_size;
+ push_constant.history_size = history_size;
+ static const uint32_t ray_count[RS::ENV_SDFGI_RAY_COUNT_MAX] = { 4, 8, 16, 32, 64, 96, 128 };
+ push_constant.ray_count = ray_count[gi->sdfgi_ray_count];
+ push_constant.ray_bias = probe_bias;
+ push_constant.image_size[0] = probe_axis_count * probe_axis_count;
+ push_constant.image_size[1] = probe_axis_count;
+ push_constant.store_ambient_texture = false;
+
+ push_constant.sky_mode = 0;
+ push_constant.y_mult = y_mult;
+
+ // Then store values into the lightprobe texture. Separating these steps has a small performance hit, but it allows for multiple bounces
+ RENDER_TIMESTAMP("Average Probes");
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_STORE]);
+
+ //convert to octahedral to store
+ push_constant.image_size[0] *= SDFGI::LIGHTPROBE_OCT_SIZE;
+ push_constant.image_size[1] *= SDFGI::LIGHTPROBE_OCT_SIZE;
+
+ for (uint32_t i = 0; i < cascades.size(); i++) {
+ push_constant.cascade = i;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[i].integrate_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi->sdfgi_shader.integrate_default_sky_uniform_set, 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::IntegratePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, probe_axis_count * probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, 1);
+ }
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE);
+
+ RD::get_singleton()->draw_command_end_label();
+}
+
+int RendererSceneGIRD::SDFGI::get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const {
+ int dirty_count = 0;
+ for (uint32_t i = 0; i < cascades.size(); i++) {
+ const SDFGI::Cascade &c = cascades[i];
+
+ if (c.dirty_regions == SDFGI::Cascade::DIRTY_ALL) {
+ if (dirty_count == p_region) {
+ r_local_offset = Vector3i();
+ r_local_size = Vector3i(1, 1, 1) * cascade_size;
+
+ r_bounds.position = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + c.position)) * c.cell_size * Vector3(1, 1.0 / y_mult, 1);
+ r_bounds.size = Vector3(r_local_size) * c.cell_size * Vector3(1, 1.0 / y_mult, 1);
+ return i;
+ }
+ dirty_count++;
+ } else {
+ for (int j = 0; j < 3; j++) {
+ if (c.dirty_regions[j] != 0) {
+ if (dirty_count == p_region) {
+ Vector3i from = Vector3i(0, 0, 0);
+ Vector3i to = Vector3i(1, 1, 1) * cascade_size;
+
+ if (c.dirty_regions[j] > 0) {
+ //fill from the beginning
+ to[j] = c.dirty_regions[j];
+ } else {
+ //fill from the end
+ from[j] = to[j] + c.dirty_regions[j];
+ }
+
+ for (int k = 0; k < j; k++) {
+ // "chip" away previous regions to avoid re-voxelizing the same thing
+ if (c.dirty_regions[k] > 0) {
+ from[k] += c.dirty_regions[k];
+ } else if (c.dirty_regions[k] < 0) {
+ to[k] += c.dirty_regions[k];
+ }
+ }
+
+ r_local_offset = from;
+ r_local_size = to - from;
+
+ r_bounds.position = Vector3(from + Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + c.position) * c.cell_size * Vector3(1, 1.0 / y_mult, 1);
+ r_bounds.size = Vector3(r_local_size) * c.cell_size * Vector3(1, 1.0 / y_mult, 1);
+
+ return i;
+ }
+
+ dirty_count++;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+void RendererSceneGIRD::SDFGI::update_cascades() {
+ //update cascades
+ SDFGI::Cascade::UBO cascade_data[SDFGI::MAX_CASCADES];
+ int32_t probe_divisor = cascade_size / SDFGI::PROBE_DIVISOR;
+
+ for (uint32_t i = 0; i < cascades.size(); i++) {
+ Vector3 pos = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cascades[i].position)) * cascades[i].cell_size;
+
+ cascade_data[i].offset[0] = pos.x;
+ cascade_data[i].offset[1] = pos.y;
+ cascade_data[i].offset[2] = pos.z;
+ cascade_data[i].to_cell = 1.0 / cascades[i].cell_size;
+ cascade_data[i].probe_offset[0] = cascades[i].position.x / probe_divisor;
+ cascade_data[i].probe_offset[1] = cascades[i].position.y / probe_divisor;
+ cascade_data[i].probe_offset[2] = cascades[i].position.z / probe_divisor;
+ cascade_data[i].pad = 0;
+ }
+
+ RD::get_singleton()->buffer_update(cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, RD::BARRIER_MASK_COMPUTE);
+}
+
+void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) {
+ if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
+ if (i < cascades.size()) {
+ u.ids.push_back(cascades[i].sdf_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
+ if (i < cascades.size()) {
+ u.ids.push_back(cascades[i].light_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 3;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
+ if (i < cascades.size()) {
+ u.ids.push_back(cascades[i].light_aniso_0_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
+ if (i < cascades.size()) {
+ u.ids.push_back(cascades[i].light_aniso_1_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 5;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.push_back(occlusion_texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 8;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 9;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.ids.push_back(cascades_ubo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 10;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.ids.push_back(p_texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 11;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.push_back(lightprobe_texture);
+ uniforms.push_back(u);
+ }
+ debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.debug_shader_version, 0);
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.debug_pipeline);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, debug_uniform_set, 0);
+
+ SDFGIShader::DebugPushConstant push_constant;
+ push_constant.grid_size[0] = cascade_size;
+ push_constant.grid_size[1] = cascade_size;
+ push_constant.grid_size[2] = cascade_size;
+ push_constant.max_cascades = cascades.size();
+ push_constant.screen_size[0] = p_width;
+ push_constant.screen_size[1] = p_height;
+ push_constant.probe_axis_size = probe_axis_count;
+ push_constant.use_occlusion = uses_occlusion;
+ push_constant.y_mult = y_mult;
+
+ Vector2 vp_half = p_projection.get_viewport_half_extents();
+ push_constant.cam_extent[0] = vp_half.x;
+ push_constant.cam_extent[1] = vp_half.y;
+ push_constant.cam_extent[2] = -p_projection.get_z_near();
+
+ push_constant.cam_transform[0] = p_transform.basis.elements[0][0];
+ push_constant.cam_transform[1] = p_transform.basis.elements[1][0];
+ push_constant.cam_transform[2] = p_transform.basis.elements[2][0];
+ push_constant.cam_transform[3] = 0;
+ push_constant.cam_transform[4] = p_transform.basis.elements[0][1];
+ push_constant.cam_transform[5] = p_transform.basis.elements[1][1];
+ push_constant.cam_transform[6] = p_transform.basis.elements[2][1];
+ push_constant.cam_transform[7] = 0;
+ push_constant.cam_transform[8] = p_transform.basis.elements[0][2];
+ push_constant.cam_transform[9] = p_transform.basis.elements[1][2];
+ push_constant.cam_transform[10] = p_transform.basis.elements[2][2];
+ push_constant.cam_transform[11] = 0;
+ push_constant.cam_transform[12] = p_transform.origin.x;
+ push_constant.cam_transform[13] = p_transform.origin.y;
+ push_constant.cam_transform[14] = p_transform.origin.z;
+ push_constant.cam_transform[15] = 1;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DebugPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_width, p_height, 1);
+ RD::get_singleton()->compute_list_end();
+
+ Size2 rtsize = storage->render_target_get_size(p_render_target);
+ storage->get_effects()->copy_to_fb_rect(p_texture, storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true);
+}
+
+void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) {
+ SDFGIShader::DebugProbesPushConstant push_constant;
+
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ push_constant.projection[i * 4 + j] = p_camera_with_transform.matrix[i][j];
+ }
+ }
+
+ //gen spheres from strips
+ uint32_t band_points = 16;
+ push_constant.band_power = 4;
+ push_constant.sections_in_band = ((band_points / 2) - 1);
+ push_constant.band_mask = band_points - 2;
+ push_constant.section_arc = Math_TAU / float(push_constant.sections_in_band);
+ push_constant.y_mult = y_mult;
+
+ uint32_t total_points = push_constant.sections_in_band * band_points;
+ uint32_t total_probes = probe_axis_count * probe_axis_count * probe_axis_count;
+
+ push_constant.grid_size[0] = cascade_size;
+ push_constant.grid_size[1] = cascade_size;
+ push_constant.grid_size[2] = cascade_size;
+ push_constant.cascade = 0;
+
+ push_constant.probe_axis_size = probe_axis_count;
+
+ if (!debug_probes_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_probes_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.ids.push_back(cascades_ubo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.push_back(lightprobe_texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 3;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.push_back(occlusion_texture);
+ uniforms.push_back(u);
+ }
+
+ debug_probes_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.debug_probes.version_get_shader(gi->sdfgi_shader.debug_probes_shader, 0), 0);
+ }
+
+ RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, gi->sdfgi_shader.debug_probes_pipeline[SDFGIShader::PROBE_DEBUG_PROBES].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, debug_probes_uniform_set, 0);
+ RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(SDFGIShader::DebugProbesPushConstant));
+ RD::get_singleton()->draw_list_draw(p_draw_list, false, total_probes, total_points);
+
+ if (gi->sdfgi_debug_probe_dir != Vector3()) {
+ print_line("CLICK DEBUG ME?");
+ uint32_t cascade = 0;
+ Vector3 offset = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cascades[cascade].position)) * cascades[cascade].cell_size * Vector3(1.0, 1.0 / y_mult, 1.0);
+ Vector3 probe_size = cascades[cascade].cell_size * (cascade_size / SDFGI::PROBE_DIVISOR) * Vector3(1.0, 1.0 / y_mult, 1.0);
+ Vector3 ray_from = gi->sdfgi_debug_probe_pos;
+ Vector3 ray_to = gi->sdfgi_debug_probe_pos + gi->sdfgi_debug_probe_dir * cascades[cascade].cell_size * Math::sqrt(3.0) * cascade_size;
+ float sphere_radius = 0.2;
+ float closest_dist = 1e20;
+ gi->sdfgi_debug_probe_enabled = false;
+
+ Vector3i probe_from = cascades[cascade].position / (cascade_size / SDFGI::PROBE_DIVISOR);
+ for (int i = 0; i < (SDFGI::PROBE_DIVISOR + 1); i++) {
+ for (int j = 0; j < (SDFGI::PROBE_DIVISOR + 1); j++) {
+ for (int k = 0; k < (SDFGI::PROBE_DIVISOR + 1); k++) {
+ Vector3 pos = offset + probe_size * Vector3(i, j, k);
+ Vector3 res;
+ if (Geometry3D::segment_intersects_sphere(ray_from, ray_to, pos, sphere_radius, &res)) {
+ float d = ray_from.distance_to(res);
+ if (d < closest_dist) {
+ closest_dist = d;
+ gi->sdfgi_debug_probe_enabled = true;
+ gi->sdfgi_debug_probe_index = probe_from + Vector3i(i, j, k);
+ }
+ }
+ }
+ }
+ }
+
+ if (gi->sdfgi_debug_probe_enabled) {
+ print_line("found: " + gi->sdfgi_debug_probe_index);
+ } else {
+ print_line("no found");
+ }
+ gi->sdfgi_debug_probe_dir = Vector3();
+ }
+
+ if (gi->sdfgi_debug_probe_enabled) {
+ uint32_t cascade = 0;
+ uint32_t probe_cells = (cascade_size / SDFGI::PROBE_DIVISOR);
+ Vector3i probe_from = cascades[cascade].position / probe_cells;
+ Vector3i ofs = gi->sdfgi_debug_probe_index - probe_from;
+ if (ofs.x < 0 || ofs.y < 0 || ofs.z < 0) {
+ return;
+ }
+ if (ofs.x > SDFGI::PROBE_DIVISOR || ofs.y > SDFGI::PROBE_DIVISOR || ofs.z > SDFGI::PROBE_DIVISOR) {
+ return;
+ }
+
+ uint32_t mult = (SDFGI::PROBE_DIVISOR + 1);
+ uint32_t index = ofs.z * mult * mult + ofs.y * mult + ofs.x;
+
+ push_constant.probe_debug_index = index;
+
+ uint32_t cell_count = probe_cells * 2 * probe_cells * 2 * probe_cells * 2;
+
+ RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, gi->sdfgi_shader.debug_probes_pipeline[SDFGIShader::PROBE_DEBUG_VISIBILITY].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, debug_probes_uniform_set, 0);
+ RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(SDFGIShader::DebugProbesPushConstant));
+ RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, total_points);
+ }
+}
+
+void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform &p_transform, RendererSceneRenderRD *p_scene_render) {
+ /* Update general SDFGI Buffer */
+
+ SDFGIData sdfgi_data;
+
+ sdfgi_data.grid_size[0] = cascade_size;
+ sdfgi_data.grid_size[1] = cascade_size;
+ sdfgi_data.grid_size[2] = cascade_size;
+
+ sdfgi_data.max_cascades = cascades.size();
+ sdfgi_data.probe_axis_size = probe_axis_count;
+ sdfgi_data.cascade_probe_size[0] = sdfgi_data.probe_axis_size - 1; //float version for performance
+ sdfgi_data.cascade_probe_size[1] = sdfgi_data.probe_axis_size - 1;
+ sdfgi_data.cascade_probe_size[2] = sdfgi_data.probe_axis_size - 1;
+
+ float csize = cascade_size;
+ sdfgi_data.probe_to_uvw = 1.0 / float(sdfgi_data.cascade_probe_size[0]);
+ sdfgi_data.use_occlusion = uses_occlusion;
+ //sdfgi_data.energy = energy;
+
+ sdfgi_data.y_mult = y_mult;
+
+ float cascade_voxel_size = (csize / sdfgi_data.cascade_probe_size[0]);
+ float occlusion_clamp = (cascade_voxel_size - 0.5) / cascade_voxel_size;
+ sdfgi_data.occlusion_clamp[0] = occlusion_clamp;
+ sdfgi_data.occlusion_clamp[1] = occlusion_clamp;
+ sdfgi_data.occlusion_clamp[2] = occlusion_clamp;
+ sdfgi_data.normal_bias = (normal_bias / csize) * sdfgi_data.cascade_probe_size[0];
+
+ //vec2 tex_pixel_size = 1.0 / vec2(ivec2( (OCT_SIZE+2) * params.probe_axis_size * params.probe_axis_size, (OCT_SIZE+2) * params.probe_axis_size ) );
+ //vec3 probe_uv_offset = (ivec3(OCT_SIZE+2,OCT_SIZE+2,(OCT_SIZE+2) * params.probe_axis_size)) * tex_pixel_size.xyx;
+
+ uint32_t oct_size = SDFGI::LIGHTPROBE_OCT_SIZE;
+
+ sdfgi_data.lightprobe_tex_pixel_size[0] = 1.0 / ((oct_size + 2) * sdfgi_data.probe_axis_size * sdfgi_data.probe_axis_size);
+ sdfgi_data.lightprobe_tex_pixel_size[1] = 1.0 / ((oct_size + 2) * sdfgi_data.probe_axis_size);
+ sdfgi_data.lightprobe_tex_pixel_size[2] = 1.0;
+
+ sdfgi_data.energy = energy;
+
+ sdfgi_data.lightprobe_uv_offset[0] = float(oct_size + 2) * sdfgi_data.lightprobe_tex_pixel_size[0];
+ sdfgi_data.lightprobe_uv_offset[1] = float(oct_size + 2) * sdfgi_data.lightprobe_tex_pixel_size[1];
+ sdfgi_data.lightprobe_uv_offset[2] = float((oct_size + 2) * sdfgi_data.probe_axis_size) * sdfgi_data.lightprobe_tex_pixel_size[0];
+
+ sdfgi_data.occlusion_renormalize[0] = 0.5;
+ sdfgi_data.occlusion_renormalize[1] = 1.0;
+ sdfgi_data.occlusion_renormalize[2] = 1.0 / float(sdfgi_data.max_cascades);
+
+ int32_t probe_divisor = cascade_size / SDFGI::PROBE_DIVISOR;
+
+ for (uint32_t i = 0; i < sdfgi_data.max_cascades; i++) {
+ SDFGIData::ProbeCascadeData &c = sdfgi_data.cascades[i];
+ Vector3 pos = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cascades[i].position)) * cascades[i].cell_size;
+ Vector3 cam_origin = p_transform.origin;
+ cam_origin.y *= y_mult;
+ pos -= cam_origin; //make pos local to camera, to reduce numerical error
+ c.position[0] = pos.x;
+ c.position[1] = pos.y;
+ c.position[2] = pos.z;
+ c.to_probe = 1.0 / (float(cascade_size) * cascades[i].cell_size / float(probe_axis_count - 1));
+
+ Vector3i probe_ofs = cascades[i].position / probe_divisor;
+ c.probe_world_offset[0] = probe_ofs.x;
+ c.probe_world_offset[1] = probe_ofs.y;
+ c.probe_world_offset[2] = probe_ofs.z;
+
+ c.to_cell = 1.0 / cascades[i].cell_size;
+ }
+
+ RD::get_singleton()->buffer_update(gi->sdfgi_ubo, 0, sizeof(SDFGIData), &sdfgi_data, RD::BARRIER_MASK_COMPUTE);
+
+ /* Update dynamic lights in SDFGI cascades */
+
+ for (uint32_t i = 0; i < cascades.size(); i++) {
+ SDFGI::Cascade &cascade = cascades[i];
+
+ SDFGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS];
+ uint32_t idx = 0;
+ for (uint32_t j = 0; j < (uint32_t)p_scene_render->render_state.sdfgi_update_data->directional_lights->size(); j++) {
+ if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) {
+ break;
+ }
+
+ RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.getornull(p_scene_render->render_state.sdfgi_update_data->directional_lights->get(j));
+ ERR_CONTINUE(!li);
+
+ if (storage->light_directional_is_sky_only(li->light)) {
+ continue;
+ }
+
+ Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
+ dir.y *= y_mult;
+ dir.normalize();
+ lights[idx].direction[0] = dir.x;
+ lights[idx].direction[1] = dir.y;
+ lights[idx].direction[2] = dir.z;
+ Color color = storage->light_get_color(li->light);
+ color = color.to_linear();
+ lights[idx].color[0] = color.r;
+ lights[idx].color[1] = color.g;
+ lights[idx].color[2] = color.b;
+ lights[idx].type = RS::LIGHT_DIRECTIONAL;
+ lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY);
+ lights[idx].has_shadow = storage->light_has_shadow(li->light);
+
+ idx++;
+ }
+
+ AABB cascade_aabb;
+ cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cascade.position)) * cascade.cell_size;
+ cascade_aabb.size = Vector3(1, 1, 1) * cascade_size * cascade.cell_size;
+
+ for (uint32_t j = 0; j < p_scene_render->render_state.sdfgi_update_data->positional_light_count; j++) {
+ if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) {
+ break;
+ }
+
+ RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.getornull(p_scene_render->render_state.sdfgi_update_data->positional_light_instances[j]);
+ ERR_CONTINUE(!li);
+
+ uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
+ if (i > max_sdfgi_cascade) {
+ continue;
+ }
+
+ if (!cascade_aabb.intersects(li->aabb)) {
+ continue;
+ }
+
+ Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
+ //faster to not do this here
+ //dir.y *= y_mult;
+ //dir.normalize();
+ lights[idx].direction[0] = dir.x;
+ lights[idx].direction[1] = dir.y;
+ lights[idx].direction[2] = dir.z;
+ Vector3 pos = li->transform.origin;
+ pos.y *= y_mult;
+ lights[idx].position[0] = pos.x;
+ lights[idx].position[1] = pos.y;
+ lights[idx].position[2] = pos.z;
+ Color color = storage->light_get_color(li->light);
+ color = color.to_linear();
+ lights[idx].color[0] = color.r;
+ lights[idx].color[1] = color.g;
+ lights[idx].color[2] = color.b;
+ lights[idx].type = storage->light_get_type(li->light);
+ lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY);
+ lights[idx].has_shadow = storage->light_has_shadow(li->light);
+ lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
+ lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
+ lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ lights[idx].inv_spot_attenuation = 1.0f / storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+
+ idx++;
+ }
+
+ if (idx > 0) {
+ RD::get_singleton()->buffer_update(cascade.lights_buffer, 0, idx * sizeof(SDFGIShader::Light), lights, RD::BARRIER_MASK_COMPUTE);
+ }
+
+ cascade_dynamic_light_count[i] = idx;
+ }
+}
+
+void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) {
+ //print_line("rendering region " + itos(p_region));
+ RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers);
+ ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
+ AABB bounds;
+ Vector3i from;
+ Vector3i size;
+
+ int cascade_prev = get_pending_region_data(p_region - 1, from, size, bounds);
+ int cascade_next = get_pending_region_data(p_region + 1, from, size, bounds);
+ int cascade = get_pending_region_data(p_region, from, size, bounds);
+ ERR_FAIL_COND(cascade < 0);
+
+ if (cascade_prev != cascade) {
+ //initialize render
+ RD::get_singleton()->texture_clear(render_albedo, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ RD::get_singleton()->texture_clear(render_emission, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ RD::get_singleton()->texture_clear(render_emission_aniso, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ RD::get_singleton()->texture_clear(render_geom_facing, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ }
+
+ //print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(cascades[cascade].cell_size));
+ p_scene_render->_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, render_albedo, render_emission, render_emission_aniso, render_geom_facing);
+
+ if (cascade_next != cascade) {
+ RD::get_singleton()->draw_command_begin_label("SDFGI Pre-Process Cascade");
+
+ RENDER_TIMESTAMP(">SDFGI Update SDF");
+ //done rendering! must update SDF
+ //clear dispatch indirect data
+
+ SDFGIShader::PreprocessPushConstant push_constant;
+ zeromem(&push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+
+ RENDER_TIMESTAMP("Scroll SDF");
+
+ //scroll
+ if (cascades[cascade].dirty_regions != SDFGI::Cascade::DIRTY_ALL) {
+ //for scroll
+ Vector3i dirty = cascades[cascade].dirty_regions;
+ push_constant.scroll[0] = dirty.x;
+ push_constant.scroll[1] = dirty.y;
+ push_constant.scroll[2] = dirty.z;
+ } else {
+ //for no scroll
+ push_constant.scroll[0] = 0;
+ push_constant.scroll[1] = 0;
+ push_constant.scroll[2] = 0;
+ }
+
+ cascades[cascade].all_dynamic_lights_dirty = true;
+
+ push_constant.grid_size = cascade_size;
+ push_constant.cascade = cascade;
+
+ if (cascades[cascade].dirty_regions != SDFGI::Cascade::DIRTY_ALL) {
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ //must pre scroll existing data because not all is dirty
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_SCROLL]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].scroll_uniform_set, 0);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+ RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascades[cascade].solid_cell_dispatch_buffer, 0);
+ // no barrier do all together
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_SCROLL_OCCLUSION]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].scroll_occlusion_uniform_set, 0);
+
+ Vector3i dirty = cascades[cascade].dirty_regions;
+ Vector3i groups;
+ groups.x = cascade_size - ABS(dirty.x);
+ groups.y = cascade_size - ABS(dirty.y);
+ groups.z = cascade_size - ABS(dirty.z);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, groups.x, groups.y, groups.z);
+
+ //no barrier, continue together
+
+ {
+ //scroll probes and their history also
+
+ SDFGIShader::IntegratePushConstant ipush_constant;
+ ipush_constant.grid_size[1] = cascade_size;
+ ipush_constant.grid_size[2] = cascade_size;
+ ipush_constant.grid_size[0] = cascade_size;
+ ipush_constant.max_cascades = cascades.size();
+ ipush_constant.probe_axis_size = probe_axis_count;
+ ipush_constant.history_index = 0;
+ ipush_constant.history_size = history_size;
+ ipush_constant.ray_count = 0;
+ ipush_constant.ray_bias = 0;
+ ipush_constant.sky_mode = 0;
+ ipush_constant.sky_energy = 0;
+ ipush_constant.sky_color[0] = 0;
+ ipush_constant.sky_color[1] = 0;
+ ipush_constant.sky_color[2] = 0;
+ ipush_constant.y_mult = y_mult;
+ ipush_constant.store_ambient_texture = false;
+
+ ipush_constant.image_size[0] = probe_axis_count * probe_axis_count;
+ ipush_constant.image_size[1] = probe_axis_count;
+
+ int32_t probe_divisor = cascade_size / SDFGI::PROBE_DIVISOR;
+ ipush_constant.cascade = cascade;
+ ipush_constant.world_offset[0] = cascades[cascade].position.x / probe_divisor;
+ ipush_constant.world_offset[1] = cascades[cascade].position.y / probe_divisor;
+ ipush_constant.world_offset[2] = cascades[cascade].position.z / probe_divisor;
+
+ ipush_constant.scroll[0] = dirty.x / probe_divisor;
+ ipush_constant.scroll[1] = dirty.y / probe_divisor;
+ ipush_constant.scroll[2] = dirty.z / probe_divisor;
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_SCROLL]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].integrate_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi->sdfgi_shader.integrate_default_sky_uniform_set, 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDFGIShader::IntegratePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, probe_axis_count * probe_axis_count, probe_axis_count, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_SCROLL_STORE]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].integrate_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi->sdfgi_shader.integrate_default_sky_uniform_set, 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDFGIShader::IntegratePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, probe_axis_count * probe_axis_count, probe_axis_count, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ if (bounce_feedback > 0.0) {
+ //multibounce requires this to be stored so direct light can read from it
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_STORE]);
+
+ //convert to octahedral to store
+ ipush_constant.image_size[0] *= SDFGI::LIGHTPROBE_OCT_SIZE;
+ ipush_constant.image_size[1] *= SDFGI::LIGHTPROBE_OCT_SIZE;
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].integrate_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi->sdfgi_shader.integrate_default_sky_uniform_set, 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDFGIShader::IntegratePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, probe_axis_count * probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, 1);
+ }
+ }
+
+ //ok finally barrier
+ RD::get_singleton()->compute_list_end();
+ }
+
+ //clear dispatch indirect data
+ uint32_t dispatch_indirct_data[4] = { 0, 0, 0, 0 };
+ RD::get_singleton()->buffer_update(cascades[cascade].solid_cell_dispatch_buffer, 0, sizeof(uint32_t) * 4, dispatch_indirct_data);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ bool half_size = true; //much faster, very little difference
+ static const int optimized_jf_group_size = 8;
+
+ if (half_size) {
+ push_constant.grid_size >>= 1;
+
+ uint32_t cascade_half_size = cascade_size >> 1;
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdf_initialize_half_uniform_set, 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_half_size, cascade_half_size, cascade_half_size);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //must start with regular jumpflood
+
+ push_constant.half_size = true;
+ {
+ RENDER_TIMESTAMP("SDFGI Jump Flood (Half Size)");
+
+ uint32_t s = cascade_half_size;
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD]);
+
+ int jf_us = 0;
+ //start with regular jump flood for very coarse reads, as this is impossible to optimize
+ while (s > 1) {
+ s /= 2;
+ push_constant.step_size = s;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, jump_flood_half_uniform_set[jf_us], 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_half_size, cascade_half_size, cascade_half_size);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ jf_us = jf_us == 0 ? 1 : 0;
+
+ if (cascade_half_size / (s / 2) >= optimized_jf_group_size) {
+ break;
+ }
+ }
+
+ RENDER_TIMESTAMP("SDFGI Jump Flood Optimized (Half Size)");
+
+ //continue with optimized jump flood for smaller reads
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]);
+ while (s > 1) {
+ s /= 2;
+ push_constant.step_size = s;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, jump_flood_half_uniform_set[jf_us], 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_half_size, cascade_half_size, cascade_half_size);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ jf_us = jf_us == 0 ? 1 : 0;
+ }
+ }
+
+ // restore grid size for last passes
+ push_constant.grid_size = cascade_size;
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_UPSCALE]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdf_upscale_uniform_set, 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_size, cascade_size, cascade_size);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //run one pass of fullsize jumpflood to fix up half size arctifacts
+
+ push_constant.half_size = false;
+ push_constant.step_size = 1;
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, jump_flood_uniform_set[upscale_jfa_uniform_set_index], 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_size, cascade_size, cascade_size);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ } else {
+ //full size jumpflood
+ RENDER_TIMESTAMP("SDFGI Jump Flood");
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdf_initialize_uniform_set, 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_size, cascade_size, cascade_size);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ push_constant.half_size = false;
+ {
+ uint32_t s = cascade_size;
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD]);
+
+ int jf_us = 0;
+ //start with regular jump flood for very coarse reads, as this is impossible to optimize
+ while (s > 1) {
+ s /= 2;
+ push_constant.step_size = s;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, jump_flood_uniform_set[jf_us], 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_size, cascade_size, cascade_size);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ jf_us = jf_us == 0 ? 1 : 0;
+
+ if (cascade_size / (s / 2) >= optimized_jf_group_size) {
+ break;
+ }
+ }
+
+ RENDER_TIMESTAMP("SDFGI Jump Flood Optimized");
+
+ //continue with optimized jump flood for smaller reads
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]);
+ while (s > 1) {
+ s /= 2;
+ push_constant.step_size = s;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, jump_flood_uniform_set[jf_us], 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_size, cascade_size, cascade_size);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ jf_us = jf_us == 0 ? 1 : 0;
+ }
+ }
+ }
+
+ RENDER_TIMESTAMP("SDFGI Occlusion");
+
+ // occlusion
+ {
+ uint32_t probe_size = cascade_size / SDFGI::PROBE_DIVISOR;
+ Vector3i probe_global_pos = cascades[cascade].position / probe_size;
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_OCCLUSION]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, occlusion_uniform_set, 0);
+ for (int i = 0; i < 8; i++) {
+ //dispatch all at once for performance
+ Vector3i offset(i & 1, (i >> 1) & 1, (i >> 2) & 1);
+
+ if ((probe_global_pos.x & 1) != 0) {
+ offset.x = (offset.x + 1) & 1;
+ }
+ if ((probe_global_pos.y & 1) != 0) {
+ offset.y = (offset.y + 1) & 1;
+ }
+ if ((probe_global_pos.z & 1) != 0) {
+ offset.z = (offset.z + 1) & 1;
+ }
+ push_constant.probe_offset[0] = offset.x;
+ push_constant.probe_offset[1] = offset.y;
+ push_constant.probe_offset[2] = offset.z;
+ push_constant.occlusion_index = i;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+
+ Vector3i groups = Vector3i(probe_size + 1, probe_size + 1, probe_size + 1) - offset; //if offset, it's one less probe per axis to compute
+ RD::get_singleton()->compute_list_dispatch(compute_list, groups.x, groups.y, groups.z);
+ }
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+
+ RENDER_TIMESTAMP("SDFGI Store");
+
+ // store
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_STORE]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].sdf_store_uniform_set, 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_size, cascade_size, cascade_size);
+
+ RD::get_singleton()->compute_list_end();
+
+ //clear these textures, as they will have previous garbage on next draw
+ RD::get_singleton()->texture_clear(cascades[cascade].light_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ RD::get_singleton()->texture_clear(cascades[cascade].light_aniso_0_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ RD::get_singleton()->texture_clear(cascades[cascade].light_aniso_1_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
+
+#if 0
+ Vector<uint8_t> data = RD::get_singleton()->texture_get_data(cascades[cascade].sdf, 0);
+ Ref<Image> img;
+ img.instance();
+ for (uint32_t i = 0; i < cascade_size; i++) {
+ Vector<uint8_t> subarr = data.subarray(128 * 128 * i, 128 * 128 * (i + 1) - 1);
+ img->create(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr);
+ img->save_png("res://cascade_sdf_" + itos(cascade) + "_" + itos(i) + ".png");
+ }
+
+ //finalize render and update sdf
+#endif
+
+#if 0
+ Vector<uint8_t> data = RD::get_singleton()->texture_get_data(render_albedo, 0);
+ Ref<Image> img;
+ img.instance();
+ for (uint32_t i = 0; i < cascade_size; i++) {
+ Vector<uint8_t> subarr = data.subarray(128 * 128 * i * 2, 128 * 128 * (i + 1) * 2 - 1);
+ img->createcascade_size, cascade_size, false, Image::FORMAT_RGB565, subarr);
+ img->convert(Image::FORMAT_RGBA8);
+ img->save_png("res://cascade_" + itos(cascade) + "_" + itos(i) + ".png");
+ }
+
+ //finalize render and update sdf
+#endif
+
+ RENDER_TIMESTAMP("<SDFGI Update SDF");
+ RD::get_singleton()->draw_command_end_label();
+ }
+}
+
+void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) {
+ RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers);
+ ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
+
+ RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lighs");
+
+ update_cascades();
+ ; //need cascades updated for this
+
+ SDFGIShader::Light lights[SDFGI::MAX_STATIC_LIGHTS];
+ uint32_t light_count[SDFGI::MAX_STATIC_LIGHTS];
+
+ for (uint32_t i = 0; i < p_cascade_count; i++) {
+ ERR_CONTINUE(p_cascade_indices[i] >= cascades.size());
+
+ SDFGI::Cascade &cc = cascades[p_cascade_indices[i]];
+
+ { //fill light buffer
+
+ AABB cascade_aabb;
+ cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cc.position)) * cc.cell_size;
+ cascade_aabb.size = Vector3(1, 1, 1) * cascade_size * cc.cell_size;
+
+ int idx = 0;
+
+ for (uint32_t j = 0; j < (uint32_t)p_positional_light_cull_result[i].size(); j++) {
+ if (idx == SDFGI::MAX_STATIC_LIGHTS) {
+ break;
+ }
+
+ RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.getornull(p_positional_light_cull_result[i][j]);
+ ERR_CONTINUE(!li);
+
+ uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
+ if (p_cascade_indices[i] > max_sdfgi_cascade) {
+ continue;
+ }
+
+ if (!cascade_aabb.intersects(li->aabb)) {
+ continue;
+ }
+
+ lights[idx].type = storage->light_get_type(li->light);
+
+ Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
+ if (lights[idx].type == RS::LIGHT_DIRECTIONAL) {
+ dir.y *= y_mult; //only makes sense for directional
+ dir.normalize();
+ }
+ lights[idx].direction[0] = dir.x;
+ lights[idx].direction[1] = dir.y;
+ lights[idx].direction[2] = dir.z;
+ Vector3 pos = li->transform.origin;
+ pos.y *= y_mult;
+ lights[idx].position[0] = pos.x;
+ lights[idx].position[1] = pos.y;
+ lights[idx].position[2] = pos.z;
+ Color color = storage->light_get_color(li->light);
+ color = color.to_linear();
+ lights[idx].color[0] = color.r;
+ lights[idx].color[1] = color.g;
+ lights[idx].color[2] = color.b;
+ lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY);
+ lights[idx].has_shadow = storage->light_has_shadow(li->light);
+ lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
+ lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
+ lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ lights[idx].inv_spot_attenuation = 1.0f / storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+
+ idx++;
+ }
+
+ if (idx > 0) {
+ RD::get_singleton()->buffer_update(cc.lights_buffer, 0, idx * sizeof(SDFGIShader::Light), lights);
+ }
+
+ light_count[i] = idx;
+ }
+ }
+
+ /* Static Lights */
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.direct_light_pipeline[SDFGIShader::DIRECT_LIGHT_MODE_STATIC]);
+
+ SDFGIShader::DirectLightPushConstant dl_push_constant;
+
+ dl_push_constant.grid_size[0] = cascade_size;
+ dl_push_constant.grid_size[1] = cascade_size;
+ dl_push_constant.grid_size[2] = cascade_size;
+ dl_push_constant.max_cascades = cascades.size();
+ dl_push_constant.probe_axis_size = probe_axis_count;
+ dl_push_constant.bounce_feedback = 0.0; // this is static light, do not multibounce yet
+ dl_push_constant.y_mult = y_mult;
+ dl_push_constant.use_occlusion = uses_occlusion;
+
+ //all must be processed
+ dl_push_constant.process_offset = 0;
+ dl_push_constant.process_increment = 1;
+
+ for (uint32_t i = 0; i < p_cascade_count; i++) {
+ ERR_CONTINUE(p_cascade_indices[i] >= cascades.size());
+
+ SDFGI::Cascade &cc = cascades[p_cascade_indices[i]];
+
+ dl_push_constant.light_count = light_count[i];
+ dl_push_constant.cascade = p_cascade_indices[i];
+
+ if (dl_push_constant.light_count > 0) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_uniform_set, 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &dl_push_constant, sizeof(SDFGIShader::DirectLightPushConstant));
+ RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cc.solid_cell_dispatch_buffer, 0);
+ }
+ }
+
+ RD::get_singleton()->compute_list_end();
+
+ RD::get_singleton()->draw_command_end_label();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// GIProbeInstance
+
+void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+ uint32_t data_version = storage->gi_probe_get_data_version(probe);
+
+ // (RE)CREATE IF NEEDED
+
+ if (last_probe_data_version != data_version) {
+ //need to re-create everything
+ if (texture.is_valid()) {
+ RD::get_singleton()->free(texture);
+ RD::get_singleton()->free(write_buffer);
+ mipmaps.clear();
+ }
+
+ for (int i = 0; i < dynamic_maps.size(); i++) {
+ RD::get_singleton()->free(dynamic_maps[i].texture);
+ RD::get_singleton()->free(dynamic_maps[i].depth);
+ }
+
+ dynamic_maps.clear();
+
+ Vector3i octree_size = storage->gi_probe_get_octree_size(probe);
+
+ if (octree_size != Vector3i()) {
+ //can create a 3D texture
+ Vector<int> levels = storage->gi_probe_get_level_counts(probe);
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tf.width = octree_size.x;
+ tf.height = octree_size.y;
+ tf.depth = octree_size.z;
+ tf.texture_type = RD::TEXTURE_TYPE_3D;
+ tf.mipmaps = levels.size();
+
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+
+ texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ RD::get_singleton()->texture_clear(texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1);
+
+ {
+ int total_elements = 0;
+ for (int i = 0; i < levels.size(); i++) {
+ total_elements += levels[i];
+ }
+
+ write_buffer = RD::get_singleton()->storage_buffer_create(total_elements * 16);
+ }
+
+ for (int i = 0; i < levels.size(); i++) {
+ GIProbeInstance::Mipmap mipmap;
+ mipmap.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), texture, 0, i, RD::TEXTURE_SLICE_3D);
+ mipmap.level = levels.size() - i - 1;
+ mipmap.cell_offset = 0;
+ for (uint32_t j = 0; j < mipmap.level; j++) {
+ mipmap.cell_offset += levels[j];
+ }
+ mipmap.cell_count = levels[mipmap.level];
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 1;
+ u.ids.push_back(storage->gi_probe_get_octree_buffer(probe));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.ids.push_back(storage->gi_probe_get_data_buffer(probe));
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 4;
+ u.ids.push_back(write_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 9;
+ u.ids.push_back(storage->gi_probe_get_sdf_texture(probe));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 10;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+
+ {
+ Vector<RD::Uniform> copy_uniforms = uniforms;
+ if (i == 0) {
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 3;
+ u.ids.push_back(gi->gi_probe_lights_uniform);
+ copy_uniforms.push_back(u);
+ }
+
+ mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT], 0);
+
+ copy_uniforms = uniforms; //restore
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 5;
+ u.ids.push_back(texture);
+ copy_uniforms.push_back(u);
+ }
+ mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0);
+ } else {
+ mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP], 0);
+ }
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 5;
+ u.ids.push_back(mipmap.texture);
+ uniforms.push_back(u);
+ }
+
+ mipmap.write_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE], 0);
+
+ mipmaps.push_back(mipmap);
+ }
+
+ {
+ uint32_t dynamic_map_size = MAX(MAX(octree_size.x, octree_size.y), octree_size.z);
+ uint32_t oversample = nearest_power_of_2_templated(4);
+ int mipmap_index = 0;
+
+ while (mipmap_index < mipmaps.size()) {
+ GIProbeInstance::DynamicMap dmap;
+
+ if (oversample > 0) {
+ dmap.size = dynamic_map_size * (1 << oversample);
+ dmap.mipmap = -1;
+ oversample--;
+ } else {
+ dmap.size = dynamic_map_size >> mipmap_index;
+ dmap.mipmap = mipmap_index;
+ mipmap_index++;
+ }
+
+ RD::TextureFormat dtf;
+ dtf.width = dmap.size;
+ dtf.height = dmap.size;
+ dtf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ if (dynamic_maps.size() == 0) {
+ dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
+ dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+
+ if (dynamic_maps.size() == 0) {
+ //render depth for first one
+ dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
+ dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ }
+
+ //just use depth as-is
+ dtf.format = RD::DATA_FORMAT_R32_SFLOAT;
+ dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+
+ if (dynamic_maps.size() == 0) {
+ dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+
+ Vector<RID> fb;
+ fb.push_back(dmap.albedo);
+ fb.push_back(dmap.normal);
+ fb.push_back(dmap.orm);
+ fb.push_back(dmap.texture); //emission
+ fb.push_back(dmap.depth);
+ fb.push_back(dmap.fb_depth);
+
+ dmap.fb = RD::get_singleton()->framebuffer_create(fb);
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 3;
+ u.ids.push_back(gi->gi_probe_lights_uniform);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 5;
+ u.ids.push_back(dmap.albedo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 6;
+ u.ids.push_back(dmap.normal);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 7;
+ u.ids.push_back(dmap.orm);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 8;
+ u.ids.push_back(dmap.fb_depth);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 9;
+ u.ids.push_back(storage->gi_probe_get_sdf_texture(probe));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 10;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 11;
+ u.ids.push_back(dmap.texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 12;
+ u.ids.push_back(dmap.depth);
+ uniforms.push_back(u);
+ }
+
+ dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING], 0);
+ }
+ } else {
+ bool plot = dmap.mipmap >= 0;
+ bool write = dmap.mipmap < (mipmaps.size() - 1);
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 5;
+ u.ids.push_back(dynamic_maps[dynamic_maps.size() - 1].texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 6;
+ u.ids.push_back(dynamic_maps[dynamic_maps.size() - 1].depth);
+ uniforms.push_back(u);
+ }
+
+ if (write) {
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 7;
+ u.ids.push_back(dmap.texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 8;
+ u.ids.push_back(dmap.depth);
+ uniforms.push_back(u);
+ }
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 9;
+ u.ids.push_back(storage->gi_probe_get_sdf_texture(probe));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 10;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+
+ if (plot) {
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 11;
+ u.ids.push_back(mipmaps[dmap.mipmap].texture);
+ uniforms.push_back(u);
+ }
+ }
+
+ dmap.uniform_set = RD::get_singleton()->uniform_set_create(
+ uniforms,
+ gi->giprobe_lighting_shader_version_shaders[(write && plot) ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : (write ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT)],
+ 0);
+ }
+
+ dynamic_maps.push_back(dmap);
+ }
+ }
+ }
+
+ last_probe_data_version = data_version;
+ p_update_light_instances = true; //just in case
+
+ p_scene_render->_base_uniforms_changed();
+ }
+
+ // UDPDATE TIME
+
+ if (has_dynamic_object_data) {
+ //if it has dynamic object data, it needs to be cleared
+ RD::get_singleton()->texture_clear(texture, Color(0, 0, 0, 0), 0, mipmaps.size(), 0, 1);
+ }
+
+ uint32_t light_count = 0;
+
+ if (p_update_light_instances || p_dynamic_objects.size() > 0) {
+ light_count = MIN(gi->gi_probe_max_lights, (uint32_t)p_light_instances.size());
+
+ {
+ Transform to_cell = storage->gi_probe_get_to_cell_xform(probe);
+ Transform to_probe_xform = (transform * to_cell.affine_inverse()).affine_inverse();
+ //update lights
+
+ for (uint32_t i = 0; i < light_count; i++) {
+ GIProbeLight &l = gi->gi_probe_lights[i];
+ RID light_instance = p_light_instances[i];
+ RID light = p_scene_render->light_instance_get_base_light(light_instance);
+
+ l.type = storage->light_get_type(light);
+ if (l.type == RS::LIGHT_DIRECTIONAL && storage->light_directional_is_sky_only(light)) {
+ light_count--;
+ continue;
+ }
+
+ l.attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
+ l.energy = storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length();
+ Color color = storage->light_get_color(light).to_linear();
+ l.color[0] = color.r;
+ l.color[1] = color.g;
+ l.color[2] = color.b;
+
+ l.cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ l.inv_spot_attenuation = 1.0f / storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+
+ Transform xform = p_scene_render->light_instance_get_base_transform(light_instance);
+
+ Vector3 pos = to_probe_xform.xform(xform.origin);
+ Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_axis(2)).normalized();
+
+ l.position[0] = pos.x;
+ l.position[1] = pos.y;
+ l.position[2] = pos.z;
+
+ l.direction[0] = dir.x;
+ l.direction[1] = dir.y;
+ l.direction[2] = dir.z;
+
+ l.has_shadow = storage->light_has_shadow(light);
+ }
+
+ RD::get_singleton()->buffer_update(gi->gi_probe_lights_uniform, 0, sizeof(GIProbeLight) * light_count, gi->gi_probe_lights);
+ }
+ }
+
+ if (has_dynamic_object_data || p_update_light_instances || p_dynamic_objects.size()) {
+ // PROCESS MIPMAPS
+ if (mipmaps.size()) {
+ //can update mipmaps
+
+ Vector3i probe_size = storage->gi_probe_get_octree_size(probe);
+
+ GIProbePushConstant push_constant;
+
+ push_constant.limits[0] = probe_size.x;
+ push_constant.limits[1] = probe_size.y;
+ push_constant.limits[2] = probe_size.z;
+ push_constant.stack_size = mipmaps.size();
+ push_constant.emission_scale = 1.0;
+ push_constant.propagation = storage->gi_probe_get_propagation(probe);
+ push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(probe);
+ push_constant.light_count = light_count;
+ push_constant.aniso_strength = 0;
+
+ /* print_line("probe update to version " + itos(last_probe_version));
+ print_line("propagation " + rtos(push_constant.propagation));
+ print_line("dynrange " + rtos(push_constant.dynamic_range));
+ */
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ int passes;
+ if (p_update_light_instances) {
+ passes = storage->gi_probe_is_using_two_bounces(probe) ? 2 : 1;
+ } else {
+ passes = 1; //only re-blitting is necessary
+ }
+ int wg_size = 64;
+ int wg_limit_x = RD::get_singleton()->limit_get(RD::LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X);
+
+ for (int pass = 0; pass < passes; pass++) {
+ if (p_update_light_instances) {
+ for (int i = 0; i < mipmaps.size(); i++) {
+ if (i == 0) {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[pass == 0 ? GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT : GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]);
+ } else if (i == 1) {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP]);
+ }
+
+ if (pass == 1 || i > 0) {
+ RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done
+ }
+ if (pass == 0 || i > 0) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mipmaps[i].uniform_set, 0);
+ } else {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mipmaps[i].second_bounce_uniform_set, 0);
+ }
+
+ push_constant.cell_offset = mipmaps[i].cell_offset;
+ push_constant.cell_count = mipmaps[i].cell_count;
+
+ int wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1;
+ while (wg_todo) {
+ int wg_count = MIN(wg_todo, wg_limit_x);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1);
+ wg_todo -= wg_count;
+ push_constant.cell_offset += wg_count * wg_size;
+ }
+ }
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE]);
+
+ for (int i = 0; i < mipmaps.size(); i++) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mipmaps[i].write_uniform_set, 0);
+
+ push_constant.cell_offset = mipmaps[i].cell_offset;
+ push_constant.cell_count = mipmaps[i].cell_count;
+
+ int wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1;
+ while (wg_todo) {
+ int wg_count = MIN(wg_todo, wg_limit_x);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1);
+ wg_todo -= wg_count;
+ push_constant.cell_offset += wg_count * wg_size;
+ }
+ }
+ }
+
+ RD::get_singleton()->compute_list_end();
+ }
+ }
+
+ has_dynamic_object_data = false; //clear until dynamic object data is used again
+
+ if (p_dynamic_objects.size() && dynamic_maps.size()) {
+ Vector3i octree_size = storage->gi_probe_get_octree_size(probe);
+ int multiplier = dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z);
+
+ Transform oversample_scale;
+ oversample_scale.basis.scale(Vector3(multiplier, multiplier, multiplier));
+
+ Transform to_cell = oversample_scale * storage->gi_probe_get_to_cell_xform(probe);
+ Transform to_world_xform = transform * to_cell.affine_inverse();
+ Transform to_probe_xform = to_world_xform.affine_inverse();
+
+ AABB probe_aabb(Vector3(), octree_size);
+
+ //this could probably be better parallelized in compute..
+ for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
+ RendererSceneRender::GeometryInstance *instance = p_dynamic_objects[i];
+
+ //transform aabb to giprobe
+ AABB aabb = (to_probe_xform * p_scene_render->geometry_instance_get_transform(instance)).xform(p_scene_render->geometry_instance_get_aabb(instance));
+
+ //this needs to wrap to grid resolution to avoid jitter
+ //also extend margin a bit just in case
+ Vector3i begin = aabb.position - Vector3i(1, 1, 1);
+ Vector3i end = aabb.position + aabb.size + Vector3i(1, 1, 1);
+
+ for (int j = 0; j < 3; j++) {
+ if ((end[j] - begin[j]) & 1) {
+ end[j]++; //for half extents split, it needs to be even
+ }
+ begin[j] = MAX(begin[j], 0);
+ end[j] = MIN(end[j], octree_size[j] * multiplier);
+ }
+
+ //aabb = aabb.intersection(probe_aabb); //intersect
+ aabb.position = begin;
+ aabb.size = end - begin;
+
+ //print_line("aabb: " + aabb);
+
+ for (int j = 0; j < 6; j++) {
+ //if (j != 0 && j != 3) {
+ // continue;
+ //}
+ static const Vector3 render_z[6] = {
+ Vector3(1, 0, 0),
+ Vector3(0, 1, 0),
+ Vector3(0, 0, 1),
+ Vector3(-1, 0, 0),
+ Vector3(0, -1, 0),
+ Vector3(0, 0, -1),
+ };
+ static const Vector3 render_up[6] = {
+ Vector3(0, 1, 0),
+ Vector3(0, 0, 1),
+ Vector3(0, 1, 0),
+ Vector3(0, 1, 0),
+ Vector3(0, 0, 1),
+ Vector3(0, 1, 0),
+ };
+
+ Vector3 render_dir = render_z[j];
+ Vector3 up_dir = render_up[j];
+
+ Vector3 center = aabb.position + aabb.size * 0.5;
+ Transform xform;
+ xform.set_look_at(center - aabb.size * 0.5 * render_dir, center, up_dir);
+
+ Vector3 x_dir = xform.basis.get_axis(0).abs();
+ int x_axis = int(Vector3(0, 1, 2).dot(x_dir));
+ Vector3 y_dir = xform.basis.get_axis(1).abs();
+ int y_axis = int(Vector3(0, 1, 2).dot(y_dir));
+ Vector3 z_dir = -xform.basis.get_axis(2);
+ int z_axis = int(Vector3(0, 1, 2).dot(z_dir.abs()));
+
+ Rect2i rect(aabb.position[x_axis], aabb.position[y_axis], aabb.size[x_axis], aabb.size[y_axis]);
+ bool x_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(0)) < 0);
+ bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(1)) < 0);
+ bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(2)) > 0);
+
+ CameraMatrix cm;
+ cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]);
+
+ if (p_scene_render->cull_argument.size() == 0) {
+ p_scene_render->cull_argument.push_back(nullptr);
+ }
+ p_scene_render->cull_argument[0] = instance;
+
+ p_scene_render->_render_material(to_world_xform * xform, cm, true, p_scene_render->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size));
+
+ GIProbeDynamicPushConstant push_constant;
+ zeromem(&push_constant, sizeof(GIProbeDynamicPushConstant));
+ push_constant.limits[0] = octree_size.x;
+ push_constant.limits[1] = octree_size.y;
+ push_constant.limits[2] = octree_size.z;
+ push_constant.light_count = p_light_instances.size();
+ push_constant.x_dir[0] = x_dir[0];
+ push_constant.x_dir[1] = x_dir[1];
+ push_constant.x_dir[2] = x_dir[2];
+ push_constant.y_dir[0] = y_dir[0];
+ push_constant.y_dir[1] = y_dir[1];
+ push_constant.y_dir[2] = y_dir[2];
+ push_constant.z_dir[0] = z_dir[0];
+ push_constant.z_dir[1] = z_dir[1];
+ push_constant.z_dir[2] = z_dir[2];
+ push_constant.z_base = xform.origin[z_axis];
+ push_constant.z_sign = (z_flip ? -1.0 : 1.0);
+ push_constant.pos_multiplier = float(1.0) / multiplier;
+ push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(probe);
+ push_constant.flip_x = x_flip;
+ push_constant.flip_y = y_flip;
+ push_constant.rect_pos[0] = rect.position[0];
+ push_constant.rect_pos[1] = rect.position[1];
+ push_constant.rect_size[0] = rect.size[0];
+ push_constant.rect_size[1] = rect.size[1];
+ push_constant.prev_rect_ofs[0] = 0;
+ push_constant.prev_rect_ofs[1] = 0;
+ push_constant.prev_rect_size[0] = 0;
+ push_constant.prev_rect_size[1] = 0;
+ push_constant.on_mipmap = false;
+ push_constant.propagation = storage->gi_probe_get_propagation(probe);
+ push_constant.pad[0] = 0;
+ push_constant.pad[1] = 0;
+ push_constant.pad[2] = 0;
+
+ //process lighting
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[0].uniform_set, 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1);
+ //print_line("rect: " + itos(i) + ": " + rect);
+
+ for (int k = 1; k < dynamic_maps.size(); k++) {
+ // enlarge the rect if needed so all pixels fit when downscaled,
+ // this ensures downsampling is smooth and optimal because no pixels are left behind
+
+ //x
+ if (rect.position.x & 1) {
+ rect.size.x++;
+ push_constant.prev_rect_ofs[0] = 1; //this is used to ensure reading is also optimal
+ } else {
+ push_constant.prev_rect_ofs[0] = 0;
+ }
+ if (rect.size.x & 1) {
+ rect.size.x++;
+ }
+
+ rect.position.x >>= 1;
+ rect.size.x = MAX(1, rect.size.x >> 1);
+
+ //y
+ if (rect.position.y & 1) {
+ rect.size.y++;
+ push_constant.prev_rect_ofs[1] = 1;
+ } else {
+ push_constant.prev_rect_ofs[1] = 0;
+ }
+ if (rect.size.y & 1) {
+ rect.size.y++;
+ }
+
+ rect.position.y >>= 1;
+ rect.size.y = MAX(1, rect.size.y >> 1);
+
+ //shrink limits to ensure plot does not go outside map
+ if (dynamic_maps[k].mipmap > 0) {
+ for (int l = 0; l < 3; l++) {
+ push_constant.limits[l] = MAX(1, push_constant.limits[l] >> 1);
+ }
+ }
+
+ //print_line("rect: " + itos(i) + ": " + rect);
+ push_constant.rect_pos[0] = rect.position[0];
+ push_constant.rect_pos[1] = rect.position[1];
+ push_constant.prev_rect_size[0] = push_constant.rect_size[0];
+ push_constant.prev_rect_size[1] = push_constant.rect_size[1];
+ push_constant.rect_size[0] = rect.size[0];
+ push_constant.rect_size[1] = rect.size[1];
+ push_constant.on_mipmap = dynamic_maps[k].mipmap > 0;
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ if (dynamic_maps[k].mipmap < 0) {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE]);
+ } else if (k < dynamic_maps.size() - 1) {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT]);
+ } else {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT]);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[k].uniform_set, 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1);
+ }
+
+ RD::get_singleton()->compute_list_end();
+ }
+ }
+
+ has_dynamic_object_data = true; //clear until dynamic object data is used again
+ }
+
+ last_probe_version = storage->gi_probe_get_version(probe);
+}
+
+void RendererSceneGIRD::GIProbeInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+ if (mipmaps.size() == 0) {
+ return;
+ }
+
+ CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(storage->gi_probe_get_to_cell_xform(probe).affine_inverse());
+
+ int level = 0;
+ Vector3i octree_size = storage->gi_probe_get_octree_size(probe);
+
+ GIProbeDebugPushConstant push_constant;
+ push_constant.alpha = p_alpha;
+ push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(probe);
+ push_constant.cell_offset = mipmaps[level].cell_offset;
+ push_constant.level = level;
+
+ push_constant.bounds[0] = octree_size.x >> level;
+ push_constant.bounds[1] = octree_size.y >> level;
+ push_constant.bounds[2] = octree_size.z >> level;
+ push_constant.pad = 0;
+
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ push_constant.projection[i * 4 + j] = cam_transform.matrix[i][j];
+ }
+ }
+
+ if (gi->giprobe_debug_uniform_set.is_valid()) {
+ RD::get_singleton()->free(gi->giprobe_debug_uniform_set);
+ }
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 1;
+ u.ids.push_back(storage->gi_probe_get_data_buffer(probe));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2;
+ u.ids.push_back(texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 3;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+
+ int cell_count;
+ if (!p_emission && p_lighting && has_dynamic_object_data) {
+ cell_count = push_constant.bounds[0] * push_constant.bounds[1] * push_constant.bounds[2];
+ } else {
+ cell_count = mipmaps[level].cell_count;
+ }
+
+ gi->giprobe_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->giprobe_debug_shader_version_shaders[0], 0);
+
+ int giprobe_debug_pipeline = GI_PROBE_DEBUG_COLOR;
+ if (p_emission) {
+ giprobe_debug_pipeline = GI_PROBE_DEBUG_EMISSION;
+ } else if (p_lighting) {
+ giprobe_debug_pipeline = has_dynamic_object_data ? GI_PROBE_DEBUG_LIGHT_FULL : GI_PROBE_DEBUG_LIGHT;
+ }
+ RD::get_singleton()->draw_list_bind_render_pipeline(
+ p_draw_list,
+ gi->giprobe_debug_shader_version_pipelines[giprobe_debug_pipeline].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, gi->giprobe_debug_uniform_set, 0);
+ RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(GIProbeDebugPushConstant));
+ RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, 36);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// GIRD
+
+RendererSceneGIRD::RendererSceneGIRD() {
+ sdfgi_ray_count = RS::EnvironmentSDFGIRayCount(CLAMP(int32_t(GLOBAL_GET("rendering/global_illumination/sdfgi/probe_ray_count")), 0, int32_t(RS::ENV_SDFGI_RAY_COUNT_MAX - 1)));
+ sdfgi_frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(CLAMP(int32_t(GLOBAL_GET("rendering/global_illumination/sdfgi/frames_to_converge")), 0, int32_t(RS::ENV_SDFGI_CONVERGE_MAX - 1)));
+ sdfgi_frames_to_update_light = RS::EnvironmentSDFGIFramesToUpdateLight(CLAMP(int32_t(GLOBAL_GET("rendering/global_illumination/sdfgi/frames_to_update_lights")), 0, int32_t(RS::ENV_SDFGI_UPDATE_LIGHT_MAX - 1)));
+}
+
+RendererSceneGIRD::~RendererSceneGIRD() {
+}
+
+void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {
+ storage = p_storage;
+
+ /* GI */
+
+ {
+ //kinda complicated to compute the amount of slots, we try to use as many as we can
+
+ gi_probe_max_lights = 32;
+
+ gi_probe_lights = memnew_arr(GIProbeLight, gi_probe_max_lights);
+ gi_probe_lights_uniform = RD::get_singleton()->uniform_buffer_create(gi_probe_max_lights * sizeof(GIProbeLight));
+ gi_probe_quality = RS::GIProbeQuality(CLAMP(int(GLOBAL_GET("rendering/global_illumination/gi_probes/quality")), 0, 1));
+
+ String defines = "\n#define MAX_LIGHTS " + itos(gi_probe_max_lights) + "\n";
+
+ Vector<String> versions;
+ versions.push_back("\n#define MODE_COMPUTE_LIGHT\n");
+ versions.push_back("\n#define MODE_SECOND_BOUNCE\n");
+ versions.push_back("\n#define MODE_UPDATE_MIPMAPS\n");
+ versions.push_back("\n#define MODE_WRITE_TEXTURE\n");
+ versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_LIGHTING\n");
+ versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_WRITE\n");
+ versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n");
+ versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n#define MODE_DYNAMIC_SHRINK_WRITE\n");
+
+ giprobe_shader.initialize(versions, defines);
+ giprobe_lighting_shader_version = giprobe_shader.version_create();
+ for (int i = 0; i < GI_PROBE_SHADER_VERSION_MAX; i++) {
+ giprobe_lighting_shader_version_shaders[i] = giprobe_shader.version_get_shader(giprobe_lighting_shader_version, i);
+ giprobe_lighting_shader_version_pipelines[i] = RD::get_singleton()->compute_pipeline_create(giprobe_lighting_shader_version_shaders[i]);
+ }
+ }
+
+ {
+ String defines;
+ Vector<String> versions;
+ versions.push_back("\n#define MODE_DEBUG_COLOR\n");
+ versions.push_back("\n#define MODE_DEBUG_LIGHT\n");
+ versions.push_back("\n#define MODE_DEBUG_EMISSION\n");
+ versions.push_back("\n#define MODE_DEBUG_LIGHT\n#define MODE_DEBUG_LIGHT_FULL\n");
+
+ giprobe_debug_shader.initialize(versions, defines);
+ giprobe_debug_shader_version = giprobe_debug_shader.version_create();
+ for (int i = 0; i < GI_PROBE_DEBUG_MAX; i++) {
+ giprobe_debug_shader_version_shaders[i] = giprobe_debug_shader.version_get_shader(giprobe_debug_shader_version, i);
+
+ RD::PipelineRasterizationState rs;
+ rs.cull_mode = RD::POLYGON_CULL_FRONT;
+ RD::PipelineDepthStencilState ds;
+ ds.enable_depth_test = true;
+ ds.enable_depth_write = true;
+ ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
+
+ giprobe_debug_shader_version_pipelines[i].setup(giprobe_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
+ }
+ }
+
+ /* SDGFI */
+
+ {
+ Vector<String> preprocess_modes;
+ preprocess_modes.push_back("\n#define MODE_SCROLL\n");
+ preprocess_modes.push_back("\n#define MODE_SCROLL_OCCLUSION\n");
+ preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD\n");
+ preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD_HALF\n");
+ preprocess_modes.push_back("\n#define MODE_JUMPFLOOD\n");
+ preprocess_modes.push_back("\n#define MODE_JUMPFLOOD_OPTIMIZED\n");
+ preprocess_modes.push_back("\n#define MODE_UPSCALE_JUMP_FLOOD\n");
+ preprocess_modes.push_back("\n#define MODE_OCCLUSION\n");
+ preprocess_modes.push_back("\n#define MODE_STORE\n");
+ String defines = "\n#define OCCLUSION_SIZE " + itos(SDFGI::CASCADE_SIZE / SDFGI::PROBE_DIVISOR) + "\n";
+ sdfgi_shader.preprocess.initialize(preprocess_modes, defines);
+ sdfgi_shader.preprocess_shader = sdfgi_shader.preprocess.version_create();
+ for (int i = 0; i < SDFGIShader::PRE_PROCESS_MAX; i++) {
+ sdfgi_shader.preprocess_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, i));
+ }
+ }
+
+ {
+ //calculate tables
+ String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
+
+ Vector<String> direct_light_modes;
+ direct_light_modes.push_back("\n#define MODE_PROCESS_STATIC\n");
+ direct_light_modes.push_back("\n#define MODE_PROCESS_DYNAMIC\n");
+ sdfgi_shader.direct_light.initialize(direct_light_modes, defines);
+ sdfgi_shader.direct_light_shader = sdfgi_shader.direct_light.version_create();
+ for (int i = 0; i < SDFGIShader::DIRECT_LIGHT_MODE_MAX; i++) {
+ sdfgi_shader.direct_light_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, i));
+ }
+ }
+
+ {
+ //calculate tables
+ String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
+ defines += "\n#define SH_SIZE " + itos(SDFGI::SH_SIZE) + "\n";
+ if (p_sky->sky_use_cubemap_array) {
+ defines += "\n#define USE_CUBEMAP_ARRAY\n";
+ }
+
+ Vector<String> integrate_modes;
+ integrate_modes.push_back("\n#define MODE_PROCESS\n");
+ integrate_modes.push_back("\n#define MODE_STORE\n");
+ integrate_modes.push_back("\n#define MODE_SCROLL\n");
+ integrate_modes.push_back("\n#define MODE_SCROLL_STORE\n");
+ sdfgi_shader.integrate.initialize(integrate_modes, defines);
+ sdfgi_shader.integrate_shader = sdfgi_shader.integrate.version_create();
+
+ for (int i = 0; i < SDFGIShader::INTEGRATE_MODE_MAX; i++) {
+ sdfgi_shader.integrate_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, i));
+ }
+
+ {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 0;
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 1;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+
+ sdfgi_shader.integrate_default_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 1);
+ }
+ }
+
+ //GK
+ {
+ //calculate tables
+ String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
+ Vector<String> gi_modes;
+ gi_modes.push_back("\n#define USE_GIPROBES\n");
+ gi_modes.push_back("\n#define USE_SDFGI\n");
+ gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_GIPROBES\n");
+ gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_GIPROBES\n");
+ gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n");
+ gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_GIPROBES\n");
+
+ shader.initialize(gi_modes, defines);
+ shader_version = shader.version_create();
+ for (int i = 0; i < MODE_MAX; i++) {
+ pipelines[i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i));
+ }
+
+ sdfgi_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGIData));
+ }
+ {
+ String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
+ Vector<String> debug_modes;
+ debug_modes.push_back("");
+ sdfgi_shader.debug.initialize(debug_modes, defines);
+ sdfgi_shader.debug_shader = sdfgi_shader.debug.version_create();
+ sdfgi_shader.debug_shader_version = sdfgi_shader.debug.version_get_shader(sdfgi_shader.debug_shader, 0);
+ sdfgi_shader.debug_pipeline = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.debug_shader_version);
+ }
+ {
+ String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
+
+ Vector<String> versions;
+ versions.push_back("\n#define MODE_PROBES\n");
+ versions.push_back("\n#define MODE_VISIBILITY\n");
+
+ sdfgi_shader.debug_probes.initialize(versions, defines);
+ sdfgi_shader.debug_probes_shader = sdfgi_shader.debug_probes.version_create();
+
+ {
+ RD::PipelineRasterizationState rs;
+ rs.cull_mode = RD::POLYGON_CULL_DISABLED;
+ RD::PipelineDepthStencilState ds;
+ ds.enable_depth_test = true;
+ ds.enable_depth_write = true;
+ ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
+ for (int i = 0; i < SDFGIShader::PROBE_DEBUG_MAX; i++) {
+ RID debug_probes_shader_version = sdfgi_shader.debug_probes.version_get_shader(sdfgi_shader.debug_probes_shader, i);
+ sdfgi_shader.debug_probes_pipeline[i].setup(debug_probes_shader_version, RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
+ }
+ }
+ }
+ default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GIProbeData) * MAX_GIPROBES);
+}
+
+void RendererSceneGIRD::free() {
+ RD::get_singleton()->free(default_giprobe_buffer);
+ RD::get_singleton()->free(gi_probe_lights_uniform);
+ RD::get_singleton()->free(sdfgi_ubo);
+
+ giprobe_debug_shader.version_free(giprobe_debug_shader_version);
+ giprobe_shader.version_free(giprobe_lighting_shader_version);
+ shader.version_free(shader_version);
+ sdfgi_shader.debug_probes.version_free(sdfgi_shader.debug_probes_shader);
+ sdfgi_shader.debug.version_free(sdfgi_shader.debug_shader);
+ sdfgi_shader.direct_light.version_free(sdfgi_shader.direct_light_shader);
+ sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader);
+ sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader);
+
+ memdelete_arr(gi_probe_lights);
+}
+
+RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
+ SDFGI *sdfgi = memnew(SDFGI);
+
+ sdfgi->create(p_env, p_world_position, p_requested_history_size, this);
+
+ return sdfgi;
+}
+
+void RendererSceneGIRD::setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used, RendererSceneRenderRD *p_scene_render) {
+ r_gi_probes_used = 0;
+
+ // feels a little dirty to use our container this way but....
+ RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers);
+ ERR_FAIL_COND(rb == nullptr);
+
+ RID gi_probe_buffer = p_scene_render->render_buffers_get_gi_probe_buffer(p_render_buffers);
+
+ RD::get_singleton()->draw_command_begin_label("GIProbes Setup");
+
+ GIProbeData gi_probe_data[MAX_GIPROBES];
+
+ bool giprobes_changed = false;
+
+ Transform to_camera;
+ to_camera.origin = p_transform.origin; //only translation, make local
+
+ for (int i = 0; i < MAX_GIPROBES; i++) {
+ RID texture;
+ if (i < (int)p_gi_probes.size()) {
+ GIProbeInstance *gipi = get_probe_instance(p_gi_probes[i]);
+
+ if (gipi) {
+ texture = gipi->texture;
+ GIProbeData &gipd = gi_probe_data[i];
+
+ RID base_probe = gipi->probe;
+
+ Transform to_cell = storage->gi_probe_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera;
+
+ gipd.xform[0] = to_cell.basis.elements[0][0];
+ gipd.xform[1] = to_cell.basis.elements[1][0];
+ gipd.xform[2] = to_cell.basis.elements[2][0];
+ gipd.xform[3] = 0;
+ gipd.xform[4] = to_cell.basis.elements[0][1];
+ gipd.xform[5] = to_cell.basis.elements[1][1];
+ gipd.xform[6] = to_cell.basis.elements[2][1];
+ gipd.xform[7] = 0;
+ gipd.xform[8] = to_cell.basis.elements[0][2];
+ gipd.xform[9] = to_cell.basis.elements[1][2];
+ gipd.xform[10] = to_cell.basis.elements[2][2];
+ gipd.xform[11] = 0;
+ gipd.xform[12] = to_cell.origin.x;
+ gipd.xform[13] = to_cell.origin.y;
+ gipd.xform[14] = to_cell.origin.z;
+ gipd.xform[15] = 1;
+
+ Vector3 bounds = storage->gi_probe_get_octree_size(base_probe);
+
+ gipd.bounds[0] = bounds.x;
+ gipd.bounds[1] = bounds.y;
+ gipd.bounds[2] = bounds.z;
+
+ gipd.dynamic_range = storage->gi_probe_get_dynamic_range(base_probe) * storage->gi_probe_get_energy(base_probe);
+ gipd.bias = storage->gi_probe_get_bias(base_probe);
+ gipd.normal_bias = storage->gi_probe_get_normal_bias(base_probe);
+ gipd.blend_ambient = !storage->gi_probe_is_interior(base_probe);
+ gipd.anisotropy_strength = 0;
+ gipd.ao = storage->gi_probe_get_ao(base_probe);
+ gipd.ao_size = Math::pow(storage->gi_probe_get_ao_size(base_probe), 4.0f);
+ gipd.mipmaps = gipi->mipmaps.size();
+ }
+
+ r_gi_probes_used++;
+ }
+
+ if (texture == RID()) {
+ texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ }
+
+ if (texture != rb->gi.giprobe_textures[i]) {
+ giprobes_changed = true;
+ rb->gi.giprobe_textures[i] = texture;
+ }
+ }
+
+ if (giprobes_changed) {
+ if (RD::get_singleton()->uniform_set_is_valid(rb->gi_uniform_set)) {
+ RD::get_singleton()->free(rb->gi_uniform_set);
+ }
+ rb->gi_uniform_set = RID();
+ if (rb->volumetric_fog) {
+ if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
+ RD::get_singleton()->free(rb->volumetric_fog->uniform_set);
+ RD::get_singleton()->free(rb->volumetric_fog->uniform_set2);
+ }
+ rb->volumetric_fog->uniform_set = RID();
+ rb->volumetric_fog->uniform_set2 = RID();
+ }
+ }
+
+ if (p_gi_probes.size() > 0) {
+ RD::get_singleton()->buffer_update(gi_probe_buffer, 0, sizeof(GIProbeData) * MIN((uint64_t)MAX_GIPROBES, p_gi_probes.size()), gi_probe_data, RD::BARRIER_MASK_COMPUTE);
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+}
+
+void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, RendererSceneRenderRD *p_scene_render) {
+ RD::get_singleton()->draw_command_begin_label("GI Render");
+
+ RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers);
+ ERR_FAIL_COND(rb == nullptr);
+ RendererSceneEnvironmentRD *env = p_scene_render->environment_owner.getornull(p_environment);
+
+ if (rb->ambient_buffer.is_null() || rb->using_half_size_gi != half_resolution) {
+ if (rb->ambient_buffer.is_valid()) {
+ RD::get_singleton()->free(rb->ambient_buffer);
+ RD::get_singleton()->free(rb->reflection_buffer);
+ }
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = rb->width;
+ tf.height = rb->height;
+ if (half_resolution) {
+ tf.width >>= 1;
+ tf.height >>= 1;
+ }
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ rb->reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->using_half_size_gi = half_resolution;
+
+ p_scene_render->_render_buffers_uniform_set_changed(p_render_buffers);
+ }
+
+ PushConstant push_constant;
+
+ push_constant.screen_size[0] = rb->width;
+ push_constant.screen_size[1] = rb->height;
+ push_constant.z_near = p_projection.get_z_near();
+ push_constant.z_far = p_projection.get_z_far();
+ push_constant.orthogonal = p_projection.is_orthogonal();
+ push_constant.proj_info[0] = -2.0f / (rb->width * p_projection.matrix[0][0]);
+ push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]);
+ push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0];
+ push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
+ push_constant.max_giprobes = MIN((uint64_t)MAX_GIPROBES, p_gi_probes.size());
+ push_constant.high_quality_vct = gi_probe_quality == RS::GI_PROBE_QUALITY_HIGH;
+
+ bool use_sdfgi = rb->sdfgi != nullptr;
+ bool use_giprobes = push_constant.max_giprobes > 0;
+
+ if (env) {
+ push_constant.ao_color[0] = env->ao_color.r;
+ push_constant.ao_color[1] = env->ao_color.g;
+ push_constant.ao_color[2] = env->ao_color.b;
+ } else {
+ push_constant.ao_color[0] = 0;
+ push_constant.ao_color[1] = 0;
+ push_constant.ao_color[2] = 0;
+ }
+
+ push_constant.cam_rotation[0] = p_transform.basis[0][0];
+ push_constant.cam_rotation[1] = p_transform.basis[1][0];
+ push_constant.cam_rotation[2] = p_transform.basis[2][0];
+ push_constant.cam_rotation[3] = 0;
+ push_constant.cam_rotation[4] = p_transform.basis[0][1];
+ push_constant.cam_rotation[5] = p_transform.basis[1][1];
+ push_constant.cam_rotation[6] = p_transform.basis[2][1];
+ push_constant.cam_rotation[7] = 0;
+ push_constant.cam_rotation[8] = p_transform.basis[0][2];
+ push_constant.cam_rotation[9] = p_transform.basis[1][2];
+ push_constant.cam_rotation[10] = p_transform.basis[2][2];
+ push_constant.cam_rotation[11] = 0;
+
+ if (rb->gi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->gi_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
+ u.ids.push_back(rb->sdfgi->cascades[j].sdf_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
+ u.ids.push_back(rb->sdfgi->cascades[j].light_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 3;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
+ u.ids.push_back(rb->sdfgi->cascades[j].light_aniso_0_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
+ u.ids.push_back(rb->sdfgi->cascades[j].light_aniso_1_tex);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 5;
+ if (rb->sdfgi) {
+ u.ids.push_back(rb->sdfgi->occlusion_texture);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 6;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 7;
+ u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 9;
+ u.ids.push_back(rb->ambient_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 10;
+ u.ids.push_back(rb->reflection_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 11;
+ if (rb->sdfgi) {
+ u.ids.push_back(rb->sdfgi->lightprobe_texture);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 12;
+ u.ids.push_back(rb->depth_texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 13;
+ u.ids.push_back(p_normal_roughness_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 14;
+ RID buffer = p_gi_probe_buffer.is_valid() ? p_gi_probe_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+ u.ids.push_back(buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 15;
+ u.ids.push_back(sdfgi_ubo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 16;
+ u.ids.push_back(rb->gi.giprobe_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 17;
+ for (int i = 0; i < MAX_GIPROBES; i++) {
+ u.ids.push_back(rb->gi.giprobe_textures[i]);
+ }
+ uniforms.push_back(u);
+ }
+
+ rb->gi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
+ }
+
+ Mode mode;
+
+ if (rb->using_half_size_gi) {
+ mode = (use_sdfgi && use_giprobes) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_GIPROBE);
+ } else {
+ mode = (use_sdfgi && use_giprobes) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_GIPROBE);
+ }
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->gi_uniform_set, 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
+
+ if (rb->using_half_size_gi) {
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width >> 1, rb->height >> 1, 1);
+ } else {
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1);
+ }
+ //do barrier later to allow oeverlap
+ //RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //no barriers, let other compute, raster and transfer happen at the same time
+ RD::get_singleton()->draw_command_end_label();
+}
+
+RID RendererSceneGIRD::gi_probe_instance_create(RID p_base) {
+ GIProbeInstance gi_probe;
+ gi_probe.gi = this;
+ gi_probe.storage = storage;
+ gi_probe.probe = p_base;
+ RID rid = gi_probe_instance_owner.make_rid(gi_probe);
+ return rid;
+}
+
+void RendererSceneGIRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {
+ GIProbeInstance *gi_probe = get_probe_instance(p_probe);
+ ERR_FAIL_COND(!gi_probe);
+
+ gi_probe->transform = p_xform;
+}
+
+bool RendererSceneGIRD::gi_probe_needs_update(RID p_probe) const {
+ GIProbeInstance *gi_probe = get_probe_instance(p_probe);
+ ERR_FAIL_COND_V(!gi_probe, false);
+
+ return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
+}
+
+void RendererSceneGIRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+ GIProbeInstance *gi_probe = get_probe_instance(p_probe);
+ ERR_FAIL_COND(!gi_probe);
+
+ gi_probe->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render);
+}
+
+void RendererSceneGIRD::debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+ GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_gi_probe);
+ ERR_FAIL_COND(!gi_probe);
+
+ gi_probe->debug(p_draw_list, p_framebuffer, p_camera_with_transform, p_lighting, p_emission, p_alpha);
+}
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
new file mode 100644
index 0000000000..c0f3318538
--- /dev/null
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
@@ -0,0 +1,668 @@
+/*************************************************************************/
+/* renderer_scene_gi_rd.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RENDERING_SERVER_SCENE_GI_RD_H
+#define RENDERING_SERVER_SCENE_GI_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
+#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
+#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/renderer_rd/shaders/gi.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/giprobe.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/giprobe_debug.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering/rendering_device.h"
+
+// Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
+class RendererSceneRenderRD;
+
+class RendererSceneGIRD {
+private:
+ RendererStorageRD *storage;
+
+ /* GIPROBE INSTANCE */
+
+ struct GIProbeLight {
+ uint32_t type;
+ float energy;
+ float radius;
+ float attenuation;
+
+ float color[3];
+ float cos_spot_angle;
+
+ float position[3];
+ float inv_spot_attenuation;
+
+ float direction[3];
+ uint32_t has_shadow;
+ };
+
+ struct GIProbePushConstant {
+ int32_t limits[3];
+ uint32_t stack_size;
+
+ float emission_scale;
+ float propagation;
+ float dynamic_range;
+ uint32_t light_count;
+
+ uint32_t cell_offset;
+ uint32_t cell_count;
+ float aniso_strength;
+ uint32_t pad;
+ };
+
+ struct GIProbeDynamicPushConstant {
+ int32_t limits[3];
+ uint32_t light_count;
+ int32_t x_dir[3];
+ float z_base;
+ int32_t y_dir[3];
+ float z_sign;
+ int32_t z_dir[3];
+ float pos_multiplier;
+ uint32_t rect_pos[2];
+ uint32_t rect_size[2];
+ uint32_t prev_rect_ofs[2];
+ uint32_t prev_rect_size[2];
+ uint32_t flip_x;
+ uint32_t flip_y;
+ float dynamic_range;
+ uint32_t on_mipmap;
+ float propagation;
+ float pad[3];
+ };
+
+ GIProbeLight *gi_probe_lights;
+ uint32_t gi_probe_max_lights;
+ RID gi_probe_lights_uniform;
+
+ enum {
+ GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT,
+ GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE,
+ GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP,
+ GI_PROBE_SHADER_VERSION_WRITE_TEXTURE,
+ GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING,
+ GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE,
+ GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT,
+ GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT,
+ GI_PROBE_SHADER_VERSION_MAX
+ };
+
+ GiprobeShaderRD giprobe_shader;
+ RID giprobe_lighting_shader_version;
+ RID giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_MAX];
+ RID giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_MAX];
+
+ enum {
+ GI_PROBE_DEBUG_COLOR,
+ GI_PROBE_DEBUG_LIGHT,
+ GI_PROBE_DEBUG_EMISSION,
+ GI_PROBE_DEBUG_LIGHT_FULL,
+ GI_PROBE_DEBUG_MAX
+ };
+
+ struct GIProbeDebugPushConstant {
+ float projection[16];
+ uint32_t cell_offset;
+ float dynamic_range;
+ float alpha;
+ uint32_t level;
+ int32_t bounds[3];
+ uint32_t pad;
+ };
+
+ GiprobeDebugShaderRD giprobe_debug_shader;
+ RID giprobe_debug_shader_version;
+ RID giprobe_debug_shader_version_shaders[GI_PROBE_DEBUG_MAX];
+ PipelineCacheRD giprobe_debug_shader_version_pipelines[GI_PROBE_DEBUG_MAX];
+ RID giprobe_debug_uniform_set;
+
+ /* SDFGI */
+
+ struct SDFGIShader {
+ enum SDFGIPreprocessShaderVersion {
+ PRE_PROCESS_SCROLL,
+ PRE_PROCESS_SCROLL_OCCLUSION,
+ PRE_PROCESS_JUMP_FLOOD_INITIALIZE,
+ PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF,
+ PRE_PROCESS_JUMP_FLOOD,
+ PRE_PROCESS_JUMP_FLOOD_OPTIMIZED,
+ PRE_PROCESS_JUMP_FLOOD_UPSCALE,
+ PRE_PROCESS_OCCLUSION,
+ PRE_PROCESS_STORE,
+ PRE_PROCESS_MAX
+ };
+
+ struct PreprocessPushConstant {
+ int32_t scroll[3];
+ int32_t grid_size;
+
+ int32_t probe_offset[3];
+ int32_t step_size;
+
+ int32_t half_size;
+ uint32_t occlusion_index;
+ int32_t cascade;
+ uint32_t pad;
+ };
+
+ SdfgiPreprocessShaderRD preprocess;
+ RID preprocess_shader;
+ RID preprocess_pipeline[PRE_PROCESS_MAX];
+
+ struct DebugPushConstant {
+ float grid_size[3];
+ uint32_t max_cascades;
+
+ int32_t screen_size[2];
+ uint32_t use_occlusion;
+ float y_mult;
+
+ float cam_extent[3];
+ uint32_t probe_axis_size;
+
+ float cam_transform[16];
+ };
+
+ SdfgiDebugShaderRD debug;
+ RID debug_shader;
+ RID debug_shader_version;
+ RID debug_pipeline;
+
+ enum ProbeDebugMode {
+ PROBE_DEBUG_PROBES,
+ PROBE_DEBUG_VISIBILITY,
+ PROBE_DEBUG_MAX
+ };
+
+ struct DebugProbesPushConstant {
+ float projection[16];
+
+ uint32_t band_power;
+ uint32_t sections_in_band;
+ uint32_t band_mask;
+ float section_arc;
+
+ float grid_size[3];
+ uint32_t cascade;
+
+ uint32_t pad;
+ float y_mult;
+ int32_t probe_debug_index;
+ int32_t probe_axis_size;
+ };
+
+ SdfgiDebugProbesShaderRD debug_probes;
+ RID debug_probes_shader;
+ RID debug_probes_shader_version;
+
+ PipelineCacheRD debug_probes_pipeline[PROBE_DEBUG_MAX];
+
+ struct Light {
+ float color[3];
+ float energy;
+
+ float direction[3];
+ uint32_t has_shadow;
+
+ float position[3];
+ float attenuation;
+
+ uint32_t type;
+ float cos_spot_angle;
+ float inv_spot_attenuation;
+ float radius;
+
+ float shadow_color[4];
+ };
+
+ struct DirectLightPushConstant {
+ float grid_size[3];
+ uint32_t max_cascades;
+
+ uint32_t cascade;
+ uint32_t light_count;
+ uint32_t process_offset;
+ uint32_t process_increment;
+
+ int32_t probe_axis_size;
+ float bounce_feedback;
+ float y_mult;
+ uint32_t use_occlusion;
+ };
+
+ enum {
+ DIRECT_LIGHT_MODE_STATIC,
+ DIRECT_LIGHT_MODE_DYNAMIC,
+ DIRECT_LIGHT_MODE_MAX
+ };
+ SdfgiDirectLightShaderRD direct_light;
+ RID direct_light_shader;
+ RID direct_light_pipeline[DIRECT_LIGHT_MODE_MAX];
+
+ enum {
+ INTEGRATE_MODE_PROCESS,
+ INTEGRATE_MODE_STORE,
+ INTEGRATE_MODE_SCROLL,
+ INTEGRATE_MODE_SCROLL_STORE,
+ INTEGRATE_MODE_MAX
+ };
+ struct IntegratePushConstant {
+ enum {
+ SKY_MODE_DISABLED,
+ SKY_MODE_COLOR,
+ SKY_MODE_SKY,
+ };
+
+ float grid_size[3];
+ uint32_t max_cascades;
+
+ uint32_t probe_axis_size;
+ uint32_t cascade;
+ uint32_t history_index;
+ uint32_t history_size;
+
+ uint32_t ray_count;
+ float ray_bias;
+ int32_t image_size[2];
+
+ int32_t world_offset[3];
+ uint32_t sky_mode;
+
+ int32_t scroll[3];
+ float sky_energy;
+
+ float sky_color[3];
+ float y_mult;
+
+ uint32_t store_ambient_texture;
+ uint32_t pad[3];
+ };
+
+ SdfgiIntegrateShaderRD integrate;
+ RID integrate_shader;
+ RID integrate_pipeline[INTEGRATE_MODE_MAX];
+
+ RID integrate_default_sky_uniform_set;
+
+ } sdfgi_shader;
+
+public:
+ /* GIPROBE INSTANCE */
+
+ //@TODO GIProbeInstance is still directly used in the render code, we'll address this when we refactor the render code itself.
+
+ struct GIProbeInstance {
+ // access to our containers
+ RendererStorageRD *storage;
+ RendererSceneGIRD *gi;
+
+ RID probe;
+ RID texture;
+ RID write_buffer;
+
+ struct Mipmap {
+ RID texture;
+ RID uniform_set;
+ RID second_bounce_uniform_set;
+ RID write_uniform_set;
+ uint32_t level;
+ uint32_t cell_offset;
+ uint32_t cell_count;
+ };
+ Vector<Mipmap> mipmaps;
+
+ struct DynamicMap {
+ RID texture; //color normally, or emission on first pass
+ RID fb_depth; //actual depth buffer for the first pass, float depth for later passes
+ RID depth; //actual depth buffer for the first pass, float depth for later passes
+ RID normal; //normal buffer for the first pass
+ RID albedo; //emission buffer for the first pass
+ RID orm; //orm buffer for the first pass
+ RID fb; //used for rendering, only valid on first map
+ RID uniform_set;
+ uint32_t size;
+ int mipmap; // mipmap to write to, -1 if no mipmap assigned
+ };
+
+ Vector<DynamicMap> dynamic_maps;
+
+ int slot = -1;
+ uint32_t last_probe_version = 0;
+ uint32_t last_probe_data_version = 0;
+
+ //uint64_t last_pass = 0;
+ uint32_t render_index = 0;
+
+ bool has_dynamic_object_data = false;
+
+ Transform transform;
+
+ void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
+ void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+ };
+
+ mutable RID_Owner<GIProbeInstance> gi_probe_instance_owner;
+
+ _FORCE_INLINE_ GIProbeInstance *get_probe_instance(RID p_probe) const {
+ return gi_probe_instance_owner.getornull(p_probe);
+ };
+
+ _FORCE_INLINE_ RID gi_probe_instance_get_texture(RID p_probe) {
+ GIProbeInstance *gi_probe = get_probe_instance(p_probe);
+ ERR_FAIL_COND_V(!gi_probe, RID());
+ return gi_probe->texture;
+ };
+
+ RS::GIProbeQuality gi_probe_quality = RS::GI_PROBE_QUALITY_HIGH;
+
+ /* SDFGI */
+
+ struct SDFGI {
+ enum {
+ MAX_CASCADES = 8,
+ CASCADE_SIZE = 128,
+ PROBE_DIVISOR = 16,
+ ANISOTROPY_SIZE = 6,
+ MAX_DYNAMIC_LIGHTS = 128,
+ MAX_STATIC_LIGHTS = 1024,
+ LIGHTPROBE_OCT_SIZE = 6,
+ SH_SIZE = 16
+ };
+
+ struct Cascade {
+ struct UBO {
+ float offset[3];
+ float to_cell;
+ int32_t probe_offset[3];
+ uint32_t pad;
+ };
+
+ //cascade blocks are full-size for volume (128^3), half size for albedo/emission
+ RID sdf_tex;
+ RID light_tex;
+ RID light_aniso_0_tex;
+ RID light_aniso_1_tex;
+
+ RID light_data;
+ RID light_aniso_0_data;
+ RID light_aniso_1_data;
+
+ struct SolidCell { // this struct is unused, but remains as reference for size
+ uint32_t position;
+ uint32_t albedo;
+ uint32_t static_light;
+ uint32_t static_light_aniso;
+ };
+
+ RID solid_cell_dispatch_buffer; //buffer for indirect compute dispatch
+ RID solid_cell_buffer;
+
+ RID lightprobe_history_tex;
+ RID lightprobe_average_tex;
+
+ float cell_size;
+ Vector3i position;
+
+ static const Vector3i DIRTY_ALL;
+ Vector3i dirty_regions; //(0,0,0 is not dirty, negative is refresh from the end, DIRTY_ALL is refresh all.
+
+ RID sdf_store_uniform_set;
+ RID sdf_direct_light_uniform_set;
+ RID scroll_uniform_set;
+ RID scroll_occlusion_uniform_set;
+ RID integrate_uniform_set;
+ RID lights_buffer;
+
+ bool all_dynamic_lights_dirty = true;
+ };
+
+ // access to our containers
+ RendererStorageRD *storage;
+ RendererSceneGIRD *gi;
+
+ // used for rendering (voxelization)
+ RID render_albedo;
+ RID render_emission;
+ RID render_emission_aniso;
+ RID render_occlusion[8];
+ RID render_geom_facing;
+
+ RID render_sdf[2];
+ RID render_sdf_half[2];
+
+ // used for ping pong processing in cascades
+ RID sdf_initialize_uniform_set;
+ RID sdf_initialize_half_uniform_set;
+ RID jump_flood_uniform_set[2];
+ RID jump_flood_half_uniform_set[2];
+ RID sdf_upscale_uniform_set;
+ int upscale_jfa_uniform_set_index;
+ RID occlusion_uniform_set;
+
+ uint32_t cascade_size = 128;
+
+ LocalVector<Cascade> cascades;
+
+ RID lightprobe_texture;
+ RID lightprobe_data;
+ RID occlusion_texture;
+ RID occlusion_data;
+ RID ambient_texture; //integrates with volumetric fog
+
+ RID lightprobe_history_scroll; //used for scrolling lightprobes
+ RID lightprobe_average_scroll; //used for scrolling lightprobes
+
+ uint32_t history_size = 0;
+ float solid_cell_ratio = 0;
+ uint32_t solid_cell_count = 0;
+
+ RS::EnvironmentSDFGICascades cascade_mode;
+ float min_cell_size = 0;
+ uint32_t probe_axis_count = 0; //amount of probes per axis, this is an odd number because it encloses endpoints
+
+ RID debug_uniform_set;
+ RID debug_probes_uniform_set;
+ RID cascades_ubo;
+
+ bool uses_occlusion = false;
+ float bounce_feedback = 0.0;
+ bool reads_sky = false;
+ float energy = 1.0;
+ float normal_bias = 1.1;
+ float probe_bias = 1.1;
+ RS::EnvironmentSDFGIYScale y_scale_mode = RS::ENV_SDFGI_Y_SCALE_DISABLED;
+
+ float y_mult = 1.0;
+
+ uint32_t render_pass = 0;
+
+ int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically
+ RID integrate_sky_uniform_set;
+
+ void create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi);
+ void erase();
+ void update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position);
+ void update_light();
+ void update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky);
+ void store_probes();
+ int get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const;
+ void update_cascades();
+
+ void debug_draw(const CameraMatrix &p_projection, const Transform &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture);
+ void debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
+
+ void pre_process_gi(const Transform &p_transform, RendererSceneRenderRD *p_scene_render);
+ void render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render);
+ void render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
+ };
+
+ RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16;
+ RS::EnvironmentSDFGIFramesToConverge sdfgi_frames_to_converge = RS::ENV_SDFGI_CONVERGE_IN_10_FRAMES;
+ RS::EnvironmentSDFGIFramesToUpdateLight sdfgi_frames_to_update_light = RS::ENV_SDFGI_UPDATE_LIGHT_IN_4_FRAMES;
+
+ float sdfgi_solid_cell_ratio = 0.25;
+ Vector3 sdfgi_debug_probe_pos;
+ Vector3 sdfgi_debug_probe_dir;
+ bool sdfgi_debug_probe_enabled = false;
+ Vector3i sdfgi_debug_probe_index;
+
+ /* SDFGI UPDATE */
+
+ int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; }
+
+ /* GI */
+ enum {
+ MAX_GIPROBES = 8
+ };
+
+ // Struct for use in render buffer
+ struct RenderBuffersGI {
+ RID giprobe_textures[MAX_GIPROBES];
+ RID giprobe_buffer;
+
+ RID full_buffer;
+ RID full_dispatch;
+ RID full_mask;
+ };
+
+ struct SDFGIData {
+ float grid_size[3];
+ uint32_t max_cascades;
+
+ uint32_t use_occlusion;
+ int32_t probe_axis_size;
+ float probe_to_uvw;
+ float normal_bias;
+
+ float lightprobe_tex_pixel_size[3];
+ float energy;
+
+ float lightprobe_uv_offset[3];
+ float y_mult;
+
+ float occlusion_clamp[3];
+ uint32_t pad3;
+
+ float occlusion_renormalize[3];
+ uint32_t pad4;
+
+ float cascade_probe_size[3];
+ uint32_t pad5;
+
+ struct ProbeCascadeData {
+ float position[3]; //offset of (0,0,0) in world coordinates
+ float to_probe; // 1/bounds * grid_size
+ int32_t probe_world_offset[3];
+ float to_cell; // 1/bounds * grid_size
+ };
+
+ ProbeCascadeData cascades[SDFGI::MAX_CASCADES];
+ };
+
+ struct GIProbeData {
+ float xform[16];
+ float bounds[3];
+ float dynamic_range;
+
+ float bias;
+ float normal_bias;
+ uint32_t blend_ambient;
+ uint32_t texture_slot;
+
+ float anisotropy_strength;
+ float ao;
+ float ao_size;
+ uint32_t mipmaps;
+ };
+
+ struct PushConstant {
+ int32_t screen_size[2];
+ float z_near;
+ float z_far;
+
+ float proj_info[4];
+ float ao_color[3];
+ uint32_t max_giprobes;
+
+ uint32_t high_quality_vct;
+ uint32_t orthogonal;
+ uint32_t pad[2];
+
+ float cam_rotation[12];
+ };
+
+ RID sdfgi_ubo;
+ enum Mode {
+ MODE_GIPROBE,
+ MODE_SDFGI,
+ MODE_COMBINED,
+ MODE_HALF_RES_GIPROBE,
+ MODE_HALF_RES_SDFGI,
+ MODE_HALF_RES_COMBINED,
+ MODE_MAX
+ };
+
+ RID default_giprobe_buffer;
+
+ bool half_resolution = false;
+ GiShaderRD shader;
+ RID shader_version;
+ RID pipelines[MODE_MAX];
+
+ RendererSceneGIRD();
+ ~RendererSceneGIRD();
+
+ void init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky);
+ void free();
+
+ SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
+
+ void setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used, RendererSceneRenderRD *p_scene_render);
+ void process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, RendererSceneRenderRD *p_scene_render);
+
+ RID gi_probe_instance_create(RID p_base);
+ void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
+ bool gi_probe_needs_update(RID p_probe) const;
+ void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
+ void debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+};
+
+#endif /* !RENDERING_SERVER_SCENE_GI_RD_H */
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp b/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.cpp
index a20a5073c3..7a19495f48 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene_render_forward.cpp */
+/* renderer_scene_render_forward_clustered.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "renderer_scene_render_forward.h"
+#include "renderer_scene_render_forward_clustered.h"
#include "core/config/project_settings.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_server_default.h"
/* SCENE SHADER */
-void RendererSceneRenderForward::ShaderData::set_code(const String &p_code) {
+void RendererSceneRenderForwardClustered::ShaderData::set_code(const String &p_code) {
//compile
code = p_code;
@@ -123,7 +123,7 @@ void RendererSceneRenderForward::ShaderData::set_code(const String &p_code) {
actions.uniforms = &uniforms;
- RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton;
+ RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton;
Error err = scene_singleton->shader.compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
@@ -257,7 +257,7 @@ void RendererSceneRenderForward::ShaderData::set_code(const String &p_code) {
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j];
for (int k = 0; k < SHADER_VERSION_MAX; k++) {
- if (!static_cast<RendererSceneRenderForward *>(singleton)->shader.scene_shader.is_variant_enabled(k)) {
+ if (!static_cast<RendererSceneRenderForwardClustered *>(singleton)->shader.scene_shader.is_variant_enabled(k)) {
continue;
}
RD::PipelineRasterizationState raster_state;
@@ -324,7 +324,7 @@ void RendererSceneRenderForward::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererSceneRenderForward::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RendererSceneRenderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
if (!p_texture.is_valid()) {
default_texture_params.erase(p_name);
} else {
@@ -332,7 +332,7 @@ void RendererSceneRenderForward::ShaderData::set_default_texture_param(const Str
}
}
-void RendererSceneRenderForward::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void RendererSceneRenderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
@@ -354,7 +354,7 @@ void RendererSceneRenderForward::ShaderData::get_param_list(List<PropertyInfo> *
}
}
-void RendererSceneRenderForward::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererSceneRenderForwardClustered::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
@@ -369,7 +369,7 @@ void RendererSceneRenderForward::ShaderData::get_instance_param_list(List<Render
}
}
-bool RendererSceneRenderForward::ShaderData::is_param_texture(const StringName &p_param) const {
+bool RendererSceneRenderForwardClustered::ShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
@@ -377,15 +377,15 @@ bool RendererSceneRenderForward::ShaderData::is_param_texture(const StringName &
return uniforms[p_param].texture_order >= 0;
}
-bool RendererSceneRenderForward::ShaderData::is_animated() const {
+bool RendererSceneRenderForwardClustered::ShaderData::is_animated() const {
return false;
}
-bool RendererSceneRenderForward::ShaderData::casts_shadows() const {
+bool RendererSceneRenderForwardClustered::ShaderData::casts_shadows() const {
return false;
}
-Variant RendererSceneRenderForward::ShaderData::get_default_parameter(const StringName &p_parameter) const {
+Variant RendererSceneRenderForwardClustered::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;
@@ -394,19 +394,19 @@ Variant RendererSceneRenderForward::ShaderData::get_default_parameter(const Stri
return Variant();
}
-RS::ShaderNativeSourceCode RendererSceneRenderForward::ShaderData::get_native_source_code() const {
- RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton;
+RS::ShaderNativeSourceCode RendererSceneRenderForwardClustered::ShaderData::get_native_source_code() const {
+ RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton;
return scene_singleton->shader.scene_shader.version_get_native_source_code(version);
}
-RendererSceneRenderForward::ShaderData::ShaderData() {
+RendererSceneRenderForwardClustered::ShaderData::ShaderData() {
valid = false;
uses_screen_texture = false;
}
-RendererSceneRenderForward::ShaderData::~ShaderData() {
- RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton;
+RendererSceneRenderForwardClustered::ShaderData::~ShaderData() {
+ RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton;
ERR_FAIL_COND(!scene_singleton);
//pipeline variants will clear themselves if shader is gone
if (version.is_valid()) {
@@ -414,21 +414,21 @@ RendererSceneRenderForward::ShaderData::~ShaderData() {
}
}
-RendererStorageRD::ShaderData *RendererSceneRenderForward::_create_shader_func() {
+RendererStorageRD::ShaderData *RendererSceneRenderForwardClustered::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
return shader_data;
}
-void RendererSceneRenderForward::MaterialData::set_render_priority(int p_priority) {
+void RendererSceneRenderForwardClustered::MaterialData::set_render_priority(int p_priority) {
priority = p_priority - RS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits
}
-void RendererSceneRenderForward::MaterialData::set_next_pass(RID p_pass) {
+void RendererSceneRenderForwardClustered::MaterialData::set_next_pass(RID p_pass) {
next_pass = p_pass;
}
-void RendererSceneRenderForward::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton;
+void RendererSceneRenderForwardClustered::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton;
if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
p_uniform_dirty = true;
@@ -453,7 +453,7 @@ void RendererSceneRenderForward::MaterialData::update_parameters(const Map<Strin
//check whether buffer changed
if (p_uniform_dirty && ubo_data.size()) {
update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
- RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
+ RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), RD::BARRIER_MASK_RASTER);
}
uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
@@ -507,7 +507,7 @@ void RendererSceneRenderForward::MaterialData::update_parameters(const Map<Strin
uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET);
}
-RendererSceneRenderForward::MaterialData::~MaterialData() {
+RendererSceneRenderForwardClustered::MaterialData::~MaterialData() {
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
RD::get_singleton()->free(uniform_set);
}
@@ -517,7 +517,7 @@ RendererSceneRenderForward::MaterialData::~MaterialData() {
}
}
-RendererStorageRD::MaterialData *RendererSceneRenderForward::_create_material_func(ShaderData *p_shader) {
+RendererStorageRD::MaterialData *RendererSceneRenderForwardClustered::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
material_data->last_frame = false;
@@ -525,11 +525,11 @@ RendererStorageRD::MaterialData *RendererSceneRenderForward::_create_material_fu
return material_data;
}
-RendererSceneRenderForward::RenderBufferDataForward::~RenderBufferDataForward() {
+RendererSceneRenderForwardClustered::RenderBufferDataForward::~RenderBufferDataForward() {
clear();
}
-void RendererSceneRenderForward::RenderBufferDataForward::ensure_specular() {
+void RendererSceneRenderForwardClustered::RenderBufferDataForward::ensure_specular() {
if (!specular.is_valid()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
@@ -583,7 +583,7 @@ void RendererSceneRenderForward::RenderBufferDataForward::ensure_specular() {
}
}
-void RendererSceneRenderForward::RenderBufferDataForward::ensure_giprobe() {
+void RendererSceneRenderForwardClustered::RenderBufferDataForward::ensure_giprobe() {
if (!giprobe_buffer.is_valid()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8G8_UINT;
@@ -619,7 +619,7 @@ void RendererSceneRenderForward::RenderBufferDataForward::ensure_giprobe() {
}
}
-void RendererSceneRenderForward::RenderBufferDataForward::clear() {
+void RendererSceneRenderForwardClustered::RenderBufferDataForward::clear() {
if (giprobe_buffer != RID()) {
RD::get_singleton()->free(giprobe_buffer);
giprobe_buffer = RID();
@@ -673,7 +673,7 @@ void RendererSceneRenderForward::RenderBufferDataForward::clear() {
}
}
-void RendererSceneRenderForward::RenderBufferDataForward::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) {
+void RendererSceneRenderForwardClustered::RenderBufferDataForward::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) {
clear();
msaa = p_msaa;
@@ -740,7 +740,7 @@ void RendererSceneRenderForward::RenderBufferDataForward::configure(RID p_color_
}
}
-void RendererSceneRenderForward::_allocate_normal_roughness_texture(RenderBufferDataForward *rb) {
+void RendererSceneRenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForward *rb) {
if (rb->normal_roughness_buffer.is_valid()) {
return;
}
@@ -778,11 +778,11 @@ void RendererSceneRenderForward::_allocate_normal_roughness_texture(RenderBuffer
_render_buffers_clear_uniform_set(rb);
}
-RendererSceneRenderRD::RenderBufferData *RendererSceneRenderForward::_create_render_buffer_data() {
+RendererSceneRenderRD::RenderBufferData *RendererSceneRenderForwardClustered::_create_render_buffer_data() {
return memnew(RenderBufferDataForward);
}
-bool RendererSceneRenderForward::free(RID p_rid) {
+bool RendererSceneRenderForwardClustered::free(RID p_rid) {
if (RendererSceneRenderRD::free(p_rid)) {
return true;
}
@@ -791,8 +791,8 @@ bool RendererSceneRenderForward::free(RID p_rid) {
/// RENDERING ///
-template <RendererSceneRenderForward::PassMode p_pass_mode>
-void RendererSceneRenderForward::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
+template <RendererSceneRenderForwardClustered::PassMode p_pass_mode>
+void RendererSceneRenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
@@ -810,10 +810,20 @@ void RendererSceneRenderForward::_render_list_template(RenderingDevice::DrawList
bool shadow_pass = (p_params->pass_mode == PASS_MODE_SHADOW) || (p_params->pass_mode == PASS_MODE_SHADOW_DP);
- float old_offset[2] = { 0, 0 };
+ SceneState::PushConstant push_constant;
+
+ if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
+ push_constant.uv_offset = Math::make_half_float(p_params->uv_offset.y) << 16;
+ push_constant.uv_offset |= Math::make_half_float(p_params->uv_offset.x);
+ } else {
+ push_constant.uv_offset = 0;
+ }
for (uint32_t i = p_from_element; i < p_to_element; i++) {
const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i];
+ const RenderElementInfo &element_info = p_params->element_info[i];
+
+ push_constant.base_index = i + p_params->element_offset;
RID material_uniform_set;
ShaderData *shader;
@@ -834,13 +844,6 @@ void RendererSceneRenderForward::_render_list_template(RenderingDevice::DrawList
continue;
}
- if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
- old_offset[0] = surf->owner->push_constant.lightmap_uv_scale[0];
- old_offset[1] = surf->owner->push_constant.lightmap_uv_scale[1];
- surf->owner->push_constant.lightmap_uv_scale[0] = p_params->uv_offset.x;
- surf->owner->push_constant.lightmap_uv_scale[1] = p_params->uv_offset.y;
- }
-
//find cull variant
ShaderData::CullVariant cull_variant;
@@ -862,16 +865,16 @@ void RendererSceneRenderForward::_render_list_template(RenderingDevice::DrawList
switch (p_params->pass_mode) {
case PASS_MODE_COLOR:
case PASS_MODE_COLOR_TRANSPARENT: {
- if (surf->sort.uses_lightmap) {
+ if (element_info.uses_lightmap) {
shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS;
- } else if (surf->sort.uses_forward_gi) {
+ } else if (element_info.uses_forward_gi) {
shader_version = SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI;
} else {
shader_version = SHADER_VERSION_COLOR_PASS;
}
} break;
case PASS_MODE_COLOR_SPECULAR: {
- if (surf->sort.uses_lightmap) {
+ if (element_info.uses_lightmap) {
shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR;
} else {
shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
@@ -913,31 +916,7 @@ void RendererSceneRenderForward::_render_list_template(RenderingDevice::DrawList
storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
}
- if (p_params->screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(mesh_surface)) {
- //lod
- Vector3 support_min = surf->owner->transformed_aabb.get_support(-p_params->lod_plane.normal);
- Vector3 support_max = surf->owner->transformed_aabb.get_support(p_params->lod_plane.normal);
-
- float distance_min = p_params->lod_plane.distance_to(support_min);
- float distance_max = p_params->lod_plane.distance_to(support_max);
-
- float distance = 0.0;
-
- if (distance_min * distance_max < 0.0) {
- //crossing plane
- distance = 0.0;
- } else if (distance_min >= 0.0) {
- distance = distance_min;
- } else if (distance_max <= 0.0) {
- distance = -distance_max;
- }
-
- index_array_rd = storage->mesh_surface_get_index_array_with_lod(mesh_surface, surf->owner->lod_model_scale * surf->owner->lod_bias, distance * p_params->lod_distance_multiplier, p_params->screen_lod_threshold);
-
- } else {
- //no lod
- index_array_rd = storage->mesh_surface_get_index_array(mesh_surface);
- }
+ index_array_rd = storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
if (prev_vertex_array_rd != vertex_array_rd) {
RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd);
@@ -974,18 +953,15 @@ void RendererSceneRenderForward::_render_list_template(RenderingDevice::DrawList
prev_material_uniform_set = material_uniform_set;
}
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &surf->owner->push_constant, sizeof(GeometryInstanceForward::PushConstant));
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(SceneState::PushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), surf->owner->instance_count);
-
- if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
- surf->owner->push_constant.lightmap_uv_scale[0] = old_offset[0];
- surf->owner->push_constant.lightmap_uv_scale[1] = old_offset[1];
- }
+ uint32_t instance_count = surf->owner->instance_count > 1 ? surf->owner->instance_count : element_info.repeat;
+ RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count);
+ i += element_info.repeat - 1; //skip equal elements
}
}
-void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
+void RendererSceneRenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
//use template for faster performance (pass mode comparisons are inlined)
switch (p_params->pass_mode) {
@@ -1022,7 +998,7 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
}
}
-void RendererSceneRenderForward::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) {
+void RendererSceneRenderForwardClustered::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) {
uint32_t render_total = p_params->element_count;
uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
uint32_t render_from = p_thread * render_total / total_threads;
@@ -1030,7 +1006,7 @@ void RendererSceneRenderForward::_render_list_thread_function(uint32_t p_thread,
_render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to);
}
-void RendererSceneRenderForward::_render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) {
+void RendererSceneRenderForwardClustered::_render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) {
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_framebuffer);
p_params->framebuffer_format = fb_format;
@@ -1038,17 +1014,17 @@ void RendererSceneRenderForward::_render_list_with_threads(RenderListParameters
//multi threaded
thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RendererSceneRenderForward::_render_list_thread_function, p_params);
- RD::get_singleton()->draw_list_end();
+ RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RendererSceneRenderForwardClustered::_render_list_thread_function, p_params);
+ RD::get_singleton()->draw_list_end(p_params->barrier);
} else {
//single threaded
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
_render_list(draw_list, fb_format, p_params, 0, p_params->element_count);
- RD::get_singleton()->draw_list_end();
+ RD::get_singleton()->draw_list_end(p_params->barrier);
}
}
-void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows) {
+void RendererSceneRenderForwardClustered::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) {
//CameraMatrix projection = p_cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
CameraMatrix correction;
@@ -1154,7 +1130,7 @@ void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_ren
//vec2 tex_pixel_size = 1.0 / vec2(ivec2( (OCT_SIZE+2) * params.probe_axis_size * params.probe_axis_size, (OCT_SIZE+2) * params.probe_axis_size ) );
//vec3 probe_uv_offset = (ivec3(OCT_SIZE+2,OCT_SIZE+2,(OCT_SIZE+2) * params.probe_axis_size)) * tex_pixel_size.xyx;
- uint32_t oct_size = sdfgi_get_lightprobe_octahedron_size();
+ uint32_t oct_size = gi.sdfgi_get_lightprobe_octahedron_size();
scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[0] = 1.0 / ((oct_size + 2) * scene_state.ubo.sdfgi_probe_axis_size * scene_state.ubo.sdfgi_probe_axis_size);
scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[1] = 1.0 / ((oct_size + 2) * scene_state.ubo.sdfgi_probe_axis_size);
@@ -1287,27 +1263,125 @@ void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_ren
scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount();
scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit();
- RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo);
+ if (p_index >= (int)scene_state.uniform_buffers.size()) {
+ uint32_t from = scene_state.uniform_buffers.size();
+ scene_state.uniform_buffers.resize(p_index + 1);
+ render_pass_uniform_sets.resize(p_index + 1);
+ for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) {
+ scene_state.uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));
+ }
+ }
+ RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER);
+}
+
+void RendererSceneRenderForwardClustered::_update_instance_data_buffer(RenderListType p_render_list) {
+ if (scene_state.instance_data[p_render_list].size() > 0) {
+ if (scene_state.instance_buffer[p_render_list] == RID() || scene_state.instance_buffer_size[p_render_list] < scene_state.instance_data[p_render_list].size()) {
+ if (scene_state.instance_buffer[p_render_list] != RID()) {
+ RD::get_singleton()->free(scene_state.instance_buffer[p_render_list]);
+ }
+ uint32_t new_size = nearest_power_of_2_templated(MAX(uint64_t(INSTANCE_DATA_BUFFER_MIN_SIZE), scene_state.instance_data[p_render_list].size()));
+ scene_state.instance_buffer[p_render_list] = RD::get_singleton()->storage_buffer_create(new_size * sizeof(SceneState::InstanceData));
+ scene_state.instance_buffer_size[p_render_list] = new_size;
+ }
+ RD::get_singleton()->buffer_update(scene_state.instance_buffer[p_render_list], 0, sizeof(SceneState::InstanceData) * scene_state.instance_data[p_render_list].size(), scene_state.instance_data[p_render_list].ptr(), RD::BARRIER_MASK_RASTER);
+ }
+}
+void RendererSceneRenderForwardClustered::_fill_instance_data(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements, bool p_update_buffer) {
+ RenderList *rl = &render_list[p_render_list];
+ uint32_t element_total = p_max_elements >= 0 ? uint32_t(p_max_elements) : rl->elements.size();
+
+ scene_state.instance_data[p_render_list].resize(p_offset + element_total);
+ rl->element_info.resize(p_offset + element_total);
+
+ uint32_t repeats = 0;
+ GeometryInstanceSurfaceDataCache *prev_surface = nullptr;
+ for (uint32_t i = 0; i < element_total; i++) {
+ GeometryInstanceSurfaceDataCache *surface = rl->elements[i + p_offset];
+ GeometryInstanceForwardClustered *inst = surface->owner;
+
+ SceneState::InstanceData &instance_data = scene_state.instance_data[p_render_list][i + p_offset];
+
+ if (inst->store_transform_cache) {
+ RendererStorageRD::store_transform(inst->transform, instance_data.transform);
+ } else {
+ RendererStorageRD::store_transform(Transform(), instance_data.transform);
+ }
+
+ instance_data.flags = inst->flags_cache;
+ instance_data.gi_offset = inst->gi_offset_cache;
+ instance_data.layer_mask = inst->layer_mask;
+ instance_data.instance_uniforms_ofs = uint32_t(inst->shader_parameters_offset);
+ instance_data.lightmap_uv_scale[0] = inst->lightmap_uv_scale.position.x;
+ instance_data.lightmap_uv_scale[1] = inst->lightmap_uv_scale.position.y;
+ instance_data.lightmap_uv_scale[2] = inst->lightmap_uv_scale.size.x;
+ instance_data.lightmap_uv_scale[3] = inst->lightmap_uv_scale.size.y;
+
+ bool cant_repeat = instance_data.flags & INSTANCE_DATA_FLAG_MULTIMESH || inst->mesh_instance.is_valid();
+
+ if (prev_surface != nullptr && !cant_repeat && prev_surface->sort.sort_key1 == surface->sort.sort_key1 && prev_surface->sort.sort_key2 == surface->sort.sort_key2) {
+ //this element is the same as the previous one, count repeats to draw it using instancing
+ repeats++;
+ } else {
+ if (repeats > 0) {
+ for (uint32_t j = 1; j <= repeats; j++) {
+ rl->element_info[p_offset + i - j].repeat = j;
+ }
+ }
+ repeats = 1;
+ }
+
+ RenderElementInfo &element_info = rl->element_info[p_offset + i];
+
+ element_info.lod_index = surface->sort.lod_index;
+ element_info.uses_forward_gi = surface->sort.uses_forward_gi;
+ element_info.uses_lightmap = surface->sort.uses_lightmap;
+
+ if (cant_repeat) {
+ prev_surface = nullptr;
+ } else {
+ prev_surface = surface;
+ }
+ }
+
+ if (repeats > 0) {
+ for (uint32_t j = 1; j <= repeats; j++) {
+ rl->element_info[p_offset + element_total - j].repeat = j;
+ }
+ }
+
+ if (p_update_buffer) {
+ _update_instance_data_buffer(p_render_list);
+ }
}
-void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi, bool p_using_opaque_gi) {
- scene_state.used_sss = false;
- scene_state.used_screen_texture = false;
- scene_state.used_normal_texture = false;
- scene_state.used_depth_texture = false;
+void RendererSceneRenderForwardClustered::_fill_render_list(RenderListType p_render_list, const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi, bool p_using_opaque_gi, const Plane &p_lod_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_append) {
+ if (p_render_list == RENDER_LIST_OPAQUE) {
+ scene_state.used_sss = false;
+ scene_state.used_screen_texture = false;
+ scene_state.used_normal_texture = false;
+ scene_state.used_depth_texture = false;
+ }
+ uint32_t lightmap_captures_used = 0;
Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(Vector3::AXIS_Z));
near_plane.d += p_cam_projection.get_z_near();
float z_max = p_cam_projection.get_z_far() - p_cam_projection.get_z_near();
- uint32_t lightmap_captures_used = 0;
+ RenderList *rl = &render_list[p_render_list];
_update_dirty_geometry_instances();
- render_list.clear();
+
+ if (!p_append) {
+ rl->clear();
+ if (p_render_list == RENDER_LIST_OPAQUE) {
+ render_list[RENDER_LIST_ALPHA].clear(); //opaque fills alpha too
+ }
+ }
//fill list
for (int i = 0; i < (int)p_instances.size(); i++) {
- GeometryInstanceForward *inst = static_cast<GeometryInstanceForward *>(p_instances[i]);
+ GeometryInstanceForwardClustered *inst = static_cast<GeometryInstanceForwardClustered *>(p_instances[i]);
Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal);
inst->depth = near_plane.distance_to(support_min);
@@ -1318,7 +1392,7 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInst
bool uses_lightmap = false;
bool uses_gi = false;
- if (p_pass_mode == PASS_MODE_COLOR) {
+ if (p_render_list == RENDER_LIST_OPAQUE) {
//setup GI
if (inst->lightmap_instance.is_valid()) {
@@ -1330,15 +1404,15 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInst
}
}
if (lightmap_cull_index >= 0) {
- inst->push_constant.gi_offset &= 0xFFFF;
- inst->push_constant.gi_offset |= lightmap_cull_index;
+ inst->gi_offset_cache = inst->lightmap_slice_index << 16;
+ inst->gi_offset_cache |= lightmap_cull_index;
flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP;
if (scene_state.lightmap_has_sh[lightmap_cull_index]) {
flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP;
}
uses_lightmap = true;
} else {
- inst->push_constant.gi_offset = 0xFFFFFFFF;
+ inst->gi_offset_cache = 0xFFFFFFFF;
}
} else if (inst->lightmap_sh) {
@@ -1352,7 +1426,7 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInst
lcd.sh[j * 4 + 3] = src_capture[j].a;
}
flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE;
- inst->push_constant.gi_offset = lightmap_captures_used;
+ inst->gi_offset_cache = lightmap_captures_used;
lightmap_captures_used++;
uses_lightmap = true;
}
@@ -1379,7 +1453,7 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInst
SWAP(probe0_index, probe1_index);
}
- inst->push_constant.gi_offset = probe0_index | (probe1_index << 16);
+ inst->gi_offset_cache = probe0_index | (probe1_index << 16);
flags |= INSTANCE_DATA_FLAG_USE_GIPROBE;
uses_gi = true;
} else {
@@ -1387,11 +1461,11 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInst
flags |= INSTANCE_DATA_FLAG_USE_SDFGI;
uses_gi = true;
}
- inst->push_constant.gi_offset = 0xFFFFFFFF;
+ inst->gi_offset_cache = 0xFFFFFFFF;
}
}
}
- inst->push_constant.flags = flags;
+ inst->flags_cache = flags;
GeometryInstanceSurfaceDataCache *surf = inst->surface_caches;
@@ -1399,12 +1473,39 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInst
surf->sort.uses_forward_gi = 0;
surf->sort.uses_lightmap = 0;
+ // LOD
+
+ if (p_screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) {
+ //lod
+ Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_lod_plane.normal);
+ Vector3 lod_support_max = inst->transformed_aabb.get_support(p_lod_plane.normal);
+
+ float distance_min = p_lod_plane.distance_to(lod_support_min);
+ float distance_max = p_lod_plane.distance_to(lod_support_max);
+
+ float distance = 0.0;
+
+ if (distance_min * distance_max < 0.0) {
+ //crossing plane
+ distance = 0.0;
+ } else if (distance_min >= 0.0) {
+ distance = distance_min;
+ } else if (distance_max <= 0.0) {
+ distance = -distance_max;
+ }
+
+ surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_lod_distance_multiplier, p_screen_lod_threshold);
+ } else {
+ surf->sort.lod_index = 0;
+ }
+
+ // ADD Element
if (p_pass_mode == PASS_MODE_COLOR) {
if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
- render_list.add_element(surf);
+ rl->add_element(surf);
}
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA) {
- render_list.add_alpha_element(surf);
+ render_list[RENDER_LIST_ALPHA].add_element(surf);
if (uses_gi) {
surf->sort.uses_forward_gi = 1;
}
@@ -1429,11 +1530,11 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInst
} else if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) {
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW) {
- render_list.add_element(surf);
+ rl->add_element(surf);
}
} else {
if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
- render_list.add_element(surf);
+ rl->add_element(surf);
}
}
@@ -1443,19 +1544,19 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInst
}
}
- if (lightmap_captures_used) {
- RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures);
+ if (p_render_list == RENDER_LIST_OPAQUE && lightmap_captures_used) {
+ RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, RD::BARRIER_MASK_RASTER);
}
}
-void RendererSceneRenderForward::_setup_giprobes(const PagedArray<RID> &p_giprobes) {
+void RendererSceneRenderForwardClustered::_setup_giprobes(const PagedArray<RID> &p_giprobes) {
scene_state.giprobes_used = MIN(p_giprobes.size(), uint32_t(MAX_GI_PROBES));
for (uint32_t i = 0; i < scene_state.giprobes_used; i++) {
scene_state.giprobe_ids[i] = p_giprobes[i];
}
}
-void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) {
+void RendererSceneRenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) {
scene_state.lightmaps_used = 0;
for (int i = 0; i < (int)p_lightmaps.size(); i++) {
if (i >= (int)scene_state.max_lightmaps) {
@@ -1473,29 +1574,22 @@ void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<RID> &p_light
scene_state.lightmaps_used++;
}
if (scene_state.lightmaps_used > 0) {
- RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * scene_state.lightmaps_used, scene_state.lightmaps);
+ RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * scene_state.lightmaps_used, scene_state.lightmaps, RD::BARRIER_MASK_RASTER);
}
}
-void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
+void RendererSceneRenderForwardClustered::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
RenderBufferDataForward *render_buffer = nullptr;
if (p_render_buffer.is_valid()) {
render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer);
}
+ RendererSceneEnvironmentRD *env = get_environment(p_environment);
//first of all, make a new render pass
- render_pass++;
-
//fill up ubo
RENDER_TIMESTAMP("Setup 3D Scene");
- if (p_reflection_probe.is_valid()) {
- scene_state.ubo.reflection_multiplier = 0.0;
- } else {
- scene_state.ubo.reflection_multiplier = 1.0;
- }
-
float lod_distance_multiplier = p_cam_projection.get_lod_multiplier();
Plane lod_camera_plane(p_cam_transform.get_origin(), -p_cam_transform.basis.get_axis(Vector3::AXIS_Z));
@@ -1508,7 +1602,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
Vector2 vp_he = p_cam_projection.get_viewport_half_extents();
scene_state.ubo.viewport_size[0] = vp_he.x;
scene_state.ubo.viewport_size[1] = vp_he.y;
- scene_state.ubo.directional_light_count = p_directional_light_count;
+ scene_state.ubo.directional_light_count = 0;
Size2i screen_size;
RID opaque_framebuffer;
@@ -1592,13 +1686,21 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
ERR_FAIL(); //bug?
}
+ RD::get_singleton()->draw_command_begin_label("Render Setup");
+
_setup_lightmaps(p_lightmaps, p_cam_transform);
_setup_giprobes(p_gi_probes);
_setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_cluster_size, p_max_cluster_elements, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
- _fill_render_list(p_instances, PASS_MODE_COLOR, p_cam_projection, p_cam_transform, using_sdfgi, using_sdfgi || using_giprobe);
+ _fill_render_list(RENDER_LIST_OPAQUE, p_instances, PASS_MODE_COLOR, p_cam_projection, p_cam_transform, using_sdfgi, using_sdfgi || using_giprobe, lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
+ render_list[RENDER_LIST_OPAQUE].sort_by_key();
+ render_list[RENDER_LIST_ALPHA].sort_by_depth();
+ _fill_instance_data(RENDER_LIST_OPAQUE);
+ _fill_instance_data(RENDER_LIST_ALPHA);
+
+ RD::get_singleton()->draw_command_end_label();
bool using_sss = !low_end && render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
@@ -1628,7 +1730,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
clear_color.b *= bg_energy;
if (render_buffers_has_volumetric_fog(p_render_buffer) || environment_is_fog_enabled(p_environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
}
} break;
case RS::ENV_BG_COLOR: {
@@ -1638,7 +1740,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
clear_color.b *= bg_energy;
if (render_buffers_has_volumetric_fog(p_render_buffer) || environment_is_fog_enabled(p_environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
}
} break;
case RS::ENV_BG_SKY: {
@@ -1666,12 +1768,12 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
projection = correction * p_cam_projection;
}
- _setup_sky(p_environment, p_render_buffer, projection, p_cam_transform, screen_size);
+ sky.setup(env, p_render_buffer, projection, p_cam_transform, screen_size, this);
- RID sky = environment_get_sky(p_environment);
- if (sky.is_valid()) {
- _update_sky(p_environment, projection, p_cam_transform);
- radiance_texture = sky_get_radiance_texture_rd(sky);
+ RID sky_rid = env->sky;
+ if (sky_rid.is_valid()) {
+ sky.update(env, projection, p_cam_transform, time);
+ radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
draw_sky = false;
@@ -1682,8 +1784,6 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
clear_color = p_default_bg_color;
}
- render_list.sort_by_key(false);
-
bool debug_giprobes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION;
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
bool depth_pre_pass = !low_end && depth_framebuffer.is_valid();
@@ -1691,42 +1791,64 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
bool using_ssao = depth_pre_pass && p_render_buffer.is_valid() && p_environment.is_valid() && environment_is_ssao_enabled(p_environment);
bool continue_depth = false;
if (depth_pre_pass) { //depth pre pass
- RENDER_TIMESTAMP("Render Depth Pre-Pass");
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
+ bool needs_pre_resolve = _needs_post_prepass_render(using_sdfgi || using_giprobe);
+ if (needs_pre_resolve) {
+ RENDER_TIMESTAMP("GI + Render Depth Pre-Pass (parallel)");
+ } else {
+ RENDER_TIMESTAMP("Render Depth Pre-Pass");
+ }
+ if (needs_pre_resolve) {
+ //pre clear the depth framebuffer, as AMD (and maybe others?) use compute for it, and barrier other compute shaders.
+ RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
+ RD::get_singleton()->draw_list_end();
+ //start compute processes here, so they run at the same time as depth pre-pass
+ _post_prepass_render(using_sdfgi || using_giprobe);
+ }
- bool finish_depth = using_ssao || using_sdfgi || using_giprobe;
- RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
RD::get_singleton()->draw_command_begin_label("Render Depth Pre-Pass");
- _render_list_with_threads(&render_list_params, depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
+
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
+
+ bool finish_depth = using_ssao || using_sdfgi || using_giprobe;
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), false, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
+ _render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
+
RD::get_singleton()->draw_command_end_label();
+
+ if (needs_pre_resolve) {
+ _pre_resolve_render(using_sdfgi || using_giprobe);
+ }
+
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
RENDER_TIMESTAMP("Resolve Depth Pre-Pass");
- RD::get_singleton()->draw_command_insert_label("Resolve Depth Pre-Pass");
+ RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass");
if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE) {
+ if (needs_pre_resolve) {
+ RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, RD::BARRIER_MASK_COMPUTE);
+ }
static int texture_samples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8, 16 };
storage->get_effects()->resolve_gi(render_buffer->depth_msaa, render_buffer->normal_roughness_buffer_msaa, using_giprobe ? render_buffer->giprobe_buffer_msaa : RID(), render_buffer->depth, render_buffer->normal_roughness_buffer, using_giprobe ? render_buffer->giprobe_buffer : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_samples[render_buffer->msaa]);
} else if (finish_depth) {
RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth);
}
+ RD::get_singleton()->draw_command_end_label();
}
continue_depth = !finish_depth;
}
- if (using_ssao) {
- _process_ssao(p_render_buffer, p_environment, render_buffer->normal_roughness_buffer, p_cam_projection);
- }
+ _pre_opaque_render(using_ssao, using_sdfgi || using_giprobe, render_buffer ? render_buffer->normal_roughness_buffer : RID(), render_buffer ? render_buffer->giprobe_buffer : RID());
- if (using_sdfgi || using_giprobe) {
- _process_gi(p_render_buffer, render_buffer->normal_roughness_buffer, render_buffer->giprobe_buffer, p_environment, p_cam_projection, p_cam_transform, p_gi_probes);
- }
+ RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
+
+ scene_state.ubo.directional_light_count = _get_render_state_directional_light_count();
_setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_cluster_size, p_max_cluster_elements, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.is_valid());
RENDER_TIMESTAMP("Render Opaque Pass");
- RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_cluster_buffer, p_gi_probes, p_lightmaps, true);
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_cluster_buffer, p_gi_probes, p_lightmaps, true);
bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss;
bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss;
@@ -1747,10 +1869,8 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
}
RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
- RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
- RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
- _render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
- RD::get_singleton()->draw_command_end_label();
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
+ _render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
if (will_continue_color && using_separate_specular) {
// close the specular framebuffer, as it's no longer used
RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);
@@ -1758,6 +1878,8 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
}
}
+ RD::get_singleton()->draw_command_end_label();
+
if (debug_giprobes) {
//debug giprobes
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
@@ -1769,7 +1891,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
RD::get_singleton()->draw_command_begin_label("Debug GIProbes");
for (int i = 0; i < (int)p_gi_probes.size(); i++) {
- _debug_giprobe(p_gi_probes[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0);
+ gi.debug_giprobe(p_gi_probes[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0);
}
RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
@@ -1800,7 +1922,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
projection = correction * p_cam_projection;
}
RD::get_singleton()->draw_command_begin_label("Draw Sky");
- _draw_sky(can_continue_color, can_continue_depth, opaque_framebuffer, p_environment, projection, p_cam_transform);
+ sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, projection, p_cam_transform, time);
RD::get_singleton()->draw_command_end_label();
}
@@ -1837,32 +1959,44 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
RENDER_TIMESTAMP("Render Transparent Pass");
- _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_cluster_size, p_max_cluster_elements, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
+ RD::get_singleton()->draw_command_begin_label("Render Transparent Pass");
- render_list.sort_by_reverse_depth_and_priority(true);
+ rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_cluster_buffer, p_gi_probes, p_lightmaps, true);
+
+ _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_cluster_size, p_max_cluster_elements, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
{
- RD::get_singleton()->draw_command_begin_label("Render Transparent Pass");
- RenderListParameters render_list_params(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
_render_list_with_threads(&render_list_params, alpha_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);
- RD::get_singleton()->draw_command_end_label();
}
+ RD::get_singleton()->draw_command_end_label();
+
+ RD::get_singleton()->draw_command_begin_label("Resolve");
+
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color);
}
-}
-void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) {
- RENDER_TIMESTAMP("Setup Rendering Shadow");
+ RD::get_singleton()->draw_command_end_label();
+}
+void RendererSceneRenderForwardClustered::_render_shadow_begin() {
+ scene_state.shadow_passes.clear();
+ RD::get_singleton()->draw_command_begin_label("Shadow Setup");
_update_render_base_uniform_set();
- render_pass++;
+ render_list[RENDER_LIST_SECONDARY].clear();
+ scene_state.instance_data[RENDER_LIST_SECONDARY].clear();
+}
+void RendererSceneRenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) {
+ uint32_t shadow_pass_index = scene_state.shadow_passes.size();
+
+ SceneState::ShadowPass shadow_pass;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
- _setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), 1, 32, RID(), !p_flip_y, Color(), 0, p_zfar, false, p_use_pancake);
+ _setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), 1, 32, RID(), !p_flip_y, Color(), 0, p_zfar, false, p_use_pancake, shadow_pass_index);
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
p_screen_lod_threshold = 0.0;
@@ -1870,13 +2004,11 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedAr
PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
- _fill_render_list(p_instances, pass_mode, p_projection, p_transform);
-
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
-
- RENDER_TIMESTAMP("Render Shadow");
-
- render_list.sort_by_key(false);
+ uint32_t render_list_from = render_list[RENDER_LIST_SECONDARY].elements.size();
+ _fill_render_list(RENDER_LIST_SECONDARY, p_instances, pass_mode, p_projection, p_transform, false, false, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, true);
+ uint32_t render_list_size = render_list[RENDER_LIST_SECONDARY].elements.size() - render_list_from;
+ render_list[RENDER_LIST_SECONDARY].sort_by_key_range(render_list_from, render_list_size);
+ _fill_instance_data(RENDER_LIST_SECONDARY, render_list_from, render_list_size, false);
{
//regular forward for now
@@ -1884,49 +2016,87 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedAr
if (p_flip_y) {
flip_cull = !flip_cull;
}
- RD::get_singleton()->draw_command_begin_label("Render Shadow");
- RenderListParameters render_list_params(render_list.elements, render_list.element_count, flip_cull, pass_mode, true, rp_uniform_set, false, Vector2(), p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
- _render_list_with_threads(&render_list_params, p_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, p_begin ? (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR) : RD::INITIAL_ACTION_CONTINUE, p_end ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, Vector<Color>(), 1.0, 0, p_rect);
- RD::get_singleton()->draw_command_end_label();
+
+ shadow_pass.element_from = render_list_from;
+ shadow_pass.element_count = render_list_size;
+ shadow_pass.flip_cull = flip_cull;
+ shadow_pass.pass_mode = pass_mode;
+
+ shadow_pass.rp_uniform_set = RID(); //will be filled later when instance buffer is complete
+ shadow_pass.camera_plane = p_camera_plane;
+ shadow_pass.screen_lod_threshold = p_screen_lod_threshold;
+ shadow_pass.lod_distance_multiplier = p_lod_distance_multiplier;
+
+ shadow_pass.framebuffer = p_framebuffer;
+ shadow_pass.initial_depth_action = p_begin ? (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR) : (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE : RD::INITIAL_ACTION_CONTINUE);
+ shadow_pass.final_depth_action = p_end ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE;
+ shadow_pass.rect = p_rect;
+
+ scene_state.shadow_passes.push_back(shadow_pass);
}
}
-void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
- RENDER_TIMESTAMP("Setup Render Collider Heightfield");
+void RendererSceneRenderForwardClustered::_render_shadow_process() {
+ _update_instance_data_buffer(RENDER_LIST_SECONDARY);
+ //render shadows one after the other, so this can be done un-barriered and the driver can optimize (as well as allow us to run compute at the same time)
- _update_render_base_uniform_set();
+ for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
+ //render passes need to be configured after instance buffer is done, since they need the latest version
+ SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
+ shadow_pass.rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>(), false, i);
+ }
- render_pass++;
+ RD::get_singleton()->draw_command_end_label();
+}
+void RendererSceneRenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
+ RD::get_singleton()->draw_command_begin_label("Shadow Render");
+
+ for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
+ SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ _render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
+ }
+
+ if (p_barrier != RD::BARRIER_MASK_NO_BARRIER) {
+ RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, p_barrier);
+ }
+ RD::get_singleton()->draw_command_end_label();
+}
+
+void RendererSceneRenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
+ RENDER_TIMESTAMP("Setup Render Collider Heightfield");
+ RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
+
+ _update_render_base_uniform_set();
scene_state.ubo.dual_paraboloid_side = 0;
_setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), 1, 32, RID(), true, Color(), 0, p_cam_projection.get_z_far(), false, false);
PassMode pass_mode = PASS_MODE_SHADOW;
- _fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform);
+ _fill_render_list(RENDER_LIST_SECONDARY, p_instances, pass_mode, p_cam_projection, p_cam_transform);
+ render_list[RENDER_LIST_SECONDARY].sort_by_key();
+ _fill_instance_data(RENDER_LIST_SECONDARY);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Collider Heightfield");
- render_list.sort_by_key(false);
-
{
//regular forward for now
- RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
- RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, pass_mode, true, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, true, rp_uniform_set);
_render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
- RD::get_singleton()->draw_command_end_label();
}
+ RD::get_singleton()->draw_command_end_label();
}
-void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForwardClustered::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering Material");
- _update_render_base_uniform_set();
+ RD::get_singleton()->draw_command_begin_label("Render Material");
- render_pass++;
+ _update_render_base_uniform_set();
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = false;
@@ -1934,16 +2104,16 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
_setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), 1, 32, RID(), false, Color(), 0, 0);
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
- _fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform);
+ _fill_render_list(RENDER_LIST_SECONDARY, p_instances, pass_mode, p_cam_projection, p_cam_transform);
+ render_list[RENDER_LIST_SECONDARY].sort_by_key();
+ _fill_instance_data(RENDER_LIST_SECONDARY);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Material");
- render_list.sort_by_key(false);
-
{
- RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, rp_uniform_set);
//regular forward for now
Vector<Color> clear;
clear.push_back(Color(0, 0, 0, 0));
@@ -1955,14 +2125,16 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count);
RD::get_singleton()->draw_list_end();
}
+
+ RD::get_singleton()->draw_command_end_label();
}
-void RendererSceneRenderForward::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering UV2");
- _update_render_base_uniform_set();
+ RD::get_singleton()->draw_command_begin_label("Render UV2");
- render_pass++;
+ _update_render_base_uniform_set();
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = true;
@@ -1970,16 +2142,16 @@ void RendererSceneRenderForward::_render_uv2(const PagedArray<GeometryInstance *
_setup_environment(RID(), RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), 1, 32, RID(), false, Color(), 0, 0);
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
- _fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform());
+ _fill_render_list(RENDER_LIST_SECONDARY, p_instances, pass_mode, CameraMatrix(), Transform());
+ render_list[RENDER_LIST_SECONDARY].sort_by_key();
+ _fill_instance_data(RENDER_LIST_SECONDARY);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Material");
- render_list.sort_by_key(false);
-
{
- RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, true);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, rp_uniform_set, true);
//regular forward for now
Vector<Color> clear;
clear.push_back(Color(0, 0, 0, 0));
@@ -2015,23 +2187,24 @@ void RendererSceneRenderForward::_render_uv2(const PagedArray<GeometryInstance *
RD::get_singleton()->draw_list_end();
}
+
+ RD::get_singleton()->draw_command_end_label();
}
-void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RendererSceneRenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
RENDER_TIMESTAMP("Render SDFGI");
+ RD::get_singleton()->draw_command_begin_label("Render SDFGI Voxel");
+
_update_render_base_uniform_set();
RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers);
ERR_FAIL_COND(!render_buffer);
- render_pass++;
-
PassMode pass_mode = PASS_MODE_SDF;
- _fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform());
- render_list.sort_by_key(false);
-
- RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture);
+ _fill_render_list(RENDER_LIST_SECONDARY, p_instances, pass_mode, CameraMatrix(), Transform());
+ render_list[RENDER_LIST_SECONDARY].sort_by_key();
+ _fill_instance_data(RENDER_LIST_SECONDARY);
Vector3 half_extents = p_bounds.size * 0.5;
Vector3 center = p_bounds.position + half_extents;
@@ -2084,25 +2257,29 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto
_setup_environment(RID(), RID(), camera_proj, cam_xform, RID(), true, Vector2(1, 1), 1, 32, RID(), false, Color(), 0, 0);
+ RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture);
+
Map<Size2i, RID>::Element *E = sdfgi_framebuffer_size_cache.find(fb_size);
if (!E) {
RID fb = RD::get_singleton()->framebuffer_create_empty(fb_size);
E = sdfgi_framebuffer_size_cache.insert(fb_size, fb);
}
- RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, false);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, rp_uniform_set, false);
_render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs);
}
+
+ RD::get_singleton()->draw_command_end_label();
}
-void RendererSceneRenderForward::_base_uniforms_changed() {
+void RendererSceneRenderForwardClustered::_base_uniforms_changed() {
if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
render_base_uniform_set = RID();
}
-void RendererSceneRenderForward::_update_render_base_uniform_set() {
+void RendererSceneRenderForwardClustered::_update_render_base_uniform_set() {
if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) {
if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
@@ -2144,21 +2321,13 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.binding = 3;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(scene_state.uniform_buffer);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_omni_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 5;
+ u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_spot_light_buffer());
uniforms.push_back(u);
@@ -2166,35 +2335,35 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
{
RD::Uniform u;
- u.binding = 6;
+ u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_reflection_probe_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 7;
+ u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(get_directional_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 8;
+ u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.lightmap_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 9;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.lightmap_capture_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 10;
+ u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture();
u.ids.push_back(decal_atlas);
@@ -2202,7 +2371,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 11;
+ u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture_srgb();
u.ids.push_back(decal_atlas);
@@ -2210,7 +2379,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 12;
+ u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_decal_buffer());
uniforms.push_back(u);
@@ -2219,7 +2388,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 13;
+ u.binding = 12;
u.ids.push_back(storage->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -2227,7 +2396,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
if (!low_end) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 14;
+ u.binding = 13;
u.ids.push_back(sdfgi_get_ubo());
uniforms.push_back(u);
}
@@ -2236,10 +2405,9 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
}
}
-RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas) {
- if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
- RD::get_singleton()->free(render_pass_uniform_set);
- }
+RID RendererSceneRenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas, int p_index) {
+ //there should always be enough uniform buffers for render passes, otherwise bugs
+ ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID());
RenderBufferDataForward *rb = nullptr;
if (p_render_buffers.is_valid()) {
@@ -2251,6 +2419,24 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
Vector<RD::Uniform> uniforms;
{
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.ids.push_back(scene_state.uniform_buffers[p_index]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ RID instance_buffer = scene_state.instance_buffer[p_render_list];
+ if (instance_buffer == RID()) {
+ instance_buffer = default_vec4_xform_buffer; // any buffer will do since its not used
+ }
+ u.ids.push_back(instance_buffer);
+ uniforms.push_back(u);
+ }
+ {
RID radiance_texture;
if (p_radiance_texture.is_valid()) {
radiance_texture = p_radiance_texture;
@@ -2258,7 +2444,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
}
RD::Uniform u;
- u.binding = 0;
+ u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.push_back(radiance_texture);
uniforms.push_back(u);
@@ -2267,7 +2453,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID();
RD::Uniform u;
- u.binding = 1;
+ u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (ref_texture.is_valid()) {
u.ids.push_back(ref_texture);
@@ -2279,7 +2465,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 2;
+ u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture;
if (p_shadow_atlas.is_valid()) {
@@ -2293,7 +2479,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 3;
+ u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
u.ids.push_back(directional_shadow_get_texture());
@@ -2304,7 +2490,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 4;
+ u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.resize(scene_state.max_lightmaps);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
@@ -2323,13 +2509,13 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 5;
+ u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.resize(MAX_GI_PROBES);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_GI_PROBES; i++) {
if (i < (int)p_gi_probes.size()) {
- RID tex = gi_probe_instance_get_texture(p_gi_probes[i]);
+ RID tex = gi.gi_probe_instance_get_texture(p_gi_probes[i]);
if (!tex.is_valid()) {
tex = default_tex;
}
@@ -2344,7 +2530,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 6;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
RID cb = p_cluster_buffer.is_valid() ? p_cluster_buffer : default_vec4_xform_buffer;
u.ids.push_back(cb);
@@ -2353,7 +2539,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 7;
+ u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture = (false && rb && rb->depth.is_valid()) ? rb->depth : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
u.ids.push_back(texture);
@@ -2361,7 +2547,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 8;
+ u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_buffers) : RID();
RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
@@ -2372,7 +2558,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
if (!low_end) {
{
RD::Uniform u;
- u.binding = 9;
+ u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL);
u.ids.push_back(texture);
@@ -2381,7 +2567,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 10;
+ u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID aot = rb ? render_buffers_get_ao_texture(p_render_buffers) : RID();
RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
@@ -2391,7 +2577,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 11;
+ u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID ambient_buffer = p_render_buffers.is_valid() ? render_buffers_get_gi_ambient_texture(p_render_buffers) : RID();
RID texture = ambient_buffer.is_valid() ? ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
@@ -2401,7 +2587,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 12;
+ u.binding = 14;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID reflection_buffer = p_render_buffers.is_valid() ? render_buffers_get_gi_reflection_texture(p_render_buffers) : RID();
RID texture = reflection_buffer.is_valid() ? reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
@@ -2410,7 +2596,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 13;
+ u.binding = 15;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID t;
if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {
@@ -2423,7 +2609,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 14;
+ u.binding = 16;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {
u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_buffers));
@@ -2434,14 +2620,14 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 15;
+ u.binding = 17;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(rb ? render_buffers_get_gi_probe_buffer(p_render_buffers) : render_buffers_get_default_gi_probe_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 16;
+ u.binding = 18;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID vfog = RID();
if (rb && render_buffers_has_volumetric_fog(p_render_buffers)) {
@@ -2457,11 +2643,19 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
}
- render_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_PASS_UNIFORM_SET);
- return render_pass_uniform_set;
+ if (p_index >= (int)render_pass_uniform_sets.size()) {
+ render_pass_uniform_sets.resize(p_index + 1);
+ }
+
+ if (render_pass_uniform_sets[p_index].is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_sets[p_index])) {
+ RD::get_singleton()->free(render_pass_uniform_sets[p_index]);
+ }
+
+ render_pass_uniform_sets[p_index] = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_PASS_UNIFORM_SET);
+ return render_pass_uniform_sets[p_index];
}
-RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) {
+RID RendererSceneRenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) {
if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) {
RD::get_singleton()->free(sdfgi_pass_uniform_set);
}
@@ -2469,10 +2663,24 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
Vector<RD::Uniform> uniforms;
{
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.ids.push_back(scene_state.uniform_buffers[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(scene_state.instance_buffer[RENDER_LIST_SECONDARY]);
+ uniforms.push_back(u);
+ }
+ {
// No radiance texture.
RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
RD::Uniform u;
- u.binding = 0;
+ u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.push_back(radiance_texture);
uniforms.push_back(u);
@@ -2482,7 +2690,7 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
// No reflection atlas.
RID ref_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
RD::Uniform u;
- u.binding = 1;
+ u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.push_back(ref_texture);
uniforms.push_back(u);
@@ -2491,7 +2699,7 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
{
// No shadow atlas.
RD::Uniform u;
- u.binding = 2;
+ u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
u.ids.push_back(texture);
@@ -2501,7 +2709,7 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
{
// No directional shadow atlas.
RD::Uniform u;
- u.binding = 3;
+ u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
u.ids.push_back(texture);
@@ -2511,7 +2719,7 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
{
// No Lightmaps
RD::Uniform u;
- u.binding = 4;
+ u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.resize(scene_state.max_lightmaps);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
@@ -2525,7 +2733,7 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
{
// No GIProbes
RD::Uniform u;
- u.binding = 5;
+ u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.resize(MAX_GI_PROBES);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
@@ -2538,7 +2746,7 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
{
RD::Uniform u;
- u.binding = 6;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
RID cb = default_vec4_xform_buffer;
u.ids.push_back(cb);
@@ -2550,28 +2758,28 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 7;
+ u.binding = 9;
u.ids.push_back(p_albedo_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 8;
+ u.binding = 10;
u.ids.push_back(p_emission_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 9;
+ u.binding = 11;
u.ids.push_back(p_emission_aniso_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 10;
+ u.binding = 12;
u.ids.push_back(p_geom_facing_texture);
uniforms.push_back(u);
}
@@ -2580,30 +2788,25 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
return sdfgi_pass_uniform_set;
}
-void RendererSceneRenderForward::_render_buffers_clear_uniform_set(RenderBufferDataForward *rb) {
+void RendererSceneRenderForwardClustered::_render_buffers_clear_uniform_set(RenderBufferDataForward *rb) {
}
-void RendererSceneRenderForward::_render_buffers_uniform_set_changed(RID p_render_buffers) {
+void RendererSceneRenderForwardClustered::_render_buffers_uniform_set_changed(RID p_render_buffers) {
RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers);
_render_buffers_clear_uniform_set(rb);
}
-RID RendererSceneRenderForward::_render_buffers_get_normal_texture(RID p_render_buffers) {
+RID RendererSceneRenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) {
RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers);
return rb->normal_roughness_buffer;
}
-RendererSceneRenderForward *RendererSceneRenderForward::singleton = nullptr;
+RendererSceneRenderForwardClustered *RendererSceneRenderForwardClustered::singleton = nullptr;
-void RendererSceneRenderForward::set_time(double p_time, double p_step) {
- time = p_time;
- RendererSceneRenderRD::set_time(p_time, p_step);
-}
-
-void RendererSceneRenderForward::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
if (ginstance->dirty_list_element.in_list()) {
return;
}
@@ -2622,7 +2825,7 @@ void RendererSceneRenderForward::_geometry_instance_mark_dirty(GeometryInstance
geometry_instance_dirty_list.add(&ginstance->dirty_list_element);
}
-void RendererSceneRenderForward::_geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
+void RendererSceneRenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha);
bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
@@ -2646,7 +2849,7 @@ void RendererSceneRenderForward::_geometry_instance_add_surface_with_material(Ge
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE;
}
- if (ginstance->data->cast_double_sided_shaodows) {
+ if (ginstance->data->cast_double_sided_shadows) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS;
}
@@ -2709,15 +2912,16 @@ void RendererSceneRenderForward::_geometry_instance_add_surface_with_material(Ge
sdcache->sort.sort_key1 = 0;
sdcache->sort.sort_key2 = 0;
- sdcache->sort.surface_type = ginstance->data->base_type;
- sdcache->sort.material_id = p_material_id;
+ sdcache->sort.surface_index = p_surface;
+ sdcache->sort.material_id_low = p_material_id & 0x3FFF;
+ sdcache->sort.material_id_hi = p_material_id >> 14;
sdcache->sort.shader_id = p_shader_id;
- sdcache->sort.geometry_id = p_mesh.get_local_index();
+ sdcache->sort.geometry_id = p_mesh.get_local_index(); //only meshes can repeat anyway
sdcache->sort.uses_forward_gi = ginstance->can_sdfgi;
sdcache->sort.priority = p_material->priority;
}
-void RendererSceneRenderForward::_geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
+void RendererSceneRenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
RID m_src;
m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material;
@@ -2757,8 +2961,8 @@ void RendererSceneRenderForward::_geometry_instance_add_surface(GeometryInstance
}
}
-void RendererSceneRenderForward::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
if (ginstance->data->dirty_dependencies) {
ginstance->data->dependency_tracker.update_begin();
@@ -2842,11 +3046,6 @@ void RendererSceneRenderForward::_geometry_instance_update(GeometryInstance *p_g
//Fill push constant
- ginstance->push_constant.instance_uniforms_ofs = ginstance->data->shader_parameters_offset >= 0 ? ginstance->data->shader_parameters_offset : 0;
- ginstance->push_constant.layer_mask = ginstance->data->layer_mask;
- ginstance->push_constant.flags = 0;
- ginstance->push_constant.gi_offset = 0xFFFFFFFF; //disabled
-
bool store_transform = true;
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
@@ -2903,21 +3102,10 @@ void RendererSceneRenderForward::_geometry_instance_update(GeometryInstance *p_g
}
}
- if (store_transform) {
- RendererStorageRD::store_transform(ginstance->data->transform, ginstance->push_constant.transform);
- } else {
- RendererStorageRD::store_transform(Transform(), ginstance->push_constant.transform);
- }
-
+ ginstance->store_transform_cache = store_transform;
ginstance->can_sdfgi = false;
- if (lightmap_instance_is_valid(ginstance->lightmap_instance)) {
- ginstance->push_constant.gi_offset = ginstance->data->lightmap_slice_index << 16;
- ginstance->push_constant.lightmap_uv_scale[0] = ginstance->data->lightmap_uv_scale.position.x;
- ginstance->push_constant.lightmap_uv_scale[1] = ginstance->data->lightmap_uv_scale.position.y;
- ginstance->push_constant.lightmap_uv_scale[2] = ginstance->data->lightmap_uv_scale.size.width;
- ginstance->push_constant.lightmap_uv_scale[3] = ginstance->data->lightmap_uv_scale.size.height;
- } else if (!low_end) {
+ if (!lightmap_instance_is_valid(ginstance->lightmap_instance) && !low_end) {
if (ginstance->gi_probes[0].is_null() && (ginstance->data->use_baked_light || ginstance->data->use_dynamic_gi)) {
ginstance->can_sdfgi = true;
}
@@ -2931,24 +3119,24 @@ void RendererSceneRenderForward::_geometry_instance_update(GeometryInstance *p_g
ginstance->dirty_list_element.remove_from_list();
}
-void RendererSceneRenderForward::_update_dirty_geometry_instances() {
+void RendererSceneRenderForwardClustered::_update_dirty_geometry_instances() {
while (geometry_instance_dirty_list.first()) {
_geometry_instance_update(geometry_instance_dirty_list.first()->self());
}
}
-void RendererSceneRenderForward::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) {
+void RendererSceneRenderForwardClustered::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) {
switch (p_notification) {
case RendererStorage::DEPENDENCY_CHANGED_MATERIAL:
case RendererStorage::DEPENDENCY_CHANGED_MESH:
case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: {
- static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ static_cast<RendererSceneRenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
} break;
case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_tracker->userdata);
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
- ginstance->instance_count = static_cast<RendererSceneRenderForward *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ ginstance->instance_count = static_cast<RendererSceneRenderForwardClustered *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
default: {
@@ -2956,16 +3144,16 @@ void RendererSceneRenderForward::_geometry_instance_dependency_changed(RendererS
} break;
}
}
-void RendererSceneRenderForward::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
- static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+void RendererSceneRenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
+ static_cast<RendererSceneRenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
}
-RendererSceneRender::GeometryInstance *RendererSceneRenderForward::geometry_instance_create(RID p_base) {
+RendererSceneRender::GeometryInstance *RendererSceneRenderForwardClustered::geometry_instance_create(RID p_base) {
RS::InstanceType type = storage->get_base_type(p_base);
ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
- GeometryInstanceForward *ginstance = geometry_instance_alloc.alloc();
- ginstance->data = memnew(GeometryInstanceForward::Data);
+ GeometryInstanceForwardClustered *ginstance = geometry_instance_alloc.alloc();
+ ginstance->data = memnew(GeometryInstanceForwardClustered::Data);
ginstance->data->base = p_base;
ginstance->data->base_type = type;
@@ -2977,38 +3165,37 @@ RendererSceneRender::GeometryInstance *RendererSceneRenderForward::geometry_inst
return ginstance;
}
-void RendererSceneRenderForward::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
ginstance->data->skeleton = p_skeleton;
_geometry_instance_mark_dirty(ginstance);
ginstance->data->dirty_dependencies = true;
}
-void RendererSceneRenderForward::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
ginstance->data->material_override = p_override;
_geometry_instance_mark_dirty(ginstance);
ginstance->data->dirty_dependencies = true;
}
-void RendererSceneRenderForward::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
ginstance->data->surface_materials = p_materials;
_geometry_instance_mark_dirty(ginstance);
ginstance->data->dirty_dependencies = true;
}
-void RendererSceneRenderForward::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
ginstance->mesh_instance = p_mesh_instance;
_geometry_instance_mark_dirty(ginstance);
}
-void RendererSceneRenderForward::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
- RendererStorageRD::store_transform(p_transform, ginstance->push_constant.transform);
- ginstance->data->transform = p_transform;
+ ginstance->transform = p_transform;
ginstance->mirror = p_transform.basis.determinant() < 0;
ginstance->data->aabb = p_aabb;
ginstance->transformed_aabb = p_transformed_aabb;
@@ -3022,33 +3209,33 @@ void RendererSceneRenderForward::geometry_instance_set_transform(GeometryInstanc
ginstance->lod_model_scale = max_scale;
}
-void RendererSceneRenderForward::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
ginstance->lod_bias = p_lod_bias;
}
-void RendererSceneRenderForward::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
ginstance->data->use_baked_light = p_enable;
_geometry_instance_mark_dirty(ginstance);
}
-void RendererSceneRenderForward::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
ginstance->data->use_dynamic_gi = p_enable;
_geometry_instance_mark_dirty(ginstance);
}
-void RendererSceneRenderForward::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
ginstance->lightmap_instance = p_lightmap_instance;
- ginstance->data->lightmap_uv_scale = p_lightmap_uv_scale;
- ginstance->data->lightmap_slice_index = p_lightmap_slice_index;
+ ginstance->lightmap_uv_scale = p_lightmap_uv_scale;
+ ginstance->lightmap_slice_index = p_lightmap_slice_index;
_geometry_instance_mark_dirty(ginstance);
}
-void RendererSceneRenderForward::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
if (p_sh9) {
if (ginstance->lightmap_sh == nullptr) {
@@ -3064,29 +3251,28 @@ void RendererSceneRenderForward::geometry_instance_set_lightmap_capture(Geometry
}
_geometry_instance_mark_dirty(ginstance);
}
-void RendererSceneRenderForward::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
- ginstance->data->shader_parameters_offset = p_offset;
+ ginstance->shader_parameters_offset = p_offset;
_geometry_instance_mark_dirty(ginstance);
}
-void RendererSceneRenderForward::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
- ginstance->data->cast_double_sided_shaodows = p_enable;
+ ginstance->data->cast_double_sided_shadows = p_enable;
_geometry_instance_mark_dirty(ginstance);
}
-void RendererSceneRenderForward::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
- ginstance->data->layer_mask = p_layer_mask;
- ginstance->push_constant.layer_mask = p_layer_mask;
+ ginstance->layer_mask = p_layer_mask;
}
-void RendererSceneRenderForward::geometry_instance_free(GeometryInstance *p_geometry_instance) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry_instance) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
if (ginstance->lightmap_sh != nullptr) {
geometry_instance_lightmap_sh.free(ginstance->lightmap_sh);
@@ -3101,29 +3287,29 @@ void RendererSceneRenderForward::geometry_instance_free(GeometryInstance *p_geom
geometry_instance_alloc.free(ginstance);
}
-uint32_t RendererSceneRenderForward::geometry_instance_get_pair_mask() {
+uint32_t RendererSceneRenderForwardClustered::geometry_instance_get_pair_mask() {
return (1 << RS::INSTANCE_GI_PROBE);
}
-void RendererSceneRenderForward::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
+void RendererSceneRenderForwardClustered::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
}
-void RendererSceneRenderForward::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
+void RendererSceneRenderForwardClustered::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
}
-void RendererSceneRenderForward::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
+void RendererSceneRenderForwardClustered::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
}
-Transform RendererSceneRenderForward::geometry_instance_get_transform(GeometryInstance *p_instance) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance);
+Transform RendererSceneRenderForwardClustered::geometry_instance_get_transform(GeometryInstance *p_instance) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance);
ERR_FAIL_COND_V(!ginstance, Transform());
- return ginstance->data->transform;
+ return ginstance->transform;
}
-AABB RendererSceneRenderForward::geometry_instance_get_aabb(GeometryInstance *p_instance) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance);
+AABB RendererSceneRenderForwardClustered::geometry_instance_get_aabb(GeometryInstance *p_instance) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance);
ERR_FAIL_COND_V(!ginstance, AABB());
return ginstance->data->aabb;
}
-void RendererSceneRenderForward::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) {
- GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+void RendererSceneRenderForwardClustered::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
if (p_gi_probe_instance_count > 0) {
ginstance->gi_probes[0] = p_gi_probe_instances[0];
@@ -3138,11 +3324,10 @@ void RendererSceneRenderForward::geometry_instance_pair_gi_probe_instances(Geome
}
}
-RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_storage) :
+RendererSceneRenderForwardClustered::RendererSceneRenderForwardClustered(RendererStorageRD *p_storage) :
RendererSceneRenderRD(p_storage) {
singleton = this;
low_end = is_low_end();
- storage = p_storage;
/* SCENE SHADER */
@@ -3156,7 +3341,7 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
if (is_using_radiance_cubemap_array()) {
defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
}
- defines += "\n#define SDFGI_OCT_SIZE " + itos(sdfgi_get_lightprobe_octahedron_size()) + "\n";
+ defines += "\n#define SDFGI_OCT_SIZE " + itos(gi.sdfgi_get_lightprobe_octahedron_size()) + "\n";
defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(get_max_directional_lights()) + "\n";
{
@@ -3339,7 +3524,7 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
- bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley");
+ bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley");
if (!force_lambert) {
actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
@@ -3351,7 +3536,7 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
actions.render_mode_defines["sss_mode_skin"] = "#define SSS_MODE_SKIN\n";
- bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx");
+ bool force_blinn = GLOBAL_GET("rendering/shading/overrides/force_blinn_over_ggx");
if (!force_blinn) {
actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
@@ -3382,18 +3567,13 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
shader.compiler.initialize(actions);
}
- //render list
- render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)128000);
- render_list.init();
- render_pass = 0;
-
- scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));
-
{
//default material and shader
- default_shader = storage->shader_create();
+ default_shader = storage->shader_allocate();
+ storage->shader_initialize(default_shader);
storage->shader_set_code(default_shader, "shader_type spatial; void vertex() { ROUGHNESS = 0.8; } void fragment() { ALBEDO=vec3(0.6); ROUGHNESS=0.8; METALLIC=0.2; } \n");
- default_material = storage->material_create();
+ default_material = storage->material_allocate();
+ storage->material_initialize(default_material);
storage->material_set_shader(default_material, default_shader);
MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
@@ -3404,14 +3584,18 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
}
{
- overdraw_material_shader = storage->shader_create();
+ overdraw_material_shader = storage->shader_allocate();
+ storage->shader_initialize(overdraw_material_shader);
storage->shader_set_code(overdraw_material_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }");
- overdraw_material = storage->material_create();
+ overdraw_material = storage->material_allocate();
+ storage->material_initialize(overdraw_material);
storage->material_set_shader(overdraw_material, overdraw_material_shader);
- wireframe_material_shader = storage->shader_create();
+ wireframe_material_shader = storage->shader_allocate();
+ storage->shader_initialize(wireframe_material_shader);
storage->shader_set_code(wireframe_material_shader, "shader_type spatial;\nrender_mode wireframe,unshaded;\n void fragment() { ALBEDO=vec3(0.0,0.0,0.0); }");
- wireframe_material = storage->material_create();
+ wireframe_material = storage->material_allocate();
+ storage->material_initialize(wireframe_material);
storage->material_set_shader(wireframe_material, wireframe_material_shader);
}
@@ -3435,15 +3619,17 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
- render_list_thread_threshold = GLOBAL_GET("rendering/forward_renderer/threaded_render_minimum_instances");
+ render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances");
}
-RendererSceneRenderForward::~RendererSceneRenderForward() {
+RendererSceneRenderForwardClustered::~RendererSceneRenderForwardClustered() {
directional_shadow_atlas_set_size(0);
//clear base uniform set if still valid
- if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
- RD::get_singleton()->free(render_pass_uniform_set);
+ for (uint32_t i = 0; i < render_pass_uniform_sets.size(); i++) {
+ if (render_pass_uniform_sets[i].is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_sets[i])) {
+ RD::get_singleton()->free(render_pass_uniform_sets[i]);
+ }
}
if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) {
@@ -3462,9 +3648,16 @@ RendererSceneRenderForward::~RendererSceneRenderForward() {
storage->free(default_material);
{
- RD::get_singleton()->free(scene_state.uniform_buffer);
+ for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) {
+ RD::get_singleton()->free(scene_state.uniform_buffers[i]);
+ }
RD::get_singleton()->free(scene_state.lightmap_buffer);
RD::get_singleton()->free(scene_state.lightmap_capture_buffer);
+ for (uint32_t i = 0; i < RENDER_LIST_MAX; i++) {
+ if (scene_state.instance_buffer[i] != RID()) {
+ RD::get_singleton()->free(scene_state.instance_buffer[i]);
+ }
+ }
memdelete_arr(scene_state.lightmap_captures);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.h b/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.h
index 0b57c7f76c..98e2a7efcc 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_forward.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene_render_forward.h */
+/* renderer_scene_render_forward_clustered.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,16 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_H
-#define RENDERING_SERVER_SCENE_RENDER_FORWARD_H
+#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
+#define RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
#include "core/templates/paged_allocator.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-#include "servers/rendering/renderer_rd/shaders/scene_forward.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h"
-class RendererSceneRenderForward : public RendererSceneRenderRD {
+class RendererSceneRenderForwardClustered : public RendererSceneRenderRD {
enum {
SCENE_UNIFORM_SET = 0,
RENDER_PASS_UNIFORM_SET = 1,
@@ -50,6 +50,15 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
MAX_GI_PROBES = 8,
MAX_LIGHTMAPS = 8,
MAX_GI_PROBES_PER_INSTANCE = 2,
+ INSTANCE_DATA_BUFFER_MIN_SIZE = 4096
+ };
+
+ enum RenderListType {
+ RENDER_LIST_OPAQUE, //used for opaque objects
+ RENDER_LIST_ALPHA, //used for transparent objects
+ RENDER_LIST_SECONDARY, //used for shadows and other objects
+ RENDER_LIST_MAX
+
};
/* Scene Shader */
@@ -70,12 +79,10 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
};
struct {
- SceneForwardShaderRD scene_shader;
+ SceneForwardClusteredShaderRD scene_shader;
ShaderCompilerRD compiler;
} shader;
- RendererStorageRD *storage;
-
/* Material */
struct ShaderData : public RendererStorageRD::ShaderData {
@@ -177,7 +184,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
RendererStorageRD::ShaderData *_create_shader_func();
static RendererStorageRD::ShaderData *_create_shader_funcs() {
- return static_cast<RendererSceneRenderForward *>(singleton)->_create_shader_func();
+ return static_cast<RendererSceneRenderForwardClustered *>(singleton)->_create_shader_func();
}
struct MaterialData : public RendererStorageRD::MaterialData {
@@ -199,7 +206,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
- return static_cast<RendererSceneRenderForward *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
+ return static_cast<RendererSceneRenderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
/* Framebuffer */
@@ -245,7 +252,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
RID shadow_sampler;
RID render_base_uniform_set;
- RID render_pass_uniform_set;
+ LocalVector<RID> render_pass_uniform_sets;
RID sdfgi_pass_uniform_set;
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
@@ -257,7 +264,58 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
void _update_render_base_uniform_set();
RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
- RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas = false);
+ RID _setup_render_pass_uniform_set(RenderListType p_render_list, RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas = false, int p_index = 0);
+
+ enum PassMode {
+ PASS_MODE_COLOR,
+ PASS_MODE_COLOR_SPECULAR,
+ PASS_MODE_COLOR_TRANSPARENT,
+ PASS_MODE_SHADOW,
+ PASS_MODE_SHADOW_DP,
+ PASS_MODE_DEPTH,
+ PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
+ PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE,
+ PASS_MODE_DEPTH_MATERIAL,
+ PASS_MODE_SDF,
+ };
+
+ struct GeometryInstanceSurfaceDataCache;
+ struct RenderElementInfo;
+
+ struct RenderListParameters {
+ GeometryInstanceSurfaceDataCache **elements = nullptr;
+ RenderElementInfo *element_info = nullptr;
+ int element_count = 0;
+ bool reverse_cull = false;
+ PassMode pass_mode = PASS_MODE_COLOR;
+ bool no_gi = false;
+ RID render_pass_uniform_set;
+ bool force_wireframe = false;
+ Vector2 uv_offset;
+ Plane lod_plane;
+ float lod_distance_multiplier = 0.0;
+ float screen_lod_threshold = 0.0;
+ RD::FramebufferFormatID framebuffer_format = 0;
+ uint32_t element_offset = 0;
+ uint32_t 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, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ elements = p_elements;
+ element_info = p_element_info;
+ element_count = p_element_count;
+ reverse_cull = p_reverse_cull;
+ pass_mode = p_pass_mode;
+ no_gi = p_no_gi;
+ render_pass_uniform_set = p_render_pass_uniform_set;
+ force_wireframe = p_force_wireframe;
+ uv_offset = p_uv_offset;
+ lod_plane = p_lod_plane;
+ lod_distance_multiplier = p_lod_distance_multiplier;
+ screen_lod_threshold = p_screen_lod_threshold;
+ element_offset = p_element_offset;
+ barrier = p_barrier;
+ }
+ };
struct LightmapData {
float normal_xform[12];
@@ -367,9 +425,24 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
uint32_t pancake_shadows;
};
+ struct PushConstant {
+ uint32_t base_index; //
+ uint32_t uv_offset; //packed
+ uint32_t pad[2];
+ };
+
+ struct InstanceData {
+ float transform[16];
+ uint32_t flags;
+ uint32_t instance_uniforms_ofs; //base offset in global buffer for instance variables
+ uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap index)
+ uint32_t layer_mask;
+ float lightmap_uv_scale[4];
+ };
+
UBO ubo;
- RID uniform_buffer;
+ LocalVector<RID> uniform_buffers;
LightmapData lightmaps[MAX_LIGHTMAPS];
RID lightmap_ids[MAX_LIGHTMAPS];
@@ -378,6 +451,10 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
uint32_t max_lightmaps;
RID lightmap_buffer;
+ RID instance_buffer[RENDER_LIST_MAX];
+ uint32_t instance_buffer_size[RENDER_LIST_MAX] = { 0, 0, 0 };
+ LocalVector<InstanceData> instance_data[RENDER_LIST_MAX];
+
LightmapCaptureData *lightmap_captures;
uint32_t max_lightmap_captures;
RID lightmap_capture_buffer;
@@ -390,11 +467,29 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
bool used_depth_texture = false;
bool used_sss = false;
+ struct ShadowPass {
+ uint32_t element_from;
+ uint32_t element_count;
+ bool flip_cull;
+ PassMode pass_mode;
+
+ RID rp_uniform_set;
+ Plane camera_plane;
+ float lod_distance_multiplier;
+ float screen_lod_threshold;
+
+ RID framebuffer;
+ RD::InitialAction initial_depth_action;
+ RD::FinalAction final_depth_action;
+ Rect2i rect;
+ };
+
+ LocalVector<ShadowPass> shadow_passes;
+
} scene_state;
- static RendererSceneRenderForward *singleton;
- uint64_t render_pass;
- double time;
+ static RendererSceneRenderForwardClustered *singleton;
+
RID default_shader;
RID default_material;
RID overdraw_material_shader;
@@ -407,51 +502,15 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
RID default_vec4_xform_buffer;
RID default_vec4_xform_uniform_set;
- enum PassMode {
- PASS_MODE_COLOR,
- PASS_MODE_COLOR_SPECULAR,
- PASS_MODE_COLOR_TRANSPARENT,
- PASS_MODE_SHADOW,
- PASS_MODE_SHADOW_DP,
- PASS_MODE_DEPTH,
- PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
- PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE,
- PASS_MODE_DEPTH_MATERIAL,
- PASS_MODE_SDF,
- };
-
- void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
+ void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0);
void _setup_giprobes(const PagedArray<RID> &p_giprobes);
void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform);
- struct GeometryInstanceSurfaceDataCache;
-
- struct RenderListParameters {
- GeometryInstanceSurfaceDataCache **elements = nullptr;
- int element_count = 0;
- bool reverse_cull = false;
- PassMode pass_mode = PASS_MODE_COLOR;
- bool no_gi = false;
- RID render_pass_uniform_set;
- bool force_wireframe = false;
- Vector2 uv_offset;
- Plane lod_plane;
- float lod_distance_multiplier = 0.0;
- float screen_lod_threshold = 0.0;
- RD::FramebufferFormatID framebuffer_format = 0;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) {
- elements = p_elements;
- element_count = p_element_count;
- reverse_cull = p_reverse_cull;
- pass_mode = p_pass_mode;
- no_gi = p_no_gi;
- render_pass_uniform_set = p_render_pass_uniform_set;
- force_wireframe = p_force_wireframe;
- uv_offset = p_uv_offset;
- lod_plane = p_lod_plane;
- lod_distance_multiplier = p_lod_distance_multiplier;
- screen_lod_threshold = p_screen_lod_threshold;
- }
+ struct RenderElementInfo {
+ uint32_t repeat : 22;
+ uint32_t uses_lightmap : 1;
+ uint32_t uses_forward_gi : 1;
+ uint32_t lod_index : 8;
};
template <PassMode p_pass_mode>
@@ -465,12 +524,14 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
uint32_t render_list_thread_threshold = 500;
- void _fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false, bool p_using_opaque_gi = false);
+ void _update_instance_data_buffer(RenderListType p_render_list);
+ void _fill_instance_data(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
+ void _fill_render_list(RenderListType p_render_list, const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, const Plane &p_lod_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, bool p_append = false);
Map<Size2i, RID> sdfgi_framebuffer_size_cache;
struct GeometryInstanceData;
- struct GeometryInstanceForward;
+ struct GeometryInstanceForwardClustered;
struct GeometryInstanceLightmapSH {
Color sh[9];
@@ -493,14 +554,17 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
union {
struct {
- uint32_t geometry_id;
- uint32_t material_id;
- uint32_t shader_id;
- uint32_t surface_type : 4;
- uint32_t uses_forward_gi : 1; //set during addition
- uint32_t uses_lightmap : 1; //set during addition
- uint32_t depth_layer : 4; //set during addition
- uint32_t priority : 8;
+ uint64_t lod_index : 8;
+ uint64_t surface_index : 10;
+ uint64_t geometry_id : 32;
+ uint64_t material_id_low : 14;
+
+ uint64_t material_id_hi : 18;
+ uint64_t shader_id : 32;
+ uint64_t uses_forward_gi : 1;
+ uint64_t uses_lightmap : 1;
+ uint64_t depth_layer : 4;
+ uint64_t priority : 8;
};
struct {
uint64_t sort_key1;
@@ -521,10 +585,10 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
ShaderData *shader_shadow = nullptr;
GeometryInstanceSurfaceDataCache *next = nullptr;
- GeometryInstanceForward *owner = nullptr;
+ GeometryInstanceForwardClustered *owner = nullptr;
};
- struct GeometryInstanceForward : public GeometryInstance {
+ struct GeometryInstanceForwardClustered : public GeometryInstance {
//used during rendering
bool mirror = false;
bool non_uniform_scale = false;
@@ -532,25 +596,25 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
float lod_model_scale = 1.0;
AABB transformed_aabb; //needed for LOD
float depth = 0;
- struct PushConstant {
- float transform[16];
- uint32_t flags;
- uint32_t instance_uniforms_ofs; //base offset in global buffer for instance variables
- uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap index)
- uint32_t layer_mask;
- float lightmap_uv_scale[4];
- } push_constant;
+ uint32_t gi_offset_cache = 0;
+ uint32_t flags_cache = 0;
+ bool store_transform_cache = true;
+ int32_t shader_parameters_offset = -1;
+ uint32_t lightmap_slice_index;
+ Rect2 lightmap_uv_scale;
+ uint32_t layer_mask = 1;
RID transforms_uniform_set;
uint32_t instance_count = 0;
RID mesh_instance;
bool can_sdfgi = false;
//used during setup
uint32_t base_flags = 0;
+ Transform transform;
RID gi_probes[MAX_GI_PROBES_PER_INSTANCE];
RID lightmap_instance;
GeometryInstanceLightmapSH *lightmap_sh = nullptr;
GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
- SelfList<GeometryInstanceForward> dirty_list_element;
+ SelfList<GeometryInstanceForwardClustered> dirty_list_element;
struct Data {
//data used less often goes into regular heap
@@ -558,21 +622,14 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
RS::InstanceType base_type;
RID skeleton;
-
- uint32_t layer_mask = 1;
-
Vector<RID> surface_materials;
RID material_override;
- Transform transform;
AABB aabb;
- int32_t shader_parameters_offset = -1;
bool use_dynamic_gi = false;
bool use_baked_light = false;
- bool cast_double_sided_shaodows = false;
+ bool cast_double_sided_shadows = false;
bool mirror = false;
- Rect2 lightmap_uv_scale;
- uint32_t lightmap_slice_index = 0;
bool dirty_dependencies = false;
RendererStorage::DependencyTracker dependency_tracker;
@@ -580,21 +637,21 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
Data *data = nullptr;
- GeometryInstanceForward() :
+ GeometryInstanceForwardClustered() :
dirty_list_element(this) {}
};
static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
- SelfList<GeometryInstanceForward>::List geometry_instance_dirty_list;
+ SelfList<GeometryInstanceForwardClustered>::List geometry_instance_dirty_list;
- PagedAllocator<GeometryInstanceForward> geometry_instance_alloc;
+ PagedAllocator<GeometryInstanceForwardClustered> geometry_instance_alloc;
PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc;
PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh;
- void _geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
- void _geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
+ void _geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
+ void _geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
void _geometry_instance_update(GeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances();
@@ -604,16 +661,12 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
/* Render List */
struct RenderList {
- int max_elements;
-
- GeometryInstanceSurfaceDataCache **elements = nullptr;
-
- int element_count;
- int alpha_element_count;
+ LocalVector<GeometryInstanceSurfaceDataCache *> elements;
+ LocalVector<RenderElementInfo> element_info;
void clear() {
- element_count = 0;
- alpha_element_count = 0;
+ elements.clear();
+ element_info.clear();
}
//should eventually be replaced by radix
@@ -624,13 +677,14 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
}
};
- void sort_by_key(bool p_alpha) {
+ void sort_by_key() {
SortArray<GeometryInstanceSurfaceDataCache *, SortByKey> sorter;
- if (p_alpha) {
- sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
- } else {
- sorter.sort(elements, element_count);
- }
+ sorter.sort(elements.ptr(), elements.size());
+ }
+
+ void sort_by_key_range(uint32_t p_from, uint32_t p_size) {
+ SortArray<GeometryInstanceSurfaceDataCache *, SortByKey> sorter;
+ sorter.sort(elements.ptr() + p_from, p_size);
}
struct SortByDepth {
@@ -639,14 +693,10 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
}
};
- void sort_by_depth(bool p_alpha) { //used for shadows
+ void sort_by_depth() { //used for shadows
SortArray<GeometryInstanceSurfaceDataCache *, SortByDepth> sorter;
- if (p_alpha) {
- sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
- } else {
- sorter.sort(elements, element_count);
- }
+ sorter.sort(elements.ptr(), elements.size());
}
struct SortByReverseDepthAndPriority {
@@ -658,50 +708,24 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
SortArray<GeometryInstanceSurfaceDataCache *, SortByReverseDepthAndPriority> sorter;
- if (p_alpha) {
- sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
- } else {
- sorter.sort(elements, element_count);
- }
+ sorter.sort(elements.ptr(), elements.size());
}
_FORCE_INLINE_ void add_element(GeometryInstanceSurfaceDataCache *p_element) {
- if (element_count + alpha_element_count >= max_elements) {
- return;
- }
- elements[element_count] = p_element;
- element_count++;
- }
-
- _FORCE_INLINE_ void add_alpha_element(GeometryInstanceSurfaceDataCache *p_element) {
- if (element_count + alpha_element_count >= max_elements) {
- return;
- }
- int idx = max_elements - alpha_element_count - 1;
- elements[idx] = p_element;
- alpha_element_count++;
- }
-
- void init() {
- element_count = 0;
- alpha_element_count = 0;
- elements = memnew_arr(GeometryInstanceSurfaceDataCache *, max_elements);
- }
-
- RenderList() {
- max_elements = 0;
- }
-
- ~RenderList() {
- memdelete_arr(elements);
+ elements.push_back(p_element);
}
};
- RenderList render_list;
+ RenderList render_list[RENDER_LIST_MAX];
protected:
- virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
- virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_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);
+ virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
+
+ virtual void _render_shadow_begin();
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &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_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);
+ virtual void _render_shadow_process();
+ virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
@@ -734,11 +758,9 @@ public:
virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count);
virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count);
- virtual void set_time(double p_time, double p_step);
-
virtual bool free(RID p_rid);
- RendererSceneRenderForward(RendererStorageRD *p_storage);
- ~RendererSceneRenderForward();
+ RendererSceneRenderForwardClustered(RendererStorageRD *p_storage);
+ ~RendererSceneRenderForwardClustered();
};
-#endif // RASTERIZER_SCENE_HIGHEND_RD_H
+#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index d5c9ccd956..4cf296f0db 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -35,8 +35,6 @@
#include "renderer_compositor_rd.h"
#include "servers/rendering/rendering_server_default.h"
-uint64_t RendererSceneRenderRD::auto_exposure_counter = 2;
-
void get_vogel_disk(float *r_kernel, int p_sample_count) {
const float golden_angle = 2.4;
@@ -49,973 +47,42 @@ void get_vogel_disk(float *r_kernel, int p_sample_count) {
}
}
-void RendererSceneRenderRD::_clear_reflection_data(ReflectionData &rd) {
- rd.layers.clear();
- rd.radiance_base_cubemap = RID();
- if (rd.downsampled_radiance_cubemap.is_valid()) {
- RD::get_singleton()->free(rd.downsampled_radiance_cubemap);
- }
- rd.downsampled_radiance_cubemap = RID();
- rd.downsampled_layer.mipmaps.clear();
- rd.coefficient_buffer = RID();
-}
-
-void RendererSceneRenderRD::_update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality) {
- //recreate radiance and all data
-
- int mipmaps = p_mipmaps;
- uint32_t w = p_size, h = p_size;
-
- if (p_use_array) {
- int layers = p_low_quality ? 8 : roughness_layers;
-
- for (int i = 0; i < layers; i++) {
- ReflectionData::Layer layer;
- uint32_t mmw = w;
- uint32_t mmh = h;
- layer.mipmaps.resize(mipmaps);
- layer.views.resize(mipmaps);
- for (int j = 0; j < mipmaps; j++) {
- ReflectionData::Layer::Mipmap &mm = layer.mipmaps.write[j];
- mm.size.width = mmw;
- mm.size.height = mmh;
- for (int k = 0; k < 6; k++) {
- mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6 + k, j);
- Vector<RID> fbtex;
- fbtex.push_back(mm.views[k]);
- mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
- }
-
- layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6, j, RD::TEXTURE_SLICE_CUBEMAP);
-
- mmw = MAX(1, mmw >> 1);
- mmh = MAX(1, mmh >> 1);
- }
-
- rd.layers.push_back(layer);
- }
-
- } else {
- mipmaps = p_low_quality ? 8 : mipmaps;
- //regular cubemap, lower quality (aliasing, less memory)
- ReflectionData::Layer layer;
- uint32_t mmw = w;
- uint32_t mmh = h;
- layer.mipmaps.resize(mipmaps);
- layer.views.resize(mipmaps);
- for (int j = 0; j < mipmaps; j++) {
- ReflectionData::Layer::Mipmap &mm = layer.mipmaps.write[j];
- mm.size.width = mmw;
- mm.size.height = mmh;
- for (int k = 0; k < 6; k++) {
- mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + k, j);
- Vector<RID> fbtex;
- fbtex.push_back(mm.views[k]);
- mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
- }
-
- layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, j, RD::TEXTURE_SLICE_CUBEMAP);
-
- mmw = MAX(1, mmw >> 1);
- mmh = MAX(1, mmh >> 1);
- }
-
- rd.layers.push_back(layer);
- }
-
- rd.radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, RD::TEXTURE_SLICE_CUBEMAP);
-
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = 64; // Always 64x64
- tf.height = 64;
- tf.texture_type = RD::TEXTURE_TYPE_CUBE;
- tf.array_layers = 6;
- tf.mipmaps = 7;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
-
- rd.downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
- {
- uint32_t mmw = 64;
- uint32_t mmh = 64;
- rd.downsampled_layer.mipmaps.resize(7);
- for (int j = 0; j < rd.downsampled_layer.mipmaps.size(); j++) {
- ReflectionData::DownsampleLayer::Mipmap &mm = rd.downsampled_layer.mipmaps.write[j];
- mm.size.width = mmw;
- mm.size.height = mmh;
- mm.view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rd.downsampled_radiance_cubemap, 0, j, RD::TEXTURE_SLICE_CUBEMAP);
-
- mmw = MAX(1, mmw >> 1);
- mmh = MAX(1, mmh >> 1);
- }
- }
-}
-
-void RendererSceneRenderRD::_create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays) {
- storage->get_effects()->cubemap_downsample(rd.radiance_base_cubemap, rd.downsampled_layer.mipmaps[0].view, rd.downsampled_layer.mipmaps[0].size);
-
- for (int i = 1; i < rd.downsampled_layer.mipmaps.size(); i++) {
- storage->get_effects()->cubemap_downsample(rd.downsampled_layer.mipmaps[i - 1].view, rd.downsampled_layer.mipmaps[i].view, rd.downsampled_layer.mipmaps[i].size);
- }
-
- Vector<RID> views;
- if (p_use_arrays) {
- for (int i = 1; i < rd.layers.size(); i++) {
- views.push_back(rd.layers[i].views[0]);
- }
- } else {
- for (int i = 1; i < rd.layers[0].views.size(); i++) {
- views.push_back(rd.layers[0].views[i]);
- }
- }
-
- storage->get_effects()->cubemap_filter(rd.downsampled_radiance_cubemap, views, p_use_arrays);
-}
-
-void RendererSceneRenderRD::_create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer) {
- if (p_use_arrays) {
- //render directly to the layers
- storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, rd.layers[p_base_layer].views[0], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers.size() - 1.0), rd.layers[p_base_layer].mipmaps[0].size.x);
- } else {
- storage->get_effects()->cubemap_roughness(rd.layers[0].views[p_base_layer - 1], rd.layers[0].views[p_base_layer], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers[0].mipmaps.size() - 1.0), rd.layers[0].mipmaps[p_base_layer].size.x);
- }
-}
-
-void RendererSceneRenderRD::_update_reflection_mipmaps(ReflectionData &rd, int p_start, int p_end) {
- for (int i = p_start; i < p_end; i++) {
- for (int j = 0; j < rd.layers[i].views.size() - 1; j++) {
- RID view = rd.layers[i].views[j];
- RID texture = rd.layers[i].views[j + 1];
- Size2i size = rd.layers[i].mipmaps[j + 1].size;
- storage->get_effects()->cubemap_downsample(view, texture, size);
- }
- }
-}
-
-void RendererSceneRenderRD::_sdfgi_erase(RenderBuffers *rb) {
- for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) {
- const SDFGI::Cascade &c = rb->sdfgi->cascades[i];
- RD::get_singleton()->free(c.light_data);
- RD::get_singleton()->free(c.light_aniso_0_tex);
- RD::get_singleton()->free(c.light_aniso_1_tex);
- RD::get_singleton()->free(c.sdf_tex);
- RD::get_singleton()->free(c.solid_cell_dispatch_buffer);
- RD::get_singleton()->free(c.solid_cell_buffer);
- RD::get_singleton()->free(c.lightprobe_history_tex);
- RD::get_singleton()->free(c.lightprobe_average_tex);
- RD::get_singleton()->free(c.lights_buffer);
- }
-
- RD::get_singleton()->free(rb->sdfgi->render_albedo);
- RD::get_singleton()->free(rb->sdfgi->render_emission);
- RD::get_singleton()->free(rb->sdfgi->render_emission_aniso);
-
- RD::get_singleton()->free(rb->sdfgi->render_sdf[0]);
- RD::get_singleton()->free(rb->sdfgi->render_sdf[1]);
-
- RD::get_singleton()->free(rb->sdfgi->render_sdf_half[0]);
- RD::get_singleton()->free(rb->sdfgi->render_sdf_half[1]);
-
- for (int i = 0; i < 8; i++) {
- RD::get_singleton()->free(rb->sdfgi->render_occlusion[i]);
- }
-
- RD::get_singleton()->free(rb->sdfgi->render_geom_facing);
-
- RD::get_singleton()->free(rb->sdfgi->lightprobe_data);
- RD::get_singleton()->free(rb->sdfgi->lightprobe_history_scroll);
- RD::get_singleton()->free(rb->sdfgi->occlusion_data);
- RD::get_singleton()->free(rb->sdfgi->ambient_texture);
-
- RD::get_singleton()->free(rb->sdfgi->cascades_ubo);
-
- memdelete(rb->sdfgi);
-
- rb->sdfgi = nullptr;
-}
-
-const Vector3i RendererSceneRenderRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF);
-
void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) {
- Environment *env = environment_owner.getornull(p_environment);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_environment);
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
bool needs_sdfgi = env && env->sdfgi_enabled;
if (!needs_sdfgi) {
if (rb->sdfgi != nullptr) {
//erase it
- _sdfgi_erase(rb);
+ rb->sdfgi->erase();
+ memdelete(rb->sdfgi);
+ rb->sdfgi = nullptr;
+
_render_buffers_uniform_set_changed(p_render_buffers);
}
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[sdfgi_frames_to_converge];
+ uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge];
if (rb->sdfgi && (rb->sdfgi->cascade_mode != env->sdfgi_cascades || rb->sdfgi->min_cell_size != env->sdfgi_min_cell_size || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != env->sdfgi_use_occlusion || rb->sdfgi->y_scale_mode != env->sdfgi_y_scale)) {
//configuration changed, erase
- _sdfgi_erase(rb);
+ rb->sdfgi->erase();
+ memdelete(rb->sdfgi);
+ rb->sdfgi = nullptr;
}
- SDFGI *sdfgi = rb->sdfgi;
+ RendererSceneGIRD::SDFGI *sdfgi = rb->sdfgi;
if (sdfgi == nullptr) {
- //re-create
- rb->sdfgi = memnew(SDFGI);
- sdfgi = rb->sdfgi;
- sdfgi->cascade_mode = env->sdfgi_cascades;
- sdfgi->min_cell_size = env->sdfgi_min_cell_size;
- sdfgi->uses_occlusion = env->sdfgi_use_occlusion;
- sdfgi->y_scale_mode = env->sdfgi_y_scale;
- static const float y_scale[3] = { 1.0, 1.5, 2.0 };
- sdfgi->y_mult = y_scale[sdfgi->y_scale_mode];
- static const int cascasde_size[3] = { 4, 6, 8 };
- sdfgi->cascades.resize(cascasde_size[sdfgi->cascade_mode]);
- sdfgi->probe_axis_count = SDFGI::PROBE_DIVISOR + 1;
- sdfgi->solid_cell_ratio = sdfgi_solid_cell_ratio;
- sdfgi->solid_cell_count = uint32_t(float(sdfgi->cascade_size * sdfgi->cascade_size * sdfgi->cascade_size) * sdfgi->solid_cell_ratio);
-
- float base_cell_size = sdfgi->min_cell_size;
-
- RD::TextureFormat tf_sdf;
- tf_sdf.format = RD::DATA_FORMAT_R8_UNORM;
- tf_sdf.width = sdfgi->cascade_size; // Always 64x64
- tf_sdf.height = sdfgi->cascade_size;
- tf_sdf.depth = sdfgi->cascade_size;
- tf_sdf.texture_type = RD::TEXTURE_TYPE_3D;
- tf_sdf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
-
- {
- RD::TextureFormat tf_render = tf_sdf;
- tf_render.format = RD::DATA_FORMAT_R16_UINT;
- sdfgi->render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- tf_render.format = RD::DATA_FORMAT_R32_UINT;
- sdfgi->render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- sdfgi->render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
-
- tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize
-
- for (int i = 0; i < 8; i++) {
- sdfgi->render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- }
-
- tf_render.format = RD::DATA_FORMAT_R32_UINT;
- sdfgi->render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
-
- tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
- sdfgi->render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- sdfgi->render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
-
- tf_render.width /= 2;
- tf_render.height /= 2;
- tf_render.depth /= 2;
-
- sdfgi->render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- sdfgi->render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- }
-
- RD::TextureFormat tf_occlusion = tf_sdf;
- tf_occlusion.format = RD::DATA_FORMAT_R16_UINT;
- tf_occlusion.shareable_formats.push_back(RD::DATA_FORMAT_R16_UINT);
- tf_occlusion.shareable_formats.push_back(RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16);
- tf_occlusion.depth *= sdfgi->cascades.size(); //use depth for occlusion slices
- tf_occlusion.width *= 2; //use width for the other half
-
- RD::TextureFormat tf_light = tf_sdf;
- tf_light.format = RD::DATA_FORMAT_R32_UINT;
- tf_light.shareable_formats.push_back(RD::DATA_FORMAT_R32_UINT);
- tf_light.shareable_formats.push_back(RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32);
-
- RD::TextureFormat tf_aniso0 = tf_sdf;
- tf_aniso0.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- RD::TextureFormat tf_aniso1 = tf_sdf;
- tf_aniso1.format = RD::DATA_FORMAT_R8G8_UNORM;
-
- int passes = nearest_shift(sdfgi->cascade_size) - 1;
-
- //store lightprobe SH
- RD::TextureFormat tf_probes;
- tf_probes.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf_probes.width = sdfgi->probe_axis_count * sdfgi->probe_axis_count;
- tf_probes.height = sdfgi->probe_axis_count * SDFGI::SH_SIZE;
- tf_probes.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
- tf_probes.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
-
- sdfgi->history_size = requested_history_size;
-
- RD::TextureFormat tf_probe_history = tf_probes;
- tf_probe_history.format = RD::DATA_FORMAT_R16G16B16A16_SINT; //signed integer because SH are signed
- tf_probe_history.array_layers = sdfgi->history_size;
-
- RD::TextureFormat tf_probe_average = tf_probes;
- tf_probe_average.format = RD::DATA_FORMAT_R32G32B32A32_SINT; //signed integer because SH are signed
- tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D;
-
- sdfgi->lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
- sdfgi->lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
-
- {
- //octahedral lightprobes
- RD::TextureFormat tf_octprobes = tf_probes;
- tf_octprobes.array_layers = sdfgi->cascades.size() * 2;
- tf_octprobes.format = RD::DATA_FORMAT_R32_UINT; //pack well with RGBE
- tf_octprobes.width = sdfgi->probe_axis_count * sdfgi->probe_axis_count * (SDFGI::LIGHTPROBE_OCT_SIZE + 2);
- tf_octprobes.height = sdfgi->probe_axis_count * (SDFGI::LIGHTPROBE_OCT_SIZE + 2);
- tf_octprobes.shareable_formats.push_back(RD::DATA_FORMAT_R32_UINT);
- tf_octprobes.shareable_formats.push_back(RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32);
- //lightprobe texture is an octahedral texture
-
- sdfgi->lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView());
- RD::TextureView tv;
- tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
- sdfgi->lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, sdfgi->lightprobe_data);
-
- //texture handling ambient data, to integrate with volumetric foc
- RD::TextureFormat tf_ambient = tf_probes;
- tf_ambient.array_layers = sdfgi->cascades.size();
- tf_ambient.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; //pack well with RGBE
- tf_ambient.width = sdfgi->probe_axis_count * sdfgi->probe_axis_count;
- tf_ambient.height = sdfgi->probe_axis_count;
- tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- //lightprobe texture is an octahedral texture
- sdfgi->ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView());
- }
-
- sdfgi->cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES);
-
- sdfgi->occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView());
- {
- RD::TextureView tv;
- tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16;
- sdfgi->occlusion_texture = RD::get_singleton()->texture_create_shared(tv, sdfgi->occlusion_data);
- }
-
- for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) {
- SDFGI::Cascade &cascade = sdfgi->cascades[i];
-
- /* 3D Textures */
-
- cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView());
-
- cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView());
-
- cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView());
- cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView());
-
- {
- RD::TextureView tv;
- tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
- cascade.light_tex = RD::get_singleton()->texture_create_shared(tv, cascade.light_data);
-
- RD::get_singleton()->texture_clear(cascade.light_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
- RD::get_singleton()->texture_clear(cascade.light_aniso_0_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
- RD::get_singleton()->texture_clear(cascade.light_aniso_1_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
- }
-
- cascade.cell_size = base_cell_size;
- Vector3 world_position = p_world_position;
- world_position.y *= sdfgi->y_mult;
- int32_t probe_cells = sdfgi->cascade_size / SDFGI::PROBE_DIVISOR;
- Vector3 probe_size = Vector3(1, 1, 1) * cascade.cell_size * probe_cells;
- Vector3i probe_pos = Vector3i((world_position / probe_size + Vector3(0.5, 0.5, 0.5)).floor());
- cascade.position = probe_pos * probe_cells;
-
- cascade.dirty_regions = SDFGI::Cascade::DIRTY_ALL;
-
- base_cell_size *= 2.0;
-
- /* Probe History */
-
- cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
- RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work
-
- cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
- RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work
-
- /* Buffers */
-
- cascade.solid_cell_buffer = RD::get_singleton()->storage_buffer_create(sizeof(SDFGI::Cascade::SolidCell) * sdfgi->solid_cell_count);
- cascade.solid_cell_dispatch_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4, Vector<uint8_t>(), RD::STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT);
- cascade.lights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(SDGIShader::Light) * MAX(SDFGI::MAX_STATIC_LIGHTS, SDFGI::MAX_DYNAMIC_LIGHTS));
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.ids.push_back(sdfgi->render_sdf[(passes & 1) ? 1 : 0]); //if passes are even, we read from buffer 0, else we read from buffer 1
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.ids.push_back(sdfgi->render_albedo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 3;
- for (int j = 0; j < 8; j++) {
- u.ids.push_back(sdfgi->render_occlusion[j]);
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 4;
- u.ids.push_back(sdfgi->render_emission);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 5;
- u.ids.push_back(sdfgi->render_emission_aniso);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 6;
- u.ids.push_back(sdfgi->render_geom_facing);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 7;
- u.ids.push_back(cascade.sdf_tex);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 8;
- u.ids.push_back(sdfgi->occlusion_data);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 10;
- u.ids.push_back(cascade.solid_cell_dispatch_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 11;
- u.ids.push_back(cascade.solid_cell_buffer);
- uniforms.push_back(u);
- }
-
- cascade.sdf_store_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_STORE), 0);
- }
-
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.ids.push_back(sdfgi->render_albedo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.ids.push_back(sdfgi->render_geom_facing);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 3;
- u.ids.push_back(sdfgi->render_emission);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 4;
- u.ids.push_back(sdfgi->render_emission_aniso);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 5;
- u.ids.push_back(cascade.solid_cell_dispatch_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 6;
- u.ids.push_back(cascade.solid_cell_buffer);
- uniforms.push_back(u);
- }
-
- cascade.scroll_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_SCROLL), 0);
- }
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- for (int j = 0; j < 8; j++) {
- u.ids.push_back(sdfgi->render_occlusion[j]);
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.ids.push_back(sdfgi->occlusion_data);
- uniforms.push_back(u);
- }
-
- cascade.scroll_occlusion_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_SCROLL_OCCLUSION), 0);
- }
- }
-
- //direct light
- for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) {
- SDFGI::Cascade &cascade = sdfgi->cascades[i];
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (j < rb->sdfgi->cascades.size()) {
- u.ids.push_back(rb->sdfgi->cascades[j].sdf_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 3;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(cascade.solid_cell_dispatch_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 4;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(cascade.solid_cell_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 5;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.ids.push_back(cascade.light_data);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 6;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.ids.push_back(cascade.light_aniso_0_tex);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 7;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.ids.push_back(cascade.light_aniso_1_tex);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 8;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(rb->sdfgi->cascades_ubo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 9;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(cascade.lights_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 10;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(rb->sdfgi->lightprobe_texture);
- uniforms.push_back(u);
- }
-
- cascade.sdf_direct_light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, 0), 0);
- }
-
- //preprocess initialize uniform set
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.ids.push_back(sdfgi->render_albedo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.ids.push_back(sdfgi->render_sdf[0]);
- uniforms.push_back(u);
- }
-
- sdfgi->sdf_initialize_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE), 0);
- }
-
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.ids.push_back(sdfgi->render_albedo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.ids.push_back(sdfgi->render_sdf_half[0]);
- uniforms.push_back(u);
- }
-
- sdfgi->sdf_initialize_half_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF), 0);
- }
-
- //jump flood uniform set
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.ids.push_back(sdfgi->render_sdf[0]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.ids.push_back(sdfgi->render_sdf[1]);
- uniforms.push_back(u);
- }
-
- sdfgi->jump_flood_uniform_set[0] = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
- SWAP(uniforms.write[0].ids.write[0], uniforms.write[1].ids.write[0]);
- sdfgi->jump_flood_uniform_set[1] = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
- }
- //jump flood half uniform set
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.ids.push_back(sdfgi->render_sdf_half[0]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.ids.push_back(sdfgi->render_sdf_half[1]);
- uniforms.push_back(u);
- }
-
- sdfgi->jump_flood_half_uniform_set[0] = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
- SWAP(uniforms.write[0].ids.write[0], uniforms.write[1].ids.write[0]);
- sdfgi->jump_flood_half_uniform_set[1] = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
- }
-
- //upscale half size sdf
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.ids.push_back(sdfgi->render_albedo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.ids.push_back(sdfgi->render_sdf_half[(passes & 1) ? 0 : 1]); //reverse pass order because half size
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 3;
- u.ids.push_back(sdfgi->render_sdf[(passes & 1) ? 0 : 1]); //reverse pass order because it needs an extra JFA pass
- uniforms.push_back(u);
- }
-
- sdfgi->upscale_jfa_uniform_set_index = (passes & 1) ? 0 : 1;
- sdfgi->sdf_upscale_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD_UPSCALE), 0);
- }
-
- //occlusion uniform set
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.ids.push_back(sdfgi->render_albedo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- for (int i = 0; i < 8; i++) {
- u.ids.push_back(sdfgi->render_occlusion[i]);
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 3;
- u.ids.push_back(sdfgi->render_geom_facing);
- uniforms.push_back(u);
- }
-
- sdfgi->occlusion_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_OCCLUSION), 0);
- }
-
- for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) {
- //integrate uniform
-
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (j < sdfgi->cascades.size()) {
- u.ids.push_back(sdfgi->cascades[j].sdf_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (j < sdfgi->cascades.size()) {
- u.ids.push_back(sdfgi->cascades[j].light_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 3;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (j < sdfgi->cascades.size()) {
- u.ids.push_back(sdfgi->cascades[j].light_aniso_0_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 4;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (j < sdfgi->cascades.size()) {
- u.ids.push_back(sdfgi->cascades[j].light_aniso_1_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 6;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 7;
- u.ids.push_back(sdfgi->cascades_ubo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 8;
- u.ids.push_back(sdfgi->lightprobe_data);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 9;
- u.ids.push_back(sdfgi->cascades[i].lightprobe_history_tex);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 10;
- u.ids.push_back(sdfgi->cascades[i].lightprobe_average_tex);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 11;
- u.ids.push_back(sdfgi->lightprobe_history_scroll);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 12;
- u.ids.push_back(sdfgi->lightprobe_average_scroll);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 13;
- RID parent_average;
- if (i < sdfgi->cascades.size() - 1) {
- parent_average = sdfgi->cascades[i + 1].lightprobe_average_tex;
- } else {
- parent_average = sdfgi->cascades[i - 1].lightprobe_average_tex; //to use something, but it won't be used
- }
- u.ids.push_back(parent_average);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 14;
- u.ids.push_back(sdfgi->ambient_texture);
- uniforms.push_back(u);
- }
-
- sdfgi->cascades[i].integrate_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 0);
- }
-
- sdfgi->uses_multibounce = env->sdfgi_use_multibounce;
- sdfgi->energy = env->sdfgi_energy;
- sdfgi->normal_bias = env->sdfgi_normal_bias;
- sdfgi->probe_bias = env->sdfgi_probe_bias;
- sdfgi->reads_sky = env->sdfgi_read_sky_light;
+ // re-create
+ rb->sdfgi = gi.create_sdfgi(env, p_world_position, requested_history_size);
_render_buffers_uniform_set_changed(p_render_buffers);
-
- return; //done. all levels will need to be rendered which its going to take a bit
- }
-
- //check for updates
-
- sdfgi->uses_multibounce = env->sdfgi_use_multibounce;
- sdfgi->energy = env->sdfgi_energy;
- sdfgi->normal_bias = env->sdfgi_normal_bias;
- sdfgi->probe_bias = env->sdfgi_probe_bias;
- sdfgi->reads_sky = env->sdfgi_read_sky_light;
-
- int32_t drag_margin = (sdfgi->cascade_size / SDFGI::PROBE_DIVISOR) / 2;
-
- for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) {
- SDFGI::Cascade &cascade = sdfgi->cascades[i];
- cascade.dirty_regions = Vector3i();
-
- Vector3 probe_half_size = Vector3(1, 1, 1) * cascade.cell_size * float(sdfgi->cascade_size / SDFGI::PROBE_DIVISOR) * 0.5;
- probe_half_size = Vector3(0, 0, 0);
-
- Vector3 world_position = p_world_position;
- world_position.y *= sdfgi->y_mult;
- Vector3i pos_in_cascade = Vector3i((world_position + probe_half_size) / cascade.cell_size);
-
- for (int j = 0; j < 3; j++) {
- if (pos_in_cascade[j] < cascade.position[j]) {
- while (pos_in_cascade[j] < (cascade.position[j] - drag_margin)) {
- cascade.position[j] -= drag_margin * 2;
- cascade.dirty_regions[j] += drag_margin * 2;
- }
- } else if (pos_in_cascade[j] > cascade.position[j]) {
- while (pos_in_cascade[j] > (cascade.position[j] + drag_margin)) {
- cascade.position[j] += drag_margin * 2;
- cascade.dirty_regions[j] -= drag_margin * 2;
- }
- }
-
- if (cascade.dirty_regions[j] == 0) {
- continue; // not dirty
- } else if (uint32_t(ABS(cascade.dirty_regions[j])) >= sdfgi->cascade_size) {
- //moved too much, just redraw everything (make all dirty)
- cascade.dirty_regions = SDFGI::Cascade::DIRTY_ALL;
- break;
- }
- }
-
- if (cascade.dirty_regions != Vector3i() && cascade.dirty_regions != SDFGI::Cascade::DIRTY_ALL) {
- //see how much the total dirty volume represents from the total volume
- uint32_t total_volume = sdfgi->cascade_size * sdfgi->cascade_size * sdfgi->cascade_size;
- uint32_t safe_volume = 1;
- for (int j = 0; j < 3; j++) {
- safe_volume *= sdfgi->cascade_size - ABS(cascade.dirty_regions[j]);
- }
- uint32_t dirty_volume = total_volume - safe_volume;
- if (dirty_volume > (safe_volume / 2)) {
- //more than half the volume is dirty, make all dirty so its only rendered once
- cascade.dirty_regions = SDFGI::Cascade::DIRTY_ALL;
- }
- }
+ } else {
+ //check for updates
+ rb->sdfgi->update(env, p_world_position);
}
}
@@ -1030,9 +97,9 @@ int RendererSceneRenderRD::sdfgi_get_pending_region_count(RID p_render_buffers)
int dirty_count = 0;
for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) {
- const SDFGI::Cascade &c = rb->sdfgi->cascades[i];
+ const RendererSceneGIRD::SDFGI::Cascade &c = rb->sdfgi->cascades[i];
- if (c.dirty_regions == SDFGI::Cascade::DIRTY_ALL) {
+ if (c.dirty_regions == RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL) {
dirty_count++;
} else {
for (int j = 0; j < 3; j++) {
@@ -1046,72 +113,15 @@ int RendererSceneRenderRD::sdfgi_get_pending_region_count(RID p_render_buffers)
return dirty_count;
}
-int RendererSceneRenderRD::_sdfgi_get_pending_region_data(RID p_render_buffers, int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
- ERR_FAIL_COND_V(rb == nullptr, -1);
- ERR_FAIL_COND_V(rb->sdfgi == nullptr, -1);
-
- int dirty_count = 0;
- for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) {
- const SDFGI::Cascade &c = rb->sdfgi->cascades[i];
-
- if (c.dirty_regions == SDFGI::Cascade::DIRTY_ALL) {
- if (dirty_count == p_region) {
- r_local_offset = Vector3i();
- r_local_size = Vector3i(1, 1, 1) * rb->sdfgi->cascade_size;
-
- r_bounds.position = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + c.position)) * c.cell_size * Vector3(1, 1.0 / rb->sdfgi->y_mult, 1);
- r_bounds.size = Vector3(r_local_size) * c.cell_size * Vector3(1, 1.0 / rb->sdfgi->y_mult, 1);
- return i;
- }
- dirty_count++;
- } else {
- for (int j = 0; j < 3; j++) {
- if (c.dirty_regions[j] != 0) {
- if (dirty_count == p_region) {
- Vector3i from = Vector3i(0, 0, 0);
- Vector3i to = Vector3i(1, 1, 1) * rb->sdfgi->cascade_size;
-
- if (c.dirty_regions[j] > 0) {
- //fill from the beginning
- to[j] = c.dirty_regions[j];
- } else {
- //fill from the end
- from[j] = to[j] + c.dirty_regions[j];
- }
-
- for (int k = 0; k < j; k++) {
- // "chip" away previous regions to avoid re-voxelizing the same thing
- if (c.dirty_regions[k] > 0) {
- from[k] += c.dirty_regions[k];
- } else if (c.dirty_regions[k] < 0) {
- to[k] += c.dirty_regions[k];
- }
- }
-
- r_local_offset = from;
- r_local_size = to - from;
-
- r_bounds.position = Vector3(from + Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + c.position) * c.cell_size * Vector3(1, 1.0 / rb->sdfgi->y_mult, 1);
- r_bounds.size = Vector3(r_local_size) * c.cell_size * Vector3(1, 1.0 / rb->sdfgi->y_mult, 1);
-
- return i;
- }
-
- dirty_count++;
- }
- }
- }
- }
- return -1;
-}
-
AABB RendererSceneRenderRD::sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const {
AABB bounds;
Vector3i from;
Vector3i size;
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ ERR_FAIL_COND_V(rb == nullptr, AABB());
+ ERR_FAIL_COND_V(rb->sdfgi == nullptr, AABB());
- int c = _sdfgi_get_pending_region_data(p_render_buffers, p_region, from, size, bounds);
+ int c = rb->sdfgi->get_pending_region_data(p_region, from, size, bounds);
ERR_FAIL_COND_V(c == -1, AABB());
return bounds;
}
@@ -1120,1895 +130,179 @@ uint32_t RendererSceneRenderRD::sdfgi_get_pending_region_cascade(RID p_render_bu
AABB bounds;
Vector3i from;
Vector3i size;
-
- return _sdfgi_get_pending_region_data(p_render_buffers, p_region, from, size, bounds);
-}
-
-void RendererSceneRenderRD::_sdfgi_update_cascades(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
- ERR_FAIL_COND(rb == nullptr);
- if (rb->sdfgi == nullptr) {
- return;
- }
-
- //update cascades
- SDFGI::Cascade::UBO cascade_data[SDFGI::MAX_CASCADES];
- int32_t probe_divisor = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR;
-
- for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) {
- Vector3 pos = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + rb->sdfgi->cascades[i].position)) * rb->sdfgi->cascades[i].cell_size;
-
- cascade_data[i].offset[0] = pos.x;
- cascade_data[i].offset[1] = pos.y;
- cascade_data[i].offset[2] = pos.z;
- cascade_data[i].to_cell = 1.0 / rb->sdfgi->cascades[i].cell_size;
- cascade_data[i].probe_offset[0] = rb->sdfgi->cascades[i].position.x / probe_divisor;
- cascade_data[i].probe_offset[1] = rb->sdfgi->cascades[i].position.y / probe_divisor;
- cascade_data[i].probe_offset[2] = rb->sdfgi->cascades[i].position.z / probe_divisor;
- cascade_data[i].pad = 0;
- }
-
- RD::get_singleton()->buffer_update(rb->sdfgi->cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data);
-}
-
-void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_environment, const Vector<RID> &p_directional_lights, const RID *p_positional_light_instances, uint32_t p_positional_light_count) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
- ERR_FAIL_COND(rb == nullptr);
- if (rb->sdfgi == nullptr) {
- return;
- }
- Environment *env = environment_owner.getornull(p_environment);
-
- RENDER_TIMESTAMP(">SDFGI Update Probes");
-
- /* Update Cascades UBO */
- _sdfgi_update_cascades(p_render_buffers);
- /* Update Dynamic Lights Buffer */
-
- RENDER_TIMESTAMP("Update Lights");
-
- /* Update dynamic lights */
-
- {
- int32_t cascade_light_count[SDFGI::MAX_CASCADES];
-
- for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) {
- SDFGI::Cascade &cascade = rb->sdfgi->cascades[i];
-
- SDGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS];
- uint32_t idx = 0;
- for (uint32_t j = 0; j < (uint32_t)p_directional_lights.size(); j++) {
- if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) {
- break;
- }
-
- LightInstance *li = light_instance_owner.getornull(p_directional_lights[j]);
- ERR_CONTINUE(!li);
-
- if (storage->light_directional_is_sky_only(li->light)) {
- continue;
- }
-
- Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
- dir.y *= rb->sdfgi->y_mult;
- dir.normalize();
- lights[idx].direction[0] = dir.x;
- lights[idx].direction[1] = dir.y;
- lights[idx].direction[2] = dir.z;
- Color color = storage->light_get_color(li->light);
- color = color.to_linear();
- lights[idx].color[0] = color.r;
- lights[idx].color[1] = color.g;
- lights[idx].color[2] = color.b;
- lights[idx].type = RS::LIGHT_DIRECTIONAL;
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY);
- lights[idx].has_shadow = storage->light_has_shadow(li->light);
-
- idx++;
- }
-
- AABB cascade_aabb;
- cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + cascade.position)) * cascade.cell_size;
- cascade_aabb.size = Vector3(1, 1, 1) * rb->sdfgi->cascade_size * cascade.cell_size;
-
- for (uint32_t j = 0; j < p_positional_light_count; j++) {
- if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) {
- break;
- }
-
- LightInstance *li = light_instance_owner.getornull(p_positional_light_instances[j]);
- ERR_CONTINUE(!li);
-
- uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
- if (i > max_sdfgi_cascade) {
- continue;
- }
-
- if (!cascade_aabb.intersects(li->aabb)) {
- continue;
- }
-
- Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
- //faster to not do this here
- //dir.y *= rb->sdfgi->y_mult;
- //dir.normalize();
- lights[idx].direction[0] = dir.x;
- lights[idx].direction[1] = dir.y;
- lights[idx].direction[2] = dir.z;
- Vector3 pos = li->transform.origin;
- pos.y *= rb->sdfgi->y_mult;
- lights[idx].position[0] = pos.x;
- lights[idx].position[1] = pos.y;
- lights[idx].position[2] = pos.z;
- Color color = storage->light_get_color(li->light);
- color = color.to_linear();
- lights[idx].color[0] = color.r;
- lights[idx].color[1] = color.g;
- lights[idx].color[2] = color.b;
- lights[idx].type = storage->light_get_type(li->light);
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY);
- lights[idx].has_shadow = storage->light_has_shadow(li->light);
- lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
- lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
- lights[idx].spot_angle = Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE));
- lights[idx].spot_attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
-
- idx++;
- }
-
- if (idx > 0) {
- RD::get_singleton()->buffer_update(cascade.lights_buffer, 0, idx * sizeof(SDGIShader::Light), lights);
- }
-
- cascade_light_count[i] = idx;
- }
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.direct_light_pipeline[SDGIShader::DIRECT_LIGHT_MODE_DYNAMIC]);
-
- SDGIShader::DirectLightPushConstant push_constant;
-
- push_constant.grid_size[0] = rb->sdfgi->cascade_size;
- push_constant.grid_size[1] = rb->sdfgi->cascade_size;
- push_constant.grid_size[2] = rb->sdfgi->cascade_size;
- push_constant.max_cascades = rb->sdfgi->cascades.size();
- push_constant.probe_axis_size = rb->sdfgi->probe_axis_count;
- push_constant.multibounce = rb->sdfgi->uses_multibounce;
- push_constant.y_mult = rb->sdfgi->y_mult;
-
- for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) {
- SDFGI::Cascade &cascade = rb->sdfgi->cascades[i];
- push_constant.light_count = cascade_light_count[i];
- push_constant.cascade = i;
-
- if (rb->sdfgi->cascades[i].all_dynamic_lights_dirty || sdfgi_frames_to_update_light == RS::ENV_SDFGI_UPDATE_LIGHT_IN_1_FRAME) {
- push_constant.process_offset = 0;
- push_constant.process_increment = 1;
- } else {
- static uint32_t frames_to_update_table[RS::ENV_SDFGI_UPDATE_LIGHT_MAX] = {
- 1, 2, 4, 8, 16
- };
-
- uint32_t frames_to_update = frames_to_update_table[sdfgi_frames_to_update_light];
-
- push_constant.process_offset = RSG::rasterizer->get_frame_number() % frames_to_update;
- push_constant.process_increment = frames_to_update;
- }
- rb->sdfgi->cascades[i].all_dynamic_lights_dirty = false;
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::DirectLightPushConstant));
- RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer, 0);
- }
- RD::get_singleton()->compute_list_end();
- }
-
- RENDER_TIMESTAMP("Raytrace");
-
- SDGIShader::IntegratePushConstant push_constant;
- push_constant.grid_size[1] = rb->sdfgi->cascade_size;
- push_constant.grid_size[2] = rb->sdfgi->cascade_size;
- push_constant.grid_size[0] = rb->sdfgi->cascade_size;
- push_constant.max_cascades = rb->sdfgi->cascades.size();
- push_constant.probe_axis_size = rb->sdfgi->probe_axis_count;
- push_constant.history_index = rb->sdfgi->render_pass % rb->sdfgi->history_size;
- push_constant.history_size = rb->sdfgi->history_size;
- static const uint32_t ray_count[RS::ENV_SDFGI_RAY_COUNT_MAX] = { 4, 8, 16, 32, 64, 96, 128 };
- push_constant.ray_count = ray_count[sdfgi_ray_count];
- push_constant.ray_bias = rb->sdfgi->probe_bias;
- push_constant.image_size[0] = rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count;
- push_constant.image_size[1] = rb->sdfgi->probe_axis_count;
- push_constant.store_ambient_texture = env->volumetric_fog_enabled;
-
- RID sky_uniform_set = sdfgi_shader.integrate_default_sky_uniform_set;
- push_constant.sky_mode = SDGIShader::IntegratePushConstant::SKY_MODE_DISABLED;
- push_constant.y_mult = rb->sdfgi->y_mult;
-
- if (rb->sdfgi->reads_sky && env) {
- push_constant.sky_energy = env->bg_energy;
-
- if (env->background == RS::ENV_BG_CLEAR_COLOR) {
- push_constant.sky_mode = SDGIShader::IntegratePushConstant::SKY_MODE_COLOR;
- Color c = storage->get_default_clear_color().to_linear();
- push_constant.sky_color[0] = c.r;
- push_constant.sky_color[1] = c.g;
- push_constant.sky_color[2] = c.b;
- } else if (env->background == RS::ENV_BG_COLOR) {
- push_constant.sky_mode = SDGIShader::IntegratePushConstant::SKY_MODE_COLOR;
- Color c = env->bg_color;
- push_constant.sky_color[0] = c.r;
- push_constant.sky_color[1] = c.g;
- push_constant.sky_color[2] = c.b;
-
- } else if (env->background == RS::ENV_BG_SKY) {
- Sky *sky = sky_owner.getornull(env->sky);
- if (sky && sky->radiance.is_valid()) {
- if (sky->sdfgi_integrate_sky_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(sky->sdfgi_integrate_sky_uniform_set)) {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 0;
- u.ids.push_back(sky->radiance);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 1;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
-
- sky->sdfgi_integrate_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 1);
- }
- sky_uniform_set = sky->sdfgi_integrate_sky_uniform_set;
- push_constant.sky_mode = SDGIShader::IntegratePushConstant::SKY_MODE_SKY;
- }
- }
- }
-
- rb->sdfgi->render_pass++;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.integrate_pipeline[SDGIShader::INTEGRATE_MODE_PROCESS]);
-
- int32_t probe_divisor = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR;
- for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) {
- push_constant.cascade = i;
- push_constant.world_offset[0] = rb->sdfgi->cascades[i].position.x / probe_divisor;
- push_constant.world_offset[1] = rb->sdfgi->cascades[i].position.y / probe_divisor;
- push_constant.world_offset[2] = rb->sdfgi->cascades[i].position.z / probe_divisor;
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[i].integrate_uniform_set, 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sky_uniform_set, 1);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::IntegratePushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count, rb->sdfgi->probe_axis_count, 1, 8, 8, 1);
- }
-
- RD::get_singleton()->compute_list_add_barrier(compute_list); //wait until done
-
- // Then store values into the lightprobe texture. Separating these steps has a small performance hit, but it allows for multiple bounces
- RENDER_TIMESTAMP("Average Probes");
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.integrate_pipeline[SDGIShader::INTEGRATE_MODE_STORE]);
-
- //convert to octahedral to store
- push_constant.image_size[0] *= SDFGI::LIGHTPROBE_OCT_SIZE;
- push_constant.image_size[1] *= SDFGI::LIGHTPROBE_OCT_SIZE;
-
- for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) {
- push_constant.cascade = i;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[i].integrate_uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::IntegratePushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, rb->sdfgi->probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, 1, 8, 8, 1);
- }
-
- RD::get_singleton()->compute_list_end();
-
- RENDER_TIMESTAMP("<SDFGI Update Probes");
-}
-
-void RendererSceneRenderRD::_setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used) {
- r_gi_probes_used = 0;
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
- ERR_FAIL_COND(rb == nullptr);
-
- RID gi_probe_buffer = render_buffers_get_gi_probe_buffer(p_render_buffers);
- GI::GIProbeData gi_probe_data[RenderBuffers::MAX_GIPROBES];
-
- bool giprobes_changed = false;
-
- Transform to_camera;
- to_camera.origin = p_transform.origin; //only translation, make local
-
- for (int i = 0; i < RenderBuffers::MAX_GIPROBES; i++) {
- RID texture;
- if (i < (int)p_gi_probes.size()) {
- GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_gi_probes[i]);
-
- if (gipi) {
- texture = gipi->texture;
- GI::GIProbeData &gipd = gi_probe_data[i];
-
- RID base_probe = gipi->probe;
-
- Transform to_cell = storage->gi_probe_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera;
-
- gipd.xform[0] = to_cell.basis.elements[0][0];
- gipd.xform[1] = to_cell.basis.elements[1][0];
- gipd.xform[2] = to_cell.basis.elements[2][0];
- gipd.xform[3] = 0;
- gipd.xform[4] = to_cell.basis.elements[0][1];
- gipd.xform[5] = to_cell.basis.elements[1][1];
- gipd.xform[6] = to_cell.basis.elements[2][1];
- gipd.xform[7] = 0;
- gipd.xform[8] = to_cell.basis.elements[0][2];
- gipd.xform[9] = to_cell.basis.elements[1][2];
- gipd.xform[10] = to_cell.basis.elements[2][2];
- gipd.xform[11] = 0;
- gipd.xform[12] = to_cell.origin.x;
- gipd.xform[13] = to_cell.origin.y;
- gipd.xform[14] = to_cell.origin.z;
- gipd.xform[15] = 1;
-
- Vector3 bounds = storage->gi_probe_get_octree_size(base_probe);
-
- gipd.bounds[0] = bounds.x;
- gipd.bounds[1] = bounds.y;
- gipd.bounds[2] = bounds.z;
-
- gipd.dynamic_range = storage->gi_probe_get_dynamic_range(base_probe) * storage->gi_probe_get_energy(base_probe);
- gipd.bias = storage->gi_probe_get_bias(base_probe);
- gipd.normal_bias = storage->gi_probe_get_normal_bias(base_probe);
- gipd.blend_ambient = !storage->gi_probe_is_interior(base_probe);
- gipd.anisotropy_strength = 0;
- gipd.ao = storage->gi_probe_get_ao(base_probe);
- gipd.ao_size = Math::pow(storage->gi_probe_get_ao_size(base_probe), 4.0f);
- gipd.mipmaps = gipi->mipmaps.size();
- }
-
- r_gi_probes_used++;
- }
-
- if (texture == RID()) {
- texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
- }
-
- if (texture != rb->giprobe_textures[i]) {
- giprobes_changed = true;
- rb->giprobe_textures[i] = texture;
- }
- }
-
- if (giprobes_changed) {
- if (RD::get_singleton()->uniform_set_is_valid(rb->gi_uniform_set)) {
- RD::get_singleton()->free(rb->gi_uniform_set);
- }
- rb->gi_uniform_set = RID();
- if (rb->volumetric_fog) {
- if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set);
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set2);
- }
- rb->volumetric_fog->uniform_set = RID();
- rb->volumetric_fog->uniform_set2 = RID();
- }
- }
-
- if (p_gi_probes.size() > 0) {
- RD::get_singleton()->buffer_update(gi_probe_buffer, 0, sizeof(GI::GIProbeData) * MIN((uint64_t)RenderBuffers::MAX_GIPROBES, p_gi_probes.size()), gi_probe_data);
- }
-}
-
-void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes) {
- RENDER_TIMESTAMP("Render GI");
-
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
- ERR_FAIL_COND(rb == nullptr);
- Environment *env = environment_owner.getornull(p_environment);
-
- if (rb->ambient_buffer.is_null() || rb->using_half_size_gi != gi.half_resolution) {
- if (rb->ambient_buffer.is_valid()) {
- RD::get_singleton()->free(rb->ambient_buffer);
- RD::get_singleton()->free(rb->reflection_buffer);
- }
-
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->width;
- tf.height = rb->height;
- if (gi.half_resolution) {
- tf.width >>= 1;
- tf.height >>= 1;
- }
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- rb->ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- rb->using_half_size_gi = gi.half_resolution;
-
- _render_buffers_uniform_set_changed(p_render_buffers);
- }
-
- GI::PushConstant push_constant;
-
- push_constant.screen_size[0] = rb->width;
- push_constant.screen_size[1] = rb->height;
- push_constant.z_near = p_projection.get_z_near();
- push_constant.z_far = p_projection.get_z_far();
- push_constant.orthogonal = p_projection.is_orthogonal();
- push_constant.proj_info[0] = -2.0f / (rb->width * p_projection.matrix[0][0]);
- push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]);
- push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0];
- push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
- push_constant.max_giprobes = MIN((uint64_t)RenderBuffers::MAX_GIPROBES, p_gi_probes.size());
- push_constant.high_quality_vct = gi_probe_quality == RS::GI_PROBE_QUALITY_HIGH;
-
- bool use_sdfgi = rb->sdfgi != nullptr;
- bool use_giprobes = push_constant.max_giprobes > 0;
-
- if (env) {
- push_constant.ao_color[0] = env->ao_color.r;
- push_constant.ao_color[1] = env->ao_color.g;
- push_constant.ao_color[2] = env->ao_color.b;
- } else {
- push_constant.ao_color[0] = 0;
- push_constant.ao_color[1] = 0;
- push_constant.ao_color[2] = 0;
- }
-
- push_constant.cam_rotation[0] = p_transform.basis[0][0];
- push_constant.cam_rotation[1] = p_transform.basis[1][0];
- push_constant.cam_rotation[2] = p_transform.basis[2][0];
- push_constant.cam_rotation[3] = 0;
- push_constant.cam_rotation[4] = p_transform.basis[0][1];
- push_constant.cam_rotation[5] = p_transform.basis[1][1];
- push_constant.cam_rotation[6] = p_transform.basis[2][1];
- push_constant.cam_rotation[7] = 0;
- push_constant.cam_rotation[8] = p_transform.basis[0][2];
- push_constant.cam_rotation[9] = p_transform.basis[1][2];
- push_constant.cam_rotation[10] = p_transform.basis[2][2];
- push_constant.cam_rotation[11] = 0;
-
- if (rb->sdfgi) {
- GI::SDFGIData sdfgi_data;
-
- sdfgi_data.grid_size[0] = rb->sdfgi->cascade_size;
- sdfgi_data.grid_size[1] = rb->sdfgi->cascade_size;
- sdfgi_data.grid_size[2] = rb->sdfgi->cascade_size;
-
- sdfgi_data.max_cascades = rb->sdfgi->cascades.size();
- sdfgi_data.probe_axis_size = rb->sdfgi->probe_axis_count;
- sdfgi_data.cascade_probe_size[0] = sdfgi_data.probe_axis_size - 1; //float version for performance
- sdfgi_data.cascade_probe_size[1] = sdfgi_data.probe_axis_size - 1;
- sdfgi_data.cascade_probe_size[2] = sdfgi_data.probe_axis_size - 1;
-
- float csize = rb->sdfgi->cascade_size;
- sdfgi_data.probe_to_uvw = 1.0 / float(sdfgi_data.cascade_probe_size[0]);
- sdfgi_data.use_occlusion = rb->sdfgi->uses_occlusion;
- //sdfgi_data.energy = rb->sdfgi->energy;
-
- sdfgi_data.y_mult = rb->sdfgi->y_mult;
-
- float cascade_voxel_size = (csize / sdfgi_data.cascade_probe_size[0]);
- float occlusion_clamp = (cascade_voxel_size - 0.5) / cascade_voxel_size;
- sdfgi_data.occlusion_clamp[0] = occlusion_clamp;
- sdfgi_data.occlusion_clamp[1] = occlusion_clamp;
- sdfgi_data.occlusion_clamp[2] = occlusion_clamp;
- sdfgi_data.normal_bias = (rb->sdfgi->normal_bias / csize) * sdfgi_data.cascade_probe_size[0];
-
- //vec2 tex_pixel_size = 1.0 / vec2(ivec2( (OCT_SIZE+2) * params.probe_axis_size * params.probe_axis_size, (OCT_SIZE+2) * params.probe_axis_size ) );
- //vec3 probe_uv_offset = (ivec3(OCT_SIZE+2,OCT_SIZE+2,(OCT_SIZE+2) * params.probe_axis_size)) * tex_pixel_size.xyx;
-
- uint32_t oct_size = SDFGI::LIGHTPROBE_OCT_SIZE;
-
- sdfgi_data.lightprobe_tex_pixel_size[0] = 1.0 / ((oct_size + 2) * sdfgi_data.probe_axis_size * sdfgi_data.probe_axis_size);
- sdfgi_data.lightprobe_tex_pixel_size[1] = 1.0 / ((oct_size + 2) * sdfgi_data.probe_axis_size);
- sdfgi_data.lightprobe_tex_pixel_size[2] = 1.0;
-
- sdfgi_data.energy = rb->sdfgi->energy;
-
- sdfgi_data.lightprobe_uv_offset[0] = float(oct_size + 2) * sdfgi_data.lightprobe_tex_pixel_size[0];
- sdfgi_data.lightprobe_uv_offset[1] = float(oct_size + 2) * sdfgi_data.lightprobe_tex_pixel_size[1];
- sdfgi_data.lightprobe_uv_offset[2] = float((oct_size + 2) * sdfgi_data.probe_axis_size) * sdfgi_data.lightprobe_tex_pixel_size[0];
-
- sdfgi_data.occlusion_renormalize[0] = 0.5;
- sdfgi_data.occlusion_renormalize[1] = 1.0;
- sdfgi_data.occlusion_renormalize[2] = 1.0 / float(sdfgi_data.max_cascades);
-
- int32_t probe_divisor = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR;
-
- for (uint32_t i = 0; i < sdfgi_data.max_cascades; i++) {
- GI::SDFGIData::ProbeCascadeData &c = sdfgi_data.cascades[i];
- Vector3 pos = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + rb->sdfgi->cascades[i].position)) * rb->sdfgi->cascades[i].cell_size;
- Vector3 cam_origin = p_transform.origin;
- cam_origin.y *= rb->sdfgi->y_mult;
- pos -= cam_origin; //make pos local to camera, to reduce numerical error
- c.position[0] = pos.x;
- c.position[1] = pos.y;
- c.position[2] = pos.z;
- c.to_probe = 1.0 / (float(rb->sdfgi->cascade_size) * rb->sdfgi->cascades[i].cell_size / float(rb->sdfgi->probe_axis_count - 1));
-
- Vector3i probe_ofs = rb->sdfgi->cascades[i].position / probe_divisor;
- c.probe_world_offset[0] = probe_ofs.x;
- c.probe_world_offset[1] = probe_ofs.y;
- c.probe_world_offset[2] = probe_ofs.z;
-
- c.to_cell = 1.0 / rb->sdfgi->cascades[i].cell_size;
- }
-
- RD::get_singleton()->buffer_update(gi.sdfgi_ubo, 0, sizeof(GI::SDFGIData), &sdfgi_data);
- }
-
- if (rb->gi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->gi_uniform_set)) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
- u.ids.push_back(rb->sdfgi->cascades[j].sdf_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
- u.ids.push_back(rb->sdfgi->cascades[j].light_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 3;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
- u.ids.push_back(rb->sdfgi->cascades[j].light_aniso_0_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 4;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
- u.ids.push_back(rb->sdfgi->cascades[j].light_aniso_1_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 5;
- if (rb->sdfgi) {
- u.ids.push_back(rb->sdfgi->occlusion_texture);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 6;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 7;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 9;
- u.ids.push_back(rb->ambient_buffer);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 10;
- u.ids.push_back(rb->reflection_buffer);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 11;
- if (rb->sdfgi) {
- u.ids.push_back(rb->sdfgi->lightprobe_texture);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 12;
- u.ids.push_back(rb->depth_texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 13;
- u.ids.push_back(p_normal_roughness_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 14;
- RID buffer = p_gi_probe_buffer.is_valid() ? p_gi_probe_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
- u.ids.push_back(buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 15;
- u.ids.push_back(gi.sdfgi_ubo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 16;
- u.ids.push_back(rb->giprobe_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 17;
- for (int i = 0; i < RenderBuffers::MAX_GIPROBES; i++) {
- u.ids.push_back(rb->giprobe_textures[i]);
- }
- uniforms.push_back(u);
- }
-
- rb->gi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi.shader.version_get_shader(gi.shader_version, 0), 0);
- }
-
- GI::Mode mode;
-
- if (rb->using_half_size_gi) {
- mode = (use_sdfgi && use_giprobes) ? GI::MODE_HALF_RES_COMBINED : (use_sdfgi ? GI::MODE_HALF_RES_SDFGI : GI::MODE_HALF_RES_GIPROBE);
- } else {
- mode = (use_sdfgi && use_giprobes) ? GI::MODE_COMBINED : (use_sdfgi ? GI::MODE_SDFGI : GI::MODE_GIPROBE);
- }
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi.pipelines[mode]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->gi_uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GI::PushConstant));
+ ERR_FAIL_COND_V(rb == nullptr, -1);
+ ERR_FAIL_COND_V(rb->sdfgi == nullptr, -1);
- if (rb->using_half_size_gi) {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width >> 1, rb->height >> 1, 1, 8, 8, 1);
- } else {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1, 8, 8, 1);
- }
- RD::get_singleton()->compute_list_end();
+ return rb->sdfgi->get_pending_region_data(p_region, from, size, bounds);
}
-RID RendererSceneRenderRD::sky_create() {
- return sky_owner.make_rid(Sky());
+RID RendererSceneRenderRD::sky_allocate() {
+ return sky.allocate_sky_rid();
}
-
-void RendererSceneRenderRD::_sky_invalidate(Sky *p_sky) {
- if (!p_sky->dirty) {
- p_sky->dirty = true;
- p_sky->dirty_list = dirty_sky_list;
- dirty_sky_list = p_sky;
- }
+void RendererSceneRenderRD::sky_initialize(RID p_rid) {
+ sky.initialize_sky_rid(p_rid);
}
void RendererSceneRenderRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
- Sky *sky = sky_owner.getornull(p_sky);
- ERR_FAIL_COND(!sky);
- ERR_FAIL_COND(p_radiance_size < 32 || p_radiance_size > 2048);
- if (sky->radiance_size == p_radiance_size) {
- return;
- }
- sky->radiance_size = p_radiance_size;
-
- if (sky->mode == RS::SKY_MODE_REALTIME && sky->radiance_size != 256) {
- WARN_PRINT("Realtime Skies can only use a radiance size of 256. Radiance size will be set to 256 internally.");
- sky->radiance_size = 256;
- }
-
- _sky_invalidate(sky);
- if (sky->radiance.is_valid()) {
- RD::get_singleton()->free(sky->radiance);
- sky->radiance = RID();
- }
- _clear_reflection_data(sky->reflection);
+ sky.sky_set_radiance_size(p_sky, p_radiance_size);
}
void RendererSceneRenderRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) {
- Sky *sky = sky_owner.getornull(p_sky);
- ERR_FAIL_COND(!sky);
-
- if (sky->mode == p_mode) {
- return;
- }
-
- sky->mode = p_mode;
-
- if (sky->mode == RS::SKY_MODE_REALTIME && sky->radiance_size != 256) {
- WARN_PRINT("Realtime Skies can only use a radiance size of 256. Radiance size will be set to 256 internally.");
- sky_set_radiance_size(p_sky, 256);
- }
-
- _sky_invalidate(sky);
- if (sky->radiance.is_valid()) {
- RD::get_singleton()->free(sky->radiance);
- sky->radiance = RID();
- }
- _clear_reflection_data(sky->reflection);
+ sky.sky_set_mode(p_sky, p_mode);
}
void RendererSceneRenderRD::sky_set_material(RID p_sky, RID p_material) {
- Sky *sky = sky_owner.getornull(p_sky);
- ERR_FAIL_COND(!sky);
- sky->material = p_material;
- _sky_invalidate(sky);
+ sky.sky_set_material(p_sky, p_material);
}
Ref<Image> RendererSceneRenderRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) {
- Sky *sky = sky_owner.getornull(p_sky);
- ERR_FAIL_COND_V(!sky, Ref<Image>());
-
- _update_dirty_skys();
-
- if (sky->radiance.is_valid()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- tf.width = p_size.width;
- tf.height = p_size.height;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
-
- RID rad_tex = RD::get_singleton()->texture_create(tf, RD::TextureView());
- storage->get_effects()->copy_cubemap_to_panorama(sky->radiance, rad_tex, p_size, p_bake_irradiance ? roughness_layers : 0, sky->reflection.layers.size() > 1);
- Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rad_tex, 0);
- RD::get_singleton()->free(rad_tex);
-
- Ref<Image> img;
- img.instance();
- img->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data);
- for (int i = 0; i < p_size.width; i++) {
- for (int j = 0; j < p_size.height; j++) {
- Color c = img->get_pixel(i, j);
- c.r *= p_energy;
- c.g *= p_energy;
- c.b *= p_energy;
- img->set_pixel(i, j, c);
- }
- }
- return img;
- }
-
- return Ref<Image>();
-}
-
-void RendererSceneRenderRD::_update_dirty_skys() {
- Sky *sky = dirty_sky_list;
-
- while (sky) {
- bool texture_set_dirty = false;
- //update sky configuration if texture is missing
-
- if (sky->radiance.is_null()) {
- int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1;
-
- uint32_t w = sky->radiance_size, h = sky->radiance_size;
- int layers = roughness_layers;
- if (sky->mode == RS::SKY_MODE_REALTIME) {
- layers = 8;
- if (roughness_layers != 8) {
- WARN_PRINT("When using REALTIME skies, roughness_layers should be set to 8 in the project settings for best quality reflections");
- }
- }
-
- if (sky_use_cubemap_array) {
- //array (higher quality, 6 times more memory)
- RD::TextureFormat tf;
- tf.array_layers = layers * 6;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
- tf.mipmaps = mipmaps;
- tf.width = w;
- tf.height = h;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-
- sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- _update_reflection_data(sky->reflection, sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME);
-
- } else {
- //regular cubemap, lower quality (aliasing, less memory)
- RD::TextureFormat tf;
- tf.array_layers = 6;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_CUBE;
- tf.mipmaps = MIN(mipmaps, layers);
- tf.width = w;
- tf.height = h;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-
- sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- _update_reflection_data(sky->reflection, sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME);
- }
- 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 = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- 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 = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- 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;
- sky->processing_layer = 0;
-
- Sky *next = sky->dirty_list;
- sky->dirty_list = nullptr;
- sky->dirty = false;
- sky = next;
- }
-
- dirty_sky_list = nullptr;
-}
-
-RID RendererSceneRenderRD::sky_get_radiance_texture_rd(RID p_sky) const {
- Sky *sky = sky_owner.getornull(p_sky);
- ERR_FAIL_COND_V(!sky, RID());
-
- return sky->radiance;
-}
-
-RID RendererSceneRenderRD::sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const {
- Sky *sky = sky_owner.getornull(p_sky);
- ERR_FAIL_COND_V(!sky, RID());
-
- if (sky->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(sky->uniform_set)) {
- sky->uniform_set = RID();
- if (sky->radiance.is_valid()) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 0;
- u.ids.push_back(sky->radiance);
- uniforms.push_back(u);
- }
-
- sky->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
- }
-
- return sky->uniform_set;
-}
-
-RID RendererSceneRenderRD::_get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version) {
- if (p_sky->texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(p_sky->texture_uniform_sets[p_version])) {
- return p_sky->texture_uniform_sets[p_version];
- }
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 0;
- if (p_sky->radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) {
- u.ids.push_back(p_sky->radiance);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1; // half res
- if (p_sky->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) {
- u.ids.push_back(p_sky->reflection.layers[0].views[1]);
- } else {
- u.ids.push_back(p_sky->half_res_pass);
- }
- } else {
- if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2; // quarter res
- if (p_sky->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) {
- u.ids.push_back(p_sky->reflection.layers[0].views[2]);
- } else {
- u.ids.push_back(p_sky->quarter_res_pass);
- }
- } else {
- if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
- }
- }
- uniforms.push_back(u);
- }
-
- p_sky->texture_uniform_sets[p_version] = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_TEXTURES);
- return p_sky->texture_uniform_sets[p_version];
-}
-
-RID RendererSceneRenderRD::sky_get_material(RID p_sky) const {
- Sky *sky = sky_owner.getornull(p_sky);
- ERR_FAIL_COND_V(!sky, RID());
-
- return sky->material;
-}
-
-void RendererSceneRenderRD::_draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) {
- ERR_FAIL_COND(!is_environment(p_environment));
-
- SkyMaterialData *material = nullptr;
-
- Sky *sky = sky_owner.getornull(environment_get_sky(p_environment));
-
- RID sky_material;
-
- RS::EnvironmentBG background = environment_get_background(p_environment);
-
- if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
- ERR_FAIL_COND(!sky);
- sky_material = sky_get_material(environment_get_sky(p_environment));
-
- if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
- if (!material || !material->shader_data->valid) {
- material = nullptr;
- }
- }
-
- if (!material) {
- sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
- }
- }
-
- if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
- sky_material = sky_scene_state.fog_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
- }
-
- ERR_FAIL_COND(!material);
-
- SkyShaderData *shader_data = material->shader_data;
-
- ERR_FAIL_COND(!shader_data);
-
- Basis sky_transform = environment_get_sky_orientation(p_environment);
- sky_transform.invert();
-
- float multiplier = environment_get_bg_energy(p_environment);
- float custom_fov = environment_get_sky_custom_fov(p_environment);
- // Camera
- CameraMatrix camera;
-
- if (custom_fov) {
- float near_plane = p_projection.get_z_near();
- float far_plane = p_projection.get_z_far();
- float aspect = p_projection.get_aspect();
-
- camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
-
- } else {
- camera = p_projection;
- }
-
- sky_transform = p_transform.basis * sky_transform;
-
- if (shader_data->uses_quarter_res) {
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_QUARTER_RES];
-
- RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_QUARTER_RES);
-
- 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);
- storage->get_effects()->render_sky(draw_list, time, sky->quarter_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
- RD::get_singleton()->draw_list_end();
- }
-
- if (shader_data->uses_half_res) {
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_HALF_RES];
-
- RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_HALF_RES);
-
- 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);
- storage->get_effects()->render_sky(draw_list, time, sky->half_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
- RD::get_singleton()->draw_list_end();
- }
-
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_BACKGROUND];
-
- RID texture_uniform_set;
- if (sky) {
- texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_BACKGROUND);
- } 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);
- storage->get_effects()->render_sky(draw_list, time, p_fb, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
- RD::get_singleton()->draw_list_end();
+ return sky.sky_bake_panorama(p_sky, p_energy, p_bake_irradiance, p_size);
}
-void RendererSceneRenderRD::_setup_sky(RID p_environment, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size) {
- ERR_FAIL_COND(!is_environment(p_environment));
-
- SkyMaterialData *material = nullptr;
-
- Sky *sky = sky_owner.getornull(environment_get_sky(p_environment));
-
- RID sky_material;
-
- SkyShaderData *shader_data = nullptr;
-
- RS::EnvironmentBG background = environment_get_background(p_environment);
-
- if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
- ERR_FAIL_COND(!sky);
- sky_material = sky_get_material(environment_get_sky(p_environment));
-
- if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
- if (!material || !material->shader_data->valid) {
- material = nullptr;
- }
- }
-
- if (!material) {
- sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
- }
-
- ERR_FAIL_COND(!material);
-
- shader_data = material->shader_data;
-
- ERR_FAIL_COND(!shader_data);
- }
-
- if (sky) {
- // 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();
- }
- _sky_invalidate(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();
- }
- _sky_invalidate(sky);
- }
- }
-
- // 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()) {
- _sky_invalidate(sky);
- _update_dirty_skys();
- }
-
- if (shader_data->uses_time && time - sky->prev_time > 0.00001) {
- sky->prev_time = time;
- sky->reflection.dirty = true;
- RenderingServerDefault::redraw_request();
- }
-
- if (material != sky->prev_material) {
- sky->prev_material = material;
- sky->reflection.dirty = true;
- }
-
- if (material->uniform_set_updated) {
- material->uniform_set_updated = false;
- sky->reflection.dirty = true;
- }
-
- if (!p_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) {
- sky->prev_position = p_transform.origin;
- sky->reflection.dirty = true;
- }
-
- if (shader_data->uses_light) {
- // Check whether the directional_light_buffer changes
- bool light_data_dirty = false;
-
- if (sky_scene_state.ubo.directional_light_count != sky_scene_state.last_frame_directional_light_count) {
- light_data_dirty = true;
- for (uint32_t i = sky_scene_state.ubo.directional_light_count; i < sky_scene_state.max_directional_lights; i++) {
- sky_scene_state.directional_lights[i].enabled = false;
- }
- }
- if (!light_data_dirty) {
- for (uint32_t i = 0; i < sky_scene_state.ubo.directional_light_count; i++) {
- if (sky_scene_state.directional_lights[i].direction[0] != sky_scene_state.last_frame_directional_lights[i].direction[0] ||
- sky_scene_state.directional_lights[i].direction[1] != sky_scene_state.last_frame_directional_lights[i].direction[1] ||
- sky_scene_state.directional_lights[i].direction[2] != sky_scene_state.last_frame_directional_lights[i].direction[2] ||
- sky_scene_state.directional_lights[i].energy != sky_scene_state.last_frame_directional_lights[i].energy ||
- sky_scene_state.directional_lights[i].color[0] != sky_scene_state.last_frame_directional_lights[i].color[0] ||
- sky_scene_state.directional_lights[i].color[1] != sky_scene_state.last_frame_directional_lights[i].color[1] ||
- sky_scene_state.directional_lights[i].color[2] != sky_scene_state.last_frame_directional_lights[i].color[2] ||
- sky_scene_state.directional_lights[i].enabled != sky_scene_state.last_frame_directional_lights[i].enabled ||
- sky_scene_state.directional_lights[i].size != sky_scene_state.last_frame_directional_lights[i].size) {
- light_data_dirty = true;
- break;
- }
- }
- }
-
- if (light_data_dirty) {
- RD::get_singleton()->buffer_update(sky_scene_state.directional_light_buffer, 0, sizeof(SkyDirectionalLightData) * sky_scene_state.max_directional_lights, sky_scene_state.directional_lights);
-
- RendererSceneRenderRD::SkyDirectionalLightData *temp = sky_scene_state.last_frame_directional_lights;
- sky_scene_state.last_frame_directional_lights = sky_scene_state.directional_lights;
- sky_scene_state.directional_lights = temp;
- sky_scene_state.last_frame_directional_light_count = sky_scene_state.ubo.directional_light_count;
- sky->reflection.dirty = true;
- }
- }
- }
-
- //setup fog variables
- sky_scene_state.ubo.volumetric_fog_enabled = false;
- if (p_render_buffers.is_valid()) {
- if (render_buffers_has_volumetric_fog(p_render_buffers)) {
- sky_scene_state.ubo.volumetric_fog_enabled = true;
-
- float fog_end = render_buffers_get_volumetric_fog_end(p_render_buffers);
- if (fog_end > 0.0) {
- sky_scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;
- } else {
- sky_scene_state.ubo.volumetric_fog_inv_length = 1.0;
- }
-
- float fog_detail_spread = render_buffers_get_volumetric_fog_detail_spread(p_render_buffers); //reverse lookup
- if (fog_detail_spread > 0.0) {
- sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread;
- } else {
- sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0;
- }
- }
-
- RID fog_uniform_set = render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers);
-
- if (fog_uniform_set != RID()) {
- sky_scene_state.fog_uniform_set = fog_uniform_set;
- } else {
- sky_scene_state.fog_uniform_set = sky_scene_state.default_fog_uniform_set;
- }
- }
-
- sky_scene_state.ubo.z_far = p_projection.get_z_far();
- sky_scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_environment);
- sky_scene_state.ubo.fog_density = environment_get_fog_density(p_environment);
- sky_scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_environment);
- Color fog_color = environment_get_fog_light_color(p_environment).to_linear();
- float fog_energy = environment_get_fog_light_energy(p_environment);
- sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
- sky_scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy;
- sky_scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy;
- sky_scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_environment);
-
- RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);
+RID RendererSceneRenderRD::environment_allocate() {
+ return environment_owner.allocate_rid();
}
-
-void RendererSceneRenderRD::_update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) {
- ERR_FAIL_COND(!is_environment(p_environment));
-
- Sky *sky = sky_owner.getornull(environment_get_sky(p_environment));
- ERR_FAIL_COND(!sky);
-
- RID sky_material = sky_get_material(environment_get_sky(p_environment));
-
- SkyMaterialData *material = nullptr;
-
- if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
- if (!material || !material->shader_data->valid) {
- material = nullptr;
- }
- }
-
- if (!material) {
- sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
- }
-
- ERR_FAIL_COND(!material);
-
- SkyShaderData *shader_data = material->shader_data;
-
- ERR_FAIL_COND(!shader_data);
-
- float multiplier = environment_get_bg_energy(p_environment);
-
- bool update_single_frame = sky->mode == RS::SKY_MODE_REALTIME || sky->mode == RS::SKY_MODE_QUALITY;
- RS::SkyMode sky_mode = sky->mode;
-
- if (sky_mode == RS::SKY_MODE_AUTOMATIC) {
- if (shader_data->uses_time || shader_data->uses_position) {
- update_single_frame = true;
- sky_mode = RS::SKY_MODE_REALTIME;
- } else if (shader_data->uses_light || shader_data->ubo_size > 0) {
- update_single_frame = false;
- sky_mode = RS::SKY_MODE_INCREMENTAL;
- } else {
- update_single_frame = true;
- sky_mode = RS::SKY_MODE_QUALITY;
- }
- }
-
- if (sky->processing_layer == 0 && sky_mode == RS::SKY_MODE_INCREMENTAL) {
- // On the first frame after creating sky, rebuild in single frame
- update_single_frame = true;
- sky_mode = RS::SKY_MODE_QUALITY;
- }
-
- int max_processing_layer = sky_use_cubemap_array ? sky->reflection.layers.size() : sky->reflection.layers[0].mipmaps.size();
-
- // Update radiance cubemap
- if (sky->reflection.dirty && (sky->processing_layer >= max_processing_layer || update_single_frame)) {
- static const Vector3 view_normals[6] = {
- Vector3(+1, 0, 0),
- Vector3(-1, 0, 0),
- Vector3(0, +1, 0),
- Vector3(0, -1, 0),
- Vector3(0, 0, +1),
- Vector3(0, 0, -1)
- };
- static const Vector3 view_up[6] = {
- Vector3(0, -1, 0),
- Vector3(0, -1, 0),
- Vector3(0, 0, +1),
- Vector3(0, 0, -1),
- Vector3(0, -1, 0),
- Vector3(0, -1, 0)
- };
-
- CameraMatrix cm;
- cm.set_perspective(90, 1, 0.01, 10.0);
- CameraMatrix correction;
- correction.set_depth_correction(true);
- cm = correction * cm;
-
- if (shader_data->uses_quarter_res) {
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES];
-
- Vector<Color> clear_colors;
- clear_colors.push_back(Color(0.0, 0.0, 0.0));
- RD::DrawListID cubemap_draw_list;
-
- for (int i = 0; i < 6; i++) {
- Transform local_view;
- local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
- RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES);
-
- 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);
- storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
- RD::get_singleton()->draw_list_end();
- }
- }
-
- if (shader_data->uses_half_res) {
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES];
-
- Vector<Color> clear_colors;
- clear_colors.push_back(Color(0.0, 0.0, 0.0));
- RD::DrawListID cubemap_draw_list;
-
- for (int i = 0; i < 6; i++) {
- Transform local_view;
- local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
- RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_CUBEMAP_HALF_RES);
-
- 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);
- storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
- RD::get_singleton()->draw_list_end();
- }
- }
-
- RD::DrawListID cubemap_draw_list;
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP];
-
- for (int i = 0; i < 6; i++) {
- Transform local_view;
- local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
- RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_CUBEMAP);
-
- 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);
- storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
- RD::get_singleton()->draw_list_end();
- }
-
- if (sky_mode == RS::SKY_MODE_REALTIME) {
- _create_reflection_fast_filter(sky->reflection, sky_use_cubemap_array);
- if (sky_use_cubemap_array) {
- _update_reflection_mipmaps(sky->reflection, 0, sky->reflection.layers.size());
- }
- } else {
- if (update_single_frame) {
- for (int i = 1; i < max_processing_layer; i++) {
- _create_reflection_importance_sample(sky->reflection, sky_use_cubemap_array, 10, i);
- }
- if (sky_use_cubemap_array) {
- _update_reflection_mipmaps(sky->reflection, 0, sky->reflection.layers.size());
- }
- } else {
- if (sky_use_cubemap_array) {
- // Multi-Frame so just update the first array level
- _update_reflection_mipmaps(sky->reflection, 0, 1);
- }
- }
- sky->processing_layer = 1;
- }
-
- sky->reflection.dirty = false;
-
- } else {
- if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) {
- _create_reflection_importance_sample(sky->reflection, sky_use_cubemap_array, 10, sky->processing_layer);
-
- if (sky_use_cubemap_array) {
- _update_reflection_mipmaps(sky->reflection, sky->processing_layer, sky->processing_layer + 1);
- }
-
- sky->processing_layer++;
- }
- }
-}
-
-/* SKY SHADER */
-
-void RendererSceneRenderRD::SkyShaderData::set_code(const String &p_code) {
- //compile
-
- code = p_code;
- valid = false;
- ubo_size = 0;
- uniforms.clear();
-
- if (code == String()) {
- return; //just invalid, but no error
- }
-
- ShaderCompilerRD::GeneratedCode gen_code;
- ShaderCompilerRD::IdentifierActions actions;
-
- uses_time = false;
- uses_half_res = false;
- uses_quarter_res = false;
- uses_position = false;
- uses_light = false;
-
- actions.render_mode_flags["use_half_res_pass"] = &uses_half_res;
- actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res;
-
- actions.usage_flag_pointers["TIME"] = &uses_time;
- actions.usage_flag_pointers["POSITION"] = &uses_position;
- actions.usage_flag_pointers["LIGHT0_ENABLED"] = &uses_light;
- actions.usage_flag_pointers["LIGHT0_ENERGY"] = &uses_light;
- actions.usage_flag_pointers["LIGHT0_DIRECTION"] = &uses_light;
- actions.usage_flag_pointers["LIGHT0_COLOR"] = &uses_light;
- actions.usage_flag_pointers["LIGHT0_SIZE"] = &uses_light;
- actions.usage_flag_pointers["LIGHT1_ENABLED"] = &uses_light;
- actions.usage_flag_pointers["LIGHT1_ENERGY"] = &uses_light;
- actions.usage_flag_pointers["LIGHT1_DIRECTION"] = &uses_light;
- actions.usage_flag_pointers["LIGHT1_COLOR"] = &uses_light;
- actions.usage_flag_pointers["LIGHT1_SIZE"] = &uses_light;
- actions.usage_flag_pointers["LIGHT2_ENABLED"] = &uses_light;
- actions.usage_flag_pointers["LIGHT2_ENERGY"] = &uses_light;
- actions.usage_flag_pointers["LIGHT2_DIRECTION"] = &uses_light;
- actions.usage_flag_pointers["LIGHT2_COLOR"] = &uses_light;
- actions.usage_flag_pointers["LIGHT2_SIZE"] = &uses_light;
- actions.usage_flag_pointers["LIGHT3_ENABLED"] = &uses_light;
- actions.usage_flag_pointers["LIGHT3_ENERGY"] = &uses_light;
- actions.usage_flag_pointers["LIGHT3_DIRECTION"] = &uses_light;
- actions.usage_flag_pointers["LIGHT3_COLOR"] = &uses_light;
- actions.usage_flag_pointers["LIGHT3_SIZE"] = &uses_light;
-
- actions.uniforms = &uniforms;
-
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
-
- Error err = scene_singleton->sky_shader.compiler.compile(RS::SHADER_SKY, code, &actions, path, gen_code);
-
- ERR_FAIL_COND(err != OK);
-
- if (version.is_null()) {
- version = scene_singleton->sky_shader.shader.version_create();
- }
-
-#if 0
- print_line("**compiling shader:");
- print_line("**defines:\n");
- for (int i = 0; i < gen_code.defines.size(); i++) {
- print_line(gen_code.defines[i]);
- }
- print_line("\n**uniforms:\n" + gen_code.uniforms);
- // print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
- // print_line("\n**vertex_code:\n" + gen_code.vertex);
- print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
- print_line("\n**fragment_code:\n" + gen_code.fragment);
- print_line("\n**light_code:\n" + gen_code.light);
-#endif
-
- scene_singleton->sky_shader.shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines);
- ERR_FAIL_COND(!scene_singleton->sky_shader.shader.version_is_valid(version));
-
- ubo_size = gen_code.uniform_total_size;
- ubo_offsets = gen_code.uniform_offsets;
- texture_uniforms = gen_code.texture_uniforms;
-
- //update pipelines
-
- for (int i = 0; i < SKY_VERSION_MAX; i++) {
- RD::PipelineDepthStencilState depth_stencil_state;
- depth_stencil_state.enable_depth_test = true;
- depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
-
- RID shader_variant = scene_singleton->sky_shader.shader.version_get_shader(version, i);
- pipelines[i].setup(shader_variant, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0);
- }
-
- valid = true;
-}
-
-void RendererSceneRenderRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
- if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
- } else {
- default_texture_params[p_name] = p_texture;
- }
-}
-
-void RendererSceneRenderRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- Map<int, StringName> order;
-
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- if (E->get().texture_order >= 0) {
- order[E->get().texture_order + 100000] = E->key();
- } else {
- order[E->get().order] = E->key();
- }
- }
-
- for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
- pi.name = E->get();
- p_param_list->push_back(pi);
- }
-}
-
-void RendererSceneRenderRD::SkyShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- RendererStorage::InstanceShaderParam p;
- p.info = ShaderLanguage::uniform_to_property_info(E->get());
- p.info.name = E->key(); //supply name
- p.index = E->get().instance_index;
- p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint);
- p_param_list->push_back(p);
- }
-}
-
-bool RendererSceneRenderRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
-bool RendererSceneRenderRD::SkyShaderData::is_animated() const {
- return false;
-}
-
-bool RendererSceneRenderRD::SkyShaderData::casts_shadows() const {
- return false;
-}
-
-Variant RendererSceneRenderRD::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.hint);
- }
- return Variant();
-}
-
-RS::ShaderNativeSourceCode RendererSceneRenderRD::SkyShaderData::get_native_source_code() const {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
-
- return scene_singleton->sky_shader.shader.version_get_native_source_code(version);
-}
-
-RendererSceneRenderRD::SkyShaderData::SkyShaderData() {
- valid = false;
-}
-
-RendererSceneRenderRD::SkyShaderData::~SkyShaderData() {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
- ERR_FAIL_COND(!scene_singleton);
- //pipeline variants will clear themselves if shader is gone
- if (version.is_valid()) {
- scene_singleton->sky_shader.shader.version_free(version);
- }
-}
-
-RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_sky_shader_func() {
- SkyShaderData *shader_data = memnew(SkyShaderData);
- return shader_data;
-}
-
-void RendererSceneRenderRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
-
- uniform_set_updated = true;
-
- if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
- p_uniform_dirty = true;
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- uniform_buffer = RID();
- }
-
- ubo_data.resize(shader_data->ubo_size);
- if (ubo_data.size()) {
- uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
- memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
- }
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- //check whether buffer changed
- if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
- RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
- }
-
- uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
-
- if ((uint32_t)texture_cache.size() != tex_uniform_count) {
- texture_cache.resize(tex_uniform_count);
- p_textures_dirty = true;
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
- }
-
- if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) {
- // This material does not require an uniform set, so don't create it.
- return;
- }
-
- if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- //no reason to update uniform set, only UBO (or nothing) was needed to update
- return;
- }
-
- Vector<RD::Uniform> uniforms;
-
- {
- if (shader_data->ubo_size) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.ids.push_back(uniform_buffer);
- uniforms.push_back(u);
- }
-
- const RID *textures = texture_cache.ptrw();
- for (uint32_t i = 0; i < tex_uniform_count; i++) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1 + i;
- u.ids.push_back(textures[i]);
- uniforms.push_back(u);
- }
- }
-
- uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL);
-}
-
-RendererSceneRenderRD::SkyMaterialData::~SkyMaterialData() {
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->free(uniform_set);
- }
-
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- }
-}
-
-RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_sky_material_func(SkyShaderData *p_shader) {
- SkyMaterialData *material_data = memnew(SkyMaterialData);
- material_data->shader_data = p_shader;
- material_data->last_frame = false;
- //update will happen later anyway so do nothing.
- return material_data;
-}
-
-RID RendererSceneRenderRD::environment_create() {
- return environment_owner.make_rid(Environment());
+void RendererSceneRenderRD::environment_initialize(RID p_rid) {
+ environment_owner.initialize_rid(p_rid, RendererSceneEnvironmentRD());
}
void RendererSceneRenderRD::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->background = p_bg;
}
void RendererSceneRenderRD::environment_set_sky(RID p_env, RID p_sky) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->sky = p_sky;
}
void RendererSceneRenderRD::environment_set_sky_custom_fov(RID p_env, float p_scale) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->sky_custom_fov = p_scale;
}
void RendererSceneRenderRD::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->sky_orientation = p_orientation;
}
void RendererSceneRenderRD::environment_set_bg_color(RID p_env, const Color &p_color) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->bg_color = p_color;
}
void RendererSceneRenderRD::environment_set_bg_energy(RID p_env, float p_energy) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->bg_energy = p_energy;
}
void RendererSceneRenderRD::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->canvas_max_layer = p_max_layer;
}
void RendererSceneRenderRD::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
- env->ambient_light = p_color;
- env->ambient_source = p_ambient;
- env->ambient_light_energy = p_energy;
- env->ambient_sky_contribution = p_sky_contribution;
- env->reflection_source = p_reflection_source;
- env->ao_color = p_ao_color;
+ env->set_ambient_light(p_color, p_ambient, p_energy, p_sky_contribution, p_reflection_source, p_ao_color);
}
RS::EnvironmentBG RendererSceneRenderRD::environment_get_background(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX);
return env->background;
}
RID RendererSceneRenderRD::environment_get_sky(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, RID());
return env->sky;
}
float RendererSceneRenderRD::environment_get_sky_custom_fov(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->sky_custom_fov;
}
Basis RendererSceneRenderRD::environment_get_sky_orientation(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, Basis());
return env->sky_orientation;
}
Color RendererSceneRenderRD::environment_get_bg_color(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, Color());
return env->bg_color;
}
float RendererSceneRenderRD::environment_get_bg_energy(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->bg_energy;
}
int RendererSceneRenderRD::environment_get_canvas_max_layer(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->canvas_max_layer;
}
Color RendererSceneRenderRD::environment_get_ambient_light_color(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, Color());
return env->ambient_light;
}
RS::EnvironmentAmbientSource RendererSceneRenderRD::environment_get_ambient_source(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, RS::ENV_AMBIENT_SOURCE_BG);
return env->ambient_source;
}
float RendererSceneRenderRD::environment_get_ambient_light_energy(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->ambient_light_energy;
}
float RendererSceneRenderRD::environment_get_ambient_sky_contribution(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->ambient_sky_contribution;
}
RS::EnvironmentReflectionSource RendererSceneRenderRD::environment_get_reflection_source(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, RS::ENV_REFLECTION_SOURCE_DISABLED);
return env->reflection_source;
}
Color RendererSceneRenderRD::environment_get_ao_color(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, Color());
return env->ao_color;
}
void RendererSceneRenderRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
- env->exposure = p_exposure;
- env->tone_mapper = p_tone_mapper;
- if (!env->auto_exposure && p_auto_exposure) {
- env->auto_exposure_version = ++auto_exposure_counter;
- }
- env->auto_exposure = p_auto_exposure;
- env->white = p_white;
- env->min_luminance = p_min_luminance;
- env->max_luminance = p_max_luminance;
- env->auto_exp_speed = p_auto_exp_speed;
- env->auto_exp_scale = p_auto_exp_scale;
+ env->set_tonemap(p_tone_mapper, p_exposure, p_white, p_auto_exposure, p_min_luminance, p_max_luminance, p_auto_exp_speed, p_auto_exp_scale);
}
void RendererSceneRenderRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
- ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
- env->glow_enabled = p_enable;
- env->glow_levels = p_levels;
- env->glow_intensity = p_intensity;
- env->glow_strength = p_strength;
- env->glow_mix = p_mix;
- env->glow_bloom = p_bloom_threshold;
- env->glow_blend_mode = p_blend_mode;
- env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold;
- env->glow_hdr_bleed_scale = p_hdr_bleed_scale;
- env->glow_hdr_luminance_cap = p_hdr_luminance_cap;
+ env->set_glow(p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap);
}
void RendererSceneRenderRD::environment_glow_set_use_bicubic_upscale(bool p_enable) {
@@ -3019,100 +313,77 @@ void RendererSceneRenderRD::environment_glow_set_use_high_quality(bool p_enable)
glow_high_quality = p_enable;
}
-void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
- Environment *env = environment_owner.getornull(p_env);
+void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
if (low_end) {
return;
}
- env->sdfgi_enabled = p_enable;
- env->sdfgi_cascades = p_cascades;
- env->sdfgi_min_cell_size = p_min_cell_size;
- env->sdfgi_use_occlusion = p_use_occlusion;
- env->sdfgi_use_multibounce = p_use_multibounce;
- env->sdfgi_read_sky_light = p_read_sky;
- env->sdfgi_energy = p_energy;
- env->sdfgi_normal_bias = p_normal_bias;
- env->sdfgi_probe_bias = p_probe_bias;
- env->sdfgi_y_scale = p_y_scale;
+ env->set_sdfgi(p_enable, p_cascades, p_min_cell_size, p_y_scale, p_use_occlusion, p_bounce_feedback, p_read_sky, p_energy, p_normal_bias, p_probe_bias);
}
void RendererSceneRenderRD::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
- env->fog_enabled = p_enable;
- env->fog_light_color = p_light_color;
- env->fog_light_energy = p_light_energy;
- env->fog_sun_scatter = p_sun_scatter;
- env->fog_density = p_density;
- env->fog_height = p_height;
- env->fog_height_density = p_height_density;
- env->fog_aerial_perspective = p_fog_aerial_perspective;
+ env->set_fog(p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_fog_aerial_perspective);
}
bool RendererSceneRenderRD::environment_is_fog_enabled(RID p_env) const {
- const Environment *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, false);
return env->fog_enabled;
}
Color RendererSceneRenderRD::environment_get_fog_light_color(RID p_env) const {
- const Environment *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, Color());
return env->fog_light_color;
}
float RendererSceneRenderRD::environment_get_fog_light_energy(RID p_env) const {
- const Environment *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_light_energy;
}
float RendererSceneRenderRD::environment_get_fog_sun_scatter(RID p_env) const {
- const Environment *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_sun_scatter;
}
float RendererSceneRenderRD::environment_get_fog_density(RID p_env) const {
- const Environment *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_density;
}
float RendererSceneRenderRD::environment_get_fog_height(RID p_env) const {
- const Environment *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_height;
}
float RendererSceneRenderRD::environment_get_fog_height_density(RID p_env) const {
- const Environment *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_height_density;
}
float RendererSceneRenderRD::environment_get_fog_aerial_perspective(RID p_env) const {
- const Environment *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_aerial_perspective;
}
-void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RenderingServer::EnvVolumetricFogShadowFilter p_shadow_filter) {
- Environment *env = environment_owner.getornull(p_env);
+void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) {
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
if (low_end) {
return;
}
- env->volumetric_fog_enabled = p_enable;
- env->volumetric_fog_density = p_density;
- env->volumetric_fog_light = p_light;
- env->volumetric_fog_light_energy = p_light_energy;
- env->volumetric_fog_length = p_length;
- env->volumetric_fog_detail_spread = p_detail_spread;
- env->volumetric_fog_shadow_filter = p_shadow_filter;
- env->volumetric_fog_gi_inject = p_gi_inject;
+ env->set_volumetric_fog(p_enable, p_density, p_light, p_light_energy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount);
}
void RendererSceneRenderRD::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) {
@@ -3123,50 +394,27 @@ void RendererSceneRenderRD::environment_set_volumetric_fog_volume_size(int p_siz
void RendererSceneRenderRD::environment_set_volumetric_fog_filter_active(bool p_enable) {
volumetric_fog_filter_active = p_enable;
}
-void RendererSceneRenderRD::environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) {
- p_shrink_size = nearest_power_of_2_templated(p_shrink_size);
- if (volumetric_fog_directional_shadow_shrink == (uint32_t)p_shrink_size) {
- return;
- }
-
- _clear_shadow_shrink_stages(directional_shadow.shrink_stages);
-}
-void RendererSceneRenderRD::environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size) {
- p_shrink_size = nearest_power_of_2_templated(p_shrink_size);
- if (volumetric_fog_positional_shadow_shrink == (uint32_t)p_shrink_size) {
- return;
- }
-
- for (uint32_t i = 0; i < shadow_atlas_owner.get_rid_count(); i++) {
- ShadowAtlas *sa = shadow_atlas_owner.get_ptr_by_index(i);
- _clear_shadow_shrink_stages(sa->shrink_stages);
- }
-}
void RendererSceneRenderRD::environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) {
- sdfgi_ray_count = p_ray_count;
+ gi.sdfgi_ray_count = p_ray_count;
}
void RendererSceneRenderRD::environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) {
- sdfgi_frames_to_converge = p_frames;
+ gi.sdfgi_frames_to_converge = p_frames;
}
void RendererSceneRenderRD::environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) {
- sdfgi_frames_to_update_light = p_update;
+ gi.sdfgi_frames_to_update_light = p_update;
}
void RendererSceneRenderRD::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
if (low_end) {
return;
}
- env->ssr_enabled = p_enable;
- env->ssr_max_steps = p_max_steps;
- env->ssr_fade_in = p_fade_int;
- env->ssr_fade_out = p_fade_out;
- env->ssr_depth_tolerance = p_depth_tolerance;
+ env->set_ssr(p_enable, p_max_steps, p_fade_int, p_fade_out, p_depth_tolerance);
}
void RendererSceneRenderRD::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
@@ -3178,22 +426,14 @@ RS::EnvironmentSSRRoughnessQuality RendererSceneRenderRD::environment_get_ssr_ro
}
void RendererSceneRenderRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
if (low_end) {
return;
}
- env->ssao_enabled = p_enable;
- env->ssao_radius = p_radius;
- env->ssao_intensity = p_intensity;
- env->ssao_power = p_power;
- env->ssao_detail = p_detail;
- env->ssao_horizon = p_horizon;
- env->ssao_sharpness = p_sharpness;
- env->ssao_direct_light_affect = p_light_affect;
- env->ssao_ao_channel_affect = p_ao_channel_affect;
+ env->set_ssao(p_enable, p_radius, p_intensity, p_power, p_detail, p_horizon, p_sharpness, p_light_affect, p_ao_channel_affect);
}
void RendererSceneRenderRD::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
@@ -3206,30 +446,30 @@ void RendererSceneRenderRD::environment_set_ssao_quality(RS::EnvironmentSSAOQual
}
bool RendererSceneRenderRD::environment_is_ssao_enabled(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, false);
return env->ssao_enabled;
}
float RendererSceneRenderRD::environment_get_ssao_ao_affect(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0.0);
return env->ssao_ao_channel_affect;
}
float RendererSceneRenderRD::environment_get_ssao_light_affect(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0.0);
return env->ssao_direct_light_affect;
}
bool RendererSceneRenderRD::environment_is_ssr_enabled(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, false);
return env->ssr_enabled;
}
bool RendererSceneRenderRD::environment_is_sdfgi_enabled(RID p_env) const {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, false);
return env->sdfgi_enabled;
}
@@ -3239,7 +479,7 @@ bool RendererSceneRenderRD::is_environment(RID p_env) const {
}
Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, Ref<Image>());
if (env->background == RS::ENV_BG_CAMERA_FEED || env->background == RS::ENV_BG_CANVAS || env->background == RS::ENV_BG_KEEP) {
@@ -3279,8 +519,8 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
RID RendererSceneRenderRD::reflection_atlas_create() {
ReflectionAtlas ra;
- ra.count = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_count");
- ra.size = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_size");
+ ra.count = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_count");
+ ra.size = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_size");
ra.cluster_builder = memnew(ClusterBuilderRD);
ra.cluster_builder->set_shared(&cluster_builder_shared);
@@ -3309,7 +549,7 @@ void RendererSceneRenderRD::reflection_atlas_set_size(RID p_ref_atlas, int p_ref
RD::get_singleton()->free(ra->depth_buffer);
ra->depth_buffer = RID();
for (int i = 0; i < ra->reflections.size(); i++) {
- _clear_reflection_data(ra->reflections.write[i].data);
+ ra->reflections.write[i].data.clear_reflection_data();
if (ra->reflections[i].owner.is_null()) {
continue;
}
@@ -3413,7 +653,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
}
if (atlas->reflection.is_null()) {
- int mipmaps = MIN(roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1);
+ int mipmaps = MIN(sky.roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1);
mipmaps = storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering
{
//reflection atlas was unused, create:
@@ -3438,7 +678,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
}
atlas->reflections.resize(atlas->count);
for (int i = 0; i < atlas->count; i++) {
- _update_reflection_data(atlas->reflections.write[i].data, atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS);
+ atlas->reflections.write[i].data.update_reflection_data(atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers);
for (int j = 0; j < 6; j++) {
Vector<RID> fb;
fb.push_back(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j]);
@@ -3498,7 +738,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins
if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
// Using real time reflections, all roughness is done in one step
- _create_reflection_fast_filter(atlas->reflections.write[rpi->atlas_index].data, false);
+ atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(storage, false);
rpi->rendering = false;
rpi->processing_side = 0;
rpi->processing_layer = 1;
@@ -3506,7 +746,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins
}
if (rpi->processing_layer > 1) {
- _create_reflection_importance_sample(atlas->reflections.write[rpi->atlas_index].data, false, 10, rpi->processing_layer);
+ atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(storage, false, 10, rpi->processing_layer, sky.sky_ggx_samples_quality);
rpi->processing_layer++;
if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) {
rpi->rendering = false;
@@ -3517,7 +757,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins
return false;
} else {
- _create_reflection_importance_sample(atlas->reflections.write[rpi->atlas_index].data, false, rpi->processing_side, rpi->processing_layer);
+ atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(storage, false, rpi->processing_side, rpi->processing_layer, sky.sky_ggx_samples_quality);
}
rpi->processing_side++;
@@ -3593,7 +833,6 @@ void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size, bool
if (shadow_atlas->depth.is_valid()) {
RD::get_singleton()->free(shadow_atlas->depth);
shadow_atlas->depth = RID();
- _clear_shadow_shrink_stages(shadow_atlas->shrink_stages);
}
for (int i = 0; i < 4; i++) {
//clear subdivisions
@@ -3892,7 +1131,6 @@ void RendererSceneRenderRD::directional_shadow_atlas_set_size(int p_size, bool p
if (directional_shadow.depth.is_valid()) {
RD::get_singleton()->free(directional_shadow.depth);
- _clear_shadow_shrink_stages(directional_shadow.shrink_stages);
directional_shadow.depth = RID();
_base_uniforms_changed();
}
@@ -3949,8 +1187,11 @@ int RendererSceneRenderRD::get_directional_light_shadow_size(RID p_light_intance
//////////////////////////////////////////////////
-RID RendererSceneRenderRD::camera_effects_create() {
- return camera_effects_owner.make_rid(CameraEffects());
+RID RendererSceneRenderRD::camera_effects_allocate() {
+ return camera_effects_owner.allocate_rid();
+}
+void RendererSceneRenderRD::camera_effects_initialize(RID p_rid) {
+ camera_effects_owner.initialize_rid(p_rid, CameraEffects());
}
void RendererSceneRenderRD::camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) {
@@ -4015,11 +1256,7 @@ void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_inst
LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
ERR_FAIL_COND(!light_instance);
- if (storage->light_get_type(light_instance->light) != RS::LIGHT_DIRECTIONAL) {
- p_pass = 0;
- }
-
- ERR_FAIL_INDEX(p_pass, 4);
+ ERR_FAIL_INDEX(p_pass, 6);
light_instance->shadow_transform[p_pass].camera = p_projection;
light_instance->shadow_transform[p_pass].transform = p_transform;
@@ -4095,817 +1332,27 @@ void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, cons
/////////////////////////////////
RID RendererSceneRenderRD::gi_probe_instance_create(RID p_base) {
- GIProbeInstance gi_probe;
- gi_probe.probe = p_base;
- RID rid = gi_probe_instance_owner.make_rid(gi_probe);
- return rid;
+ return gi.gi_probe_instance_create(p_base);
}
void RendererSceneRenderRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
- ERR_FAIL_COND(!gi_probe);
-
- gi_probe->transform = p_xform;
+ gi.gi_probe_instance_set_transform_to_data(p_probe, p_xform);
}
bool RendererSceneRenderRD::gi_probe_needs_update(RID p_probe) const {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gi_probe, false);
-
if (low_end) {
return false;
}
- //return true;
- return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
+ return gi.gi_probe_needs_update(p_probe);
}
void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
- ERR_FAIL_COND(!gi_probe);
-
if (low_end) {
return;
}
- uint32_t data_version = storage->gi_probe_get_data_version(gi_probe->probe);
-
- // (RE)CREATE IF NEEDED
-
- if (gi_probe->last_probe_data_version != data_version) {
- //need to re-create everything
- if (gi_probe->texture.is_valid()) {
- RD::get_singleton()->free(gi_probe->texture);
- RD::get_singleton()->free(gi_probe->write_buffer);
- gi_probe->mipmaps.clear();
- }
-
- for (int i = 0; i < gi_probe->dynamic_maps.size(); i++) {
- RD::get_singleton()->free(gi_probe->dynamic_maps[i].texture);
- RD::get_singleton()->free(gi_probe->dynamic_maps[i].depth);
- }
-
- gi_probe->dynamic_maps.clear();
-
- Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe);
-
- if (octree_size != Vector3i()) {
- //can create a 3D texture
- Vector<int> levels = storage->gi_probe_get_level_counts(gi_probe->probe);
-
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tf.width = octree_size.x;
- tf.height = octree_size.y;
- tf.depth = octree_size.z;
- tf.texture_type = RD::TEXTURE_TYPE_3D;
- tf.mipmaps = levels.size();
-
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
-
- gi_probe->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- RD::get_singleton()->texture_clear(gi_probe->texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1);
-
- {
- int total_elements = 0;
- for (int i = 0; i < levels.size(); i++) {
- total_elements += levels[i];
- }
-
- gi_probe->write_buffer = RD::get_singleton()->storage_buffer_create(total_elements * 16);
- }
-
- for (int i = 0; i < levels.size(); i++) {
- GIProbeInstance::Mipmap mipmap;
- mipmap.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), gi_probe->texture, 0, i, RD::TEXTURE_SLICE_3D);
- mipmap.level = levels.size() - i - 1;
- mipmap.cell_offset = 0;
- for (uint32_t j = 0; j < mipmap.level; j++) {
- mipmap.cell_offset += levels[j];
- }
- mipmap.cell_count = levels[mipmap.level];
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 1;
- u.ids.push_back(storage->gi_probe_get_octree_buffer(gi_probe->probe));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe));
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 4;
- u.ids.push_back(gi_probe->write_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 9;
- u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 10;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
-
- {
- Vector<RD::Uniform> copy_uniforms = uniforms;
- if (i == 0) {
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 3;
- u.ids.push_back(gi_probe_lights_uniform);
- copy_uniforms.push_back(u);
- }
-
- mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT], 0);
-
- copy_uniforms = uniforms; //restore
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 5;
- u.ids.push_back(gi_probe->texture);
- copy_uniforms.push_back(u);
- }
- mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0);
- } else {
- mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP], 0);
- }
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 5;
- u.ids.push_back(mipmap.texture);
- uniforms.push_back(u);
- }
-
- mipmap.write_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE], 0);
-
- gi_probe->mipmaps.push_back(mipmap);
- }
-
- {
- uint32_t dynamic_map_size = MAX(MAX(octree_size.x, octree_size.y), octree_size.z);
- uint32_t oversample = nearest_power_of_2_templated(4);
- int mipmap_index = 0;
-
- while (mipmap_index < gi_probe->mipmaps.size()) {
- GIProbeInstance::DynamicMap dmap;
-
- if (oversample > 0) {
- dmap.size = dynamic_map_size * (1 << oversample);
- dmap.mipmap = -1;
- oversample--;
- } else {
- dmap.size = dynamic_map_size >> mipmap_index;
- dmap.mipmap = mipmap_index;
- mipmap_index++;
- }
-
- RD::TextureFormat dtf;
- dtf.width = dmap.size;
- dtf.height = dmap.size;
- dtf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
-
- if (gi_probe->dynamic_maps.size() == 0) {
- dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- }
- dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView());
-
- if (gi_probe->dynamic_maps.size() == 0) {
- //render depth for first one
- dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
- dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
- dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
- }
-
- //just use depth as-is
- dtf.format = RD::DATA_FORMAT_R32_SFLOAT;
- dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
-
- dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
-
- if (gi_probe->dynamic_maps.size() == 0) {
- dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView());
- dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView());
- dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView());
-
- Vector<RID> fb;
- fb.push_back(dmap.albedo);
- fb.push_back(dmap.normal);
- fb.push_back(dmap.orm);
- fb.push_back(dmap.texture); //emission
- fb.push_back(dmap.depth);
- fb.push_back(dmap.fb_depth);
-
- dmap.fb = RD::get_singleton()->framebuffer_create(fb);
-
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 3;
- u.ids.push_back(gi_probe_lights_uniform);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 5;
- u.ids.push_back(dmap.albedo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 6;
- u.ids.push_back(dmap.normal);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 7;
- u.ids.push_back(dmap.orm);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 8;
- u.ids.push_back(dmap.fb_depth);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 9;
- u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 10;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 11;
- u.ids.push_back(dmap.texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 12;
- u.ids.push_back(dmap.depth);
- uniforms.push_back(u);
- }
-
- dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING], 0);
- }
- } else {
- bool plot = dmap.mipmap >= 0;
- bool write = dmap.mipmap < (gi_probe->mipmaps.size() - 1);
-
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 5;
- u.ids.push_back(gi_probe->dynamic_maps[gi_probe->dynamic_maps.size() - 1].texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 6;
- u.ids.push_back(gi_probe->dynamic_maps[gi_probe->dynamic_maps.size() - 1].depth);
- uniforms.push_back(u);
- }
-
- if (write) {
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 7;
- u.ids.push_back(dmap.texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 8;
- u.ids.push_back(dmap.depth);
- uniforms.push_back(u);
- }
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 9;
- u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 10;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
-
- if (plot) {
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 11;
- u.ids.push_back(gi_probe->mipmaps[dmap.mipmap].texture);
- uniforms.push_back(u);
- }
- }
-
- dmap.uniform_set = RD::get_singleton()->uniform_set_create(
- uniforms,
- giprobe_lighting_shader_version_shaders[(write && plot) ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : (write ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT)],
- 0);
- }
-
- gi_probe->dynamic_maps.push_back(dmap);
- }
- }
- }
-
- gi_probe->last_probe_data_version = data_version;
- p_update_light_instances = true; //just in case
-
- _base_uniforms_changed();
- }
-
- // UDPDATE TIME
-
- if (gi_probe->has_dynamic_object_data) {
- //if it has dynamic object data, it needs to be cleared
- RD::get_singleton()->texture_clear(gi_probe->texture, Color(0, 0, 0, 0), 0, gi_probe->mipmaps.size(), 0, 1);
- }
-
- uint32_t light_count = 0;
-
- if (p_update_light_instances || p_dynamic_objects.size() > 0) {
- light_count = MIN(gi_probe_max_lights, (uint32_t)p_light_instances.size());
-
- {
- Transform to_cell = storage->gi_probe_get_to_cell_xform(gi_probe->probe);
- Transform to_probe_xform = (gi_probe->transform * to_cell.affine_inverse()).affine_inverse();
- //update lights
-
- for (uint32_t i = 0; i < light_count; i++) {
- GIProbeLight &l = gi_probe_lights[i];
- RID light_instance = p_light_instances[i];
- RID light = light_instance_get_base_light(light_instance);
-
- l.type = storage->light_get_type(light);
- if (l.type == RS::LIGHT_DIRECTIONAL && storage->light_directional_is_sky_only(light)) {
- light_count--;
- continue;
- }
-
- l.attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
- l.energy = storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length();
- Color color = storage->light_get_color(light).to_linear();
- l.color[0] = color.r;
- l.color[1] = color.g;
- l.color[2] = color.b;
-
- l.spot_angle_radians = Math::deg2rad(storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE));
- l.spot_attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
-
- Transform xform = light_instance_get_base_transform(light_instance);
-
- Vector3 pos = to_probe_xform.xform(xform.origin);
- Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_axis(2)).normalized();
-
- l.position[0] = pos.x;
- l.position[1] = pos.y;
- l.position[2] = pos.z;
-
- l.direction[0] = dir.x;
- l.direction[1] = dir.y;
- l.direction[2] = dir.z;
-
- l.has_shadow = storage->light_has_shadow(light);
- }
-
- RD::get_singleton()->buffer_update(gi_probe_lights_uniform, 0, sizeof(GIProbeLight) * light_count, gi_probe_lights);
- }
- }
-
- if (gi_probe->has_dynamic_object_data || p_update_light_instances || p_dynamic_objects.size()) {
- // PROCESS MIPMAPS
- if (gi_probe->mipmaps.size()) {
- //can update mipmaps
-
- Vector3i probe_size = storage->gi_probe_get_octree_size(gi_probe->probe);
-
- GIProbePushConstant push_constant;
-
- push_constant.limits[0] = probe_size.x;
- push_constant.limits[1] = probe_size.y;
- push_constant.limits[2] = probe_size.z;
- push_constant.stack_size = gi_probe->mipmaps.size();
- push_constant.emission_scale = 1.0;
- push_constant.propagation = storage->gi_probe_get_propagation(gi_probe->probe);
- push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe);
- push_constant.light_count = light_count;
- push_constant.aniso_strength = 0;
-
- /* print_line("probe update to version " + itos(gi_probe->last_probe_version));
- print_line("propagation " + rtos(push_constant.propagation));
- print_line("dynrange " + rtos(push_constant.dynamic_range));
- */
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- int passes;
- if (p_update_light_instances) {
- passes = storage->gi_probe_is_using_two_bounces(gi_probe->probe) ? 2 : 1;
- } else {
- passes = 1; //only re-blitting is necessary
- }
- int wg_size = 64;
- int wg_limit_x = RD::get_singleton()->limit_get(RD::LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X);
-
- for (int pass = 0; pass < passes; pass++) {
- if (p_update_light_instances) {
- for (int i = 0; i < gi_probe->mipmaps.size(); i++) {
- if (i == 0) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[pass == 0 ? GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT : GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]);
- } else if (i == 1) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP]);
- }
-
- if (pass == 1 || i > 0) {
- RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done
- }
- if (pass == 0 || i > 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].uniform_set, 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].second_bounce_uniform_set, 0);
- }
-
- push_constant.cell_offset = gi_probe->mipmaps[i].cell_offset;
- push_constant.cell_count = gi_probe->mipmaps[i].cell_count;
-
- int wg_todo = (gi_probe->mipmaps[i].cell_count - 1) / wg_size + 1;
- while (wg_todo) {
- int wg_count = MIN(wg_todo, wg_limit_x);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1);
- wg_todo -= wg_count;
- push_constant.cell_offset += wg_count * wg_size;
- }
- }
-
- RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE]);
-
- for (int i = 0; i < gi_probe->mipmaps.size(); i++) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].write_uniform_set, 0);
-
- push_constant.cell_offset = gi_probe->mipmaps[i].cell_offset;
- push_constant.cell_count = gi_probe->mipmaps[i].cell_count;
-
- int wg_todo = (gi_probe->mipmaps[i].cell_count - 1) / wg_size + 1;
- while (wg_todo) {
- int wg_count = MIN(wg_todo, wg_limit_x);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1);
- wg_todo -= wg_count;
- push_constant.cell_offset += wg_count * wg_size;
- }
- }
- }
-
- RD::get_singleton()->compute_list_end();
- }
- }
-
- gi_probe->has_dynamic_object_data = false; //clear until dynamic object data is used again
-
- if (p_dynamic_objects.size() && gi_probe->dynamic_maps.size()) {
- Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe);
- int multiplier = gi_probe->dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z);
-
- Transform oversample_scale;
- oversample_scale.basis.scale(Vector3(multiplier, multiplier, multiplier));
-
- Transform to_cell = oversample_scale * storage->gi_probe_get_to_cell_xform(gi_probe->probe);
- Transform to_world_xform = gi_probe->transform * to_cell.affine_inverse();
- Transform to_probe_xform = to_world_xform.affine_inverse();
-
- AABB probe_aabb(Vector3(), octree_size);
-
- //this could probably be better parallelized in compute..
- for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
- GeometryInstance *instance = p_dynamic_objects[i];
-
- //transform aabb to giprobe
- AABB aabb = (to_probe_xform * geometry_instance_get_transform(instance)).xform(geometry_instance_get_aabb(instance));
-
- //this needs to wrap to grid resolution to avoid jitter
- //also extend margin a bit just in case
- Vector3i begin = aabb.position - Vector3i(1, 1, 1);
- Vector3i end = aabb.position + aabb.size + Vector3i(1, 1, 1);
-
- for (int j = 0; j < 3; j++) {
- if ((end[j] - begin[j]) & 1) {
- end[j]++; //for half extents split, it needs to be even
- }
- begin[j] = MAX(begin[j], 0);
- end[j] = MIN(end[j], octree_size[j] * multiplier);
- }
-
- //aabb = aabb.intersection(probe_aabb); //intersect
- aabb.position = begin;
- aabb.size = end - begin;
-
- //print_line("aabb: " + aabb);
-
- for (int j = 0; j < 6; j++) {
- //if (j != 0 && j != 3) {
- // continue;
- //}
- static const Vector3 render_z[6] = {
- Vector3(1, 0, 0),
- Vector3(0, 1, 0),
- Vector3(0, 0, 1),
- Vector3(-1, 0, 0),
- Vector3(0, -1, 0),
- Vector3(0, 0, -1),
- };
- static const Vector3 render_up[6] = {
- Vector3(0, 1, 0),
- Vector3(0, 0, 1),
- Vector3(0, 1, 0),
- Vector3(0, 1, 0),
- Vector3(0, 0, 1),
- Vector3(0, 1, 0),
- };
-
- Vector3 render_dir = render_z[j];
- Vector3 up_dir = render_up[j];
-
- Vector3 center = aabb.position + aabb.size * 0.5;
- Transform xform;
- xform.set_look_at(center - aabb.size * 0.5 * render_dir, center, up_dir);
-
- Vector3 x_dir = xform.basis.get_axis(0).abs();
- int x_axis = int(Vector3(0, 1, 2).dot(x_dir));
- Vector3 y_dir = xform.basis.get_axis(1).abs();
- int y_axis = int(Vector3(0, 1, 2).dot(y_dir));
- Vector3 z_dir = -xform.basis.get_axis(2);
- int z_axis = int(Vector3(0, 1, 2).dot(z_dir.abs()));
-
- Rect2i rect(aabb.position[x_axis], aabb.position[y_axis], aabb.size[x_axis], aabb.size[y_axis]);
- bool x_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(0)) < 0);
- bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(1)) < 0);
- bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(2)) > 0);
-
- CameraMatrix cm;
- cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]);
-
- if (cull_argument.size() == 0) {
- cull_argument.push_back(nullptr);
- }
- cull_argument[0] = instance;
-
- _render_material(to_world_xform * xform, cm, true, cull_argument, gi_probe->dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size));
-
- GIProbeDynamicPushConstant push_constant;
- zeromem(&push_constant, sizeof(GIProbeDynamicPushConstant));
- push_constant.limits[0] = octree_size.x;
- push_constant.limits[1] = octree_size.y;
- push_constant.limits[2] = octree_size.z;
- push_constant.light_count = p_light_instances.size();
- push_constant.x_dir[0] = x_dir[0];
- push_constant.x_dir[1] = x_dir[1];
- push_constant.x_dir[2] = x_dir[2];
- push_constant.y_dir[0] = y_dir[0];
- push_constant.y_dir[1] = y_dir[1];
- push_constant.y_dir[2] = y_dir[2];
- push_constant.z_dir[0] = z_dir[0];
- push_constant.z_dir[1] = z_dir[1];
- push_constant.z_dir[2] = z_dir[2];
- push_constant.z_base = xform.origin[z_axis];
- push_constant.z_sign = (z_flip ? -1.0 : 1.0);
- push_constant.pos_multiplier = float(1.0) / multiplier;
- push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe);
- push_constant.flip_x = x_flip;
- push_constant.flip_y = y_flip;
- push_constant.rect_pos[0] = rect.position[0];
- push_constant.rect_pos[1] = rect.position[1];
- push_constant.rect_size[0] = rect.size[0];
- push_constant.rect_size[1] = rect.size[1];
- push_constant.prev_rect_ofs[0] = 0;
- push_constant.prev_rect_ofs[1] = 0;
- push_constant.prev_rect_size[0] = 0;
- push_constant.prev_rect_size[1] = 0;
- push_constant.on_mipmap = false;
- push_constant.propagation = storage->gi_probe_get_propagation(gi_probe->probe);
- push_constant.pad[0] = 0;
- push_constant.pad[1] = 0;
- push_constant.pad[2] = 0;
-
- //process lighting
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->dynamic_maps[0].uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1);
- //print_line("rect: " + itos(i) + ": " + rect);
-
- for (int k = 1; k < gi_probe->dynamic_maps.size(); k++) {
- // enlarge the rect if needed so all pixels fit when downscaled,
- // this ensures downsampling is smooth and optimal because no pixels are left behind
-
- //x
- if (rect.position.x & 1) {
- rect.size.x++;
- push_constant.prev_rect_ofs[0] = 1; //this is used to ensure reading is also optimal
- } else {
- push_constant.prev_rect_ofs[0] = 0;
- }
- if (rect.size.x & 1) {
- rect.size.x++;
- }
-
- rect.position.x >>= 1;
- rect.size.x = MAX(1, rect.size.x >> 1);
-
- //y
- if (rect.position.y & 1) {
- rect.size.y++;
- push_constant.prev_rect_ofs[1] = 1;
- } else {
- push_constant.prev_rect_ofs[1] = 0;
- }
- if (rect.size.y & 1) {
- rect.size.y++;
- }
-
- rect.position.y >>= 1;
- rect.size.y = MAX(1, rect.size.y >> 1);
-
- //shrink limits to ensure plot does not go outside map
- if (gi_probe->dynamic_maps[k].mipmap > 0) {
- for (int l = 0; l < 3; l++) {
- push_constant.limits[l] = MAX(1, push_constant.limits[l] >> 1);
- }
- }
-
- //print_line("rect: " + itos(i) + ": " + rect);
- push_constant.rect_pos[0] = rect.position[0];
- push_constant.rect_pos[1] = rect.position[1];
- push_constant.prev_rect_size[0] = push_constant.rect_size[0];
- push_constant.prev_rect_size[1] = push_constant.rect_size[1];
- push_constant.rect_size[0] = rect.size[0];
- push_constant.rect_size[1] = rect.size[1];
- push_constant.on_mipmap = gi_probe->dynamic_maps[k].mipmap > 0;
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- if (gi_probe->dynamic_maps[k].mipmap < 0) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE]);
- } else if (k < gi_probe->dynamic_maps.size() - 1) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT]);
- } else {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT]);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->dynamic_maps[k].uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1);
- }
-
- RD::get_singleton()->compute_list_end();
- }
- }
-
- gi_probe->has_dynamic_object_data = true; //clear until dynamic object data is used again
- }
-
- gi_probe->last_probe_version = storage->gi_probe_get_version(gi_probe->probe);
-}
-
-void RendererSceneRenderRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_gi_probe);
- ERR_FAIL_COND(!gi_probe);
-
- if (gi_probe->mipmaps.size() == 0) {
- return;
- }
-
- CameraMatrix transform = (p_camera_with_transform * CameraMatrix(gi_probe->transform)) * CameraMatrix(storage->gi_probe_get_to_cell_xform(gi_probe->probe).affine_inverse());
-
- int level = 0;
- Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe);
-
- GIProbeDebugPushConstant push_constant;
- push_constant.alpha = p_alpha;
- push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe);
- push_constant.cell_offset = gi_probe->mipmaps[level].cell_offset;
- push_constant.level = level;
-
- push_constant.bounds[0] = octree_size.x >> level;
- push_constant.bounds[1] = octree_size.y >> level;
- push_constant.bounds[2] = octree_size.z >> level;
- push_constant.pad = 0;
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- push_constant.projection[i * 4 + j] = transform.matrix[i][j];
- }
- }
-
- if (giprobe_debug_uniform_set.is_valid()) {
- RD::get_singleton()->free(giprobe_debug_uniform_set);
- }
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 1;
- u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2;
- u.ids.push_back(gi_probe->texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 3;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
-
- int cell_count;
- if (!p_emission && p_lighting && gi_probe->has_dynamic_object_data) {
- cell_count = push_constant.bounds[0] * push_constant.bounds[1] * push_constant.bounds[2];
- } else {
- cell_count = gi_probe->mipmaps[level].cell_count;
- }
-
- giprobe_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_debug_shader_version_shaders[0], 0);
-
- int giprobe_debug_pipeline = GI_PROBE_DEBUG_COLOR;
- if (p_emission) {
- giprobe_debug_pipeline = GI_PROBE_DEBUG_EMISSION;
- } else if (p_lighting) {
- giprobe_debug_pipeline = gi_probe->has_dynamic_object_data ? GI_PROBE_DEBUG_LIGHT_FULL : GI_PROBE_DEBUG_LIGHT;
- }
- RD::get_singleton()->draw_list_bind_render_pipeline(
- p_draw_list,
- giprobe_debug_shader_version_pipelines[giprobe_debug_pipeline].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, giprobe_debug_uniform_set, 0);
- RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(GIProbeDebugPushConstant));
- RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, 36);
+ gi.gi_probe_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this);
}
void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) {
@@ -4916,132 +1363,7 @@ void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawLi
return; //nothing to debug
}
- SDGIShader::DebugProbesPushConstant push_constant;
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- push_constant.projection[i * 4 + j] = p_camera_with_transform.matrix[i][j];
- }
- }
-
- //gen spheres from strips
- uint32_t band_points = 16;
- push_constant.band_power = 4;
- push_constant.sections_in_band = ((band_points / 2) - 1);
- push_constant.band_mask = band_points - 2;
- push_constant.section_arc = Math_TAU / float(push_constant.sections_in_band);
- push_constant.y_mult = rb->sdfgi->y_mult;
-
- uint32_t total_points = push_constant.sections_in_band * band_points;
- uint32_t total_probes = rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count;
-
- push_constant.grid_size[0] = rb->sdfgi->cascade_size;
- push_constant.grid_size[1] = rb->sdfgi->cascade_size;
- push_constant.grid_size[2] = rb->sdfgi->cascade_size;
- push_constant.cascade = 0;
-
- push_constant.probe_axis_size = rb->sdfgi->probe_axis_count;
-
- if (!rb->sdfgi->debug_probes_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(rb->sdfgi->debug_probes_uniform_set)) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(rb->sdfgi->cascades_ubo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(rb->sdfgi->lightprobe_texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 3;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 4;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(rb->sdfgi->occlusion_texture);
- uniforms.push_back(u);
- }
-
- rb->sdfgi->debug_probes_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.debug_probes.version_get_shader(sdfgi_shader.debug_probes_shader, 0), 0);
- }
-
- RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, sdfgi_shader.debug_probes_pipeline[SDGIShader::PROBE_DEBUG_PROBES].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, rb->sdfgi->debug_probes_uniform_set, 0);
- RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(SDGIShader::DebugProbesPushConstant));
- RD::get_singleton()->draw_list_draw(p_draw_list, false, total_probes, total_points);
-
- if (sdfgi_debug_probe_dir != Vector3()) {
- print_line("CLICK DEBUG ME?");
- uint32_t cascade = 0;
- Vector3 offset = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + rb->sdfgi->cascades[cascade].position)) * rb->sdfgi->cascades[cascade].cell_size * Vector3(1.0, 1.0 / rb->sdfgi->y_mult, 1.0);
- Vector3 probe_size = rb->sdfgi->cascades[cascade].cell_size * (rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR) * Vector3(1.0, 1.0 / rb->sdfgi->y_mult, 1.0);
- Vector3 ray_from = sdfgi_debug_probe_pos;
- Vector3 ray_to = sdfgi_debug_probe_pos + sdfgi_debug_probe_dir * rb->sdfgi->cascades[cascade].cell_size * Math::sqrt(3.0) * rb->sdfgi->cascade_size;
- float sphere_radius = 0.2;
- float closest_dist = 1e20;
- sdfgi_debug_probe_enabled = false;
-
- Vector3i probe_from = rb->sdfgi->cascades[cascade].position / (rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR);
- for (int i = 0; i < (SDFGI::PROBE_DIVISOR + 1); i++) {
- for (int j = 0; j < (SDFGI::PROBE_DIVISOR + 1); j++) {
- for (int k = 0; k < (SDFGI::PROBE_DIVISOR + 1); k++) {
- Vector3 pos = offset + probe_size * Vector3(i, j, k);
- Vector3 res;
- if (Geometry3D::segment_intersects_sphere(ray_from, ray_to, pos, sphere_radius, &res)) {
- float d = ray_from.distance_to(res);
- if (d < closest_dist) {
- closest_dist = d;
- sdfgi_debug_probe_enabled = true;
- sdfgi_debug_probe_index = probe_from + Vector3i(i, j, k);
- }
- }
- }
- }
- }
-
- if (sdfgi_debug_probe_enabled) {
- print_line("found: " + sdfgi_debug_probe_index);
- } else {
- print_line("no found");
- }
- sdfgi_debug_probe_dir = Vector3();
- }
-
- if (sdfgi_debug_probe_enabled) {
- uint32_t cascade = 0;
- uint32_t probe_cells = (rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR);
- Vector3i probe_from = rb->sdfgi->cascades[cascade].position / probe_cells;
- Vector3i ofs = sdfgi_debug_probe_index - probe_from;
- if (ofs.x < 0 || ofs.y < 0 || ofs.z < 0) {
- return;
- }
- if (ofs.x > SDFGI::PROBE_DIVISOR || ofs.y > SDFGI::PROBE_DIVISOR || ofs.z > SDFGI::PROBE_DIVISOR) {
- return;
- }
-
- uint32_t mult = (SDFGI::PROBE_DIVISOR + 1);
- uint32_t index = ofs.z * mult * mult + ofs.y * mult + ofs.x;
-
- push_constant.probe_debug_index = index;
-
- uint32_t cell_count = probe_cells * 2 * probe_cells * 2 * probe_cells * 2;
-
- RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, sdfgi_shader.debug_probes_pipeline[SDGIShader::PROBE_DEBUG_VISIBILITY].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, rb->sdfgi->debug_probes_uniform_set, 0);
- RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(SDGIShader::DebugProbesPushConstant));
- RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, total_points);
- }
+ rb->sdfgi->debug_probes(p_draw_list, p_framebuffer, p_camera_with_transform);
}
////////////////////////////////
@@ -5150,9 +1472,6 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
RD::get_singleton()->free(rb->luminance.reduce[i]);
}
- for (int i = 0; i < rb->luminance.reduce.size(); i++) {
- RD::get_singleton()->free(rb->luminance.reduce[i]);
- }
rb->luminance.reduce.clear();
if (rb->luminance.current.is_valid()) {
@@ -5233,7 +1552,7 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
return;
}
- Environment *env = environment_owner.getornull(p_environment);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_environment);
ERR_FAIL_COND(!env);
ERR_FAIL_COND(!env->ssr_enabled);
@@ -5278,7 +1597,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb);
- Environment *env = environment_owner.getornull(p_environment);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_environment);
ERR_FAIL_COND(!env);
RENDER_TIMESTAMP("Process SSAO");
@@ -5424,7 +1743,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(RID p_rende
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb);
- Environment *env = environment_owner.getornull(p_environment);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_environment);
//glow (if enabled)
CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects);
@@ -5617,7 +1936,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
}
void RendererSceneRenderRD::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) {
- Environment *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->adjustments_enabled = p_enable;
@@ -5628,152 +1947,6 @@ void RendererSceneRenderRD::environment_set_adjustment(RID p_env, bool p_enable,
env->color_correction = p_color_correction;
}
-void RendererSceneRenderRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
- ERR_FAIL_COND(!rb);
-
- if (!rb->sdfgi) {
- return; //eh
- }
-
- if (!rb->sdfgi->debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(rb->sdfgi->debug_uniform_set)) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
- if (i < rb->sdfgi->cascades.size()) {
- u.ids.push_back(rb->sdfgi->cascades[i].sdf_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
- if (i < rb->sdfgi->cascades.size()) {
- u.ids.push_back(rb->sdfgi->cascades[i].light_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 3;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
- if (i < rb->sdfgi->cascades.size()) {
- u.ids.push_back(rb->sdfgi->cascades[i].light_aniso_0_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 4;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
- if (i < rb->sdfgi->cascades.size()) {
- u.ids.push_back(rb->sdfgi->cascades[i].light_aniso_1_tex);
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 5;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(rb->sdfgi->occlusion_texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 8;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 9;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(rb->sdfgi->cascades_ubo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 10;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.ids.push_back(rb->texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 11;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(rb->sdfgi->lightprobe_texture);
- uniforms.push_back(u);
- }
- rb->sdfgi->debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.debug_shader_version, 0);
- }
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.debug_pipeline);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->debug_uniform_set, 0);
-
- SDGIShader::DebugPushConstant push_constant;
- push_constant.grid_size[0] = rb->sdfgi->cascade_size;
- push_constant.grid_size[1] = rb->sdfgi->cascade_size;
- push_constant.grid_size[2] = rb->sdfgi->cascade_size;
- push_constant.max_cascades = rb->sdfgi->cascades.size();
- push_constant.screen_size[0] = rb->width;
- push_constant.screen_size[1] = rb->height;
- push_constant.probe_axis_size = rb->sdfgi->probe_axis_count;
- push_constant.use_occlusion = rb->sdfgi->uses_occlusion;
- push_constant.y_mult = rb->sdfgi->y_mult;
-
- Vector2 vp_half = p_projection.get_viewport_half_extents();
- push_constant.cam_extent[0] = vp_half.x;
- push_constant.cam_extent[1] = vp_half.y;
- push_constant.cam_extent[2] = -p_projection.get_z_near();
-
- push_constant.cam_transform[0] = p_transform.basis.elements[0][0];
- push_constant.cam_transform[1] = p_transform.basis.elements[1][0];
- push_constant.cam_transform[2] = p_transform.basis.elements[2][0];
- push_constant.cam_transform[3] = 0;
- push_constant.cam_transform[4] = p_transform.basis.elements[0][1];
- push_constant.cam_transform[5] = p_transform.basis.elements[1][1];
- push_constant.cam_transform[6] = p_transform.basis.elements[2][1];
- push_constant.cam_transform[7] = 0;
- push_constant.cam_transform[8] = p_transform.basis.elements[0][2];
- push_constant.cam_transform[9] = p_transform.basis.elements[1][2];
- push_constant.cam_transform[10] = p_transform.basis.elements[2][2];
- push_constant.cam_transform[11] = 0;
- push_constant.cam_transform[12] = p_transform.origin.x;
- push_constant.cam_transform[13] = p_transform.origin.y;
- push_constant.cam_transform[14] = p_transform.origin.z;
- push_constant.cam_transform[15] = 1;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::DebugPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1, 8, 8, 1);
- RD::get_singleton()->compute_list_end();
-
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
- storage->get_effects()->copy_to_fb_rect(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), true);
-}
-
RID RendererSceneRenderRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
@@ -5793,14 +1966,14 @@ RID RendererSceneRenderRD::render_buffers_get_ao_texture(RID p_render_buffers) {
RID RendererSceneRenderRD::render_buffers_get_gi_probe_buffer(RID p_render_buffers) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
- if (rb->giprobe_buffer.is_null()) {
- rb->giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::GIProbeData) * RenderBuffers::MAX_GIPROBES);
+ if (rb->gi.giprobe_buffer.is_null()) {
+ rb->gi.giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(RendererSceneGIRD::GIProbeData) * RendererSceneGIRD::MAX_GIPROBES);
}
- return rb->giprobe_buffer;
+ return rb->gi.giprobe_buffer;
}
RID RendererSceneRenderRD::render_buffers_get_default_gi_probe_buffer() {
- return default_giprobe_buffer;
+ return gi.default_giprobe_buffer;
}
RID RendererSceneRenderRD::render_buffers_get_gi_ambient_texture(RID p_render_buffers) {
@@ -5849,7 +2022,7 @@ Vector3i RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_offset(RI
ERR_FAIL_COND_V(!rb, Vector3i());
ERR_FAIL_COND_V(!rb->sdfgi, Vector3i());
ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), Vector3i());
- int32_t probe_divisor = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR;
+ int32_t probe_divisor = rb->sdfgi->cascade_size / RendererSceneGIRD::SDFGI::PROBE_DIVISOR;
return rb->sdfgi->cascades[p_cascade].position / probe_divisor;
}
@@ -6098,11 +2271,11 @@ void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_q
}
int RendererSceneRenderRD::get_roughness_layers() const {
- return roughness_layers;
+ return sky.roughness_layers;
}
bool RendererSceneRenderRD::is_using_radiance_cubemap_array() const {
- return sky_use_cubemap_array;
+ return sky.sky_use_cubemap_array;
}
RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_get_data(RID p_render_buffers) {
@@ -6179,7 +2352,7 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
}
if (cluster.reflection_count) {
- RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, cluster.reflection_count * sizeof(ReflectionData), cluster.reflections);
+ RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, cluster.reflection_count * sizeof(RendererSceneSkyRD::ReflectionData), cluster.reflections, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
}
}
@@ -6188,7 +2361,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
r_directional_light_count = 0;
r_positional_light_count = 0;
- sky_scene_state.ubo.directional_light_count = 0;
+ sky.sky_scene_state.ubo.directional_light_count = 0;
Plane camera_plane(p_camera_transform.origin, -p_camera_transform.basis.get_axis(Vector3::AXIS_Z).normalized());
@@ -6208,8 +2381,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
switch (type) {
case RS::LIGHT_DIRECTIONAL: {
// Copy to SkyDirectionalLightData
- if (r_directional_light_count < sky_scene_state.max_directional_lights) {
- SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[r_directional_light_count];
+ if (r_directional_light_count < sky.sky_scene_state.max_directional_lights) {
+ RendererSceneSkyRD::SkyDirectionalLightData &sky_light_data = sky.sky_scene_state.directional_lights[r_directional_light_count];
Transform light_transform = li->transform;
Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
@@ -6237,7 +2410,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
angular_diameter = 0.0;
}
sky_light_data.size = angular_diameter;
- sky_scene_state.ubo.directional_light_count++;
+ sky.sky_scene_state.ubo.directional_light_count++;
}
if (r_directional_light_count >= cluster.max_directional_lights || storage->light_directional_is_sky_only(base)) {
@@ -6431,8 +2604,6 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
LightInstance *li = (i < cluster.omni_light_count) ? cluster.omni_light_sort[index].instance : cluster.spot_light_sort[index].instance;
RID base = li->light;
- cluster.lights_instances[i] = li->self;
-
Transform light_transform = li->transform;
float sign = storage->light_is_negative(base) ? -1 : 1;
@@ -6466,9 +2637,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.size = size;
- light_data.cone_attenuation = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ light_data.inv_spot_attenuation = 1.0f / storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
- light_data.cone_angle = Math::cos(Math::deg2rad(spot_angle));
+ light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle));
light_data.mask = storage->light_get_cull_mask(base);
@@ -6571,16 +2742,17 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
r_positional_light_count++;
}
+ //update without barriers
if (cluster.omni_light_count) {
- RD::get_singleton()->buffer_update(cluster.omni_light_buffer, 0, sizeof(Cluster::LightData) * cluster.omni_light_count, cluster.omni_lights);
+ RD::get_singleton()->buffer_update(cluster.omni_light_buffer, 0, sizeof(Cluster::LightData) * cluster.omni_light_count, cluster.omni_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
}
if (cluster.spot_light_count) {
- RD::get_singleton()->buffer_update(cluster.spot_light_buffer, 0, sizeof(Cluster::LightData) * cluster.spot_light_count, cluster.spot_lights);
+ RD::get_singleton()->buffer_update(cluster.spot_light_buffer, 0, sizeof(Cluster::LightData) * cluster.spot_light_count, cluster.spot_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
}
if (r_directional_light_count) {
- RD::get_singleton()->buffer_update(cluster.directional_light_buffer, 0, sizeof(Cluster::DirectionalLightData) * r_directional_light_count, cluster.directional_lights);
+ RD::get_singleton()->buffer_update(cluster.directional_light_buffer, 0, sizeof(Cluster::DirectionalLightData) * r_directional_light_count, cluster.directional_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
}
}
@@ -6741,13 +2913,14 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
}
if (cluster.decal_count > 0) {
- RD::get_singleton()->buffer_update(cluster.decal_buffer, 0, sizeof(Cluster::DecalData) * cluster.decal_count, cluster.decals);
+ RD::get_singleton()->buffer_update(cluster.decal_buffer, 0, sizeof(Cluster::DecalData) * cluster.decal_count, cluster.decals, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
}
}
void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
ERR_FAIL_COND(!rb->volumetric_fog);
+ RD::get_singleton()->free(rb->volumetric_fog->prev_light_density_map);
RD::get_singleton()->free(rb->volumetric_fog->light_density_map);
RD::get_singleton()->free(rb->volumetric_fog->fog_map);
@@ -6769,53 +2942,10 @@ void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
rb->volumetric_fog = nullptr;
}
-void RendererSceneRenderRD::_allocate_shadow_shrink_stages(RID p_base, int p_base_size, Vector<ShadowShrinkStage> &shrink_stages, uint32_t p_target_size) {
- //create fog mipmaps
- uint32_t fog_texture_size = p_target_size;
- uint32_t base_texture_size = p_base_size;
-
- ShadowShrinkStage first;
- first.size = base_texture_size;
- first.texture = p_base;
- shrink_stages.push_back(first); //put depth first in case we dont find smaller ones
-
- while (fog_texture_size < base_texture_size) {
- base_texture_size = MAX(base_texture_size / 8, fog_texture_size);
-
- ShadowShrinkStage s;
- s.size = base_texture_size;
-
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- tf.width = base_texture_size;
- tf.height = base_texture_size;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
-
- if (base_texture_size == fog_texture_size) {
- s.filter_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT;
- }
-
- s.texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- shrink_stages.push_back(s);
- }
-}
-
-void RendererSceneRenderRD::_clear_shadow_shrink_stages(Vector<ShadowShrinkStage> &shrink_stages) {
- for (int i = 1; i < shrink_stages.size(); i++) {
- RD::get_singleton()->free(shrink_stages[i].texture);
- if (shrink_stages[i].filter_texture.is_valid()) {
- RD::get_singleton()->free(shrink_stages[i].filter_texture);
- }
- }
- shrink_stages.clear();
-}
-
void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_gi_probe_count) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb);
- Environment *env = environment_owner.getornull(p_environment);
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_environment);
float ratio = float(rb->width) / float((rb->width + rb->height) / 2);
uint32_t target_width = uint32_t(float(volumetric_fog_size) * ratio);
@@ -6834,6 +2964,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
return;
}
+ RENDER_TIMESTAMP(">Volumetric Fog");
+
if (env && env->volumetric_fog_enabled && !rb->volumetric_fog) {
//required volumetric fog but not existing, create
rb->volumetric_fog = memnew(VolumetricFog);
@@ -6847,11 +2979,16 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
tf.height = target_height;
tf.depth = volumetric_fog_depth;
tf.texture_type = RD::TEXTURE_TYPE_3D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
rb->volumetric_fog->light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+
+ rb->volumetric_fog->prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->texture_clear(rb->volumetric_fog->prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
_render_buffers_uniform_set_changed(p_render_buffers);
@@ -6865,165 +3002,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
uniforms.push_back(u);
}
- rb->volumetric_fog->sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_FOG);
- }
-
- //update directional shadow
-
- if (p_use_directional_shadows) {
- if (directional_shadow.shrink_stages.is_empty()) {
- if (rb->volumetric_fog->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
- //invalidate uniform set, we will need a new one
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set);
- rb->volumetric_fog->uniform_set = RID();
- }
- _allocate_shadow_shrink_stages(directional_shadow.depth, directional_shadow.size, directional_shadow.shrink_stages, volumetric_fog_directional_shadow_shrink);
- }
-
- if (directional_shadow.shrink_stages.size() > 1) {
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- for (int i = 1; i < directional_shadow.shrink_stages.size(); i++) {
- int32_t src_size = directional_shadow.shrink_stages[i - 1].size;
- int32_t dst_size = directional_shadow.shrink_stages[i].size;
- Rect2i r(0, 0, src_size, src_size);
- int32_t shrink_limit = 8 / (src_size / dst_size);
-
- storage->get_effects()->reduce_shadow(directional_shadow.shrink_stages[i - 1].texture, directional_shadow.shrink_stages[i].texture, Size2i(src_size, src_size), r, shrink_limit, compute_list);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- if (env->volumetric_fog_shadow_filter != RS::ENV_VOLUMETRIC_FOG_SHADOW_FILTER_DISABLED && directional_shadow.shrink_stages[i].filter_texture.is_valid()) {
- Rect2i rf(0, 0, dst_size, dst_size);
- storage->get_effects()->filter_shadow(directional_shadow.shrink_stages[i].texture, directional_shadow.shrink_stages[i].filter_texture, Size2i(dst_size, dst_size), rf, env->volumetric_fog_shadow_filter, compute_list);
- }
- }
- RD::get_singleton()->compute_list_end();
- }
- }
-
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
-
- if (shadow_atlas) {
- //shrink shadows that need to be shrunk
-
- bool force_shrink_shadows = false;
-
- if (shadow_atlas->shrink_stages.is_empty()) {
- if (rb->volumetric_fog->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
- //invalidate uniform set, we will need a new one
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set);
- rb->volumetric_fog->uniform_set = RID();
- }
- _allocate_shadow_shrink_stages(shadow_atlas->depth, shadow_atlas->size, shadow_atlas->shrink_stages, volumetric_fog_positional_shadow_shrink);
- force_shrink_shadows = true;
- }
-
- if (rb->volumetric_fog->last_shadow_filter != env->volumetric_fog_shadow_filter) {
- //if shadow filter changed, invalidate caches
- rb->volumetric_fog->last_shadow_filter = env->volumetric_fog_shadow_filter;
- force_shrink_shadows = true;
- }
-
- cluster.lights_shadow_rect_cache_count = 0;
-
- for (uint32_t i = 0; i < cluster.omni_light_count + cluster.spot_light_count; i++) {
- Cluster::LightData &ld = i < cluster.omni_light_count ? cluster.omni_lights[i] : cluster.spot_lights[i - cluster.omni_light_count];
-
- if (ld.shadow_enabled != 0) {
- RID li = cluster.lights_instances[i];
-
- ERR_CONTINUE(!shadow_atlas->shadow_owners.has(li));
-
- uint32_t key = shadow_atlas->shadow_owners[li];
-
- uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
- uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
-
- ERR_CONTINUE((int)shadow >= shadow_atlas->quadrants[quadrant].shadows.size());
-
- ShadowAtlas::Quadrant::Shadow &s = shadow_atlas->quadrants[quadrant].shadows.write[shadow];
-
- if (!force_shrink_shadows && s.fog_version == s.version) {
- continue; //do not update, no need
- }
-
- s.fog_version = s.version;
-
- uint32_t quadrant_size = shadow_atlas->size >> 1;
-
- Rect2i atlas_rect;
-
- atlas_rect.position.x = (quadrant & 1) * quadrant_size;
- atlas_rect.position.y = (quadrant >> 1) * quadrant_size;
-
- uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
- atlas_rect.position.x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
- atlas_rect.position.y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
-
- atlas_rect.size.x = shadow_size;
- atlas_rect.size.y = shadow_size;
-
- cluster.lights_shadow_rect_cache[cluster.lights_shadow_rect_cache_count] = atlas_rect;
-
- cluster.lights_shadow_rect_cache_count++;
-
- if (cluster.lights_shadow_rect_cache_count == cluster.max_lights * 2) {
- break; //light limit reached
- }
- }
- }
-
- if (cluster.lights_shadow_rect_cache_count > 0) {
- //there are shadows to be shrunk, try to do them in parallel
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- for (int i = 1; i < shadow_atlas->shrink_stages.size(); i++) {
- int32_t base_size = shadow_atlas->shrink_stages[0].size;
- int32_t src_size = shadow_atlas->shrink_stages[i - 1].size;
- int32_t dst_size = shadow_atlas->shrink_stages[i].size;
-
- uint32_t rect_divisor = base_size / src_size;
-
- int32_t shrink_limit = 8 / (src_size / dst_size);
-
- //shrink in parallel for more performance
- for (uint32_t j = 0; j < cluster.lights_shadow_rect_cache_count; j++) {
- Rect2i src_rect = cluster.lights_shadow_rect_cache[j];
-
- src_rect.position /= rect_divisor;
- src_rect.size /= rect_divisor;
-
- storage->get_effects()->reduce_shadow(shadow_atlas->shrink_stages[i - 1].texture, shadow_atlas->shrink_stages[i].texture, Size2i(src_size, src_size), src_rect, shrink_limit, compute_list);
- }
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- if (env->volumetric_fog_shadow_filter != RS::ENV_VOLUMETRIC_FOG_SHADOW_FILTER_DISABLED && shadow_atlas->shrink_stages[i].filter_texture.is_valid()) {
- uint32_t filter_divisor = base_size / dst_size;
-
- //filter in parallel for more performance
- for (uint32_t j = 0; j < cluster.lights_shadow_rect_cache_count; j++) {
- Rect2i dst_rect = cluster.lights_shadow_rect_cache[j];
-
- dst_rect.position /= filter_divisor;
- dst_rect.size /= filter_divisor;
-
- storage->get_effects()->filter_shadow(shadow_atlas->shrink_stages[i].texture, shadow_atlas->shrink_stages[i].filter_texture, Size2i(dst_size, dst_size), dst_rect, env->volumetric_fog_shadow_filter, compute_list, true, false);
- }
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- for (uint32_t j = 0; j < cluster.lights_shadow_rect_cache_count; j++) {
- Rect2i dst_rect = cluster.lights_shadow_rect_cache[j];
-
- dst_rect.position /= filter_divisor;
- dst_rect.size /= filter_divisor;
-
- storage->get_effects()->filter_shadow(shadow_atlas->shrink_stages[i].texture, shadow_atlas->shrink_stages[i].filter_texture, Size2i(dst_size, dst_size), dst_rect, env->volumetric_fog_shadow_filter, compute_list, false, true);
- }
- }
- }
-
- RD::get_singleton()->compute_list_end();
- }
+ rb->volumetric_fog->sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky.sky_shader.default_shader_rd, RendererSceneSkyRD::SKY_SET_FOG);
}
//update volumetric fog
@@ -7037,10 +3016,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1;
- if (shadow_atlas == nullptr || shadow_atlas->shrink_stages.size() == 0) {
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) {
u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
} else {
- u.ids.push_back(shadow_atlas->shrink_stages[shadow_atlas->shrink_stages.size() - 1].texture);
+ u.ids.push_back(shadow_atlas->depth);
}
uniforms.push_back(u);
@@ -7050,10 +3030,10 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2;
- if (directional_shadow.shrink_stages.size() == 0) {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
+ if (directional_shadow.depth.is_valid()) {
+ u.ids.push_back(directional_shadow.depth);
} else {
- u.ids.push_back(directional_shadow.shrink_stages[directional_shadow.shrink_stages.size() - 1].texture);
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
}
uniforms.push_back(u);
}
@@ -7133,8 +3113,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 12;
- for (int i = 0; i < RenderBuffers::MAX_GIPROBES; i++) {
- u.ids.push_back(rb->giprobe_textures[i]);
+ for (int i = 0; i < RendererSceneGIRD::MAX_GIPROBES; i++) {
+ u.ids.push_back(rb->gi.giprobe_textures[i]);
}
uniforms.push_back(u);
}
@@ -7152,6 +3132,13 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.ids.push_back(volumetric_fog.params_ubo);
uniforms.push_back(u);
}
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 15;
+ u.ids.push_back(rb->volumetric_fog->prev_light_density_map);
+ uniforms.push_back(u);
+ }
rb->volumetric_fog->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, 0), 0);
@@ -7253,6 +3240,13 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.cam_rotation[11] = 0;
params.filter_axis = 0;
params.max_gi_probes = env->volumetric_fog_gi_inject > 0.001 ? p_gi_probe_count : 0;
+ params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
+
+ Transform to_prev_cam_view = rb->volumetric_fog->prev_cam_transform.affine_inverse() * p_cam_transform;
+ storage->store_transform(to_prev_cam_view, params.to_prev_view);
+
+ params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
+ params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;
{
uint32_t cluster_size = rb->cluster_builder->get_cluster_size();
@@ -7273,10 +3267,10 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
push_constant.directional_shadow_pixel_size[1] = 1.0 / dssize.y;
*/
- RENDER_TIMESTAMP(">Volumetric Fog");
+ RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog");
RENDER_TIMESTAMP("Render Fog");
- RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params);
+ RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params, RD::BARRIER_MASK_COMPUTE);
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@@ -7289,17 +3283,25 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
if (using_sdfgi) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1);
}
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth, 4, 4, 4);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
+
+ RD::get_singleton()->draw_command_end_label();
+
+ RD::get_singleton()->compute_list_end();
+
+ RD::get_singleton()->texture_copy(rb->volumetric_fog->light_density_map, rb->volumetric_fog->prev_light_density_map, Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), 0, 0, 0, 0);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
+ compute_list = RD::get_singleton()->compute_list_begin();
if (use_filter) {
+ RD::get_singleton()->draw_command_begin_label("Filter Fog");
+
RENDER_TIMESTAMP("Filter Fog");
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[VOLUMETRIC_FOG_SHADER_FILTER]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth, 8, 8, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
RD::get_singleton()->compute_list_end();
//need restart for buffer update
@@ -7313,95 +3315,189 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
if (using_sdfgi) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1);
}
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth, 8, 8, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label();
}
RENDER_TIMESTAMP("Integrate Fog");
+ RD::get_singleton()->draw_command_begin_label("Integrate Fog");
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[VOLUMETRIC_FOG_SHADER_FOG]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, 1, 8, 8, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, 1);
- RD::get_singleton()->compute_list_end();
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
RENDER_TIMESTAMP("<Volumetric Fog");
+ RD::get_singleton()->draw_command_end_label();
+
+ rb->volumetric_fog->prev_cam_transform = p_cam_transform;
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
- Color clear_color;
- if (p_render_buffers.is_valid()) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
- ERR_FAIL_COND(!rb);
- clear_color = storage->render_target_get_clear_request_color(rb->render_target);
- } else {
- clear_color = storage->get_default_clear_color();
+uint32_t RendererSceneRenderRD::_get_render_state_directional_light_count() const {
+ return render_state.directional_light_count;
+}
+
+bool RendererSceneRenderRD::_needs_post_prepass_render(bool p_use_gi) {
+ if (render_state.render_buffers.is_valid()) {
+ RenderBuffers *rb = render_buffers_owner.getornull(render_state.render_buffers);
+ if (rb->sdfgi != nullptr) {
+ return true;
+ }
}
+ return false;
+}
- //assign render indices to giprobes
- for (uint32_t i = 0; i < (uint32_t)p_gi_probes.size(); i++) {
- GIProbeInstance *giprobe_inst = gi_probe_instance_owner.getornull(p_gi_probes[i]);
- if (giprobe_inst) {
- giprobe_inst->render_index = i;
+void RendererSceneRenderRD::_post_prepass_render(bool p_use_gi) {
+ if (render_state.render_buffers.is_valid()) {
+ if (p_use_gi) {
+ RenderBuffers *rb = render_buffers_owner.getornull(render_state.render_buffers);
+ ERR_FAIL_COND(rb == nullptr);
+ if (rb->sdfgi == nullptr) {
+ return;
+ }
+
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(render_state.environment);
+ rb->sdfgi->update_probes(env, sky.sky_owner.getornull(env->sky));
+ }
+ }
+}
+
+void RendererSceneRenderRD::_pre_resolve_render(bool p_use_gi) {
+ if (render_state.render_buffers.is_valid()) {
+ if (p_use_gi) {
+ RD::get_singleton()->compute_list_end();
}
}
+}
- const PagedArray<RID> *lights = &p_lights;
- const PagedArray<RID> *reflections = &p_reflection_probes;
- const PagedArray<RID> *gi_probes = &p_gi_probes;
+void RendererSceneRenderRD::_pre_opaque_render(bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_gi_probe_buffer) {
+ // Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
- PagedArray<RID> empty;
+ if (render_state.render_buffers.is_valid() && p_use_gi) {
+ RenderBuffers *rb = render_buffers_owner.getornull(render_state.render_buffers);
+ ERR_FAIL_COND(rb == nullptr);
+ if (rb->sdfgi == nullptr) {
+ return;
+ }
- if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
- lights = &empty;
- reflections = &empty;
- gi_probes = &empty;
+ rb->sdfgi->store_probes();
}
- if (render_buffers_owner.owns(p_render_buffers)) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
- current_cluster_builder = rb->cluster_builder;
- } else if (reflection_probe_instance_owner.owns(p_reflection_probe)) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_reflection_probe);
- ReflectionAtlas *ra = reflection_atlas_owner.getornull(rpi->atlas);
- if (!ra) {
- ERR_PRINT("reflection probe has no reflection atlas! Bug?");
- current_cluster_builder = nullptr;
- } else {
- current_cluster_builder = ra->cluster_builder;
+ render_state.cube_shadows.clear();
+ render_state.shadows.clear();
+ render_state.directional_shadows.clear();
+
+ Plane camera_plane(render_state.cam_transform.origin, -render_state.cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ float lod_distance_multiplier = render_state.cam_projection.get_lod_multiplier();
+
+ {
+ for (int i = 0; i < render_state.render_shadow_count; i++) {
+ LightInstance *li = light_instance_owner.getornull(render_state.render_shadows[i].light);
+
+ if (storage->light_get_type(li->light) == RS::LIGHT_DIRECTIONAL) {
+ render_state.directional_shadows.push_back(i);
+ } else if (storage->light_get_type(li->light) == RS::LIGHT_OMNI && storage->light_omni_get_shadow_mode(li->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
+ render_state.cube_shadows.push_back(i);
+ } else {
+ render_state.shadows.push_back(i);
+ }
+ }
+
+ //cube shadows are rendered in their own way
+ for (uint32_t i = 0; i < render_state.cube_shadows.size(); i++) {
+ _render_shadow_pass(render_state.render_shadows[render_state.cube_shadows[i]].light, render_state.shadow_atlas, render_state.render_shadows[render_state.cube_shadows[i]].pass, render_state.render_shadows[render_state.cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, render_state.screen_lod_threshold, true, true, true);
+ }
+
+ if (render_state.directional_shadows.size()) {
+ //open the pass for directional shadows
+ _update_directional_shadow_atlas();
+ RD::get_singleton()->draw_list_begin(directional_shadow.fb, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE);
+ RD::get_singleton()->draw_list_end();
+ }
+ }
+
+ // Render GI
+
+ bool render_shadows = render_state.directional_shadows.size() || render_state.shadows.size();
+ bool render_gi = render_state.render_buffers.is_valid() && p_use_gi;
+
+ if (render_shadows && render_gi) {
+ RENDER_TIMESTAMP("Render GI + Render Shadows (parallel)");
+ } else if (render_shadows) {
+ RENDER_TIMESTAMP("Render Shadows");
+ } else if (render_gi) {
+ RENDER_TIMESTAMP("Render GI");
+ }
+
+ //prepare shadow rendering
+ if (render_shadows) {
+ _render_shadow_begin();
+
+ //render directional shadows
+ for (uint32_t i = 0; i < render_state.directional_shadows.size(); i++) {
+ _render_shadow_pass(render_state.render_shadows[render_state.directional_shadows[i]].light, render_state.shadow_atlas, render_state.render_shadows[render_state.directional_shadows[i]].pass, render_state.render_shadows[render_state.directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, render_state.screen_lod_threshold, false, i == render_state.directional_shadows.size() - 1, false);
+ }
+ //render positional shadows
+ for (uint32_t i = 0; i < render_state.shadows.size(); i++) {
+ _render_shadow_pass(render_state.render_shadows[render_state.shadows[i]].light, render_state.shadow_atlas, render_state.render_shadows[render_state.shadows[i]].pass, render_state.render_shadows[render_state.shadows[i]].instances, camera_plane, lod_distance_multiplier, render_state.screen_lod_threshold, i == 0, i == render_state.shadows.size() - 1, true);
+ }
+
+ _render_shadow_process();
+ }
+
+ //start GI
+ if (render_gi) {
+ gi.process_gi(render_state.render_buffers, p_normal_roughness_buffer, p_gi_probe_buffer, render_state.environment, render_state.cam_projection, render_state.cam_transform, *render_state.gi_probes, this);
+ }
+
+ //Do shadow rendering (in parallel with GI)
+ if (render_shadows) {
+ _render_shadow_end(RD::BARRIER_MASK_NO_BARRIER);
+ }
+
+ if (render_gi) {
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //use a later barrier
+ }
+
+ if (render_state.render_buffers.is_valid()) {
+ if (p_use_ssao) {
+ _process_ssao(render_state.render_buffers, render_state.environment, p_normal_roughness_buffer, render_state.cam_projection);
}
- } else {
- ERR_PRINT("No cluster builder, bug"); //should never happen, will crash
- current_cluster_builder = nullptr;
}
- current_cluster_builder->begin(p_cam_transform, p_cam_projection, !p_reflection_probe.is_valid());
+ //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);
+
+ if (current_cluster_builder) {
+ current_cluster_builder->begin(render_state.cam_transform, render_state.cam_projection, !render_state.reflection_probe.is_valid());
+ }
bool using_shadows = true;
- if (p_reflection_probe.is_valid()) {
- if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_reflection_probe))) {
+ if (render_state.reflection_probe.is_valid()) {
+ if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(render_state.reflection_probe))) {
using_shadows = false;
}
} else {
//do not render reflections when rendering a reflection probe
- _setup_reflections(*reflections, p_cam_transform.affine_inverse(), p_environment);
+ _setup_reflections(*render_state.reflection_probes, render_state.cam_transform.affine_inverse(), render_state.environment);
}
uint32_t directional_light_count = 0;
uint32_t positional_light_count = 0;
- _setup_lights(*lights, p_cam_transform, p_shadow_atlas, using_shadows, directional_light_count, positional_light_count);
- _setup_decals(p_decals, p_cam_transform.affine_inverse());
+ _setup_lights(*render_state.lights, render_state.cam_transform, render_state.shadow_atlas, using_shadows, directional_light_count, positional_light_count);
+ _setup_decals(*render_state.decals, render_state.cam_transform.affine_inverse());
- current_cluster_builder->bake_cluster();
+ render_state.directional_light_count = directional_light_count;
- uint32_t gi_probe_count = 0;
- if (p_render_buffers.is_valid()) {
- _setup_giprobes(p_render_buffers, p_cam_transform, *gi_probes, gi_probe_count);
+ if (current_cluster_builder) {
+ current_cluster_builder->bake_cluster();
}
- if (p_render_buffers.is_valid()) {
+ if (render_state.render_buffers.is_valid()) {
bool directional_shadows = false;
for (uint32_t i = 0; i < directional_light_count; i++) {
if (cluster.directional_lights[i].shadow_enabled) {
@@ -7409,10 +3505,111 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
break;
}
}
- _update_volumetric_fog(p_render_buffers, p_environment, p_cam_projection, p_cam_transform, p_shadow_atlas, directional_light_count, directional_shadows, positional_light_count, gi_probe_count);
+ _update_volumetric_fog(render_state.render_buffers, render_state.environment, render_state.cam_projection, render_state.cam_transform, render_state.shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.gi_probe_count);
+ }
+}
+
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data) {
+ // getting this here now so we can direct call a bunch of things more easily
+ RenderBuffers *rb = nullptr;
+ if (p_render_buffers.is_valid()) {
+ rb = render_buffers_owner.getornull(p_render_buffers);
+ ERR_FAIL_COND(!rb); // !BAS! Do we fail here or skip the parts that won't work. can't really see a case why we would be rendering without buffers....
+ }
+
+ //assign render data
+ {
+ render_state.render_buffers = p_render_buffers;
+ render_state.cam_transform = p_cam_transform;
+ render_state.cam_projection = p_cam_projection;
+ render_state.cam_ortogonal = p_cam_projection.is_orthogonal();
+ render_state.instances = &p_instances;
+ render_state.lights = &p_lights;
+ render_state.reflection_probes = &p_reflection_probes;
+ render_state.gi_probes = &p_gi_probes;
+ render_state.decals = &p_decals;
+ render_state.lightmaps = &p_lightmaps;
+ render_state.environment = p_environment;
+ render_state.camera_effects = p_camera_effects;
+ render_state.shadow_atlas = p_shadow_atlas;
+ render_state.reflection_atlas = p_reflection_atlas;
+ render_state.reflection_probe = p_reflection_probe;
+ render_state.reflection_probe_pass = p_reflection_probe_pass;
+ render_state.screen_lod_threshold = p_screen_lod_threshold;
+
+ render_state.render_shadows = p_render_shadows;
+ render_state.render_shadow_count = p_render_shadow_count;
+ render_state.render_sdfgi_regions = p_render_sdfgi_regions;
+ render_state.render_sdfgi_region_count = p_render_sdfgi_region_count;
+ render_state.sdfgi_update_data = p_sdfgi_update_data;
+ }
+
+ PagedArray<RID> empty;
+
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
+ render_state.lights = &empty;
+ render_state.reflection_probes = &empty;
+ render_state.gi_probes = &empty;
+ }
+
+ //sdfgi first
+ if (rb != nullptr && rb->sdfgi != nullptr) {
+ for (int i = 0; i < render_state.render_sdfgi_region_count; i++) {
+ rb->sdfgi->render_region(p_render_buffers, render_state.render_sdfgi_regions[i].region, render_state.render_sdfgi_regions[i].instances, this);
+ }
+ if (render_state.sdfgi_update_data->update_static) {
+ rb->sdfgi->render_static_lights(p_render_buffers, render_state.sdfgi_update_data->static_cascade_count, p_sdfgi_update_data->static_cascade_indices, render_state.sdfgi_update_data->static_positional_lights, this);
+ }
+ }
+
+ Color clear_color;
+ if (p_render_buffers.is_valid()) {
+ clear_color = storage->render_target_get_clear_request_color(rb->render_target);
+ } else {
+ clear_color = storage->get_default_clear_color();
+ }
+
+ //assign render indices to giprobes
+ for (uint32_t i = 0; i < (uint32_t)p_gi_probes.size(); i++) {
+ RendererSceneGIRD::GIProbeInstance *giprobe_inst = gi.gi_probe_instance_owner.getornull(p_gi_probes[i]);
+ if (giprobe_inst) {
+ giprobe_inst->render_index = i;
+ }
+ }
+
+ if (render_buffers_owner.owns(render_state.render_buffers)) {
+ RenderBuffers *rs_rb = render_buffers_owner.getornull(render_state.render_buffers);
+ current_cluster_builder = rs_rb->cluster_builder;
+ } else if (reflection_probe_instance_owner.owns(render_state.reflection_probe)) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(render_state.reflection_probe);
+ ReflectionAtlas *ra = reflection_atlas_owner.getornull(rpi->atlas);
+ if (!ra) {
+ ERR_PRINT("reflection probe has no reflection atlas! Bug?");
+ current_cluster_builder = nullptr;
+ } else {
+ current_cluster_builder = ra->cluster_builder;
+ }
+ } else {
+ ERR_PRINT("No cluster builder, bug"); //should never happen, will crash
+ current_cluster_builder = nullptr;
+ }
+
+ if (rb != nullptr && rb->sdfgi != nullptr) {
+ rb->sdfgi->update_cascades();
+
+ rb->sdfgi->pre_process_gi(p_cam_transform, this);
+ }
+
+ render_state.gi_probe_count = 0;
+ if (rb != nullptr && rb->sdfgi != nullptr) {
+ gi.setup_giprobes(render_state.render_buffers, render_state.cam_transform, *render_state.gi_probes, render_state.gi_probe_count, this);
+
+ rb->sdfgi->update_light();
}
- _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, directional_light_count, *gi_probes, p_lightmaps, p_environment, current_cluster_builder->get_cluster_buffer(), current_cluster_builder->get_cluster_size(), current_cluster_builder->get_max_cluster_elements(), p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
+ render_state.depth_prepass_used = false;
+ //calls _pre_opaque_render between depth pre-pass and opaque pass
+ _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, *render_state.gi_probes, p_lightmaps, p_environment, current_cluster_builder->get_cluster_buffer(), current_cluster_builder->get_cluster_size(), current_cluster_builder->get_max_cluster_elements(), p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
if (p_render_buffers.is_valid()) {
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) {
@@ -7440,13 +3637,13 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
_render_buffers_post_process_and_tonemap(p_render_buffers, p_environment, p_camera_effects, p_cam_projection);
_render_buffers_debug_draw(p_render_buffers, p_shadow_atlas);
- if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI) {
- _sdfgi_debug_draw(p_render_buffers, p_cam_projection, p_cam_transform);
+ if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) {
+ rb->sdfgi->debug_draw(p_cam_projection, p_cam_transform, rb->width, rb->height, rb->render_target, rb->texture);
}
}
}
-void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region) {
LightInstance *light_instance = light_instance_owner.getornull(p_light);
ERR_FAIL_COND(!light_instance);
@@ -7469,13 +3666,7 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
CameraMatrix light_projection;
Transform light_transform;
- bool clear_region = true;
- bool begin_texture = true;
- bool end_texture = true;
-
if (storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
- _update_directional_shadow_atlas();
-
//set pssm stuff
if (light_instance->last_scene_shadow_pass != scene_pass) {
light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light);
@@ -7492,7 +3683,6 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
atlas_rect.size.width = light_instance->directional_rect.size.x;
atlas_rect.size.height = light_instance->directional_rect.size.y;
- int pass_count = 1;
if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
atlas_rect.size.width /= 2;
atlas_rect.size.height /= 2;
@@ -7505,7 +3695,6 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
atlas_rect.position.x += atlas_rect.size.width;
atlas_rect.position.y += atlas_rect.size.height;
}
- pass_count = 4;
} else if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
atlas_rect.size.height /= 2;
@@ -7513,7 +3702,6 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
} else {
atlas_rect.position.y += atlas_rect.size.height;
}
- pass_count = 2;
}
light_instance->shadow_transform[p_pass].atlas_rect = atlas_rect;
@@ -7527,10 +3715,6 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
render_texture = RID();
flip_y = true;
- clear_region = false;
- begin_texture = (directional_shadow.current_light == 1) && (p_pass == 0); //light is 1-index because it was incremented above
- end_texture = (directional_shadow.current_light == directional_shadow.light_count) && (p_pass == pass_count - 1);
-
} else {
//set from shadow atlas
@@ -7568,14 +3752,17 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
render_fb = cubemap->side_fb[p_pass];
render_texture = cubemap->cubemap;
- light_projection = light_instance->shadow_transform[0].camera;
- light_transform = light_instance->shadow_transform[0].transform;
+ light_projection = light_instance->shadow_transform[p_pass].camera;
+ light_transform = light_instance->shadow_transform[p_pass].transform;
render_cubemap = true;
finalize_cubemap = p_pass == 5;
atlas_fb = shadow_atlas->fb;
atlas_size = shadow_atlas->size;
- clear_region = false;
+
+ if (p_pass == 0) {
+ _render_shadow_begin();
+ }
} else {
light_projection = light_instance->shadow_transform[0].camera;
@@ -7602,8 +3789,10 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
if (render_cubemap) {
//rendering to cubemap
- _render_shadow(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, Rect2(), false, true, true, true);
if (finalize_cubemap) {
+ _render_shadow_process();
+ _render_shadow_end();
//reblit
Rect2 atlas_rect_norm = atlas_rect;
atlas_rect_norm.position.x /= float(atlas_size);
@@ -7614,10 +3803,14 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, light_projection.get_z_near(), light_projection.get_z_far(), false);
atlas_rect_norm.position.y += atlas_rect_norm.size.height;
storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, light_projection.get_z_near(), light_projection.get_z_far(), true);
+
+ //restore transform so it can be properly used
+ light_instance_set_shadow_transform(p_light, CameraMatrix(), light_instance->transform, zfar, 0, 0, 0);
}
+
} else {
//render shadow
- _render_shadow(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, atlas_rect, flip_y, clear_region, begin_texture, end_texture);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass);
}
}
@@ -7625,363 +3818,6 @@ void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, co
_render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region);
}
-void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances) {
- //print_line("rendering region " + itos(p_region));
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
- ERR_FAIL_COND(!rb);
- ERR_FAIL_COND(!rb->sdfgi);
- AABB bounds;
- Vector3i from;
- Vector3i size;
-
- int cascade_prev = _sdfgi_get_pending_region_data(p_render_buffers, p_region - 1, from, size, bounds);
- int cascade_next = _sdfgi_get_pending_region_data(p_render_buffers, p_region + 1, from, size, bounds);
- int cascade = _sdfgi_get_pending_region_data(p_render_buffers, p_region, from, size, bounds);
- ERR_FAIL_COND(cascade < 0);
-
- if (cascade_prev != cascade) {
- //initialize render
- RD::get_singleton()->texture_clear(rb->sdfgi->render_albedo, Color(0, 0, 0, 0), 0, 1, 0, 1);
- RD::get_singleton()->texture_clear(rb->sdfgi->render_emission, Color(0, 0, 0, 0), 0, 1, 0, 1);
- RD::get_singleton()->texture_clear(rb->sdfgi->render_emission_aniso, Color(0, 0, 0, 0), 0, 1, 0, 1);
- RD::get_singleton()->texture_clear(rb->sdfgi->render_geom_facing, Color(0, 0, 0, 0), 0, 1, 0, 1);
- }
-
- //print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(rb->sdfgi->cascades[cascade].cell_size));
- _render_sdfgi(p_render_buffers, from, size, bounds, p_instances, rb->sdfgi->render_albedo, rb->sdfgi->render_emission, rb->sdfgi->render_emission_aniso, rb->sdfgi->render_geom_facing);
-
- if (cascade_next != cascade) {
- RENDER_TIMESTAMP(">SDFGI Update SDF");
- //done rendering! must update SDF
- //clear dispatch indirect data
-
- SDGIShader::PreprocessPushConstant push_constant;
- zeromem(&push_constant, sizeof(SDGIShader::PreprocessPushConstant));
-
- RENDER_TIMESTAMP("Scroll SDF");
-
- //scroll
- if (rb->sdfgi->cascades[cascade].dirty_regions != SDFGI::Cascade::DIRTY_ALL) {
- //for scroll
- Vector3i dirty = rb->sdfgi->cascades[cascade].dirty_regions;
- push_constant.scroll[0] = dirty.x;
- push_constant.scroll[1] = dirty.y;
- push_constant.scroll[2] = dirty.z;
- } else {
- //for no scroll
- push_constant.scroll[0] = 0;
- push_constant.scroll[1] = 0;
- push_constant.scroll[2] = 0;
- }
-
- rb->sdfgi->cascades[cascade].all_dynamic_lights_dirty = true;
-
- push_constant.grid_size = rb->sdfgi->cascade_size;
- push_constant.cascade = cascade;
-
- if (rb->sdfgi->cascades[cascade].dirty_regions != SDFGI::Cascade::DIRTY_ALL) {
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- //must pre scroll existing data because not all is dirty
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_SCROLL]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].scroll_uniform_set, 0);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
- RD::get_singleton()->compute_list_dispatch_indirect(compute_list, rb->sdfgi->cascades[cascade].solid_cell_dispatch_buffer, 0);
- // no barrier do all together
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_SCROLL_OCCLUSION]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].scroll_occlusion_uniform_set, 0);
-
- Vector3i dirty = rb->sdfgi->cascades[cascade].dirty_regions;
- Vector3i groups;
- groups.x = rb->sdfgi->cascade_size - ABS(dirty.x);
- groups.y = rb->sdfgi->cascade_size - ABS(dirty.y);
- groups.z = rb->sdfgi->cascade_size - ABS(dirty.z);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, groups.x, groups.y, groups.z, 4, 4, 4);
-
- //no barrier, continue together
-
- {
- //scroll probes and their history also
-
- SDGIShader::IntegratePushConstant ipush_constant;
- ipush_constant.grid_size[1] = rb->sdfgi->cascade_size;
- ipush_constant.grid_size[2] = rb->sdfgi->cascade_size;
- ipush_constant.grid_size[0] = rb->sdfgi->cascade_size;
- ipush_constant.max_cascades = rb->sdfgi->cascades.size();
- ipush_constant.probe_axis_size = rb->sdfgi->probe_axis_count;
- ipush_constant.history_index = 0;
- ipush_constant.history_size = rb->sdfgi->history_size;
- ipush_constant.ray_count = 0;
- ipush_constant.ray_bias = 0;
- ipush_constant.sky_mode = 0;
- ipush_constant.sky_energy = 0;
- ipush_constant.sky_color[0] = 0;
- ipush_constant.sky_color[1] = 0;
- ipush_constant.sky_color[2] = 0;
- ipush_constant.y_mult = rb->sdfgi->y_mult;
- ipush_constant.store_ambient_texture = false;
-
- ipush_constant.image_size[0] = rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count;
- ipush_constant.image_size[1] = rb->sdfgi->probe_axis_count;
-
- int32_t probe_divisor = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR;
- ipush_constant.cascade = cascade;
- ipush_constant.world_offset[0] = rb->sdfgi->cascades[cascade].position.x / probe_divisor;
- ipush_constant.world_offset[1] = rb->sdfgi->cascades[cascade].position.y / probe_divisor;
- ipush_constant.world_offset[2] = rb->sdfgi->cascades[cascade].position.z / probe_divisor;
-
- ipush_constant.scroll[0] = dirty.x / probe_divisor;
- ipush_constant.scroll[1] = dirty.y / probe_divisor;
- ipush_constant.scroll[2] = dirty.z / probe_divisor;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.integrate_pipeline[SDGIShader::INTEGRATE_MODE_SCROLL]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].integrate_uniform_set, 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdfgi_shader.integrate_default_sky_uniform_set, 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDGIShader::IntegratePushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count, rb->sdfgi->probe_axis_count, 1, 8, 8, 1);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.integrate_pipeline[SDGIShader::INTEGRATE_MODE_SCROLL_STORE]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].integrate_uniform_set, 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdfgi_shader.integrate_default_sky_uniform_set, 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDGIShader::IntegratePushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count, rb->sdfgi->probe_axis_count, 1, 8, 8, 1);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- if (rb->sdfgi->uses_multibounce) {
- //multibounce requires this to be stored so direct light can read from it
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.integrate_pipeline[SDGIShader::INTEGRATE_MODE_STORE]);
-
- //convert to octahedral to store
- ipush_constant.image_size[0] *= SDFGI::LIGHTPROBE_OCT_SIZE;
- ipush_constant.image_size[1] *= SDFGI::LIGHTPROBE_OCT_SIZE;
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].integrate_uniform_set, 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdfgi_shader.integrate_default_sky_uniform_set, 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDGIShader::IntegratePushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, rb->sdfgi->probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, 1, 8, 8, 1);
- }
- }
-
- //ok finally barrier
- RD::get_singleton()->compute_list_end();
- }
-
- //clear dispatch indirect data
- uint32_t dispatch_indirct_data[4] = { 0, 0, 0, 0 };
- RD::get_singleton()->buffer_update(rb->sdfgi->cascades[cascade].solid_cell_dispatch_buffer, 0, sizeof(uint32_t) * 4, dispatch_indirct_data);
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- bool half_size = true; //much faster, very little difference
- static const int optimized_jf_group_size = 8;
-
- if (half_size) {
- push_constant.grid_size >>= 1;
-
- uint32_t cascade_half_size = rb->sdfgi->cascade_size >> 1;
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->sdf_initialize_half_uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_half_size, cascade_half_size, cascade_half_size, 4, 4, 4);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- //must start with regular jumpflood
-
- push_constant.half_size = true;
- {
- RENDER_TIMESTAMP("SDFGI Jump Flood (Half Size)");
-
- uint32_t s = cascade_half_size;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD]);
-
- int jf_us = 0;
- //start with regular jump flood for very coarse reads, as this is impossible to optimize
- while (s > 1) {
- s /= 2;
- push_constant.step_size = s;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->jump_flood_half_uniform_set[jf_us], 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_half_size, cascade_half_size, cascade_half_size, 4, 4, 4);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- jf_us = jf_us == 0 ? 1 : 0;
-
- if (cascade_half_size / (s / 2) >= optimized_jf_group_size) {
- break;
- }
- }
-
- RENDER_TIMESTAMP("SDFGI Jump Flood Optimized (Half Size)");
-
- //continue with optimized jump flood for smaller reads
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]);
- while (s > 1) {
- s /= 2;
- push_constant.step_size = s;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->jump_flood_half_uniform_set[jf_us], 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_half_size, cascade_half_size, cascade_half_size, optimized_jf_group_size, optimized_jf_group_size, optimized_jf_group_size);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- jf_us = jf_us == 0 ? 1 : 0;
- }
- }
-
- // restore grid size for last passes
- push_constant.grid_size = rb->sdfgi->cascade_size;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_UPSCALE]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->sdf_upscale_uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, 4, 4, 4);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- //run one pass of fullsize jumpflood to fix up half size arctifacts
-
- push_constant.half_size = false;
- push_constant.step_size = 1;
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->jump_flood_uniform_set[rb->sdfgi->upscale_jfa_uniform_set_index], 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, optimized_jf_group_size, optimized_jf_group_size, optimized_jf_group_size);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- } else {
- //full size jumpflood
- RENDER_TIMESTAMP("SDFGI Jump Flood");
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->sdf_initialize_uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, 4, 4, 4);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- push_constant.half_size = false;
- {
- uint32_t s = rb->sdfgi->cascade_size;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD]);
-
- int jf_us = 0;
- //start with regular jump flood for very coarse reads, as this is impossible to optimize
- while (s > 1) {
- s /= 2;
- push_constant.step_size = s;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->jump_flood_uniform_set[jf_us], 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, 4, 4, 4);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- jf_us = jf_us == 0 ? 1 : 0;
-
- if (rb->sdfgi->cascade_size / (s / 2) >= optimized_jf_group_size) {
- break;
- }
- }
-
- RENDER_TIMESTAMP("SDFGI Jump Flood Optimized");
-
- //continue with optimized jump flood for smaller reads
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]);
- while (s > 1) {
- s /= 2;
- push_constant.step_size = s;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->jump_flood_uniform_set[jf_us], 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, optimized_jf_group_size, optimized_jf_group_size, optimized_jf_group_size);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- jf_us = jf_us == 0 ? 1 : 0;
- }
- }
- }
-
- RENDER_TIMESTAMP("SDFGI Occlusion");
-
- // occlusion
- {
- uint32_t probe_size = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR;
- Vector3i probe_global_pos = rb->sdfgi->cascades[cascade].position / probe_size;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_OCCLUSION]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->occlusion_uniform_set, 0);
- for (int i = 0; i < 8; i++) {
- //dispatch all at once for performance
- Vector3i offset(i & 1, (i >> 1) & 1, (i >> 2) & 1);
-
- if ((probe_global_pos.x & 1) != 0) {
- offset.x = (offset.x + 1) & 1;
- }
- if ((probe_global_pos.y & 1) != 0) {
- offset.y = (offset.y + 1) & 1;
- }
- if ((probe_global_pos.z & 1) != 0) {
- offset.z = (offset.z + 1) & 1;
- }
- push_constant.probe_offset[0] = offset.x;
- push_constant.probe_offset[1] = offset.y;
- push_constant.probe_offset[2] = offset.z;
- push_constant.occlusion_index = i;
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
-
- Vector3i groups = Vector3i(probe_size + 1, probe_size + 1, probe_size + 1) - offset; //if offset, it's one less probe per axis to compute
- RD::get_singleton()->compute_list_dispatch(compute_list, groups.x, groups.y, groups.z);
- }
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
-
- RENDER_TIMESTAMP("SDFGI Store");
-
- // store
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_STORE]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].sdf_store_uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, 4, 4, 4);
-
- RD::get_singleton()->compute_list_end();
-
- //clear these textures, as they will have previous garbage on next draw
- RD::get_singleton()->texture_clear(rb->sdfgi->cascades[cascade].light_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
- RD::get_singleton()->texture_clear(rb->sdfgi->cascades[cascade].light_aniso_0_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
- RD::get_singleton()->texture_clear(rb->sdfgi->cascades[cascade].light_aniso_1_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
-
-#if 0
- Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rb->sdfgi->cascades[cascade].sdf, 0);
- Ref<Image> img;
- img.instance();
- for (uint32_t i = 0; i < rb->sdfgi->cascade_size; i++) {
- Vector<uint8_t> subarr = data.subarray(128 * 128 * i, 128 * 128 * (i + 1) - 1);
- img->create(rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, false, Image::FORMAT_L8, subarr);
- img->save_png("res://cascade_sdf_" + itos(cascade) + "_" + itos(i) + ".png");
- }
-
- //finalize render and update sdf
-#endif
-
-#if 0
- Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rb->sdfgi->render_albedo, 0);
- Ref<Image> img;
- img.instance();
- for (uint32_t i = 0; i < rb->sdfgi->cascade_size; i++) {
- Vector<uint8_t> subarr = data.subarray(128 * 128 * i * 2, 128 * 128 * (i + 1) * 2 - 1);
- img->create(rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, false, Image::FORMAT_RGB565, subarr);
- img->convert(Image::FORMAT_RGBA8);
- img->save_png("res://cascade_" + itos(cascade) + "_" + itos(i) + ".png");
- }
-
- //finalize render and update sdf
-#endif
-
- RENDER_TIMESTAMP("<SDFGI Update SDF");
- }
-}
-
void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));
Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
@@ -7999,128 +3835,15 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider,
_render_particle_collider_heightfield(fb, cam_xform, cm, p_instances);
}
-void RendererSceneRenderRD::render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
- ERR_FAIL_COND(!rb);
- ERR_FAIL_COND(!rb->sdfgi);
-
- _sdfgi_update_cascades(p_render_buffers); //need cascades updated for this
-
- SDGIShader::Light lights[SDFGI::MAX_STATIC_LIGHTS];
- uint32_t light_count[SDFGI::MAX_STATIC_LIGHTS];
-
- for (uint32_t i = 0; i < p_cascade_count; i++) {
- ERR_CONTINUE(p_cascade_indices[i] >= rb->sdfgi->cascades.size());
-
- SDFGI::Cascade &cc = rb->sdfgi->cascades[p_cascade_indices[i]];
-
- { //fill light buffer
-
- AABB cascade_aabb;
- cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + cc.position)) * cc.cell_size;
- cascade_aabb.size = Vector3(1, 1, 1) * rb->sdfgi->cascade_size * cc.cell_size;
-
- int idx = 0;
-
- for (uint32_t j = 0; j < (uint32_t)p_positional_light_cull_result[i].size(); j++) {
- if (idx == SDFGI::MAX_STATIC_LIGHTS) {
- break;
- }
-
- LightInstance *li = light_instance_owner.getornull(p_positional_light_cull_result[i][j]);
- ERR_CONTINUE(!li);
-
- uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
- if (p_cascade_indices[i] > max_sdfgi_cascade) {
- continue;
- }
-
- if (!cascade_aabb.intersects(li->aabb)) {
- continue;
- }
-
- lights[idx].type = storage->light_get_type(li->light);
-
- Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
- if (lights[idx].type == RS::LIGHT_DIRECTIONAL) {
- dir.y *= rb->sdfgi->y_mult; //only makes sense for directional
- dir.normalize();
- }
- lights[idx].direction[0] = dir.x;
- lights[idx].direction[1] = dir.y;
- lights[idx].direction[2] = dir.z;
- Vector3 pos = li->transform.origin;
- pos.y *= rb->sdfgi->y_mult;
- lights[idx].position[0] = pos.x;
- lights[idx].position[1] = pos.y;
- lights[idx].position[2] = pos.z;
- Color color = storage->light_get_color(li->light);
- color = color.to_linear();
- lights[idx].color[0] = color.r;
- lights[idx].color[1] = color.g;
- lights[idx].color[2] = color.b;
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY);
- lights[idx].has_shadow = storage->light_has_shadow(li->light);
- lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
- lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
- lights[idx].spot_angle = Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE));
- lights[idx].spot_attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
-
- idx++;
- }
-
- if (idx > 0) {
- RD::get_singleton()->buffer_update(cc.lights_buffer, 0, idx * sizeof(SDGIShader::Light), lights);
- }
-
- light_count[i] = idx;
- }
- }
-
- /* Static Lights */
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.direct_light_pipeline[SDGIShader::DIRECT_LIGHT_MODE_STATIC]);
-
- SDGIShader::DirectLightPushConstant dl_push_constant;
-
- dl_push_constant.grid_size[0] = rb->sdfgi->cascade_size;
- dl_push_constant.grid_size[1] = rb->sdfgi->cascade_size;
- dl_push_constant.grid_size[2] = rb->sdfgi->cascade_size;
- dl_push_constant.max_cascades = rb->sdfgi->cascades.size();
- dl_push_constant.probe_axis_size = rb->sdfgi->probe_axis_count;
- dl_push_constant.multibounce = false; // this is static light, do not multibounce yet
- dl_push_constant.y_mult = rb->sdfgi->y_mult;
-
- //all must be processed
- dl_push_constant.process_offset = 0;
- dl_push_constant.process_increment = 1;
-
- for (uint32_t i = 0; i < p_cascade_count; i++) {
- ERR_CONTINUE(p_cascade_indices[i] >= rb->sdfgi->cascades.size());
-
- SDFGI::Cascade &cc = rb->sdfgi->cascades[p_cascade_indices[i]];
-
- dl_push_constant.light_count = light_count[i];
- dl_push_constant.cascade = p_cascade_indices[i];
-
- if (dl_push_constant.light_count > 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &dl_push_constant, sizeof(SDGIShader::DirectLightPushConstant));
- RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cc.solid_cell_dispatch_buffer, 0);
- }
- }
-
- RD::get_singleton()->compute_list_end();
-}
-
bool RendererSceneRenderRD::free(RID p_rid) {
if (render_buffers_owner.owns(p_rid)) {
RenderBuffers *rb = render_buffers_owner.getornull(p_rid);
_free_render_buffer_data(rb);
memdelete(rb->data);
if (rb->sdfgi) {
- _sdfgi_erase(rb);
+ rb->sdfgi->erase();
+ memdelete(rb->sdfgi);
+ rb->sdfgi = nullptr;
}
if (rb->volumetric_fog) {
_volumetric_fog_erase(rb);
@@ -8151,8 +3874,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
decal_instance_owner.free(p_rid);
} else if (lightmap_instance_owner.owns(p_rid)) {
lightmap_instance_owner.free(p_rid);
- } else if (gi_probe_instance_owner.owns(p_rid)) {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid);
+ } else if (gi.gi_probe_instance_owner.owns(p_rid)) {
+ RendererSceneGIRD::GIProbeInstance *gi_probe = gi.gi_probe_instance_owner.getornull(p_rid);
if (gi_probe->texture.is_valid()) {
RD::get_singleton()->free(gi_probe->texture);
RD::get_singleton()->free(gi_probe->write_buffer);
@@ -8163,37 +3886,10 @@ bool RendererSceneRenderRD::free(RID p_rid) {
RD::get_singleton()->free(gi_probe->dynamic_maps[i].depth);
}
- gi_probe_instance_owner.free(p_rid);
- } else if (sky_owner.owns(p_rid)) {
- _update_dirty_skys();
- Sky *sky = sky_owner.getornull(p_rid);
-
- if (sky->radiance.is_valid()) {
- RD::get_singleton()->free(sky->radiance);
- sky->radiance = RID();
- }
- _clear_reflection_data(sky->reflection);
-
- if (sky->uniform_buffer.is_valid()) {
- RD::get_singleton()->free(sky->uniform_buffer);
- sky->uniform_buffer = RID();
- }
-
- if (sky->half_res_pass.is_valid()) {
- RD::get_singleton()->free(sky->half_res_pass);
- sky->half_res_pass = RID();
- }
-
- if (sky->quarter_res_pass.is_valid()) {
- RD::get_singleton()->free(sky->quarter_res_pass);
- sky->quarter_res_pass = RID();
- }
-
- if (sky->material.is_valid()) {
- storage->free(sky->material);
- }
-
- sky_owner.free(p_rid);
+ gi.gi_probe_instance_owner.free(p_rid);
+ } else if (sky.sky_owner.owns(p_rid)) {
+ sky.update_dirty_skys();
+ sky.free_sky(p_rid);
} else if (light_instance_owner.owns(p_rid)) {
LightInstance *light_instance = light_instance_owner.getornull(p_rid);
@@ -8227,7 +3923,7 @@ void RendererSceneRenderRD::set_debug_draw_mode(RS::ViewportDebugDraw p_debug_dr
}
void RendererSceneRenderRD::update() {
- _update_dirty_skys();
+ sky.update_dirty_skys();
}
void RendererSceneRenderRD::set_time(double p_time, double p_step) {
@@ -8353,8 +4049,8 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
}
void RendererSceneRenderRD::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) {
- sdfgi_debug_probe_pos = p_position;
- sdfgi_debug_probe_dir = p_dir;
+ gi.sdfgi_debug_probe_pos = p_position;
+ gi.sdfgi_debug_probe_dir = p_dir;
}
RendererSceneRenderRD *RendererSceneRenderRD::singleton = nullptr;
@@ -8385,404 +4081,30 @@ bool RendererSceneRenderRD::is_low_end() const {
}
RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
- max_cluster_elements = GLOBAL_GET("rendering/cluster_builder/max_clustered_elements");
+ max_cluster_elements = GLOBAL_GET("rendering/limits/cluster_builder/max_clustered_elements");
storage = p_storage;
singleton = this;
- roughness_layers = GLOBAL_GET("rendering/quality/reflections/roughness_layers");
- sky_ggx_samples_quality = GLOBAL_GET("rendering/quality/reflections/ggx_samples");
- sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections");
-
- sdfgi_ray_count = RS::EnvironmentSDFGIRayCount(CLAMP(int32_t(GLOBAL_GET("rendering/sdfgi/probe_ray_count")), 0, int32_t(RS::ENV_SDFGI_RAY_COUNT_MAX - 1)));
- sdfgi_frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(CLAMP(int32_t(GLOBAL_GET("rendering/sdfgi/frames_to_converge")), 0, int32_t(RS::ENV_SDFGI_CONVERGE_MAX - 1)));
- sdfgi_frames_to_update_light = RS::EnvironmentSDFGIFramesToUpdateLight(CLAMP(int32_t(GLOBAL_GET("rendering/sdfgi/frames_to_update_lights")), 0, int32_t(RS::ENV_SDFGI_UPDATE_LIGHT_MAX - 1)));
-
- directional_shadow.size = GLOBAL_GET("rendering/quality/directional_shadow/size");
- directional_shadow.use_16_bits = GLOBAL_GET("rendering/quality/directional_shadow/16_bits");
+ directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
+ directional_shadow.use_16_bits = GLOBAL_GET("rendering/shadows/directional_shadow/16_bits");
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
- low_end = GLOBAL_GET("rendering/quality/rd_renderer/use_low_end_renderer");
+ low_end = GLOBAL_GET("rendering/driver/rd_renderer/use_low_end_renderer");
if (textures_per_stage < 48) {
low_end = true;
}
- if (!low_end) {
- //kinda complicated to compute the amount of slots, we try to use as many as we can
-
- gi_probe_max_lights = 32;
-
- gi_probe_lights = memnew_arr(GIProbeLight, gi_probe_max_lights);
- gi_probe_lights_uniform = RD::get_singleton()->uniform_buffer_create(gi_probe_max_lights * sizeof(GIProbeLight));
- gi_probe_quality = RS::GIProbeQuality(CLAMP(int(GLOBAL_GET("rendering/quality/gi_probes/quality")), 0, 1));
-
- String defines = "\n#define MAX_LIGHTS " + itos(gi_probe_max_lights) + "\n";
-
- Vector<String> versions;
- versions.push_back("\n#define MODE_COMPUTE_LIGHT\n");
- versions.push_back("\n#define MODE_SECOND_BOUNCE\n");
- versions.push_back("\n#define MODE_UPDATE_MIPMAPS\n");
- versions.push_back("\n#define MODE_WRITE_TEXTURE\n");
- versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_LIGHTING\n");
- versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_WRITE\n");
- versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n");
- versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n#define MODE_DYNAMIC_SHRINK_WRITE\n");
-
- giprobe_shader.initialize(versions, defines);
- giprobe_lighting_shader_version = giprobe_shader.version_create();
- for (int i = 0; i < GI_PROBE_SHADER_VERSION_MAX; i++) {
- giprobe_lighting_shader_version_shaders[i] = giprobe_shader.version_get_shader(giprobe_lighting_shader_version, i);
- giprobe_lighting_shader_version_pipelines[i] = RD::get_singleton()->compute_pipeline_create(giprobe_lighting_shader_version_shaders[i]);
- }
- }
-
- if (!low_end) {
- String defines;
- Vector<String> versions;
- versions.push_back("\n#define MODE_DEBUG_COLOR\n");
- versions.push_back("\n#define MODE_DEBUG_LIGHT\n");
- versions.push_back("\n#define MODE_DEBUG_EMISSION\n");
- versions.push_back("\n#define MODE_DEBUG_LIGHT\n#define MODE_DEBUG_LIGHT_FULL\n");
-
- giprobe_debug_shader.initialize(versions, defines);
- giprobe_debug_shader_version = giprobe_debug_shader.version_create();
- for (int i = 0; i < GI_PROBE_DEBUG_MAX; i++) {
- giprobe_debug_shader_version_shaders[i] = giprobe_debug_shader.version_get_shader(giprobe_debug_shader_version, i);
-
- RD::PipelineRasterizationState rs;
- rs.cull_mode = RD::POLYGON_CULL_FRONT;
- RD::PipelineDepthStencilState ds;
- ds.enable_depth_test = true;
- ds.enable_depth_write = true;
- ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
-
- giprobe_debug_shader_version_pipelines[i].setup(giprobe_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
- }
- }
-
/* SKY SHADER */
- {
- // Start with the directional lights for the sky
- sky_scene_state.max_directional_lights = 4;
- uint32_t directional_light_buffer_size = sky_scene_state.max_directional_lights * sizeof(SkyDirectionalLightData);
- sky_scene_state.directional_lights = memnew_arr(SkyDirectionalLightData, sky_scene_state.max_directional_lights);
- sky_scene_state.last_frame_directional_lights = memnew_arr(SkyDirectionalLightData, sky_scene_state.max_directional_lights);
- sky_scene_state.last_frame_directional_light_count = sky_scene_state.max_directional_lights + 1;
- sky_scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size);
-
- String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_scene_state.max_directional_lights) + "\n";
-
- // Initialize sky
- Vector<String> sky_modes;
- sky_modes.push_back(""); // Full size
- sky_modes.push_back("\n#define USE_HALF_RES_PASS\n"); // Half Res
- sky_modes.push_back("\n#define USE_QUARTER_RES_PASS\n"); // Quarter res
- sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n"); // Cubemap
- sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_HALF_RES_PASS\n"); // Half Res Cubemap
- sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_QUARTER_RES_PASS\n"); // Quarter res Cubemap
- sky_shader.shader.initialize(sky_modes, defines);
- }
-
- // register our shader funds
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
-
- {
- ShaderCompilerRD::DefaultIdentifierActions actions;
-
- actions.renames["COLOR"] = "color";
- actions.renames["ALPHA"] = "alpha";
- actions.renames["EYEDIR"] = "cube_normal";
- actions.renames["POSITION"] = "params.position_multiplier.xyz";
- actions.renames["SKY_COORDS"] = "panorama_coords";
- actions.renames["SCREEN_UV"] = "uv";
- actions.renames["TIME"] = "params.time";
- actions.renames["HALF_RES_COLOR"] = "half_res_color";
- actions.renames["QUARTER_RES_COLOR"] = "quarter_res_color";
- actions.renames["RADIANCE"] = "radiance";
- actions.renames["FOG"] = "custom_fog";
- actions.renames["LIGHT0_ENABLED"] = "directional_lights.data[0].enabled";
- actions.renames["LIGHT0_DIRECTION"] = "directional_lights.data[0].direction_energy.xyz";
- actions.renames["LIGHT0_ENERGY"] = "directional_lights.data[0].direction_energy.w";
- actions.renames["LIGHT0_COLOR"] = "directional_lights.data[0].color_size.xyz";
- actions.renames["LIGHT0_SIZE"] = "directional_lights.data[0].color_size.w";
- actions.renames["LIGHT1_ENABLED"] = "directional_lights.data[1].enabled";
- actions.renames["LIGHT1_DIRECTION"] = "directional_lights.data[1].direction_energy.xyz";
- actions.renames["LIGHT1_ENERGY"] = "directional_lights.data[1].direction_energy.w";
- actions.renames["LIGHT1_COLOR"] = "directional_lights.data[1].color_size.xyz";
- actions.renames["LIGHT1_SIZE"] = "directional_lights.data[1].color_size.w";
- actions.renames["LIGHT2_ENABLED"] = "directional_lights.data[2].enabled";
- actions.renames["LIGHT2_DIRECTION"] = "directional_lights.data[2].direction_energy.xyz";
- actions.renames["LIGHT2_ENERGY"] = "directional_lights.data[2].direction_energy.w";
- actions.renames["LIGHT2_COLOR"] = "directional_lights.data[2].color_size.xyz";
- actions.renames["LIGHT2_SIZE"] = "directional_lights.data[2].color_size.w";
- actions.renames["LIGHT3_ENABLED"] = "directional_lights.data[3].enabled";
- actions.renames["LIGHT3_DIRECTION"] = "directional_lights.data[3].direction_energy.xyz";
- actions.renames["LIGHT3_ENERGY"] = "directional_lights.data[3].direction_energy.w";
- actions.renames["LIGHT3_COLOR"] = "directional_lights.data[3].color_size.xyz";
- actions.renames["LIGHT3_SIZE"] = "directional_lights.data[3].color_size.w";
- actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS";
- actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS";
- actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS";
- actions.custom_samplers["RADIANCE"] = "material_samplers[3]";
- actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n";
- actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n";
- actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n";
-
- actions.sampler_array_name = "material_samplers";
- actions.base_texture_binding_index = 1;
- actions.texture_layout_set = 1;
- 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_variables.data";
-
- sky_shader.compiler.initialize(actions);
- }
-
- {
- // default material and shader for sky shader
- sky_shader.default_shader = storage->shader_create();
- storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void fragment() { COLOR = vec3(0.0); } \n");
- sky_shader.default_material = storage->material_create();
- storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
-
- SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
- sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND);
-
- sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO));
-
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 0;
- u.ids.resize(12);
- RID *ids_ptr = u.ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 1;
- u.ids.push_back(storage->global_variables_get_storage_buffer());
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(sky_scene_state.uniform_buffer);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.binding = 3;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(sky_scene_state.directional_light_buffer);
- uniforms.push_back(u);
- }
-
- sky_scene_state.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_UNIFORMS);
- }
-
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 0;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
- u.ids.push_back(vfog);
- uniforms.push_back(u);
- }
-
- sky_scene_state.default_fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_FOG);
- }
-
- {
- // Need defaults for using fog with clear color
- sky_scene_state.fog_shader = storage->shader_create();
- storage->shader_set_code(sky_scene_state.fog_shader, "shader_type sky; uniform vec4 clear_color; void fragment() { COLOR = clear_color.rgb; } \n");
- sky_scene_state.fog_material = storage->material_create();
- storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader);
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 0;
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1;
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2;
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
- uniforms.push_back(u);
- }
+ sky.init(storage);
- sky_scene_state.fog_only_texture_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_TEXTURES);
- }
+ /* GI */
if (!low_end) {
- //SDFGI
- {
- Vector<String> preprocess_modes;
- preprocess_modes.push_back("\n#define MODE_SCROLL\n");
- preprocess_modes.push_back("\n#define MODE_SCROLL_OCCLUSION\n");
- preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD\n");
- preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD_HALF\n");
- preprocess_modes.push_back("\n#define MODE_JUMPFLOOD\n");
- preprocess_modes.push_back("\n#define MODE_JUMPFLOOD_OPTIMIZED\n");
- preprocess_modes.push_back("\n#define MODE_UPSCALE_JUMP_FLOOD\n");
- preprocess_modes.push_back("\n#define MODE_OCCLUSION\n");
- preprocess_modes.push_back("\n#define MODE_STORE\n");
- String defines = "\n#define OCCLUSION_SIZE " + itos(SDFGI::CASCADE_SIZE / SDFGI::PROBE_DIVISOR) + "\n";
- sdfgi_shader.preprocess.initialize(preprocess_modes, defines);
- sdfgi_shader.preprocess_shader = sdfgi_shader.preprocess.version_create();
- for (int i = 0; i < SDGIShader::PRE_PROCESS_MAX; i++) {
- sdfgi_shader.preprocess_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, i));
- }
- }
-
- {
- //calculate tables
- String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
-
- Vector<String> direct_light_modes;
- direct_light_modes.push_back("\n#define MODE_PROCESS_STATIC\n");
- direct_light_modes.push_back("\n#define MODE_PROCESS_DYNAMIC\n");
- sdfgi_shader.direct_light.initialize(direct_light_modes, defines);
- sdfgi_shader.direct_light_shader = sdfgi_shader.direct_light.version_create();
- for (int i = 0; i < SDGIShader::DIRECT_LIGHT_MODE_MAX; i++) {
- sdfgi_shader.direct_light_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, i));
- }
- }
-
- {
- //calculate tables
- String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
- defines += "\n#define SH_SIZE " + itos(SDFGI::SH_SIZE) + "\n";
- if (sky_use_cubemap_array) {
- defines += "\n#define USE_CUBEMAP_ARRAY\n";
- }
-
- Vector<String> integrate_modes;
- integrate_modes.push_back("\n#define MODE_PROCESS\n");
- integrate_modes.push_back("\n#define MODE_STORE\n");
- integrate_modes.push_back("\n#define MODE_SCROLL\n");
- integrate_modes.push_back("\n#define MODE_SCROLL_STORE\n");
- sdfgi_shader.integrate.initialize(integrate_modes, defines);
- sdfgi_shader.integrate_shader = sdfgi_shader.integrate.version_create();
-
- for (int i = 0; i < SDGIShader::INTEGRATE_MODE_MAX; i++) {
- sdfgi_shader.integrate_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, i));
- }
-
- {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 0;
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 1;
- u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
-
- sdfgi_shader.integrate_default_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 1);
- }
- }
- //GK
- {
- //calculate tables
- String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
- Vector<String> gi_modes;
- gi_modes.push_back("\n#define USE_GIPROBES\n");
- gi_modes.push_back("\n#define USE_SDFGI\n");
- gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_GIPROBES\n");
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_GIPROBES\n");
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n");
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_GIPROBES\n");
-
- gi.shader.initialize(gi_modes, defines);
- gi.shader_version = gi.shader.version_create();
- for (int i = 0; i < GI::MODE_MAX; i++) {
- gi.pipelines[i] = RD::get_singleton()->compute_pipeline_create(gi.shader.version_get_shader(gi.shader_version, i));
- }
-
- gi.sdfgi_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(GI::SDFGIData));
- }
- {
- String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
- Vector<String> debug_modes;
- debug_modes.push_back("");
- sdfgi_shader.debug.initialize(debug_modes, defines);
- sdfgi_shader.debug_shader = sdfgi_shader.debug.version_create();
- sdfgi_shader.debug_shader_version = sdfgi_shader.debug.version_get_shader(sdfgi_shader.debug_shader, 0);
- sdfgi_shader.debug_pipeline = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.debug_shader_version);
- }
- {
- String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
-
- Vector<String> versions;
- versions.push_back("\n#define MODE_PROBES\n");
- versions.push_back("\n#define MODE_VISIBILITY\n");
-
- sdfgi_shader.debug_probes.initialize(versions, defines);
- sdfgi_shader.debug_probes_shader = sdfgi_shader.debug_probes.version_create();
-
- {
- RD::PipelineRasterizationState rs;
- rs.cull_mode = RD::POLYGON_CULL_DISABLED;
- RD::PipelineDepthStencilState ds;
- ds.enable_depth_test = true;
- ds.enable_depth_write = true;
- ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
- for (int i = 0; i < SDGIShader::PROBE_DEBUG_MAX; i++) {
- RID debug_probes_shader_version = sdfgi_shader.debug_probes.version_get_shader(sdfgi_shader.debug_probes_shader, i);
- sdfgi_shader.debug_probes_pipeline[i].setup(debug_probes_shader_version, RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
- }
- }
- }
- default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::GIProbeData) * RenderBuffers::MAX_GIPROBES);
+ gi.init(storage, &sky);
}
{ //decals
@@ -8797,7 +4119,7 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
cluster.max_reflections = max_cluster_elements;
cluster.reflections = memnew_arr(Cluster::ReflectionData, cluster.max_reflections);
- cluster.reflection_sort = memnew_arr(Cluster::InstanceSort<ReflectionProbeInstance>, cluster.max_decals);
+ cluster.reflection_sort = memnew_arr(Cluster::InstanceSort<ReflectionProbeInstance>, cluster.max_reflections);
cluster.reflection_buffer = RD::get_singleton()->storage_buffer_create(sizeof(Cluster::ReflectionData) * cluster.max_reflections);
}
@@ -8813,10 +4135,6 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
cluster.spot_light_sort = memnew_arr(Cluster::InstanceSort<LightInstance>, cluster.max_lights);
//defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(cluster.max_lights) + "\n";
- //used for volumetric fog shrinking
- cluster.lights_instances = memnew_arr(RID, cluster.max_lights * 2);
- cluster.lights_shadow_rect_cache = memnew_arr(Rect2i, cluster.max_lights * 2);
-
cluster.max_directional_lights = MAX_DIRECTIONAL_LIGHTS;
uint32_t directional_light_buffer_size = cluster.max_directional_lights * sizeof(Cluster::DirectionalLightData);
cluster.directional_lights = memnew_arr(Cluster::DirectionalLightData, cluster.max_directional_lights);
@@ -8847,33 +4165,31 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
- camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_shape"))));
- camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_use_jitter"));
- environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size"), GLOBAL_GET("rendering/quality/ssao/adaptive_target"), GLOBAL_GET("rendering/quality/ssao/blur_passes"), GLOBAL_GET("rendering/quality/ssao/fadeout_from"), GLOBAL_GET("rendering/quality/ssao/fadeout_to"));
- screen_space_roughness_limiter = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_enabled");
- screen_space_roughness_limiter_amount = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_amount");
- screen_space_roughness_limiter_limit = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_limit");
- glow_bicubic_upscale = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0;
- glow_high_quality = GLOBAL_GET("rendering/quality/glow/use_high_quality");
- ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality")));
- sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_quality")));
- sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale");
- sss_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale");
+ camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape"))));
+ camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_use_jitter"));
+ environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to"));
+ screen_space_roughness_limiter = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/enabled");
+ 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");
+ ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/environment/screen_space_reflection/roughness_quality")));
+ sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality")));
+ sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale");
+ sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale");
directional_penumbra_shadow_kernel = memnew_arr(float, 128);
directional_soft_shadow_kernel = memnew_arr(float, 128);
penumbra_shadow_kernel = memnew_arr(float, 128);
soft_shadow_kernel = memnew_arr(float, 128);
- shadows_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/shadows/soft_shadow_quality"))));
- directional_shadow_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/directional_shadow/soft_shadow_quality"))));
+ shadows_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/shadows/soft_shadow_quality"))));
+ directional_shadow_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_quality"))));
- environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/volumetric_fog/volume_size"), GLOBAL_GET("rendering/volumetric_fog/volume_depth"));
- environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/volumetric_fog/use_filter"));
- environment_set_volumetric_fog_directional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/directional_shadow_shrink"));
- environment_set_volumetric_fog_positional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/positional_shadow_shrink"));
+ environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth"));
+ environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter"));
cull_argument.set_page_pool(&cull_argument_pool);
- gi.half_resolution = GLOBAL_GET("rendering/quality/gi/use_half_resolution");
+ gi.half_resolution = GLOBAL_GET("rendering/global_illumination/gi/use_half_resolution");
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
@@ -8881,40 +4197,27 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
RD::get_singleton()->free(E->get().cubemap);
}
- if (sky_scene_state.uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.uniform_set)) {
- RD::get_singleton()->free(sky_scene_state.uniform_set);
+ if (sky.sky_scene_state.uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky.sky_scene_state.uniform_set)) {
+ RD::get_singleton()->free(sky.sky_scene_state.uniform_set);
}
if (!low_end) {
- RD::get_singleton()->free(default_giprobe_buffer);
- RD::get_singleton()->free(gi_probe_lights_uniform);
- RD::get_singleton()->free(gi.sdfgi_ubo);
-
- giprobe_debug_shader.version_free(giprobe_debug_shader_version);
- giprobe_shader.version_free(giprobe_lighting_shader_version);
- gi.shader.version_free(gi.shader_version);
- sdfgi_shader.debug_probes.version_free(sdfgi_shader.debug_probes_shader);
- sdfgi_shader.debug.version_free(sdfgi_shader.debug_shader);
- sdfgi_shader.direct_light.version_free(sdfgi_shader.direct_light_shader);
- sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader);
- sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader);
+ gi.free();
volumetric_fog.shader.version_free(volumetric_fog.shader_version);
RD::get_singleton()->free(volumetric_fog.params_ubo);
-
- memdelete_arr(gi_probe_lights);
}
- SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
- sky_shader.shader.version_free(md->shader_data->version);
- RD::get_singleton()->free(sky_scene_state.directional_light_buffer);
- RD::get_singleton()->free(sky_scene_state.uniform_buffer);
- memdelete_arr(sky_scene_state.directional_lights);
- memdelete_arr(sky_scene_state.last_frame_directional_lights);
- storage->free(sky_shader.default_shader);
- storage->free(sky_shader.default_material);
- storage->free(sky_scene_state.fog_shader);
- storage->free(sky_scene_state.fog_material);
+ RendererSceneSkyRD::SkyMaterialData *md = (RendererSceneSkyRD::SkyMaterialData *)storage->material_get_data(sky.sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
+ sky.sky_shader.shader.version_free(md->shader_data->version);
+ RD::get_singleton()->free(sky.sky_scene_state.directional_light_buffer);
+ RD::get_singleton()->free(sky.sky_scene_state.uniform_buffer);
+ memdelete_arr(sky.sky_scene_state.directional_lights);
+ memdelete_arr(sky.sky_scene_state.last_frame_directional_lights);
+ storage->free(sky.sky_shader.default_shader);
+ storage->free(sky.sky_shader.default_material);
+ storage->free(sky.sky_scene_state.fog_shader);
+ storage->free(sky.sky_scene_state.fog_material);
memdelete_arr(directional_penumbra_shadow_kernel);
memdelete_arr(directional_soft_shadow_kernel);
memdelete_arr(penumbra_shadow_kernel);
@@ -8931,8 +4234,6 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
memdelete_arr(cluster.spot_lights);
memdelete_arr(cluster.omni_light_sort);
memdelete_arr(cluster.spot_light_sort);
- memdelete_arr(cluster.lights_shadow_rect_cache);
- memdelete_arr(cluster.lights_instances);
memdelete_arr(cluster.reflections);
memdelete_arr(cluster.reflection_sort);
memdelete_arr(cluster.decals);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index af8cdb9b71..001cfeb74d 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -35,68 +35,22 @@
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
+#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
+#include "servers/rendering/renderer_rd/renderer_scene_gi_rd.h"
+#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-#include "servers/rendering/renderer_rd/shaders/gi.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/giprobe.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/giprobe_debug.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/sky.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
class RendererSceneRenderRD : public RendererSceneRender {
+ friend RendererSceneSkyRD;
+ friend RendererSceneGIRD;
+
protected:
+ RendererStorageRD *storage;
double time;
-
- // Skys need less info from Directional Lights than the normal shaders
- struct SkyDirectionalLightData {
- float direction[3];
- float energy;
- float color[3];
- float size;
- uint32_t enabled;
- uint32_t pad[3];
- };
-
- struct SkySceneState {
- struct UBO {
- uint32_t volumetric_fog_enabled;
- float volumetric_fog_inv_length;
- float volumetric_fog_detail_spread;
-
- float fog_aerial_perspective;
-
- float fog_light_color[3];
- float fog_sun_scatter;
-
- uint32_t fog_enabled;
- float fog_density;
-
- float z_far;
- uint32_t directional_light_count;
- };
-
- UBO ubo;
-
- SkyDirectionalLightData *directional_lights;
- SkyDirectionalLightData *last_frame_directional_lights;
- uint32_t max_directional_lights;
- uint32_t last_frame_directional_light_count;
- RID directional_light_buffer;
- RID uniform_set;
- RID uniform_buffer;
- RID fog_uniform_set;
- RID default_fog_uniform_set;
-
- RID fog_shader;
- RID fog_material;
- RID fog_only_texture_uniform_set;
- } sky_scene_state;
+ double time_step = 0;
struct RenderBufferData {
virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) = 0;
@@ -107,16 +61,19 @@ protected:
void _setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count);
void _setup_decals(const PagedArray<RID> &p_decals, const Transform &p_camera_inverse_xform);
void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment);
- void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used);
- virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_cluster_max_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
- virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_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) = 0;
+ virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_cluster_max_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
+
+ virtual void _render_shadow_begin() = 0;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &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_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) = 0;
+ virtual void _render_shadow_process() = 0;
+ virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0;
+
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
- virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
RenderBufferData *render_buffers_get_data(RID p_render_buffers);
@@ -129,198 +86,31 @@ protected:
void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive);
void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera);
- void _setup_sky(RID p_environment, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size);
- void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
- void _draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
- void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes);
+ bool _needs_post_prepass_render(bool p_use_gi);
+ void _post_prepass_render(bool p_use_gi);
+ void _pre_resolve_render(bool p_use_gi);
+
+ void _pre_opaque_render(bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_gi_probe_buffer);
+ uint32_t _get_render_state_directional_light_count() const;
// needed for a single argument calls (material and uv2)
PagedArrayPool<GeometryInstance *> cull_argument_pool;
PagedArray<GeometryInstance *> cull_argument; //need this to exist
-private:
- RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
- double time_step = 0;
- static RendererSceneRenderRD *singleton;
-
- int roughness_layers;
-
- RendererStorageRD *storage;
-
- struct ReflectionData {
- struct Layer {
- struct Mipmap {
- RID framebuffers[6];
- RID views[6];
- Size2i size;
- };
- Vector<Mipmap> mipmaps; //per-face view
- Vector<RID> views; // per-cubemap view
- };
-
- struct DownsampleLayer {
- struct Mipmap {
- RID view;
- Size2i size;
- };
- Vector<Mipmap> mipmaps;
- };
-
- RID radiance_base_cubemap; //cubemap for first layer, first cubemap
- RID downsampled_radiance_cubemap;
- DownsampleLayer downsampled_layer;
- RID coefficient_buffer;
-
- bool dirty = true;
-
- Vector<Layer> layers;
- };
-
- void _clear_reflection_data(ReflectionData &rd);
- void _update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality);
- void _create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays);
- void _create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer);
- void _update_reflection_mipmaps(ReflectionData &rd, int p_start, int p_end);
-
- /* Sky shader */
-
- enum SkyVersion {
- SKY_VERSION_BACKGROUND,
- SKY_VERSION_HALF_RES,
- SKY_VERSION_QUARTER_RES,
- SKY_VERSION_CUBEMAP,
- SKY_VERSION_CUBEMAP_HALF_RES,
- SKY_VERSION_CUBEMAP_QUARTER_RES,
- SKY_VERSION_MAX
- };
-
- struct SkyShader {
- SkyShaderRD shader;
- ShaderCompilerRD compiler;
-
- RID default_shader;
- RID default_material;
- RID default_shader_rd;
- } sky_shader;
-
- struct SkyShaderData : public RendererStorageRD::ShaderData {
- bool valid;
- RID version;
-
- PipelineCacheRD pipelines[SKY_VERSION_MAX];
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
-
- Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
-
- String path;
- String code;
- Map<StringName, RID> default_texture_params;
-
- bool uses_time;
- bool uses_position;
- bool uses_half_res;
- bool uses_quarter_res;
- bool uses_light;
-
- virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
- virtual bool is_param_texture(const StringName &p_param) const;
- virtual bool is_animated() const;
- virtual bool casts_shadows() const;
- virtual Variant get_default_parameter(const StringName &p_parameter) const;
- virtual RS::ShaderNativeSourceCode get_native_source_code() const;
- SkyShaderData();
- virtual ~SkyShaderData();
- };
-
- RendererStorageRD::ShaderData *_create_sky_shader_func();
- static RendererStorageRD::ShaderData *_create_sky_shader_funcs() {
- return static_cast<RendererSceneRenderRD *>(singleton)->_create_sky_shader_func();
- };
-
- struct SkyMaterialData : public RendererStorageRD::MaterialData {
- uint64_t last_frame;
- SkyShaderData *shader_data;
- RID uniform_buffer;
- RID uniform_set;
- Vector<RID> texture_cache;
- Vector<uint8_t> ubo_data;
- bool uniform_set_updated;
-
- virtual void set_render_priority(int p_priority) {}
- virtual void set_next_pass(RID p_pass) {}
- virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
- virtual ~SkyMaterialData();
- };
-
- RendererStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader) {
- return static_cast<RendererSceneRenderRD *>(singleton)->_create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
- };
-
- enum SkyTextureSetVersion {
- SKY_TEXTURE_SET_BACKGROUND,
- SKY_TEXTURE_SET_HALF_RES,
- SKY_TEXTURE_SET_QUARTER_RES,
- SKY_TEXTURE_SET_CUBEMAP,
- SKY_TEXTURE_SET_CUBEMAP_HALF_RES,
- SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES,
- SKY_TEXTURE_SET_MAX
- };
-
- enum SkySet {
- SKY_SET_UNIFORMS,
- SKY_SET_MATERIAL,
- SKY_SET_TEXTURES,
- SKY_SET_FOG,
- SKY_SET_MAX
- };
-
- /* SKY */
- 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;
- RID uniform_buffer;
-
- int radiance_size = 256;
-
- RS::SkyMode mode = RS::SKY_MODE_AUTOMATIC;
- ReflectionData reflection;
- bool dirty = false;
- int processing_layer = 0;
- Sky *dirty_list = nullptr;
+ RendererSceneGIRD gi;
+ RendererSceneSkyRD sky;
- //State to track when radiance cubemap needs updating
- SkyMaterialData *prev_material;
- Vector3 prev_position;
- float prev_time;
-
- RID sdfgi_integrate_sky_uniform_set;
- };
-
- Sky *dirty_sky_list = nullptr;
-
- void _sky_invalidate(Sky *p_sky);
- void _update_dirty_skys();
- RID _get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version);
-
- uint32_t sky_ggx_samples_quality;
- bool sky_use_cubemap_array;
+ RendererSceneEnvironmentRD *get_environment(RID p_environment) {
+ if (p_environment.is_valid()) {
+ return environment_owner.getornull(p_environment);
+ } else {
+ return nullptr;
+ }
+ }
- mutable RID_Owner<Sky> sky_owner;
+private:
+ RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
+ static RendererSceneRenderRD *singleton;
/* REFLECTION ATLAS */
@@ -334,7 +124,7 @@ private:
struct Reflection {
RID owner;
- ReflectionData data;
+ RendererSceneSkyRD::ReflectionData data;
RID fbs[6];
};
@@ -384,151 +174,6 @@ private:
mutable RID_Owner<LightmapInstance> lightmap_instance_owner;
- /* GIPROBE INSTANCE */
-
- struct GIProbeLight {
- uint32_t type;
- float energy;
- float radius;
- float attenuation;
-
- float color[3];
- float spot_angle_radians;
-
- float position[3];
- float spot_attenuation;
-
- float direction[3];
- uint32_t has_shadow;
- };
-
- struct GIProbePushConstant {
- int32_t limits[3];
- uint32_t stack_size;
-
- float emission_scale;
- float propagation;
- float dynamic_range;
- uint32_t light_count;
-
- uint32_t cell_offset;
- uint32_t cell_count;
- float aniso_strength;
- uint32_t pad;
- };
-
- struct GIProbeDynamicPushConstant {
- int32_t limits[3];
- uint32_t light_count;
- int32_t x_dir[3];
- float z_base;
- int32_t y_dir[3];
- float z_sign;
- int32_t z_dir[3];
- float pos_multiplier;
- uint32_t rect_pos[2];
- uint32_t rect_size[2];
- uint32_t prev_rect_ofs[2];
- uint32_t prev_rect_size[2];
- uint32_t flip_x;
- uint32_t flip_y;
- float dynamic_range;
- uint32_t on_mipmap;
- float propagation;
- float pad[3];
- };
-
- struct GIProbeInstance {
- RID probe;
- RID texture;
- RID write_buffer;
-
- struct Mipmap {
- RID texture;
- RID uniform_set;
- RID second_bounce_uniform_set;
- RID write_uniform_set;
- uint32_t level;
- uint32_t cell_offset;
- uint32_t cell_count;
- };
- Vector<Mipmap> mipmaps;
-
- struct DynamicMap {
- RID texture; //color normally, or emission on first pass
- RID fb_depth; //actual depth buffer for the first pass, float depth for later passes
- RID depth; //actual depth buffer for the first pass, float depth for later passes
- RID normal; //normal buffer for the first pass
- RID albedo; //emission buffer for the first pass
- RID orm; //orm buffer for the first pass
- RID fb; //used for rendering, only valid on first map
- RID uniform_set;
- uint32_t size;
- int mipmap; // mipmap to write to, -1 if no mipmap assigned
- };
-
- Vector<DynamicMap> dynamic_maps;
-
- int slot = -1;
- uint32_t last_probe_version = 0;
- uint32_t last_probe_data_version = 0;
-
- //uint64_t last_pass = 0;
- uint32_t render_index = 0;
-
- bool has_dynamic_object_data = false;
-
- Transform transform;
- };
-
- GIProbeLight *gi_probe_lights;
- uint32_t gi_probe_max_lights;
- RID gi_probe_lights_uniform;
-
- enum {
- GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT,
- GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE,
- GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP,
- GI_PROBE_SHADER_VERSION_WRITE_TEXTURE,
- GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING,
- GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE,
- GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT,
- GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT,
- GI_PROBE_SHADER_VERSION_MAX
- };
- GiprobeShaderRD giprobe_shader;
- RID giprobe_lighting_shader_version;
- RID giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_MAX];
- RID giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_MAX];
-
- mutable RID_Owner<GIProbeInstance> gi_probe_instance_owner;
-
- RS::GIProbeQuality gi_probe_quality = RS::GI_PROBE_QUALITY_HIGH;
-
- enum {
- GI_PROBE_DEBUG_COLOR,
- GI_PROBE_DEBUG_LIGHT,
- GI_PROBE_DEBUG_EMISSION,
- GI_PROBE_DEBUG_LIGHT_FULL,
- GI_PROBE_DEBUG_MAX
- };
-
- struct GIProbeDebugPushConstant {
- float projection[16];
- uint32_t cell_offset;
- float dynamic_range;
- float alpha;
- uint32_t level;
- int32_t bounds[3];
- uint32_t pad;
- };
-
- GiprobeDebugShaderRD giprobe_debug_shader;
- RID giprobe_debug_shader_version;
- RID giprobe_debug_shader_version_shaders[GI_PROBE_DEBUG_MAX];
- PipelineCacheRD giprobe_debug_shader_version_pipelines[GI_PROBE_DEBUG_MAX];
- RID giprobe_debug_uniform_set;
-
/* SHADOW ATLAS */
struct ShadowShrinkStage {
@@ -578,8 +223,6 @@ private:
RID fb; //for copying
Map<RID, uint32_t> shadow_owners;
-
- Vector<ShadowShrinkStage> shrink_stages;
};
RID_Owner<ShadowAtlas> shadow_atlas_owner;
@@ -613,13 +256,8 @@ private:
bool use_16_bits = false;
int current_light = 0;
- Vector<ShadowShrinkStage> shrink_stages;
-
} directional_shadow;
- void _allocate_shadow_shrink_stages(RID p_base, int p_base_size, Vector<ShadowShrinkStage> &shrink_stages, uint32_t p_target_size);
- void _clear_shadow_shrink_stages(Vector<ShadowShrinkStage> &shrink_stages);
-
void _update_directional_shadow_atlas();
/* SHADOW CUBEMAPS */
@@ -651,7 +289,7 @@ private:
RS::LightType light_type = RS::LIGHT_DIRECTIONAL;
- ShadowTransform shadow_transform[4];
+ ShadowTransform shadow_transform[6];
AABB aabb;
RID self;
@@ -684,110 +322,6 @@ private:
/* ENVIRONMENT */
- struct Environment {
- // BG
- RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR;
- RID sky;
- float sky_custom_fov = 0.0;
- Basis sky_orientation;
- Color bg_color;
- float bg_energy = 1.0;
- int canvas_max_layer = 0;
- RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG;
- Color ambient_light;
- float ambient_light_energy = 1.0;
- float ambient_sky_contribution = 1.0;
- RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG;
- Color ao_color;
-
- /// Tonemap
-
- RS::EnvironmentToneMapper tone_mapper;
- float exposure = 1.0;
- float white = 1.0;
- bool auto_exposure = false;
- float min_luminance = 0.2;
- float max_luminance = 8.0;
- float auto_exp_speed = 0.2;
- float auto_exp_scale = 0.5;
- uint64_t auto_exposure_version = 0;
-
- // Fog
- bool fog_enabled = false;
- Color fog_light_color = Color(0.5, 0.6, 0.7);
- float fog_light_energy = 1.0;
- float fog_sun_scatter = 0.0;
- float fog_density = 0.001;
- float fog_height = 0.0;
- float fog_height_density = 0.0; //can be negative to invert effect
- float fog_aerial_perspective = 0.0;
-
- /// Volumetric Fog
- ///
- bool volumetric_fog_enabled = false;
- float volumetric_fog_density = 0.01;
- Color volumetric_fog_light = Color(0, 0, 0);
- float volumetric_fog_light_energy = 0.0;
- float volumetric_fog_length = 64.0;
- float volumetric_fog_detail_spread = 2.0;
- RS::EnvVolumetricFogShadowFilter volumetric_fog_shadow_filter = RS::ENV_VOLUMETRIC_FOG_SHADOW_FILTER_LOW;
- float volumetric_fog_gi_inject = 0.0;
-
- /// Glow
-
- bool glow_enabled = false;
- Vector<float> glow_levels;
- float glow_intensity = 0.8;
- float glow_strength = 1.0;
- float glow_bloom = 0.0;
- float glow_mix = 0.01;
- RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT;
- float glow_hdr_bleed_threshold = 1.0;
- float glow_hdr_luminance_cap = 12.0;
- float glow_hdr_bleed_scale = 2.0;
-
- /// SSAO
-
- bool ssao_enabled = false;
- float ssao_radius = 1.0;
- float ssao_intensity = 2.0;
- float ssao_power = 1.5;
- float ssao_detail = 0.5;
- float ssao_horizon = 0.06;
- float ssao_sharpness = 0.98;
- float ssao_direct_light_affect = 0.0;
- float ssao_ao_channel_affect = 0.0;
-
- /// SSR
- ///
- bool ssr_enabled = false;
- int ssr_max_steps = 64;
- float ssr_fade_in = 0.15;
- float ssr_fade_out = 2.0;
- float ssr_depth_tolerance = 0.2;
-
- /// SDFGI
- bool sdfgi_enabled = false;
- RS::EnvironmentSDFGICascades sdfgi_cascades;
- float sdfgi_min_cell_size = 0.2;
- bool sdfgi_use_occlusion = false;
- bool sdfgi_use_multibounce = false;
- bool sdfgi_read_sky_light = false;
- float sdfgi_energy = 1.0;
- float sdfgi_normal_bias = 1.1;
- float sdfgi_probe_bias = 1.1;
- RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_DISABLED;
-
- /// Adjustments
-
- bool adjustments_enabled = false;
- float adjustments_brightness = 1.0f;
- float adjustments_contrast = 1.0f;
- float adjustments_saturation = 1.0f;
- bool use_1d_color_correction = false;
- RID color_correction = RID();
- };
-
RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
bool ssao_half_size = false;
bool ssao_using_half_size = false;
@@ -800,9 +334,7 @@ private:
bool glow_high_quality = false;
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGNESS_QUALITY_LOW;
- static uint64_t auto_exposure_counter;
-
- mutable RID_Owner<Environment> environment_owner;
+ mutable RID_Owner<RendererSceneEnvironmentRD, true> environment_owner;
/* CAMERA EFFECTS */
@@ -828,21 +360,16 @@ private:
float sss_scale = 0.05;
float sss_depth_scale = 0.01;
- mutable RID_Owner<CameraEffects> camera_effects_owner;
+ mutable RID_Owner<CameraEffects, true> camera_effects_owner;
/* RENDER BUFFERS */
ClusterBuilderSharedDataRD cluster_builder_shared;
ClusterBuilderRD *current_cluster_builder = nullptr;
- struct SDFGI;
struct VolumetricFog;
struct RenderBuffers {
- enum {
- MAX_GIPROBES = 8
- };
-
RenderBufferData *data = nullptr;
int width = 0, height = 0;
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
@@ -857,7 +384,7 @@ private:
RID depth_texture; //main depth texture
RID gi_uniform_set;
- SDFGI *sdfgi = nullptr;
+ RendererSceneGIRD::SDFGI *sdfgi = nullptr;
VolumetricFog *volumetric_fog = nullptr;
ClusterBuilderRD *cluster_builder = nullptr;
@@ -899,408 +426,14 @@ private:
RID blur_radius[2];
} ssr;
- RID giprobe_textures[MAX_GIPROBES];
- RID giprobe_buffer;
-
RID ambient_buffer;
RID reflection_buffer;
bool using_half_size_gi = false;
- struct GI {
- RID full_buffer;
- RID full_dispatch;
- RID full_mask;
- } gi;
- };
-
- RID default_giprobe_buffer;
-
- /* SDFGI */
-
- struct SDFGI {
- enum {
- MAX_CASCADES = 8,
- CASCADE_SIZE = 128,
- PROBE_DIVISOR = 16,
- ANISOTROPY_SIZE = 6,
- MAX_DYNAMIC_LIGHTS = 128,
- MAX_STATIC_LIGHTS = 1024,
- LIGHTPROBE_OCT_SIZE = 6,
- SH_SIZE = 16
- };
-
- struct Cascade {
- struct UBO {
- float offset[3];
- float to_cell;
- int32_t probe_offset[3];
- uint32_t pad;
- };
-
- //cascade blocks are full-size for volume (128^3), half size for albedo/emission
- RID sdf_tex;
- RID light_tex;
- RID light_aniso_0_tex;
- RID light_aniso_1_tex;
-
- RID light_data;
- RID light_aniso_0_data;
- RID light_aniso_1_data;
-
- struct SolidCell { // this struct is unused, but remains as reference for size
- uint32_t position;
- uint32_t albedo;
- uint32_t static_light;
- uint32_t static_light_aniso;
- };
-
- RID solid_cell_dispatch_buffer; //buffer for indirect compute dispatch
- RID solid_cell_buffer;
-
- RID lightprobe_history_tex;
- RID lightprobe_average_tex;
-
- float cell_size;
- Vector3i position;
-
- static const Vector3i DIRTY_ALL;
- Vector3i dirty_regions; //(0,0,0 is not dirty, negative is refresh from the end, DIRTY_ALL is refresh all.
-
- RID sdf_store_uniform_set;
- RID sdf_direct_light_uniform_set;
- RID scroll_uniform_set;
- RID scroll_occlusion_uniform_set;
- RID integrate_uniform_set;
- RID lights_buffer;
-
- bool all_dynamic_lights_dirty = true;
- };
-
- //used for rendering (voxelization)
- RID render_albedo;
- RID render_emission;
- RID render_emission_aniso;
- RID render_occlusion[8];
- RID render_geom_facing;
-
- RID render_sdf[2];
- RID render_sdf_half[2];
-
- //used for ping pong processing in cascades
- RID sdf_initialize_uniform_set;
- RID sdf_initialize_half_uniform_set;
- RID jump_flood_uniform_set[2];
- RID jump_flood_half_uniform_set[2];
- RID sdf_upscale_uniform_set;
- int upscale_jfa_uniform_set_index;
- RID occlusion_uniform_set;
-
- uint32_t cascade_size = 128;
-
- LocalVector<Cascade> cascades;
-
- RID lightprobe_texture;
- RID lightprobe_data;
- RID occlusion_texture;
- RID occlusion_data;
- RID ambient_texture; //integrates with volumetric fog
-
- RID lightprobe_history_scroll; //used for scrolling lightprobes
- RID lightprobe_average_scroll; //used for scrolling lightprobes
-
- uint32_t history_size = 0;
- float solid_cell_ratio = 0;
- uint32_t solid_cell_count = 0;
-
- RS::EnvironmentSDFGICascades cascade_mode;
- float min_cell_size = 0;
- uint32_t probe_axis_count = 0; //amount of probes per axis, this is an odd number because it encloses endpoints
-
- RID debug_uniform_set;
- RID debug_probes_uniform_set;
- RID cascades_ubo;
-
- bool uses_occlusion = false;
- bool uses_multibounce = false;
- bool reads_sky = false;
- float energy = 1.0;
- float normal_bias = 1.1;
- float probe_bias = 1.1;
- RS::EnvironmentSDFGIYScale y_scale_mode = RS::ENV_SDFGI_Y_SCALE_DISABLED;
-
- float y_mult = 1.0;
-
- uint32_t render_pass = 0;
+ RendererSceneGIRD::RenderBuffersGI gi;
};
- RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16;
- RS::EnvironmentSDFGIFramesToConverge sdfgi_frames_to_converge = RS::ENV_SDFGI_CONVERGE_IN_10_FRAMES;
- RS::EnvironmentSDFGIFramesToUpdateLight sdfgi_frames_to_update_light = RS::ENV_SDFGI_UPDATE_LIGHT_IN_4_FRAMES;
-
- float sdfgi_solid_cell_ratio = 0.25;
- Vector3 sdfgi_debug_probe_pos;
- Vector3 sdfgi_debug_probe_dir;
- bool sdfgi_debug_probe_enabled = false;
- Vector3i sdfgi_debug_probe_index;
-
- struct SDGIShader {
- enum SDFGIPreprocessShaderVersion {
- PRE_PROCESS_SCROLL,
- PRE_PROCESS_SCROLL_OCCLUSION,
- PRE_PROCESS_JUMP_FLOOD_INITIALIZE,
- PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF,
- PRE_PROCESS_JUMP_FLOOD,
- PRE_PROCESS_JUMP_FLOOD_OPTIMIZED,
- PRE_PROCESS_JUMP_FLOOD_UPSCALE,
- PRE_PROCESS_OCCLUSION,
- PRE_PROCESS_STORE,
- PRE_PROCESS_MAX
- };
-
- struct PreprocessPushConstant {
- int32_t scroll[3];
- int32_t grid_size;
-
- int32_t probe_offset[3];
- int32_t step_size;
-
- int32_t half_size;
- uint32_t occlusion_index;
- int32_t cascade;
- uint32_t pad;
- };
-
- SdfgiPreprocessShaderRD preprocess;
- RID preprocess_shader;
- RID preprocess_pipeline[PRE_PROCESS_MAX];
-
- struct DebugPushConstant {
- float grid_size[3];
- uint32_t max_cascades;
-
- int32_t screen_size[2];
- uint32_t use_occlusion;
- float y_mult;
-
- float cam_extent[3];
- uint32_t probe_axis_size;
-
- float cam_transform[16];
- };
-
- SdfgiDebugShaderRD debug;
- RID debug_shader;
- RID debug_shader_version;
- RID debug_pipeline;
-
- enum ProbeDebugMode {
- PROBE_DEBUG_PROBES,
- PROBE_DEBUG_VISIBILITY,
- PROBE_DEBUG_MAX
- };
-
- struct DebugProbesPushConstant {
- float projection[16];
-
- uint32_t band_power;
- uint32_t sections_in_band;
- uint32_t band_mask;
- float section_arc;
-
- float grid_size[3];
- uint32_t cascade;
-
- uint32_t pad;
- float y_mult;
- int32_t probe_debug_index;
- int32_t probe_axis_size;
- };
-
- SdfgiDebugProbesShaderRD debug_probes;
- RID debug_probes_shader;
- RID debug_probes_shader_version;
-
- PipelineCacheRD debug_probes_pipeline[PROBE_DEBUG_MAX];
-
- struct Light {
- float color[3];
- float energy;
-
- float direction[3];
- uint32_t has_shadow;
-
- float position[3];
- float attenuation;
-
- uint32_t type;
- float spot_angle;
- float spot_attenuation;
- float radius;
-
- float shadow_color[4];
- };
-
- struct DirectLightPushConstant {
- float grid_size[3];
- uint32_t max_cascades;
-
- uint32_t cascade;
- uint32_t light_count;
- uint32_t process_offset;
- uint32_t process_increment;
-
- int32_t probe_axis_size;
- uint32_t multibounce;
- float y_mult;
- uint32_t pad;
- };
-
- enum {
- DIRECT_LIGHT_MODE_STATIC,
- DIRECT_LIGHT_MODE_DYNAMIC,
- DIRECT_LIGHT_MODE_MAX
- };
- SdfgiDirectLightShaderRD direct_light;
- RID direct_light_shader;
- RID direct_light_pipeline[DIRECT_LIGHT_MODE_MAX];
-
- enum {
- INTEGRATE_MODE_PROCESS,
- INTEGRATE_MODE_STORE,
- INTEGRATE_MODE_SCROLL,
- INTEGRATE_MODE_SCROLL_STORE,
- INTEGRATE_MODE_MAX
- };
- struct IntegratePushConstant {
- enum {
- SKY_MODE_DISABLED,
- SKY_MODE_COLOR,
- SKY_MODE_SKY,
- };
-
- float grid_size[3];
- uint32_t max_cascades;
-
- uint32_t probe_axis_size;
- uint32_t cascade;
- uint32_t history_index;
- uint32_t history_size;
-
- uint32_t ray_count;
- float ray_bias;
- int32_t image_size[2];
-
- int32_t world_offset[3];
- uint32_t sky_mode;
-
- int32_t scroll[3];
- float sky_energy;
-
- float sky_color[3];
- float y_mult;
-
- uint32_t store_ambient_texture;
- uint32_t pad[3];
- };
-
- SdfgiIntegrateShaderRD integrate;
- RID integrate_shader;
- RID integrate_pipeline[INTEGRATE_MODE_MAX];
-
- RID integrate_default_sky_uniform_set;
-
- } sdfgi_shader;
-
- void _sdfgi_erase(RenderBuffers *rb);
- int _sdfgi_get_pending_region_data(RID p_render_buffers, int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const;
- void _sdfgi_update_cascades(RID p_render_buffers);
-
/* GI */
-
- struct GI {
- struct SDFGIData {
- float grid_size[3];
- uint32_t max_cascades;
-
- uint32_t use_occlusion;
- int32_t probe_axis_size;
- float probe_to_uvw;
- float normal_bias;
-
- float lightprobe_tex_pixel_size[3];
- float energy;
-
- float lightprobe_uv_offset[3];
- float y_mult;
-
- float occlusion_clamp[3];
- uint32_t pad3;
-
- float occlusion_renormalize[3];
- uint32_t pad4;
-
- float cascade_probe_size[3];
- uint32_t pad5;
-
- struct ProbeCascadeData {
- float position[3]; //offset of (0,0,0) in world coordinates
- float to_probe; // 1/bounds * grid_size
- int32_t probe_world_offset[3];
- float to_cell; // 1/bounds * grid_size
- };
-
- ProbeCascadeData cascades[SDFGI::MAX_CASCADES];
- };
-
- struct GIProbeData {
- float xform[16];
- float bounds[3];
- float dynamic_range;
-
- float bias;
- float normal_bias;
- uint32_t blend_ambient;
- uint32_t texture_slot;
-
- float anisotropy_strength;
- float ao;
- float ao_size;
- uint32_t mipmaps;
- };
-
- struct PushConstant {
- int32_t screen_size[2];
- float z_near;
- float z_far;
-
- float proj_info[4];
- float ao_color[3];
- uint32_t max_giprobes;
-
- uint32_t high_quality_vct;
- uint32_t orthogonal;
- uint32_t pad[2];
-
- float cam_rotation[12];
- };
-
- RID sdfgi_ubo;
- enum Mode {
- MODE_GIPROBE,
- MODE_SDFGI,
- MODE_COMBINED,
- MODE_HALF_RES_GIPROBE,
- MODE_HALF_RES_SDFGI,
- MODE_HALF_RES_COMBINED,
- MODE_MAX
- };
-
- bool half_resolution = false;
- GiShaderRD shader;
- RID shader_version;
- RID pipelines[MODE_MAX];
- } gi;
-
bool screen_space_roughness_limiter = false;
float screen_space_roughness_limiter_amount = 0.25;
float screen_space_roughness_limiter_limit = 0.18;
@@ -1313,7 +446,6 @@ private:
void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas);
void _render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection);
- void _sdfgi_debug_draw(RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform);
/* Cluster */
@@ -1349,8 +481,8 @@ private:
float color[3];
float attenuation;
- float cone_attenuation;
- float cone_angle;
+ float inv_spot_attenuation;
+ float cos_spot_angle;
float specular_amount;
uint32_t shadow_enabled;
@@ -1450,17 +582,52 @@ private:
uint32_t omni_light_count = 0;
uint32_t spot_light_count = 0;
- RID *lights_instances;
- Rect2i *lights_shadow_rect_cache;
- uint32_t lights_shadow_rect_cache_count = 0;
-
DirectionalLightData *directional_lights;
uint32_t max_directional_lights;
RID directional_light_buffer;
} cluster;
+ struct RenderState {
+ RID render_buffers;
+ Transform cam_transform;
+ CameraMatrix cam_projection;
+ bool cam_ortogonal = false;
+ const PagedArray<GeometryInstance *> *instances = nullptr;
+ const PagedArray<RID> *lights = nullptr;
+ const PagedArray<RID> *reflection_probes = nullptr;
+ const PagedArray<RID> *gi_probes = nullptr;
+ const PagedArray<RID> *decals = nullptr;
+ const PagedArray<RID> *lightmaps = nullptr;
+ RID environment;
+ RID camera_effects;
+ RID shadow_atlas;
+ RID reflection_atlas;
+ RID reflection_probe;
+ int reflection_probe_pass = 0;
+ float screen_lod_threshold = 0.0;
+
+ const RenderShadowData *render_shadows = nullptr;
+ int render_shadow_count = 0;
+ const RenderSDFGIData *render_sdfgi_regions = nullptr;
+ int render_sdfgi_region_count = 0;
+ const RenderSDFGIUpdateData *sdfgi_update_data = nullptr;
+
+ uint32_t directional_light_count = 0;
+ uint32_t gi_probe_count = 0;
+
+ LocalVector<int> cube_shadows;
+ LocalVector<int> shadows;
+ LocalVector<int> directional_shadows;
+
+ bool depth_prepass_used;
+ } render_state;
+
struct VolumetricFog {
+ enum {
+ MAX_TEMPORAL_FRAMES = 16
+ };
+
uint32_t width = 0;
uint32_t height = 0;
uint32_t depth = 0;
@@ -1469,6 +636,8 @@ private:
float spread;
RID light_density_map;
+ RID prev_light_density_map;
+
RID fog_map;
RID uniform_set;
RID uniform_set2;
@@ -1476,6 +645,8 @@ private:
RID sky_uniform_set;
int last_shadow_filter = -1;
+
+ Transform prev_cam_transform;
};
enum {
@@ -1511,10 +682,13 @@ private:
uint32_t cluster_shift;
uint32_t cluster_width;
- uint32_t cluster_pad[3];
uint32_t max_cluster_element_count_div_32;
+ uint32_t use_temporal_reprojection;
+ uint32_t temporal_frame;
+ float temporal_blend;
float cam_rotation[12];
+ float to_prev_view[16];
};
VolumetricFogShaderRD shader;
@@ -1527,9 +701,7 @@ private:
uint32_t volumetric_fog_depth = 128;
uint32_t volumetric_fog_size = 128;
- bool volumetric_fog_filter_active = false;
- uint32_t volumetric_fog_directional_shadow_shrink = 512;
- uint32_t volumetric_fog_positional_shadow_shrink = 512;
+ bool volumetric_fog_filter_active = true;
void _volumetric_fog_erase(RenderBuffers *rb);
void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_gi_probe_count);
@@ -1539,14 +711,18 @@ private:
uint64_t scene_pass = 0;
uint64_t shadow_atlas_realloc_tolerance_msec = 500;
+ /* !BAS! is this used anywhere?
struct SDFGICosineNeighbour {
uint32_t neighbour;
float weight;
};
+ */
uint32_t max_cluster_elements = 512;
bool low_end = false;
+ void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true);
+
public:
virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance) = 0;
virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0;
@@ -1589,28 +765,26 @@ public:
/* SDFGI UPDATE */
- int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; }
virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position);
virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const;
virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const;
virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const;
- virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const Vector<RID> &p_directional_lights, const RID *p_positional_light_instances, uint32_t p_positional_light_count);
RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
+
/* SKY API */
- RID sky_create();
+ virtual RID sky_allocate();
+ virtual void sky_initialize(RID p_rid);
+
void sky_set_radiance_size(RID p_sky, int p_radiance_size);
void sky_set_mode(RID p_sky, RS::SkyMode p_mode);
void sky_set_material(RID p_sky, RID p_material);
Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size);
- RID sky_get_radiance_texture_rd(RID p_sky) const;
- RID sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const;
- RID sky_get_material(RID p_sky) const;
-
/* ENVIRONMENT API */
- RID environment_create();
+ virtual RID environment_allocate();
+ virtual void environment_initialize(RID p_rid);
void environment_set_background(RID p_env, RS::EnvironmentBG p_bg);
void environment_set_sky(RID p_env, RID p_sky);
@@ -1651,12 +825,10 @@ public:
float environment_get_fog_height_density(RID p_env) const;
float environment_get_fog_aerial_perspective(RID p_env) const;
- void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter);
+ void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount);
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth);
virtual void environment_set_volumetric_fog_filter_active(bool p_enable);
- virtual void environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size);
- virtual void environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size);
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);
void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
@@ -1667,7 +839,7 @@ public:
bool environment_is_ssr_enabled(RID p_env) const;
bool environment_is_sdfgi_enabled(RID p_env) const;
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
+ virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count);
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames);
virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update);
@@ -1680,7 +852,8 @@ public:
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size);
- virtual RID camera_effects_create();
+ virtual RID camera_effects_allocate();
+ virtual void camera_effects_initialize(RID p_rid);
virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter);
virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape);
@@ -1916,57 +1089,16 @@ public:
return li->transform;
}
+ /* gi light probes */
+
RID gi_probe_instance_create(RID p_base);
void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
bool gi_probe_needs_update(RID p_probe) const;
void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects);
+ void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi.gi_probe_quality = p_quality; }
- void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; }
+ /* render buffers */
- _FORCE_INLINE_ uint32_t gi_probe_instance_get_slot(RID p_probe) {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
- return gi_probe->slot;
- }
- _FORCE_INLINE_ RID gi_probe_instance_get_base_probe(RID p_probe) {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
- return gi_probe->probe;
- }
- _FORCE_INLINE_ Transform gi_probe_instance_get_transform_to_cell(RID p_probe) {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
- return storage->gi_probe_get_to_cell_xform(gi_probe->probe) * gi_probe->transform.affine_inverse();
- }
-
- _FORCE_INLINE_ RID gi_probe_instance_get_texture(RID p_probe) {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
- return gi_probe->texture;
- }
-
- _FORCE_INLINE_ void gi_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND(!gi_probe);
- gi_probe->render_index = p_render_index;
- }
-
- _FORCE_INLINE_ uint32_t gi_probe_instance_get_render_index(RID p_instance) {
- GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND_V(!gi_probe, 0);
-
- return gi_probe->render_index;
- }
- /*
- _FORCE_INLINE_ void gi_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) {
- GIProbeInstance *g_probe = gi_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND(!g_probe);
- g_probe->last_pass = p_render_pass;
- }
-
- _FORCE_INLINE_ uint32_t gi_probe_instance_get_render_pass(RID p_instance) {
- GIProbeInstance *g_probe = gi_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND_V(!g_probe, 0);
-
- return g_probe->last_pass;
- }
-*/
RID render_buffers_create();
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding);
void gi_set_use_half_resolution(bool p_enable);
@@ -1997,15 +1129,10 @@ public:
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
- void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
-
- void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
+ void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr);
void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances);
- void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result);
-
void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances);
virtual void set_scene_pass(uint64_t p_pass) {
@@ -2055,7 +1182,7 @@ public:
return debug_draw;
}
- virtual void set_time(double p_time, double p_step);
+ void set_time(double p_time, double p_step);
RID get_reflection_probe_buffer();
RID get_omni_light_buffer();
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
new file mode 100644
index 0000000000..769335ac16
--- /dev/null
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -0,0 +1,1491 @@
+/*************************************************************************/
+/* renderer_scene_sky_rd.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "renderer_scene_sky_rd.h"
+#include "core/config/project_settings.h"
+#include "renderer_scene_render_rd.h"
+#include "servers/rendering/rendering_server_default.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// SKY SHADER
+
+void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+
+ if (code == String()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompilerRD::GeneratedCode gen_code;
+ ShaderCompilerRD::IdentifierActions actions;
+
+ uses_time = false;
+ uses_half_res = false;
+ uses_quarter_res = false;
+ uses_position = false;
+ uses_light = false;
+
+ actions.render_mode_flags["use_half_res_pass"] = &uses_half_res;
+ actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res;
+
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+ actions.usage_flag_pointers["POSITION"] = &uses_position;
+ actions.usage_flag_pointers["LIGHT0_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_SIZE"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_SIZE"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_SIZE"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_SIZE"] = &uses_light;
+
+ actions.uniforms = &uniforms;
+
+ // !BAS! Contemplate making `SkyShader sky` accessible from this struct or even part of this struct.
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+
+ Error err = scene_singleton->sky.sky_shader.compiler.compile(RS::SHADER_SKY, code, &actions, path, gen_code);
+
+ ERR_FAIL_COND(err != OK);
+
+ if (version.is_null()) {
+ version = scene_singleton->sky.sky_shader.shader.version_create();
+ }
+
+#if 0
+ print_line("**compiling shader:");
+ print_line("**defines:\n");
+ for (int i = 0; i < gen_code.defines.size(); i++) {
+ print_line(gen_code.defines[i]);
+ }
+ print_line("\n**uniforms:\n" + gen_code.uniforms);
+ // print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
+ // print_line("\n**vertex_code:\n" + gen_code.vertex);
+ print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
+ print_line("\n**fragment_code:\n" + gen_code.fragment);
+ print_line("\n**light_code:\n" + gen_code.light);
+#endif
+
+ scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines);
+ ERR_FAIL_COND(!scene_singleton->sky.sky_shader.shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ //update pipelines
+
+ for (int i = 0; i < SKY_VERSION_MAX; i++) {
+ RD::PipelineDepthStencilState depth_stencil_state;
+ depth_stencil_state.enable_depth_test = true;
+ depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
+
+ RID shader_variant = scene_singleton->sky.sky_shader.shader.version_get_shader(version, i);
+ pipelines[i].setup(shader_variant, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0);
+ }
+
+ valid = true;
+}
+
+void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+ if (!p_texture.is_valid()) {
+ default_texture_params.erase(p_name);
+ } else {
+ default_texture_params[p_name] = p_texture;
+ }
+}
+
+void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+ Map<int, StringName> order;
+
+ for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
+ if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ if (E->get().texture_order >= 0) {
+ order[E->get().texture_order + 100000] = E->key();
+ } else {
+ order[E->get().order] = E->key();
+ }
+ }
+
+ for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
+ pi.name = E->get();
+ p_param_list->push_back(pi);
+ }
+}
+
+void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+ for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
+ if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ RendererStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E->get());
+ p.info.name = E->key(); //supply name
+ p.index = E->get().instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint);
+ p_param_list->push_back(p);
+ }
+}
+
+bool RendererSceneSkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool RendererSceneSkyRD::SkyShaderData::is_animated() const {
+ return false;
+}
+
+bool RendererSceneSkyRD::SkyShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant RendererSceneSkyRD::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.hint);
+ }
+ return Variant();
+}
+
+RS::ShaderNativeSourceCode RendererSceneSkyRD::SkyShaderData::get_native_source_code() const {
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+
+ return scene_singleton->sky.sky_shader.shader.version_get_native_source_code(version);
+}
+
+RendererSceneSkyRD::SkyShaderData::SkyShaderData() {
+ valid = false;
+}
+
+RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ ERR_FAIL_COND(!scene_singleton);
+ //pipeline variants will clear themselves if shader is gone
+ if (version.is_valid()) {
+ scene_singleton->sky.sky_shader.shader.version_free(version);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Sky material
+
+void RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+
+ uniform_set_updated = true;
+
+ if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
+ p_uniform_dirty = true;
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ uniform_buffer = RID();
+ }
+
+ ubo_data.resize(shader_data->ubo_size);
+ if (ubo_data.size()) {
+ uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
+ memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
+ }
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ //check whether buffer changed
+ if (p_uniform_dirty && ubo_data.size()) {
+ update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
+ RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
+ }
+
+ uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
+
+ if ((uint32_t)texture_cache.size() != tex_uniform_count) {
+ texture_cache.resize(tex_uniform_count);
+ p_textures_dirty = true;
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ if (p_textures_dirty && tex_uniform_count) {
+ update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
+ }
+
+ if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) {
+ // This material does not require an uniform set, so don't create it.
+ return;
+ }
+
+ if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ //no reason to update uniform set, only UBO (or nothing) was needed to update
+ return;
+ }
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ if (shader_data->ubo_size) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.ids.push_back(uniform_buffer);
+ uniforms.push_back(u);
+ }
+
+ const RID *textures = texture_cache.ptrw();
+ for (uint32_t i = 0; i < tex_uniform_count; i++) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1 + i;
+ u.ids.push_back(textures[i]);
+ uniforms.push_back(u);
+ }
+ }
+
+ uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL);
+}
+
+RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() {
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->free(uniform_set);
+ }
+
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ReflectionData
+
+void RendererSceneSkyRD::ReflectionData::clear_reflection_data() {
+ layers.clear();
+ radiance_base_cubemap = RID();
+ if (downsampled_radiance_cubemap.is_valid()) {
+ RD::get_singleton()->free(downsampled_radiance_cubemap);
+ }
+ downsampled_radiance_cubemap = RID();
+ downsampled_layer.mipmaps.clear();
+ coefficient_buffer = RID();
+}
+
+void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers) {
+ //recreate radiance and all data
+
+ int mipmaps = p_mipmaps;
+ uint32_t w = p_size, h = p_size;
+
+ if (p_use_array) {
+ int num_layers = p_low_quality ? 8 : p_roughness_layers;
+
+ for (int i = 0; i < num_layers; i++) {
+ ReflectionData::Layer layer;
+ uint32_t mmw = w;
+ uint32_t mmh = h;
+ layer.mipmaps.resize(mipmaps);
+ layer.views.resize(mipmaps);
+ for (int j = 0; j < mipmaps; j++) {
+ ReflectionData::Layer::Mipmap &mm = layer.mipmaps.write[j];
+ mm.size.width = mmw;
+ mm.size.height = mmh;
+ for (int k = 0; k < 6; k++) {
+ mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6 + k, j);
+ Vector<RID> fbtex;
+ fbtex.push_back(mm.views[k]);
+ mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
+ }
+
+ layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6, j, RD::TEXTURE_SLICE_CUBEMAP);
+
+ mmw = MAX(1, mmw >> 1);
+ mmh = MAX(1, mmh >> 1);
+ }
+
+ layers.push_back(layer);
+ }
+
+ } else {
+ mipmaps = p_low_quality ? 8 : mipmaps;
+ //regular cubemap, lower quality (aliasing, less memory)
+ ReflectionData::Layer layer;
+ uint32_t mmw = w;
+ uint32_t mmh = h;
+ layer.mipmaps.resize(mipmaps);
+ layer.views.resize(mipmaps);
+ for (int j = 0; j < mipmaps; j++) {
+ ReflectionData::Layer::Mipmap &mm = layer.mipmaps.write[j];
+ mm.size.width = mmw;
+ mm.size.height = mmh;
+ for (int k = 0; k < 6; k++) {
+ mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + k, j);
+ Vector<RID> fbtex;
+ fbtex.push_back(mm.views[k]);
+ mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
+ }
+
+ layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, j, RD::TEXTURE_SLICE_CUBEMAP);
+
+ mmw = MAX(1, mmw >> 1);
+ mmh = MAX(1, mmh >> 1);
+ }
+
+ layers.push_back(layer);
+ }
+
+ radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, RD::TEXTURE_SLICE_CUBEMAP);
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = 64; // Always 64x64
+ tf.height = 64;
+ tf.texture_type = RD::TEXTURE_TYPE_CUBE;
+ tf.array_layers = 6;
+ tf.mipmaps = 7;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ {
+ uint32_t mmw = 64;
+ uint32_t mmh = 64;
+ downsampled_layer.mipmaps.resize(7);
+ for (int j = 0; j < downsampled_layer.mipmaps.size(); j++) {
+ ReflectionData::DownsampleLayer::Mipmap &mm = downsampled_layer.mipmaps.write[j];
+ mm.size.width = mmw;
+ mm.size.height = mmh;
+ mm.view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), downsampled_radiance_cubemap, 0, j, RD::TEXTURE_SLICE_CUBEMAP);
+
+ mmw = MAX(1, mmw >> 1);
+ mmh = MAX(1, mmh >> 1);
+ }
+ }
+}
+
+void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays) {
+ p_storage->get_effects()->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size);
+
+ for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
+ p_storage->get_effects()->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size);
+ }
+
+ Vector<RID> views;
+ if (p_use_arrays) {
+ for (int i = 1; i < layers.size(); i++) {
+ views.push_back(layers[i].views[0]);
+ }
+ } else {
+ for (int i = 1; i < layers[0].views.size(); i++) {
+ views.push_back(layers[0].views[i]);
+ }
+ }
+
+ p_storage->get_effects()->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays);
+}
+
+void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) {
+ if (p_use_arrays) {
+ //render directly to the layers
+ p_storage->get_effects()->cubemap_roughness(radiance_base_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x);
+ } else {
+ p_storage->get_effects()->cubemap_roughness(
+ layers[0].views[p_base_layer - 1],
+ layers[0].views[p_base_layer],
+ p_cube_side,
+ p_sky_ggx_samples_quality,
+ float(p_base_layer) / (layers[0].mipmaps.size() - 1.0),
+ layers[0].mipmaps[p_base_layer].size.x);
+ }
+}
+
+void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end) {
+ for (int i = p_start; i < p_end; i++) {
+ for (int j = 0; j < layers[i].views.size() - 1; j++) {
+ RID view = layers[i].views[j];
+ RID texture = layers[i].views[j + 1];
+ Size2i size = layers[i].mipmaps[j + 1].size;
+ p_storage->get_effects()->cubemap_downsample(view, texture, size);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RendererSceneSkyRD::Sky
+
+void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) {
+ if (radiance.is_valid()) {
+ RD::get_singleton()->free(radiance);
+ radiance = RID();
+ }
+ reflection.clear_reflection_data();
+
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ 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()) {
+ p_storage->free(material);
+ }
+}
+
+RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd) {
+ 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;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 0;
+ if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) {
+ u.ids.push_back(radiance);
+ } else {
+ u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ }
+ uniforms.push_back(u);
+ }
+ {
+ 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) {
+ u.ids.push_back(reflection.layers[0].views[1]);
+ } else {
+ u.ids.push_back(half_res_pass);
+ }
+ } else {
+ if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
+ u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ } else {
+ u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ 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) {
+ u.ids.push_back(reflection.layers[0].views[2]);
+ } else {
+ u.ids.push_back(quarter_res_pass);
+ }
+ } else {
+ if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
+ u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ } else {
+ u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ }
+ }
+ 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];
+}
+
+bool RendererSceneSkyRD::Sky::set_radiance_size(int p_radiance_size) {
+ ERR_FAIL_COND_V(p_radiance_size < 32 || p_radiance_size > 2048, false);
+ if (radiance_size == p_radiance_size) {
+ return false;
+ }
+ radiance_size = p_radiance_size;
+
+ if (mode == RS::SKY_MODE_REALTIME && radiance_size != 256) {
+ WARN_PRINT("Realtime Skies can only use a radiance size of 256. Radiance size will be set to 256 internally.");
+ radiance_size = 256;
+ }
+
+ if (radiance.is_valid()) {
+ RD::get_singleton()->free(radiance);
+ radiance = RID();
+ }
+ reflection.clear_reflection_data();
+
+ return true;
+}
+
+bool RendererSceneSkyRD::Sky::set_mode(RS::SkyMode p_mode) {
+ if (mode == p_mode) {
+ return false;
+ }
+
+ mode = p_mode;
+
+ if (mode == RS::SKY_MODE_REALTIME && radiance_size != 256) {
+ WARN_PRINT("Realtime Skies can only use a radiance size of 256. Radiance size will be set to 256 internally.");
+ set_radiance_size(256);
+ }
+
+ if (radiance.is_valid()) {
+ RD::get_singleton()->free(radiance);
+ radiance = RID();
+ }
+ reflection.clear_reflection_data();
+
+ return true;
+}
+
+bool RendererSceneSkyRD::Sky::set_material(RID p_material) {
+ if (material == p_material) {
+ return false;
+ }
+
+ material = p_material;
+ return true;
+}
+
+Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage, float p_energy, int p_roughness_layers, const Size2i &p_size) {
+ if (radiance.is_valid()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ tf.width = p_size.width;
+ tf.height = p_size.height;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+
+ RID rad_tex = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ p_storage->get_effects()->copy_cubemap_to_panorama(radiance, rad_tex, p_size, p_roughness_layers, reflection.layers.size() > 1);
+ Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rad_tex, 0);
+ RD::get_singleton()->free(rad_tex);
+
+ Ref<Image> img;
+ img.instance();
+ img->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data);
+ for (int i = 0; i < p_size.width; i++) {
+ for (int j = 0; j < p_size.height; j++) {
+ Color c = img->get_pixel(i, j);
+ c.r *= p_energy;
+ c.g *= p_energy;
+ c.b *= p_energy;
+ img->set_pixel(i, j, c);
+ }
+ }
+ return img;
+ }
+
+ return Ref<Image>();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RendererSceneSkyRD
+
+RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
+ SkyShaderData *shader_data = memnew(SkyShaderData);
+ return shader_data;
+}
+
+RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
+ // !BAS! Why isn't _create_sky_shader_func not just static too?
+ return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func();
+};
+
+RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
+ SkyMaterialData *material_data = memnew(SkyMaterialData);
+ material_data->shader_data = p_shader;
+ material_data->last_frame = false;
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
+RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+ // !BAS! same here, we could just make _create_sky_material_func static?
+ return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
+};
+
+RendererSceneSkyRD::RendererSceneSkyRD() {
+ roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers");
+ sky_ggx_samples_quality = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples");
+ sky_use_cubemap_array = GLOBAL_GET("rendering/reflections/sky_reflections/texture_array_reflections");
+}
+
+void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
+ storage = p_storage;
+
+ {
+ // Start with the directional lights for the sky
+ sky_scene_state.max_directional_lights = 4;
+ uint32_t directional_light_buffer_size = sky_scene_state.max_directional_lights * sizeof(SkyDirectionalLightData);
+ sky_scene_state.directional_lights = memnew_arr(SkyDirectionalLightData, sky_scene_state.max_directional_lights);
+ sky_scene_state.last_frame_directional_lights = memnew_arr(SkyDirectionalLightData, sky_scene_state.max_directional_lights);
+ sky_scene_state.last_frame_directional_light_count = sky_scene_state.max_directional_lights + 1;
+ sky_scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size);
+
+ String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_scene_state.max_directional_lights) + "\n";
+
+ // Initialize sky
+ Vector<String> sky_modes;
+ sky_modes.push_back(""); // Full size
+ sky_modes.push_back("\n#define USE_HALF_RES_PASS\n"); // Half Res
+ sky_modes.push_back("\n#define USE_QUARTER_RES_PASS\n"); // Quarter res
+ sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n"); // Cubemap
+ sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_HALF_RES_PASS\n"); // Half Res Cubemap
+ sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_QUARTER_RES_PASS\n"); // Quarter res Cubemap
+ sky_shader.shader.initialize(sky_modes, defines);
+ }
+
+ // register our shader funds
+ storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
+ storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
+
+ {
+ ShaderCompilerRD::DefaultIdentifierActions actions;
+
+ actions.renames["COLOR"] = "color";
+ actions.renames["ALPHA"] = "alpha";
+ actions.renames["EYEDIR"] = "cube_normal";
+ actions.renames["POSITION"] = "params.position_multiplier.xyz";
+ actions.renames["SKY_COORDS"] = "panorama_coords";
+ actions.renames["SCREEN_UV"] = "uv";
+ actions.renames["TIME"] = "params.time";
+ actions.renames["HALF_RES_COLOR"] = "half_res_color";
+ actions.renames["QUARTER_RES_COLOR"] = "quarter_res_color";
+ actions.renames["RADIANCE"] = "radiance";
+ actions.renames["FOG"] = "custom_fog";
+ actions.renames["LIGHT0_ENABLED"] = "directional_lights.data[0].enabled";
+ actions.renames["LIGHT0_DIRECTION"] = "directional_lights.data[0].direction_energy.xyz";
+ actions.renames["LIGHT0_ENERGY"] = "directional_lights.data[0].direction_energy.w";
+ actions.renames["LIGHT0_COLOR"] = "directional_lights.data[0].color_size.xyz";
+ actions.renames["LIGHT0_SIZE"] = "directional_lights.data[0].color_size.w";
+ actions.renames["LIGHT1_ENABLED"] = "directional_lights.data[1].enabled";
+ actions.renames["LIGHT1_DIRECTION"] = "directional_lights.data[1].direction_energy.xyz";
+ actions.renames["LIGHT1_ENERGY"] = "directional_lights.data[1].direction_energy.w";
+ actions.renames["LIGHT1_COLOR"] = "directional_lights.data[1].color_size.xyz";
+ actions.renames["LIGHT1_SIZE"] = "directional_lights.data[1].color_size.w";
+ actions.renames["LIGHT2_ENABLED"] = "directional_lights.data[2].enabled";
+ actions.renames["LIGHT2_DIRECTION"] = "directional_lights.data[2].direction_energy.xyz";
+ actions.renames["LIGHT2_ENERGY"] = "directional_lights.data[2].direction_energy.w";
+ actions.renames["LIGHT2_COLOR"] = "directional_lights.data[2].color_size.xyz";
+ actions.renames["LIGHT2_SIZE"] = "directional_lights.data[2].color_size.w";
+ actions.renames["LIGHT3_ENABLED"] = "directional_lights.data[3].enabled";
+ actions.renames["LIGHT3_DIRECTION"] = "directional_lights.data[3].direction_energy.xyz";
+ actions.renames["LIGHT3_ENERGY"] = "directional_lights.data[3].direction_energy.w";
+ actions.renames["LIGHT3_COLOR"] = "directional_lights.data[3].color_size.xyz";
+ actions.renames["LIGHT3_SIZE"] = "directional_lights.data[3].color_size.w";
+ actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS";
+ actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS";
+ actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS";
+ actions.custom_samplers["RADIANCE"] = "material_samplers[3]";
+ actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n";
+ actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n";
+ actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n";
+
+ actions.sampler_array_name = "material_samplers";
+ actions.base_texture_binding_index = 1;
+ actions.texture_layout_set = 1;
+ 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_variables.data";
+
+ sky_shader.compiler.initialize(actions);
+ }
+
+ {
+ // default material and shader for sky shader
+ sky_shader.default_shader = storage->shader_allocate();
+ storage->shader_initialize(sky_shader.default_shader);
+
+ storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void fragment() { COLOR = vec3(0.0); } \n");
+
+ sky_shader.default_material = storage->material_allocate();
+ storage->material_initialize(sky_shader.default_material);
+
+ storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
+
+ SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
+ sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND);
+
+ sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO));
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 0;
+ u.ids.resize(12);
+ RID *ids_ptr = u.ids.ptrw();
+ ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 1;
+ u.ids.push_back(storage->global_variables_get_storage_buffer());
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.ids.push_back(sky_scene_state.uniform_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 3;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.ids.push_back(sky_scene_state.directional_light_buffer);
+ uniforms.push_back(u);
+ }
+
+ sky_scene_state.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_UNIFORMS);
+ }
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ RID vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ u.ids.push_back(vfog);
+ uniforms.push_back(u);
+ }
+
+ sky_scene_state.default_fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_FOG);
+ }
+
+ {
+ // Need defaults for using fog with clear color
+ sky_scene_state.fog_shader = storage->shader_allocate();
+ storage->shader_initialize(sky_scene_state.fog_shader);
+
+ storage->shader_set_code(sky_scene_state.fog_shader, "shader_type sky; uniform vec4 clear_color; void fragment() { COLOR = clear_color.rgb; } \n");
+ sky_scene_state.fog_material = storage->material_allocate();
+ storage->material_initialize(sky_scene_state.fog_material);
+
+ storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader);
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 0;
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1;
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2;
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ uniforms.push_back(u);
+ }
+
+ sky_scene_state.fog_only_texture_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_TEXTURES);
+ }
+}
+
+void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+ ERR_FAIL_COND(!p_env); // I guess without an environment we also can't have a sky...
+
+ SkyMaterialData *material = nullptr;
+ Sky *sky = get_sky(p_env->sky);
+
+ RID sky_material;
+
+ SkyShaderData *shader_data = nullptr;
+
+ RS::EnvironmentBG background = p_env->background;
+
+ if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
+ // !BAS! Possibly silently fail here, we now get error spam when you select sky as the background but haven't setup the sky yet.
+ ERR_FAIL_COND(!sky);
+ sky_material = sky_get_material(p_env->sky);
+
+ if (sky_material.is_valid()) {
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (!material) {
+ sky_material = sky_shader.default_material;
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ }
+
+ ERR_FAIL_COND(!material);
+
+ shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+ }
+
+ if (sky) {
+ // 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);
+ }
+ }
+
+ // 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()) {
+ invalidate_sky(sky);
+ update_dirty_skys();
+ }
+
+ if (shader_data->uses_time && p_scene_render->time - sky->prev_time > 0.00001) {
+ sky->prev_time = p_scene_render->time;
+ sky->reflection.dirty = true;
+ RenderingServerDefault::redraw_request();
+ }
+
+ if (material != sky->prev_material) {
+ sky->prev_material = material;
+ sky->reflection.dirty = true;
+ }
+
+ if (material->uniform_set_updated) {
+ material->uniform_set_updated = false;
+ sky->reflection.dirty = true;
+ }
+
+ if (!p_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) {
+ sky->prev_position = p_transform.origin;
+ sky->reflection.dirty = true;
+ }
+
+ if (shader_data->uses_light) {
+ // Check whether the directional_light_buffer changes
+ bool light_data_dirty = false;
+
+ if (sky_scene_state.ubo.directional_light_count != sky_scene_state.last_frame_directional_light_count) {
+ light_data_dirty = true;
+ for (uint32_t i = sky_scene_state.ubo.directional_light_count; i < sky_scene_state.max_directional_lights; i++) {
+ sky_scene_state.directional_lights[i].enabled = false;
+ }
+ }
+ if (!light_data_dirty) {
+ for (uint32_t i = 0; i < sky_scene_state.ubo.directional_light_count; i++) {
+ if (sky_scene_state.directional_lights[i].direction[0] != sky_scene_state.last_frame_directional_lights[i].direction[0] ||
+ sky_scene_state.directional_lights[i].direction[1] != sky_scene_state.last_frame_directional_lights[i].direction[1] ||
+ sky_scene_state.directional_lights[i].direction[2] != sky_scene_state.last_frame_directional_lights[i].direction[2] ||
+ sky_scene_state.directional_lights[i].energy != sky_scene_state.last_frame_directional_lights[i].energy ||
+ sky_scene_state.directional_lights[i].color[0] != sky_scene_state.last_frame_directional_lights[i].color[0] ||
+ sky_scene_state.directional_lights[i].color[1] != sky_scene_state.last_frame_directional_lights[i].color[1] ||
+ sky_scene_state.directional_lights[i].color[2] != sky_scene_state.last_frame_directional_lights[i].color[2] ||
+ sky_scene_state.directional_lights[i].enabled != sky_scene_state.last_frame_directional_lights[i].enabled ||
+ sky_scene_state.directional_lights[i].size != sky_scene_state.last_frame_directional_lights[i].size) {
+ light_data_dirty = true;
+ break;
+ }
+ }
+ }
+
+ if (light_data_dirty) {
+ RD::get_singleton()->buffer_update(sky_scene_state.directional_light_buffer, 0, sizeof(SkyDirectionalLightData) * sky_scene_state.max_directional_lights, sky_scene_state.directional_lights);
+
+ SkyDirectionalLightData *temp = sky_scene_state.last_frame_directional_lights;
+ sky_scene_state.last_frame_directional_lights = sky_scene_state.directional_lights;
+ sky_scene_state.directional_lights = temp;
+ sky_scene_state.last_frame_directional_light_count = sky_scene_state.ubo.directional_light_count;
+ sky->reflection.dirty = true;
+ }
+ }
+ }
+
+ //setup fog variables
+ sky_scene_state.ubo.volumetric_fog_enabled = false;
+ if (p_render_buffers.is_valid()) {
+ if (p_scene_render->render_buffers_has_volumetric_fog(p_render_buffers)) {
+ sky_scene_state.ubo.volumetric_fog_enabled = true;
+
+ float fog_end = p_scene_render->render_buffers_get_volumetric_fog_end(p_render_buffers);
+ if (fog_end > 0.0) {
+ sky_scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;
+ } else {
+ sky_scene_state.ubo.volumetric_fog_inv_length = 1.0;
+ }
+
+ float fog_detail_spread = p_scene_render->render_buffers_get_volumetric_fog_detail_spread(p_render_buffers); //reverse lookup
+ if (fog_detail_spread > 0.0) {
+ sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread;
+ } else {
+ sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0;
+ }
+ }
+
+ RID fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers);
+
+ if (fog_uniform_set != RID()) {
+ sky_scene_state.fog_uniform_set = fog_uniform_set;
+ } else {
+ sky_scene_state.fog_uniform_set = sky_scene_state.default_fog_uniform_set;
+ }
+ }
+
+ sky_scene_state.ubo.z_far = p_projection.get_z_far();
+ sky_scene_state.ubo.fog_enabled = p_env->fog_enabled;
+ sky_scene_state.ubo.fog_density = p_env->fog_density;
+ sky_scene_state.ubo.fog_aerial_perspective = p_env->fog_aerial_perspective;
+ Color fog_color = p_env->fog_light_color.to_linear();
+ float fog_energy = p_env->fog_light_energy;
+ sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
+ sky_scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy;
+ sky_scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy;
+ sky_scene_state.ubo.fog_sun_scatter = p_env->fog_sun_scatter;
+
+ RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);
+}
+
+void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform &p_transform, double p_time) {
+ ERR_FAIL_COND(!p_env);
+
+ Sky *sky = get_sky(p_env->sky);
+ ERR_FAIL_COND(!sky);
+
+ RID sky_material = sky_get_material(p_env->sky);
+
+ SkyMaterialData *material = nullptr;
+
+ if (sky_material.is_valid()) {
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (!material) {
+ sky_material = sky_shader.default_material;
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ }
+
+ ERR_FAIL_COND(!material);
+
+ SkyShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ float multiplier = p_env->bg_energy;
+
+ bool update_single_frame = sky->mode == RS::SKY_MODE_REALTIME || sky->mode == RS::SKY_MODE_QUALITY;
+ RS::SkyMode sky_mode = sky->mode;
+
+ if (sky_mode == RS::SKY_MODE_AUTOMATIC) {
+ if (shader_data->uses_time || shader_data->uses_position) {
+ update_single_frame = true;
+ sky_mode = RS::SKY_MODE_REALTIME;
+ } else if (shader_data->uses_light || shader_data->ubo_size > 0) {
+ update_single_frame = false;
+ sky_mode = RS::SKY_MODE_INCREMENTAL;
+ } else {
+ update_single_frame = true;
+ sky_mode = RS::SKY_MODE_QUALITY;
+ }
+ }
+
+ if (sky->processing_layer == 0 && sky_mode == RS::SKY_MODE_INCREMENTAL) {
+ // On the first frame after creating sky, rebuild in single frame
+ update_single_frame = true;
+ sky_mode = RS::SKY_MODE_QUALITY;
+ }
+
+ int max_processing_layer = sky_use_cubemap_array ? sky->reflection.layers.size() : sky->reflection.layers[0].mipmaps.size();
+
+ // Update radiance cubemap
+ if (sky->reflection.dirty && (sky->processing_layer >= max_processing_layer || update_single_frame)) {
+ static const Vector3 view_normals[6] = {
+ Vector3(+1, 0, 0),
+ Vector3(-1, 0, 0),
+ Vector3(0, +1, 0),
+ Vector3(0, -1, 0),
+ Vector3(0, 0, +1),
+ Vector3(0, 0, -1)
+ };
+ static const Vector3 view_up[6] = {
+ Vector3(0, -1, 0),
+ Vector3(0, -1, 0),
+ Vector3(0, 0, +1),
+ Vector3(0, 0, -1),
+ Vector3(0, -1, 0),
+ Vector3(0, -1, 0)
+ };
+
+ CameraMatrix cm;
+ cm.set_perspective(90, 1, 0.01, 10.0);
+ CameraMatrix correction;
+ correction.set_depth_correction(true);
+ cm = correction * cm;
+
+ if (shader_data->uses_quarter_res) {
+ PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES];
+
+ Vector<Color> clear_colors;
+ clear_colors.push_back(Color(0.0, 0.0, 0.0));
+ RD::DrawListID cubemap_draw_list;
+
+ for (int i = 0; i < 6; i++) {
+ Transform local_view;
+ local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
+
+ 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);
+ storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+ }
+
+ if (shader_data->uses_half_res) {
+ PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES];
+
+ Vector<Color> clear_colors;
+ clear_colors.push_back(Color(0.0, 0.0, 0.0));
+ RD::DrawListID cubemap_draw_list;
+
+ for (int i = 0; i < 6; i++) {
+ Transform local_view;
+ local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
+
+ 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);
+ storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+ }
+
+ RD::DrawListID cubemap_draw_list;
+ PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP];
+
+ for (int i = 0; i < 6; i++) {
+ Transform local_view;
+ local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
+
+ cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ if (sky_mode == RS::SKY_MODE_REALTIME) {
+ sky->reflection.create_reflection_fast_filter(storage, sky_use_cubemap_array);
+ if (sky_use_cubemap_array) {
+ sky->reflection.update_reflection_mipmaps(storage, 0, sky->reflection.layers.size());
+ }
+ } else {
+ if (update_single_frame) {
+ for (int i = 1; i < max_processing_layer; i++) {
+ sky->reflection.create_reflection_importance_sample(storage, sky_use_cubemap_array, 10, i, sky_ggx_samples_quality);
+ }
+ if (sky_use_cubemap_array) {
+ sky->reflection.update_reflection_mipmaps(storage, 0, sky->reflection.layers.size());
+ }
+ } else {
+ if (sky_use_cubemap_array) {
+ // Multi-Frame so just update the first array level
+ sky->reflection.update_reflection_mipmaps(storage, 0, 1);
+ }
+ }
+ sky->processing_layer = 1;
+ }
+
+ sky->reflection.dirty = false;
+
+ } else {
+ if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) {
+ sky->reflection.create_reflection_importance_sample(storage, sky_use_cubemap_array, 10, sky->processing_layer, sky_ggx_samples_quality);
+
+ if (sky_use_cubemap_array) {
+ sky->reflection.update_reflection_mipmaps(storage, sky->processing_layer, sky->processing_layer + 1);
+ }
+
+ sky->processing_layer++;
+ }
+ }
+}
+
+void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, const CameraMatrix &p_projection, const Transform &p_transform, double p_time) {
+ ERR_FAIL_COND(!p_env);
+
+ Sky *sky = get_sky(p_env->sky);
+ ERR_FAIL_COND(!sky);
+
+ SkyMaterialData *material = nullptr;
+ RID sky_material;
+
+ RS::EnvironmentBG background = p_env->background;
+
+ if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
+ ERR_FAIL_COND(!sky);
+ sky_material = sky_get_material(p_env->sky);
+
+ if (sky_material.is_valid()) {
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (!material) {
+ sky_material = sky_shader.default_material;
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ }
+ }
+
+ if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
+ sky_material = sky_scene_state.fog_material;
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ }
+
+ ERR_FAIL_COND(!material);
+
+ SkyShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ Basis sky_transform = p_env->sky_orientation;
+ sky_transform.invert();
+
+ float multiplier = p_env->bg_energy;
+ float custom_fov = p_env->sky_custom_fov;
+ // Camera
+ CameraMatrix camera;
+
+ if (custom_fov) {
+ float near_plane = p_projection.get_z_near();
+ float far_plane = p_projection.get_z_far();
+ float aspect = p_projection.get_aspect();
+
+ camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
+
+ } else {
+ camera = p_projection;
+ }
+
+ sky_transform = p_transform.basis * sky_transform;
+
+ if (shader_data->uses_quarter_res) {
+ PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_QUARTER_RES];
+
+ RID texture_uniform_set = sky->get_textures(storage, 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);
+ storage->get_effects()->render_sky(draw_list, p_time, sky->quarter_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ if (shader_data->uses_half_res) {
+ PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_HALF_RES];
+
+ RID texture_uniform_set = sky->get_textures(storage, 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);
+ storage->get_effects()->render_sky(draw_list, p_time, sky->half_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_BACKGROUND];
+
+ RID texture_uniform_set;
+ if (sky) {
+ texture_uniform_set = sky->get_textures(storage, 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);
+ storage->get_effects()->render_sky(draw_list, p_time, p_fb, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+}
+
+void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {
+ if (!p_sky->dirty) {
+ p_sky->dirty = true;
+ p_sky->dirty_list = dirty_sky_list;
+ dirty_sky_list = p_sky;
+ }
+}
+
+void RendererSceneSkyRD::update_dirty_skys() {
+ Sky *sky = dirty_sky_list;
+
+ while (sky) {
+ bool texture_set_dirty = false;
+ //update sky configuration if texture is missing
+
+ if (sky->radiance.is_null()) {
+ int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1;
+
+ uint32_t w = sky->radiance_size, h = sky->radiance_size;
+ int layers = roughness_layers;
+ if (sky->mode == RS::SKY_MODE_REALTIME) {
+ layers = 8;
+ if (roughness_layers != 8) {
+ WARN_PRINT("When using REALTIME skies, roughness_layers should be set to 8 in the project settings for best quality reflections");
+ }
+ }
+
+ if (sky_use_cubemap_array) {
+ //array (higher quality, 6 times more memory)
+ RD::TextureFormat tf;
+ tf.array_layers = layers * 6;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+ tf.mipmaps = mipmaps;
+ tf.width = w;
+ tf.height = h;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ sky->reflection.update_reflection_data(sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers);
+
+ } else {
+ //regular cubemap, lower quality (aliasing, less memory)
+ RD::TextureFormat tf;
+ tf.array_layers = 6;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_CUBE;
+ tf.mipmaps = MIN(mipmaps, layers);
+ tf.width = w;
+ tf.height = h;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ sky->reflection.update_reflection_data(sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers);
+ }
+ 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 = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ 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 = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ 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;
+ sky->processing_layer = 0;
+
+ Sky *next = sky->dirty_list;
+ sky->dirty_list = nullptr;
+ sky->dirty = false;
+ sky = next;
+ }
+
+ dirty_sky_list = nullptr;
+}
+
+RID RendererSceneSkyRD::sky_get_material(RID p_sky) const {
+ Sky *sky = get_sky(p_sky);
+ ERR_FAIL_COND_V(!sky, RID());
+
+ return sky->material;
+}
+
+RID RendererSceneSkyRD::allocate_sky_rid() {
+ return sky_owner.allocate_rid();
+}
+
+void RendererSceneSkyRD::initialize_sky_rid(RID p_rid) {
+ sky_owner.initialize_rid(p_rid, Sky());
+}
+
+RendererSceneSkyRD::Sky *RendererSceneSkyRD::get_sky(RID p_sky) const {
+ return sky_owner.getornull(p_sky);
+}
+
+void RendererSceneSkyRD::free_sky(RID p_sky) {
+ Sky *sky = get_sky(p_sky);
+ ERR_FAIL_COND(!sky);
+
+ sky->free(storage);
+ sky_owner.free(p_sky);
+}
+
+void RendererSceneSkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
+ Sky *sky = get_sky(p_sky);
+ ERR_FAIL_COND(!sky);
+
+ if (sky->set_radiance_size(p_radiance_size)) {
+ invalidate_sky(sky);
+ }
+}
+
+void RendererSceneSkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) {
+ Sky *sky = get_sky(p_sky);
+ ERR_FAIL_COND(!sky);
+
+ if (sky->set_mode(p_mode)) {
+ invalidate_sky(sky);
+ }
+}
+
+void RendererSceneSkyRD::sky_set_material(RID p_sky, RID p_material) {
+ Sky *sky = get_sky(p_sky);
+ ERR_FAIL_COND(!sky);
+
+ if (sky->set_material(p_material)) {
+ invalidate_sky(sky);
+ }
+}
+
+Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) {
+ Sky *sky = get_sky(p_sky);
+ ERR_FAIL_COND_V(!sky, Ref<Image>());
+
+ update_dirty_skys();
+
+ return sky->bake_panorama(storage, p_energy, p_bake_irradiance ? roughness_layers : 0, p_size);
+}
+
+RID RendererSceneSkyRD::sky_get_radiance_texture_rd(RID p_sky) const {
+ Sky *sky = get_sky(p_sky);
+ ERR_FAIL_COND_V(!sky, RID());
+
+ return sky->radiance;
+}
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
new file mode 100644
index 0000000000..73390a586b
--- /dev/null
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -0,0 +1,292 @@
+/*************************************************************************/
+/* renderer_scene_sky_rd.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RENDERING_SERVER_SCENE_SKY_RD_H
+#define RENDERING_SERVER_SCENE_SKY_RD_H
+
+#include "core/templates/rid_owner.h"
+#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
+#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/renderer_rd/shaders/sky.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering/rendering_device.h"
+
+// Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
+class RendererSceneRenderRD;
+
+class RendererSceneSkyRD {
+private:
+ RendererStorageRD *storage;
+
+public:
+ enum SkySet {
+ SKY_SET_UNIFORMS,
+ SKY_SET_MATERIAL,
+ SKY_SET_TEXTURES,
+ SKY_SET_FOG,
+ SKY_SET_MAX
+ };
+
+ enum SkyTextureSetVersion {
+ SKY_TEXTURE_SET_BACKGROUND,
+ SKY_TEXTURE_SET_HALF_RES,
+ SKY_TEXTURE_SET_QUARTER_RES,
+ SKY_TEXTURE_SET_CUBEMAP,
+ SKY_TEXTURE_SET_CUBEMAP_HALF_RES,
+ SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES,
+ SKY_TEXTURE_SET_MAX
+ };
+
+ enum SkyVersion {
+ SKY_VERSION_BACKGROUND,
+ SKY_VERSION_HALF_RES,
+ SKY_VERSION_QUARTER_RES,
+ SKY_VERSION_CUBEMAP,
+ SKY_VERSION_CUBEMAP_HALF_RES,
+ SKY_VERSION_CUBEMAP_QUARTER_RES,
+ SKY_VERSION_MAX
+ };
+
+ // Skys need less info from Directional Lights than the normal shaders
+ struct SkyDirectionalLightData {
+ float direction[3];
+ float energy;
+ float color[3];
+ float size;
+ uint32_t enabled;
+ uint32_t pad[3];
+ };
+
+ struct SkySceneState {
+ struct UBO {
+ uint32_t volumetric_fog_enabled;
+ float volumetric_fog_inv_length;
+ float volumetric_fog_detail_spread;
+
+ float fog_aerial_perspective;
+
+ float fog_light_color[3];
+ float fog_sun_scatter;
+
+ uint32_t fog_enabled;
+ float fog_density;
+
+ float z_far;
+ uint32_t directional_light_count;
+ };
+
+ UBO ubo;
+
+ SkyDirectionalLightData *directional_lights;
+ SkyDirectionalLightData *last_frame_directional_lights;
+ uint32_t max_directional_lights;
+ uint32_t last_frame_directional_light_count;
+ RID directional_light_buffer;
+ RID uniform_set;
+ RID uniform_buffer;
+ RID fog_uniform_set;
+ RID default_fog_uniform_set;
+
+ RID fog_shader;
+ RID fog_material;
+ RID fog_only_texture_uniform_set;
+ } sky_scene_state;
+
+ struct ReflectionData {
+ struct Layer {
+ struct Mipmap {
+ RID framebuffers[6];
+ RID views[6];
+ Size2i size;
+ };
+ Vector<Mipmap> mipmaps; //per-face view
+ Vector<RID> views; // per-cubemap view
+ };
+
+ struct DownsampleLayer {
+ struct Mipmap {
+ RID view;
+ Size2i size;
+ };
+ Vector<Mipmap> mipmaps;
+ };
+
+ RID radiance_base_cubemap; //cubemap for first layer, first cubemap
+ RID downsampled_radiance_cubemap;
+ DownsampleLayer downsampled_layer;
+ RID coefficient_buffer;
+
+ bool dirty = true;
+
+ Vector<Layer> layers;
+
+ void clear_reflection_data();
+ void update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers);
+ void create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays);
+ void create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality);
+ void update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end);
+ };
+
+ struct SkyShaderData : public RendererStorageRD::ShaderData {
+ bool valid;
+ RID version;
+
+ PipelineCacheRD pipelines[SKY_VERSION_MAX];
+ Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size;
+
+ String path;
+ String code;
+ Map<StringName, RID> default_texture_params;
+
+ bool uses_time;
+ bool uses_position;
+ bool uses_half_res;
+ bool uses_quarter_res;
+ bool uses_light;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+ SkyShaderData();
+ virtual ~SkyShaderData();
+ };
+
+ /* Sky shader */
+
+ struct SkyShader {
+ SkyShaderRD shader;
+ ShaderCompilerRD compiler;
+
+ RID default_shader;
+ RID default_material;
+ RID default_shader_rd;
+ } sky_shader;
+
+ struct SkyMaterialData : public RendererStorageRD::MaterialData {
+ uint64_t last_frame;
+ SkyShaderData *shader_data;
+ RID uniform_buffer;
+ RID uniform_set;
+ Vector<RID> texture_cache;
+ Vector<uint8_t> ubo_data;
+ bool uniform_set_updated;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual ~SkyMaterialData();
+ };
+
+ 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;
+ RID uniform_buffer;
+
+ int radiance_size = 256;
+
+ RS::SkyMode mode = RS::SKY_MODE_AUTOMATIC;
+
+ ReflectionData reflection;
+ bool dirty = false;
+ int processing_layer = 0;
+ Sky *dirty_list = nullptr;
+
+ //State to track when radiance cubemap needs updating
+ SkyMaterialData *prev_material;
+ Vector3 prev_position;
+ float prev_time;
+
+ void free(RendererStorageRD *p_storage);
+
+ RID get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd);
+ bool set_radiance_size(int p_radiance_size);
+ bool set_mode(RS::SkyMode p_mode);
+ bool set_material(RID p_material);
+ Ref<Image> bake_panorama(RendererStorageRD *p_storage, float p_energy, int p_roughness_layers, const Size2i &p_size);
+ };
+
+ uint32_t sky_ggx_samples_quality;
+ bool sky_use_cubemap_array;
+ Sky *dirty_sky_list = nullptr;
+ mutable RID_Owner<Sky, true> sky_owner;
+ int roughness_layers;
+
+ RendererStorageRD::ShaderData *_create_sky_shader_func();
+ static RendererStorageRD::ShaderData *_create_sky_shader_funcs();
+
+ RendererStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
+ static RendererStorageRD::MaterialData *_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader);
+
+ RendererSceneSkyRD();
+
+ void init(RendererStorageRD *p_storage);
+
+ void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
+ void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform &p_transform, double p_time);
+ void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, const CameraMatrix &p_projection, const Transform &p_transform, double p_time);
+
+ void invalidate_sky(Sky *p_sky);
+ void update_dirty_skys();
+
+ RID sky_get_material(RID p_sky) const;
+
+ RID allocate_sky_rid();
+ void initialize_sky_rid(RID p_rid);
+ Sky *get_sky(RID p_sky) const;
+ void free_sky(RID p_sky);
+ void sky_set_radiance_size(RID p_sky, int p_radiance_size);
+ void sky_set_mode(RID p_sky, RS::SkyMode p_mode);
+ void sky_set_material(RID p_sky, RID p_material);
+ Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size);
+
+ RID sky_get_radiance_texture_rd(RID p_sky) const;
+};
+
+#endif /* RENDERING_SERVER_SCENE_SKY_RD_H */
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 6d4343e183..ba5ace8f31 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -36,6 +36,10 @@
#include "renderer_compositor_rd.h"
#include "servers/rendering/shader_language.h"
+bool RendererStorageRD::can_create_resources_async() const {
+ return true;
+}
+
Ref<Image> RendererStorageRD::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) {
Ref<Image> image = p_image->duplicate();
@@ -535,9 +539,13 @@ Ref<Image> RendererStorageRD::_validate_texture_format(const Ref<Image> &p_image
return image;
}
-RID RendererStorageRD::texture_2d_create(const Ref<Image> &p_image) {
- ERR_FAIL_COND_V(p_image.is_null(), RID());
- ERR_FAIL_COND_V(p_image->is_empty(), RID());
+RID RendererStorageRD::texture_allocate() {
+ return texture_owner.allocate_rid();
+}
+
+void RendererStorageRD::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) {
+ ERR_FAIL_COND(p_image.is_null());
+ ERR_FAIL_COND(p_image->is_empty());
TextureToRDFormat ret_format;
Ref<Image> image = _validate_texture_format(p_image, ret_format);
@@ -585,13 +593,13 @@ RID RendererStorageRD::texture_2d_create(const Ref<Image> &p_image) {
Vector<Vector<uint8_t>> data_slices;
data_slices.push_back(data);
texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
- ERR_FAIL_COND_V(texture.rd_texture.is_null(), RID());
+ ERR_FAIL_COND(texture.rd_texture.is_null());
if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
rd_view.format_override = texture.rd_format_srgb;
texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
if (texture.rd_texture_srgb.is_null()) {
RD::get_singleton()->free(texture.rd_texture);
- ERR_FAIL_COND_V(texture.rd_texture_srgb.is_null(), RID());
+ ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
}
}
@@ -602,14 +610,14 @@ RID RendererStorageRD::texture_2d_create(const Ref<Image> &p_image) {
texture.rd_view = rd_view;
texture.is_proxy = false;
- return texture_owner.make_rid(texture);
+ texture_owner.initialize_rid(p_texture, texture);
}
-RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
- ERR_FAIL_COND_V(p_layers.size() == 0, RID());
+void RendererStorageRD::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
+ ERR_FAIL_COND(p_layers.size() == 0);
- ERR_FAIL_COND_V(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6, RID());
- ERR_FAIL_COND_V(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0), RID());
+ ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6);
+ ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0));
TextureToRDFormat ret_format;
Vector<Ref<Image>> images;
@@ -620,7 +628,7 @@ RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_lay
Image::Format valid_format = Image::FORMAT_MAX;
for (int i = 0; i < p_layers.size(); i++) {
- ERR_FAIL_COND_V(p_layers[i]->is_empty(), RID());
+ ERR_FAIL_COND(p_layers[i]->is_empty());
if (i == 0) {
valid_width = p_layers[i]->get_width();
@@ -628,10 +636,10 @@ RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_lay
valid_format = p_layers[i]->get_format();
valid_mipmaps = p_layers[i]->has_mipmaps();
} else {
- ERR_FAIL_COND_V(p_layers[i]->get_width() != valid_width, RID());
- ERR_FAIL_COND_V(p_layers[i]->get_height() != valid_height, RID());
- ERR_FAIL_COND_V(p_layers[i]->get_format() != valid_format, RID());
- ERR_FAIL_COND_V(p_layers[i]->has_mipmaps() != valid_mipmaps, RID());
+ ERR_FAIL_COND(p_layers[i]->get_width() != valid_width);
+ ERR_FAIL_COND(p_layers[i]->get_height() != valid_height);
+ ERR_FAIL_COND(p_layers[i]->get_format() != valid_format);
+ ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps);
}
images.push_back(_validate_texture_format(p_layers[i], ret_format));
@@ -695,13 +703,13 @@ RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_lay
data_slices.push_back(data);
}
texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
- ERR_FAIL_COND_V(texture.rd_texture.is_null(), RID());
+ ERR_FAIL_COND(texture.rd_texture.is_null());
if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
rd_view.format_override = texture.rd_format_srgb;
texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
if (texture.rd_texture_srgb.is_null()) {
RD::get_singleton()->free(texture.rd_texture);
- ERR_FAIL_COND_V(texture.rd_texture_srgb.is_null(), RID());
+ ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
}
}
@@ -712,14 +720,14 @@ RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_lay
texture.rd_view = rd_view;
texture.is_proxy = false;
- return texture_owner.make_rid(texture);
+ texture_owner.initialize_rid(p_texture, texture);
}
-RID RendererStorageRD::texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) {
- ERR_FAIL_COND_V(p_data.size() == 0, RID());
+void RendererStorageRD::texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) {
+ ERR_FAIL_COND(p_data.size() == 0);
Image::Image3DValidateError verr = Image::validate_3d_image(p_format, p_width, p_height, p_depth, p_mipmaps, p_data);
if (verr != Image::VALIDATE_3D_OK) {
- ERR_FAIL_V_MSG(RID(), Image::get_3d_image_validation_error_text(verr));
+ ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr));
}
TextureToRDFormat ret_format;
@@ -811,13 +819,13 @@ RID RendererStorageRD::texture_3d_create(Image::Format p_format, int p_width, in
data_slices.push_back(all_data); //one slice
texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
- ERR_FAIL_COND_V(texture.rd_texture.is_null(), RID());
+ ERR_FAIL_COND(texture.rd_texture.is_null());
if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
rd_view.format_override = texture.rd_format_srgb;
texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
if (texture.rd_texture_srgb.is_null()) {
RD::get_singleton()->free(texture.rd_texture);
- ERR_FAIL_COND_V(texture.rd_texture_srgb.is_null(), RID());
+ ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
}
}
@@ -828,12 +836,12 @@ RID RendererStorageRD::texture_3d_create(Image::Format p_format, int p_width, in
texture.rd_view = rd_view;
texture.is_proxy = false;
- return texture_owner.make_rid(texture);
+ texture_owner.initialize_rid(p_texture, texture);
}
-RID RendererStorageRD::texture_proxy_create(RID p_base) {
+void RendererStorageRD::texture_proxy_initialize(RID p_texture, RID p_base) {
Texture *tex = texture_owner.getornull(p_base);
- ERR_FAIL_COND_V(!tex, RID());
+ ERR_FAIL_COND(!tex);
Texture proxy_tex = *tex;
proxy_tex.rd_view.format_override = tex->rd_format;
@@ -847,11 +855,9 @@ RID RendererStorageRD::texture_proxy_create(RID p_base) {
proxy_tex.is_proxy = true;
proxy_tex.proxies.clear();
- RID rid = texture_owner.make_rid(proxy_tex);
-
- tex->proxies.push_back(rid);
+ texture_owner.initialize_rid(p_texture, proxy_tex);
- return rid;
+ tex->proxies.push_back(p_texture);
}
void RendererStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) {
@@ -961,7 +967,7 @@ void RendererStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) {
}
//these two APIs can be used together or in combination with the others.
-RID RendererStorageRD::texture_2d_placeholder_create() {
+void RendererStorageRD::texture_2d_placeholder_initialize(RID p_texture) {
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
Ref<Image> image;
@@ -974,10 +980,10 @@ RID RendererStorageRD::texture_2d_placeholder_create() {
}
}
- return texture_2d_create(image);
+ texture_2d_initialize(p_texture, image);
}
-RID RendererStorageRD::texture_2d_layered_placeholder_create(RS::TextureLayeredType p_layered_type) {
+void RendererStorageRD::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) {
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
Ref<Image> image;
@@ -1000,10 +1006,10 @@ RID RendererStorageRD::texture_2d_layered_placeholder_create(RS::TextureLayeredT
}
}
- return texture_2d_layered_create(images, p_layered_type);
+ texture_2d_layered_initialize(p_texture, images, p_layered_type);
}
-RID RendererStorageRD::texture_3d_placeholder_create() {
+void RendererStorageRD::texture_3d_placeholder_initialize(RID p_texture) {
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
Ref<Image> image;
@@ -1022,7 +1028,7 @@ RID RendererStorageRD::texture_3d_placeholder_create() {
images.push_back(image);
}
- return texture_3d_create(Image::FORMAT_RGBA8, 4, 4, 4, false, images);
+ texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images);
}
Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
@@ -1223,8 +1229,11 @@ RendererStorageRD::CanvasTexture::~CanvasTexture() {
clear_sets();
}
-RID RendererStorageRD::canvas_texture_create() {
- return canvas_texture_owner.make_rid(memnew(CanvasTexture));
+RID RendererStorageRD::canvas_texture_allocate() {
+ return canvas_texture_owner.allocate_rid();
+}
+void RendererStorageRD::canvas_texture_initialize(RID p_rid) {
+ canvas_texture_owner.initialize_rid(p_rid, memnew(CanvasTexture));
}
void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
@@ -1365,12 +1374,15 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas
/* SHADER API */
-RID RendererStorageRD::shader_create() {
+RID RendererStorageRD::shader_allocate() {
+ return shader_owner.allocate_rid();
+}
+void RendererStorageRD::shader_initialize(RID p_rid) {
Shader shader;
shader.data = nullptr;
shader.type = SHADER_TYPE_MAX;
- return shader_owner.make_rid(shader);
+ shader_owner.initialize_rid(p_rid, shader);
}
void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
@@ -1510,7 +1522,10 @@ RS::ShaderNativeSourceCode RendererStorageRD::shader_get_native_source_code(RID
/* COMMON MATERIAL API */
-RID RendererStorageRD::material_create() {
+RID RendererStorageRD::material_allocate() {
+ return material_owner.allocate_rid();
+}
+void RendererStorageRD::material_initialize(RID p_rid) {
Material material;
material.data = nullptr;
material.shader = nullptr;
@@ -1520,12 +1535,8 @@ RID RendererStorageRD::material_create() {
material.uniform_dirty = false;
material.texture_dirty = false;
material.priority = 0;
- RID id = material_owner.make_rid(material);
- {
- Material *material_ptr = material_owner.getornull(id);
- material_ptr->self = id;
- }
- return id;
+ material.self = p_rid;
+ material_owner.initialize_rid(p_rid, material);
}
void RendererStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
@@ -2399,8 +2410,11 @@ void RendererStorageRD::_update_queued_materials() {
/* MESH API */
-RID RendererStorageRD::mesh_create() {
- return mesh_owner.make_rid(Mesh());
+RID RendererStorageRD::mesh_allocate() {
+ return mesh_owner.allocate_rid();
+}
+void RendererStorageRD::mesh_initialize(RID p_rid) {
+ mesh_owner.initialize_rid(p_rid, Mesh());
}
void RendererStorageRD::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) {
@@ -3098,7 +3112,7 @@ void RendererStorageRD::update_mesh_instances() {
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SkeletonShader::PushConstant));
//dispatch without barrier, so all is done at the same time
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.vertex_count, 1, 1, 64, 1, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.vertex_count, 1, 1);
}
mi->dirty = false;
@@ -3298,11 +3312,14 @@ void RendererStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surf
////////////////// MULTIMESH
-RID RendererStorageRD::multimesh_create() {
- return multimesh_owner.make_rid(MultiMesh());
+RID RendererStorageRD::multimesh_allocate() {
+ return multimesh_owner.allocate_rid();
+}
+void RendererStorageRD::multimesh_initialize(RID p_rid) {
+ multimesh_owner.initialize_rid(p_rid, MultiMesh());
}
-void RendererStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
+void RendererStorageRD::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
@@ -3849,8 +3866,11 @@ void RendererStorageRD::_update_dirty_multimeshes() {
/* PARTICLES */
-RID RendererStorageRD::particles_create() {
- return particles_owner.make_rid(Particles());
+RID RendererStorageRD::particles_allocate() {
+ return particles_owner.allocate_rid();
+}
+void RendererStorageRD::particles_initialize(RID p_rid) {
+ particles_owner.initialize_rid(p_rid, Particles());
}
void RendererStorageRD::particles_set_emitting(RID p_particles, bool p_emitting) {
@@ -4555,7 +4575,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_particles->amount, 1, 1, 64, 1, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_particles->amount, 1, 1);
RD::get_singleton()->compute_list_end();
}
@@ -4609,7 +4629,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1, 64, 1, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
RD::get_singleton()->compute_list_end();
@@ -4621,7 +4641,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1, 64, 1, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
RD::get_singleton()->compute_list_end();
}
@@ -4728,7 +4748,7 @@ void RendererStorageRD::update_particles() {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1, 64, 1, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
RD::get_singleton()->compute_list_end();
}
@@ -4984,8 +5004,11 @@ RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_f
/* PARTICLES COLLISION API */
-RID RendererStorageRD::particles_collision_create() {
- return particles_collision_owner.make_rid(ParticlesCollision());
+RID RendererStorageRD::particles_collision_allocate() {
+ return particles_collision_owner.allocate_rid();
+}
+void RendererStorageRD::particles_collision_initialize(RID p_rid) {
+ particles_collision_owner.initialize_rid(p_rid, ParticlesCollision());
}
RID RendererStorageRD::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
@@ -5098,6 +5121,7 @@ void RendererStorageRD::particles_collision_height_field_update(RID p_particles_
void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
ParticlesCollision *particles_collision = particles_collision_owner.getornull(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;
@@ -5164,8 +5188,11 @@ void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_
/* SKELETON API */
-RID RendererStorageRD::skeleton_create() {
- return skeleton_owner.make_rid(Skeleton());
+RID RendererStorageRD::skeleton_allocate() {
+ return skeleton_owner.allocate_rid();
+}
+void RendererStorageRD::skeleton_initialize(RID p_rid) {
+ skeleton_owner.initialize_rid(p_rid, Skeleton());
}
void RendererStorageRD::_skeleton_make_dirty(Skeleton *skeleton) {
@@ -5176,7 +5203,7 @@ void RendererStorageRD::_skeleton_make_dirty(Skeleton *skeleton) {
}
}
-void RendererStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
+void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND(!skeleton);
ERR_FAIL_COND(p_bones < 0);
@@ -5350,7 +5377,7 @@ void RendererStorageRD::_update_dirty_skeletons() {
/* LIGHT */
-RID RendererStorageRD::light_create(RS::LightType p_type) {
+void RendererStorageRD::_light_initialize(RID p_light, RS::LightType p_type) {
Light light;
light.type = p_type;
@@ -5371,10 +5398,31 @@ RID RendererStorageRD::light_create(RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
- light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 1.0;
+ light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1;
light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
- return light_owner.make_rid(light);
+ light_owner.initialize_rid(p_light, light);
+}
+
+RID RendererStorageRD::directional_light_allocate() {
+ return light_owner.allocate_rid();
+}
+void RendererStorageRD::directional_light_initialize(RID p_light) {
+ _light_initialize(p_light, RS::LIGHT_DIRECTIONAL);
+}
+
+RID RendererStorageRD::omni_light_allocate() {
+ return light_owner.allocate_rid();
+}
+void RendererStorageRD::omni_light_initialize(RID p_light) {
+ _light_initialize(p_light, RS::LIGHT_OMNI);
+}
+
+RID RendererStorageRD::spot_light_allocate() {
+ return light_owner.allocate_rid();
+}
+void RendererStorageRD::spot_light_initialize(RID p_light) {
+ _light_initialize(p_light, RS::LIGHT_SPOT);
}
void RendererStorageRD::light_set_color(RID p_light, const Color &p_color) {
@@ -5612,8 +5660,11 @@ AABB RendererStorageRD::light_get_aabb(RID p_light) const {
/* REFLECTION PROBE */
-RID RendererStorageRD::reflection_probe_create() {
- return reflection_probe_owner.make_rid(ReflectionProbe());
+RID RendererStorageRD::reflection_probe_allocate() {
+ return reflection_probe_owner.allocate_rid();
+}
+void RendererStorageRD::reflection_probe_initialize(RID p_reflection_probe) {
+ reflection_probe_owner.initialize_rid(p_reflection_probe, ReflectionProbe());
}
void RendererStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
@@ -5835,8 +5886,11 @@ float RendererStorageRD::reflection_probe_get_ambient_color_energy(RID p_probe)
return reflection_probe->ambient_color_energy;
}
-RID RendererStorageRD::decal_create() {
- return decal_owner.make_rid(Decal());
+RID RendererStorageRD::decal_allocate() {
+ return decal_owner.allocate_rid();
+}
+void RendererStorageRD::decal_initialize(RID p_decal) {
+ decal_owner.initialize_rid(p_decal, Decal());
}
void RendererStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
@@ -5923,11 +5977,14 @@ AABB RendererStorageRD::decal_get_aabb(RID p_decal) const {
return AABB(-decal->extents, decal->extents * 2.0);
}
-RID RendererStorageRD::gi_probe_create() {
- return gi_probe_owner.make_rid(GIProbe());
+RID RendererStorageRD::gi_probe_allocate() {
+ return gi_probe_owner.allocate_rid();
+}
+void RendererStorageRD::gi_probe_initialize(RID p_gi_probe) {
+ gi_probe_owner.initialize_rid(p_gi_probe, GIProbe());
}
-void RendererStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
+void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
@@ -6276,8 +6333,12 @@ RID RendererStorageRD::gi_probe_get_sdf_texture(RID p_gi_probe) {
/* LIGHTMAP API */
-RID RendererStorageRD::lightmap_create() {
- return lightmap_owner.make_rid(Lightmap());
+RID RendererStorageRD::lightmap_allocate() {
+ return lightmap_owner.allocate_rid();
+}
+
+void RendererStorageRD::lightmap_initialize(RID p_lightmap) {
+ lightmap_owner.initialize_rid(p_lightmap, Lightmap());
}
void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
@@ -6480,7 +6541,8 @@ void RendererStorageRD::_clear_render_target(RenderTarget *rt) {
void RendererStorageRD::_update_render_target(RenderTarget *rt) {
if (rt->texture.is_null()) {
//create a placeholder until updated
- rt->texture = texture_2d_placeholder_create();
+ rt->texture = texture_allocate();
+ texture_2d_placeholder_initialize(rt->texture);
Texture *tex = texture_owner.getornull(rt->texture);
tex->is_render_target = true;
}
@@ -6980,7 +7042,7 @@ void RendererStorageRD::render_target_sdf_process(RID p_render_target) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[1], 0); //fill [0]
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
/* Process */
@@ -6996,7 +7058,7 @@ void RendererStorageRD::render_target_sdf_process(RID p_render_target) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
push_constant.stride = stride;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
stride /= 2;
swap = !swap;
RD::get_singleton()->compute_list_add_barrier(compute_list);
@@ -7007,7 +7069,7 @@ void RendererStorageRD::render_target_sdf_process(RID p_render_target) {
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_STORE_SHRINK : RenderTargetSDF::SHADER_STORE]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
RD::get_singleton()->compute_list_end();
}
@@ -8217,13 +8279,13 @@ bool RendererStorageRD::free(RID p_rid) {
} else if (multimesh_owner.owns(p_rid)) {
_update_dirty_multimeshes();
- multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
+ multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
MultiMesh *multimesh = multimesh_owner.getornull(p_rid);
multimesh->dependency.deleted_notify(p_rid);
multimesh_owner.free(p_rid);
} else if (skeleton_owner.owns(p_rid)) {
_update_dirty_skeletons();
- skeleton_allocate(p_rid, 0);
+ skeleton_allocate_data(p_rid, 0);
Skeleton *skeleton = skeleton_owner.getornull(p_rid);
skeleton->dependency.deleted_notify(p_rid);
skeleton_owner.free(p_rid);
@@ -8241,7 +8303,7 @@ bool RendererStorageRD::free(RID p_rid) {
decal->dependency.deleted_notify(p_rid);
decal_owner.free(p_rid);
} else if (gi_probe_owner.owns(p_rid)) {
- gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
+ gi_probe_allocate_data(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
gi_probe->dependency.deleted_notify(p_rid);
gi_probe_owner.free(p_rid);
@@ -8335,7 +8397,7 @@ RendererStorageRD::RendererStorageRD() {
static_assert(sizeof(GlobalVariables::Value) == 16);
- global_variables.buffer_size = GLOBAL_GET("rendering/high_end/global_shader_variables_buffer_size");
+ global_variables.buffer_size = GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size");
global_variables.buffer_size = MAX(4096, global_variables.buffer_size);
global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
zeromem(global_variables.buffer_values, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
@@ -8603,14 +8665,14 @@ RendererStorageRD::RendererStorageRD() {
sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/quality/texture_filters/anisotropic_filtering_level"));
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
} break;
case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/quality/texture_filters/anisotropic_filtering_level"));
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
} break;
default: {
@@ -8780,7 +8842,7 @@ RendererStorageRD::RendererStorageRD() {
}
}
- lightmap_probe_capture_update_speed = GLOBAL_GET("rendering/lightmapper/probe_capture_update_speed");
+ lightmap_probe_capture_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed");
/* Particles */
@@ -8847,9 +8909,11 @@ RendererStorageRD::RendererStorageRD() {
{
// default material and shader for particles shader
- particles_shader.default_shader = shader_create();
+ particles_shader.default_shader = shader_allocate();
+ shader_initialize(particles_shader.default_shader);
shader_set_code(particles_shader.default_shader, "shader_type particles; void compute() { COLOR = vec4(1.0); } \n");
- particles_shader.default_material = material_create();
+ particles_shader.default_material = material_allocate();
+ material_initialize(particles_shader.default_material);
material_set_shader(particles_shader.default_material, particles_shader.default_shader);
ParticlesMaterialData *md = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, RendererStorageRD::SHADER_TYPE_PARTICLES);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index aa7195232a..cd3d4604eb 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -221,7 +221,7 @@ private:
~CanvasTexture();
};
- RID_PtrOwner<CanvasTexture> canvas_texture_owner;
+ RID_PtrOwner<CanvasTexture, true> canvas_texture_owner;
/* TEXTURE API */
struct Texture {
@@ -367,7 +367,7 @@ private:
};
ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
- mutable RID_Owner<Shader> shader_owner;
+ mutable RID_Owner<Shader, true> shader_owner;
/* Material */
@@ -389,7 +389,7 @@ private:
};
MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
- mutable RID_Owner<Material> material_owner;
+ mutable RID_Owner<Material, true> material_owner;
Material *material_update_list;
void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
@@ -484,7 +484,7 @@ private:
Dependency dependency;
};
- mutable RID_Owner<Mesh> mesh_owner;
+ mutable RID_Owner<Mesh, true> mesh_owner;
struct MeshInstance {
Mesh *mesh;
@@ -587,7 +587,7 @@ private:
Dependency dependency;
};
- mutable RID_Owner<MultiMesh> multimesh_owner;
+ mutable RID_Owner<MultiMesh, true> multimesh_owner;
MultiMesh *multimesh_dirty_list = nullptr;
@@ -893,7 +893,7 @@ private:
void update_particles();
- mutable RID_Owner<Particles> particles_owner;
+ mutable RID_Owner<Particles, true> particles_owner;
/* Particles Collision */
@@ -915,7 +915,7 @@ private:
Dependency dependency;
};
- mutable RID_Owner<ParticlesCollision> particles_collision_owner;
+ mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
struct ParticlesCollisionInstance {
RID collision;
@@ -945,7 +945,7 @@ private:
Dependency dependency;
};
- mutable RID_Owner<Skeleton> skeleton_owner;
+ mutable RID_Owner<Skeleton, true> skeleton_owner;
_FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton);
@@ -977,7 +977,7 @@ private:
Dependency dependency;
};
- mutable RID_Owner<Light> light_owner;
+ mutable RID_Owner<Light, true> light_owner;
/* REFLECTION PROBE */
@@ -1000,7 +1000,7 @@ private:
Dependency dependency;
};
- mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
+ mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
/* DECAL */
@@ -1021,7 +1021,7 @@ private:
Dependency dependency;
};
- mutable RID_Owner<Decal> decal_owner;
+ mutable RID_Owner<Decal, true> decal_owner;
/* GI PROBE */
@@ -1064,7 +1064,7 @@ private:
RID giprobe_sdf_shader_version_shader;
RID giprobe_sdf_shader_pipeline;
- mutable RID_Owner<GIProbe> gi_probe_owner;
+ mutable RID_Owner<GIProbe, true> gi_probe_owner;
/* REFLECTION PROBE */
@@ -1095,7 +1095,7 @@ private:
uint64_t lightmap_array_version = 0;
- mutable RID_Owner<Lightmap> lightmap_owner;
+ mutable RID_Owner<Lightmap, true> lightmap_owner;
float lightmap_probe_capture_update_speed = 4;
@@ -1249,12 +1249,16 @@ private:
EffectsRD effects;
public:
+ virtual bool can_create_resources_async() const;
+
/* TEXTURE API */
- virtual RID texture_2d_create(const Ref<Image> &p_image);
- virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type);
- virtual RID texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); //all slices, then all the mipmaps, must be coherent
- virtual RID texture_proxy_create(RID p_base);
+ virtual RID texture_allocate();
+
+ virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image);
+ virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type);
+ virtual void texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); //all slices, then all the mipmaps, must be coherent
+ virtual void texture_proxy_initialize(RID p_texture, RID p_base);
virtual void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate);
@@ -1264,9 +1268,9 @@ public:
virtual void texture_proxy_update(RID p_texture, RID p_proxy_to);
//these two APIs can be used together or in combination with the others.
- virtual RID texture_2d_placeholder_create();
- virtual RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type);
- virtual RID texture_3d_placeholder_create();
+ virtual void texture_2d_placeholder_initialize(RID p_texture);
+ virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type);
+ virtual void texture_3d_placeholder_initialize(RID p_texture);
virtual Ref<Image> texture_2d_get(RID p_texture) const;
virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const;
@@ -1338,7 +1342,8 @@ public:
/* CANVAS TEXTURE API */
- virtual RID canvas_texture_create();
+ RID canvas_texture_allocate();
+ void canvas_texture_initialize(RID p_canvas_texture);
virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture);
virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess);
@@ -1350,7 +1355,8 @@ public:
/* SHADER API */
- RID shader_create();
+ RID shader_allocate();
+ void shader_initialize(RID p_shader);
void shader_set_code(RID p_shader, const String &p_code);
String shader_get_code(RID p_shader) const;
@@ -1365,7 +1371,8 @@ public:
/* COMMON MATERIAL API */
- RID material_create();
+ RID material_allocate();
+ void material_initialize(RID p_material);
void material_set_shader(RID p_material, RID p_shader);
@@ -1401,7 +1408,8 @@ public:
/* MESH API */
- virtual RID mesh_create();
+ RID mesh_allocate();
+ void mesh_initialize(RID p_mesh);
virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count);
@@ -1482,13 +1490,7 @@ public:
return s->lod_count > 0;
}
- _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
-
- return s->index_array;
- }
-
- _FORCE_INLINE_ RID mesh_surface_get_index_array_with_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_lod_threshold) const {
+ _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_lod_threshold) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
int32_t current_lod = -1;
@@ -1500,9 +1502,19 @@ public:
current_lod = i;
}
if (current_lod == -1) {
+ return 0;
+ } else {
+ return current_lod + 1;
+ }
+ }
+
+ _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+
+ if (p_lod == 0) {
return s->index_array;
} else {
- return s->lods[current_lod].index_array;
+ return s->lods[p_lod - 1].index_array;
}
}
@@ -1618,9 +1630,10 @@ public:
/* MULTIMESH API */
- RID multimesh_create();
+ RID multimesh_allocate();
+ void multimesh_initialize(RID p_multimesh);
- void multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false);
+ void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false);
int multimesh_get_instance_count(RID p_multimesh) const;
void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
@@ -1684,24 +1697,28 @@ public:
/* IMMEDIATE API */
- RID immediate_create() { return RID(); }
- void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) {}
- void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {}
- void immediate_normal(RID p_immediate, const Vector3 &p_normal) {}
- void immediate_tangent(RID p_immediate, const Plane &p_tangent) {}
- void immediate_color(RID p_immediate, const Color &p_color) {}
- void immediate_uv(RID p_immediate, const Vector2 &tex_uv) {}
- void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) {}
- void immediate_end(RID p_immediate) {}
- void immediate_clear(RID p_immediate) {}
- void immediate_set_material(RID p_immediate, RID p_material) {}
- RID immediate_get_material(RID p_immediate) const { return RID(); }
- AABB immediate_get_aabb(RID p_immediate) const { return AABB(); }
+ RID immediate_allocate() { return RID(); }
+ void immediate_initialize(RID p_immediate) {}
+
+ virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) {}
+ virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {}
+ virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) {}
+ virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) {}
+ virtual void immediate_color(RID p_immediate, const Color &p_color) {}
+ virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) {}
+ virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) {}
+ virtual void immediate_end(RID p_immediate) {}
+ virtual void immediate_clear(RID p_immediate) {}
+ virtual void immediate_set_material(RID p_immediate, RID p_material) {}
+ virtual RID immediate_get_material(RID p_immediate) const { return RID(); }
+ virtual AABB immediate_get_aabb(RID p_immediate) const { return AABB(); }
/* SKELETON API */
- RID skeleton_create();
- void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false);
+ RID skeleton_allocate();
+ void skeleton_initialize(RID p_skeleton);
+
+ void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false);
void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform);
int skeleton_get_bone_count(RID p_skeleton) const;
@@ -1735,11 +1752,16 @@ public:
}
/* Light API */
- RID light_create(RS::LightType p_type);
+ void _light_initialize(RID p_rid, RS::LightType p_type);
- RID directional_light_create() { return light_create(RS::LIGHT_DIRECTIONAL); }
- RID omni_light_create() { return light_create(RS::LIGHT_OMNI); }
- RID spot_light_create() { return light_create(RS::LIGHT_SPOT); }
+ RID directional_light_allocate();
+ void directional_light_initialize(RID p_light);
+
+ RID omni_light_allocate();
+ void omni_light_initialize(RID p_light);
+
+ RID spot_light_allocate();
+ void spot_light_initialize(RID p_light);
void light_set_color(RID p_light, const Color &p_color);
void light_set_param(RID p_light, RS::LightParam p_param, float p_value);
@@ -1842,7 +1864,8 @@ public:
/* PROBE API */
- RID reflection_probe_create();
+ RID reflection_probe_allocate();
+ void reflection_probe_initialize(RID p_reflection_probe);
void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode);
void reflection_probe_set_intensity(RID p_probe, float p_intensity);
@@ -1882,7 +1905,9 @@ public:
/* DECAL API */
- virtual RID decal_create();
+ RID decal_allocate();
+ void decal_initialize(RID p_decal);
+
virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents);
virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture);
virtual void decal_set_emission_energy(RID p_decal, float p_energy);
@@ -1957,9 +1982,10 @@ public:
/* GI PROBE API */
- RID gi_probe_create();
+ RID gi_probe_allocate();
+ void gi_probe_initialize(RID p_gi_probe);
- void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
+ void gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
AABB gi_probe_get_bounds(RID p_gi_probe) const;
Vector3i gi_probe_get_octree_size(RID p_gi_probe) const;
@@ -2010,7 +2036,8 @@ public:
/* LIGHTMAP CAPTURE */
- virtual RID lightmap_create();
+ RID lightmap_allocate();
+ void lightmap_initialize(RID p_lightmap);
virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics);
virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds);
@@ -2059,7 +2086,8 @@ public:
/* PARTICLES */
- RID particles_create();
+ RID particles_allocate();
+ void particles_initialize(RID p_particles_collision);
void particles_set_emitting(RID p_particles, bool p_emitting);
void particles_set_amount(RID p_particles, int p_amount);
@@ -2137,7 +2165,9 @@ public:
/* PARTICLES COLLISION */
- virtual RID particles_collision_create();
+ RID particles_collision_allocate();
+ void particles_collision_initialize(RID p_particles_collision);
+
virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type);
virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask);
virtual void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius); //for spheres
@@ -2233,7 +2263,7 @@ public:
void render_info_end_capture() {}
int get_captured_render_info(RS::RenderInfo p_info) { return 0; }
- int get_render_info(RS::RenderInfo p_info) { return 0; }
+ uint64_t get_render_info(RS::RenderInfo p_info) { return 0; }
String get_video_adapter_name() const { return String(); }
String get_video_adapter_vendor() const { return String(); }
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index e77141b26c..8135d388e1 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -687,7 +687,15 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
uint32_t index = p_default_actions.base_varying_index;
+ List<Pair<StringName, SL::ShaderNode::Varying>> var_frag_to_light;
+
for (Map<StringName, SL::ShaderNode::Varying>::Element *E = pnode->varyings.front(); E; E = E->next()) {
+ if (E->get().stage == SL::ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT || E->get().stage == SL::ShaderNode::Varying::STAGE_FRAGMENT) {
+ var_frag_to_light.push_back(Pair<StringName, SL::ShaderNode::Varying>(E->key(), E->get()));
+ fragment_varyings.insert(E->key());
+ continue;
+ }
+
String vcode;
String interp_mode = _interpstr(E->get().interpolation);
vcode += _prestr(E->get().precision);
@@ -705,6 +713,21 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
index++;
}
+ if (var_frag_to_light.size() > 0) {
+ String gcode = "\n\nstruct {\n";
+ for (List<Pair<StringName, SL::ShaderNode::Varying>>::Element *E = var_frag_to_light.front(); E; E = E->next()) {
+ gcode += "\t" + _prestr(E->get().second.precision) + _typestr(E->get().second.type) + " " + _mkid(E->get().first);
+ if (E->get().second.array_size > 0) {
+ gcode += "[";
+ gcode += itos(E->get().second.array_size);
+ gcode += "]";
+ }
+ gcode += ";\n";
+ }
+ gcode += "} frag_to_light;\n";
+ r_gen_code.fragment_global += gcode;
+ }
+
for (int i = 0; i < pnode->vconstants.size(); i++) {
const SL::ShaderNode::Constant &cnode = pnode->vconstants[i];
String gcode;
@@ -833,6 +856,19 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
} break;
case SL::Node::TYPE_VARIABLE: {
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
+ bool use_fragment_varying = false;
+
+ if (current_func_name != vertex_name) {
+ if (p_assigning) {
+ if (shader->varyings.has(vnode->name)) {
+ use_fragment_varying = true;
+ }
+ } else {
+ if (fragment_varyings.has(vnode->name)) {
+ use_fragment_varying = true;
+ }
+ }
+ }
if (p_assigning && p_actions.write_flag_pointers.has(vnode->name)) {
*p_actions.write_flag_pointers[vnode->name] = true;
@@ -877,7 +913,10 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
}
} else {
- code = _mkid(vnode->name); //its something else (local var most likely) use as is
+ if (use_fragment_varying) {
+ code = "frag_to_light.";
+ }
+ code += _mkid(vnode->name); //its something else (local var most likely) use as is
}
}
@@ -962,6 +1001,23 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
} break;
case SL::Node::TYPE_ARRAY: {
SL::ArrayNode *anode = (SL::ArrayNode *)p_node;
+ bool use_fragment_varying = false;
+
+ if (current_func_name != vertex_name) {
+ if (anode->assign_expression != nullptr) {
+ use_fragment_varying = true;
+ } else {
+ if (p_assigning) {
+ if (shader->varyings.has(anode->name)) {
+ use_fragment_varying = true;
+ }
+ } else {
+ if (fragment_varyings.has(anode->name)) {
+ use_fragment_varying = true;
+ }
+ }
+ }
+ }
if (p_assigning && p_actions.write_flag_pointers.has(anode->name)) {
*p_actions.write_flag_pointers[anode->name] = true;
@@ -984,7 +1040,10 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
if (p_default_actions.renames.has(anode->name)) {
code = p_default_actions.renames[anode->name];
} else {
- code = _mkid(anode->name);
+ if (use_fragment_varying) {
+ code = "frag_to_light.";
+ }
+ code += _mkid(anode->name);
}
if (anode->call_expression != nullptr) {
@@ -1277,6 +1336,7 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide
used_name_defines.clear();
used_rmode_defines.clear();
used_flag_pointers.clear();
+ fragment_varyings.clear();
shader = parser.get_shader();
function = nullptr;
@@ -1408,7 +1468,7 @@ ShaderCompilerRD::ShaderCompilerRD() {
actions[RS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
actions[RS::SHADER_SPATIAL].render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
- bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley");
+ bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley");
if (!force_lambert) {
actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
@@ -1418,7 +1478,7 @@ ShaderCompilerRD::ShaderCompilerRD() {
actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
- bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx");
+ bool force_blinn = GLOBAL_GET("rendering/shading/overrides/force_blinn_over_ggx");
if (!force_blinn) {
actions[RS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.h b/servers/rendering/renderer_rd/shader_compiler_rd.h
index d127d8e01c..6575829e73 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.h
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.h
@@ -114,6 +114,7 @@ private:
Set<StringName> used_flag_pointers;
Set<StringName> used_rmode_defines;
Set<StringName> internal_functions;
+ Set<StringName> fragment_varyings;
DefaultIdentifierActions actions;
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 2ae22a8a38..e4a39ff813 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -301,6 +301,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
builder.append(compute_codev.get_data()); // version info (if exists)
builder.append("\n"); //make sure defines begin at newline
+ builder.append(base_compute_defines.get_data());
builder.append(general_defines.get_data());
builder.append(variant_defines[p_variant].get_data());
@@ -401,7 +402,6 @@ RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_versio
builder.append(fragment_codev.get_data()); // version info (if exists)
builder.append("\n"); //make sure defines begin at newline
-
builder.append(general_defines.get_data());
builder.append(variant_defines[i].get_data());
for (int j = 0; j < version->custom_defines.size(); j++) {
@@ -440,6 +440,7 @@ RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_versio
builder.append(compute_codev.get_data()); // version info (if exists)
builder.append("\n"); //make sure defines begin at newline
+ builder.append(base_compute_defines.get_data());
builder.append(general_defines.get_data());
builder.append(variant_defines[i].get_data());
@@ -596,6 +597,22 @@ bool ShaderRD::is_variant_enabled(int p_variant) const {
return variants_enabled[p_variant];
}
+ShaderRD::ShaderRD() {
+ // Do not feel forced to use this, in most cases it makes little to no difference.
+ bool use_32_threads = false;
+ if (RD::get_singleton()->get_device_vendor_name() == "NVIDIA") {
+ use_32_threads = true;
+ }
+ String base_compute_define_text;
+ if (use_32_threads) {
+ base_compute_define_text = "\n#define NATIVE_LOCAL_GROUP_SIZE 32\n#define NATIVE_LOCAL_SIZE_2D_X 8\n#define NATIVE_LOCAL_SIZE_2D_Y 4\n";
+ } else {
+ base_compute_define_text = "\n#define NATIVE_LOCAL_GROUP_SIZE 64\n#define NATIVE_LOCAL_SIZE_2D_X 8\n#define NATIVE_LOCAL_SIZE_2D_Y 8\n";
+ }
+
+ base_compute_defines = base_compute_define_text.ascii();
+}
+
void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String &p_general_defines) {
ERR_FAIL_COND(variant_defines.size());
ERR_FAIL_COND(p_variant_defines.size() == 0);
diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h
index a3474c6f93..e0f4dcf2d0 100644
--- a/servers/rendering/renderer_rd/shader_rd.h
+++ b/servers/rendering/renderer_rd/shader_rd.h
@@ -99,8 +99,10 @@ class ShaderRD {
const char *name;
+ CharString base_compute_defines;
+
protected:
- ShaderRD() {}
+ ShaderRD();
void setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name);
public:
diff --git a/servers/rendering/renderer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub
index 1b0197c1c1..fc513d3fb9 100644
--- a/servers/rendering/renderer_rd/shaders/SCsub
+++ b/servers/rendering/renderer_rd/shaders/SCsub
@@ -3,47 +3,15 @@
Import("env")
if "RD_GLSL" in env["BUILDERS"]:
- env.RD_GLSL("canvas.glsl")
- env.RD_GLSL("canvas_occlusion.glsl")
- env.RD_GLSL("canvas_sdf.glsl")
- env.RD_GLSL("copy.glsl")
- env.RD_GLSL("copy_to_fb.glsl")
- env.RD_GLSL("cubemap_roughness.glsl")
- env.RD_GLSL("cubemap_downsampler.glsl")
- env.RD_GLSL("cubemap_filter.glsl")
- env.RD_GLSL("scene_forward.glsl")
- env.RD_GLSL("sky.glsl")
- env.RD_GLSL("tonemap.glsl")
- env.RD_GLSL("cube_to_dp.glsl")
- env.RD_GLSL("giprobe.glsl")
- env.RD_GLSL("giprobe_debug.glsl")
- env.RD_GLSL("giprobe_sdf.glsl")
- env.RD_GLSL("luminance_reduce.glsl")
- env.RD_GLSL("bokeh_dof.glsl")
- env.RD_GLSL("ssao.glsl")
- env.RD_GLSL("ssao_downsample.glsl")
- env.RD_GLSL("ssao_importance_map.glsl")
- env.RD_GLSL("ssao_blur.glsl")
- env.RD_GLSL("ssao_interleave.glsl")
- env.RD_GLSL("roughness_limiter.glsl")
- env.RD_GLSL("screen_space_reflection.glsl")
- env.RD_GLSL("screen_space_reflection_filter.glsl")
- env.RD_GLSL("screen_space_reflection_scale.glsl")
- env.RD_GLSL("subsurface_scattering.glsl")
- env.RD_GLSL("specular_merge.glsl")
- env.RD_GLSL("gi.glsl")
- env.RD_GLSL("resolve.glsl")
- env.RD_GLSL("sdfgi_preprocess.glsl")
- env.RD_GLSL("sdfgi_integrate.glsl")
- env.RD_GLSL("sdfgi_direct_light.glsl")
- env.RD_GLSL("sdfgi_debug.glsl")
- env.RD_GLSL("sdfgi_debug_probes.glsl")
- env.RD_GLSL("volumetric_fog.glsl")
- env.RD_GLSL("shadow_reduce.glsl")
- env.RD_GLSL("particles.glsl")
- env.RD_GLSL("particles_copy.glsl")
- env.RD_GLSL("sort.glsl")
- env.RD_GLSL("skeleton.glsl")
- env.RD_GLSL("cluster_render.glsl")
- env.RD_GLSL("cluster_store.glsl")
- env.RD_GLSL("cluster_debug.glsl")
+ # find all include files
+ gl_include_files = [str(f) for f in Glob("*_inc.glsl")]
+
+ # find all shader code(all glsl files excluding our include files)
+ glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
+
+ # make sure we recompile shaders if include files change
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files)
+
+ # compile shaders
+ for glsl_file in glsl_files:
+ env.RD_GLSL(glsl_file)
diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl
index 35522103df..92a5682572 100644
--- a/servers/rendering/renderer_rd/shaders/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/gi.glsl
@@ -363,57 +363,62 @@ void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, o
ray_pos += (ray_dir * 1.0 / max(abs_ray_dir.x, max(abs_ray_dir.y, abs_ray_dir.z)) + cam_normal * 1.4) * bias / sdfgi.cascades[cascade].to_cell;
}
float softness = 0.2 + min(1.0, roughness * 5.0) * 4.0; //approximation to roughness so it does not seem like a hard fade
- while (length(ray_pos) < max_distance) {
- for (uint i = 0; i < sdfgi.max_cascades; i++) {
- if (i >= cascade && length(ray_pos) < radius_sizes[i]) {
- cascade = max(i, cascade); //never go down
-
- vec3 pos = ray_pos - sdfgi.cascades[i].position;
- pos *= sdfgi.cascades[i].to_cell * pos_to_uvw;
-
- float distance = texture(sampler3D(sdf_cascades[i], linear_sampler), pos).r * 255.0 - 1.1;
-
- vec4 hit_light = vec4(0.0);
- if (distance < softness) {
- hit_light.rgb = texture(sampler3D(light_cascades[i], linear_sampler), pos).rgb;
- hit_light.rgb *= 0.5; //approximation given value read is actually meant for anisotropy
- hit_light.a = clamp(1.0 - (distance / softness), 0.0, 1.0);
- hit_light.rgb *= hit_light.a;
- }
+ uint i = 0;
+ bool found = false;
+ while (true) {
+ if (length(ray_pos) >= max_distance || light_accum.a > 0.99) {
+ break;
+ }
+ if (!found && i >= cascade && length(ray_pos) < radius_sizes[i]) {
+ uint next_i = min(i + 1, sdfgi.max_cascades - 1);
+ cascade = max(i, cascade); //never go down
- distance /= sdfgi.cascades[i].to_cell;
+ vec3 pos = ray_pos - sdfgi.cascades[i].position;
+ pos *= sdfgi.cascades[i].to_cell * pos_to_uvw;
- if (i < (sdfgi.max_cascades - 1)) {
- pos = ray_pos - sdfgi.cascades[i + 1].position;
- pos *= sdfgi.cascades[i + 1].to_cell * pos_to_uvw;
+ float fdistance = textureLod(sampler3D(sdf_cascades[i], linear_sampler), pos, 0.0).r * 255.0 - 1.1;
- float distance2 = texture(sampler3D(sdf_cascades[i + 1], linear_sampler), pos).r * 255.0 - 1.1;
+ vec4 hit_light = vec4(0.0);
+ if (fdistance < softness) {
+ hit_light.rgb = textureLod(sampler3D(light_cascades[i], linear_sampler), pos, 0.0).rgb;
+ hit_light.rgb *= 0.5; //approximation given value read is actually meant for anisotropy
+ hit_light.a = clamp(1.0 - (fdistance / softness), 0.0, 1.0);
+ hit_light.rgb *= hit_light.a;
+ }
- vec4 hit_light2 = vec4(0.0);
- if (distance2 < softness) {
- hit_light2.rgb = texture(sampler3D(light_cascades[i + 1], linear_sampler), pos).rgb;
- hit_light2.rgb *= 0.5; //approximation given value read is actually meant for anisotropy
- hit_light2.a = clamp(1.0 - (distance2 / softness), 0.0, 1.0);
- hit_light2.rgb *= hit_light2.a;
- }
+ fdistance /= sdfgi.cascades[i].to_cell;
- float prev_radius = i == 0 ? 0.0 : radius_sizes[i - 1];
- float blend = clamp((length(ray_pos) - prev_radius) / (radius_sizes[i] - prev_radius), 0.0, 1.0);
+ if (i < (sdfgi.max_cascades - 1)) {
+ pos = ray_pos - sdfgi.cascades[next_i].position;
+ pos *= sdfgi.cascades[next_i].to_cell * pos_to_uvw;
- distance2 /= sdfgi.cascades[i + 1].to_cell;
+ float fdistance2 = textureLod(sampler3D(sdf_cascades[next_i], linear_sampler), pos, 0.0).r * 255.0 - 1.1;
- hit_light = mix(hit_light, hit_light2, blend);
- distance = mix(distance, distance2, blend);
+ vec4 hit_light2 = vec4(0.0);
+ if (fdistance2 < softness) {
+ hit_light2.rgb = textureLod(sampler3D(light_cascades[next_i], linear_sampler), pos, 0.0).rgb;
+ hit_light2.rgb *= 0.5; //approximation given value read is actually meant for anisotropy
+ hit_light2.a = clamp(1.0 - (fdistance2 / softness), 0.0, 1.0);
+ hit_light2.rgb *= hit_light2.a;
}
- light_accum += hit_light;
- ray_pos += ray_dir * distance;
- break;
+ float prev_radius = i == 0 ? 0.0 : radius_sizes[max(0, i - 1)];
+ float blend = clamp((length(ray_pos) - prev_radius) / (radius_sizes[i] - prev_radius), 0.0, 1.0);
+
+ fdistance2 /= sdfgi.cascades[next_i].to_cell;
+
+ hit_light = mix(hit_light, hit_light2, blend);
+ fdistance = mix(fdistance, fdistance2, blend);
}
- }
- if (light_accum.a > 0.99) {
- break;
+ light_accum += hit_light;
+ ray_pos += ray_dir * fdistance;
+ found = true;
+ }
+ i++;
+ if (i == sdfgi.max_cascades) {
+ i = 0;
+ found = false;
}
}
diff --git a/servers/rendering/renderer_rd/shaders/giprobe.glsl b/servers/rendering/renderer_rd/shaders/giprobe.glsl
index 4f4753d147..b931461b31 100644
--- a/servers/rendering/renderer_rd/shaders/giprobe.glsl
+++ b/servers/rendering/renderer_rd/shaders/giprobe.glsl
@@ -51,10 +51,10 @@ struct Light {
float attenuation;
vec3 color;
- float spot_angle_radians;
+ float cos_spot_angle;
vec3 position;
- float spot_attenuation;
+ float inv_spot_attenuation;
vec3 direction;
bool has_shadow;
@@ -233,13 +233,15 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
vec3 rel = normalize(pos - light_pos);
- float angle = acos(dot(rel, lights.data[light].direction));
- if (angle > lights.data[light].spot_angle_radians) {
+ float cos_spot_angle = lights.data[light].cos_spot_angle;
+ float cos_angle = dot(rel, lights.data[light].direction);
+ if (cos_angle < cos_spot_angle) {
return false;
}
- float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
- attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
+ float scos = max(cos_angle, cos_spot_angle);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle));
+ attenuation *= 1.0 - pow(spot_rim, lights.data[light].inv_spot_attenuation);
}
}
diff --git a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
index 9c794f1bcc..56b3b7ccb4 100644
--- a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
+++ b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
@@ -43,10 +43,10 @@ struct Light {
float attenuation;
vec3 color;
- float spot_angle_radians;
+ float cos_spot_angle;
vec3 position;
- float spot_attenuation;
+ float inv_spot_attenuation;
vec3 direction;
bool has_shadow;
@@ -146,13 +146,15 @@ bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
vec3 rel = normalize(pos - light_pos);
- float angle = acos(dot(rel, lights.data[light].direction));
- if (angle > lights.data[light].spot_angle_radians) {
+ float cos_spot_angle = lights.data[light].cos_spot_angle;
+ float cos_angle = dot(rel, lights.data[light].direction);
+ if (cos_angle < cos_spot_angle) {
return false;
}
- float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
- attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
+ float scos = max(cos_angle, cos_spot_angle);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle));
+ attenuation *= 1.0 - pow(spot_rim, lights.data[light].inv_spot_attenuation);
}
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index ea203c8abe..7b86dac143 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -4,7 +4,7 @@
VERSION_DEFINES
-#include "scene_forward_inc.glsl"
+#include "scene_forward_clustered_inc.glsl"
/* INPUT ATTRIBS */
@@ -89,12 +89,6 @@ MATERIAL_UNIFORMS
} material;
#endif
-/* clang-format off */
-
-VERTEX_SHADER_GLOBALS
-
-/* clang-format on */
-
invariant gl_Position;
#ifdef MODE_DUAL_PARABOLOID
@@ -103,28 +97,43 @@ layout(location = 8) out float dp_clip;
#endif
+layout(location = 9) out flat uint instance_index;
+
+/* clang-format off */
+
+VERTEX_SHADER_GLOBALS
+
+/* clang-format on */
+
void main() {
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
color_interp = color_attrib;
#endif
- mat4 world_matrix = draw_call.transform;
+ instance_index = draw_call.instance_index;
+
+ bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH);
+ if (!is_multimesh) {
+ instance_index += gl_InstanceIndex;
+ }
+
+ mat4 world_matrix = instances.data[instance_index].transform;
mat3 world_normal_matrix;
- if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
world_normal_matrix = inverse(mat3(world_matrix));
} else {
world_normal_matrix = mat3(world_matrix);
}
- if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH)) {
+ if (is_multimesh) {
//multimesh, instances are for it
- uint offset = (draw_call.flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK;
+ uint offset = (instances.data[instance_index].flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK;
offset *= gl_InstanceIndex;
mat4 matrix;
- if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
offset += 2;
} else {
@@ -132,14 +141,14 @@ void main() {
offset += 3;
}
- if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
#ifdef COLOR_USED
color_interp *= transforms.data[offset];
#endif
offset += 1;
}
- if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
instance_custom = transforms.data[offset];
}
@@ -161,7 +170,7 @@ void main() {
#endif
#if 0
- if (bool(draw_call.flags & INSTANCE_FLAGS_SKELETON)) {
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_SKELETON)) {
//multimesh, instances are for it
uvec2 bones_01 = uvec2(bone_attrib.x & 0xFFFF, bone_attrib.x >> 16) * 3;
@@ -194,7 +203,7 @@ void main() {
uv2_interp = uv2_attrib;
#endif
-#ifdef USE_OVERRIDE_POSITION
+#ifdef OVERRIDE_POSITION
vec4 position;
#endif
@@ -289,7 +298,7 @@ VERTEX_SHADER_CODE
#endif //MODE_RENDER_DEPTH
-#ifdef USE_OVERRIDE_POSITION
+#ifdef OVERRIDE_POSITION
gl_Position = position;
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
@@ -304,7 +313,8 @@ VERTEX_SHADER_CODE
#endif
#ifdef MODE_RENDER_MATERIAL
if (scene_data.material_uv2_mode) {
- gl_Position.xy = (uv2_attrib.xy + draw_call.lightmap_uv_scale.xy) * 2.0 - 1.0;
+ vec2 uv_offset = unpackHalf2x16(draw_call.uv_offset);
+ gl_Position.xy = (uv2_attrib.xy + uv_offset) * 2.0 - 1.0;
gl_Position.z = 0.00001;
gl_Position.w = 1.0;
}
@@ -317,7 +327,7 @@ VERTEX_SHADER_CODE
VERSION_DEFINES
-#include "scene_forward_inc.glsl"
+#include "scene_forward_clustered_inc.glsl"
/* Varyings */
@@ -350,9 +360,11 @@ layout(location = 8) in float dp_clip;
#endif
+layout(location = 9) in flat uint instance_index;
+
//defines to keep compatibility with vertex
-#define world_matrix draw_call.transform
+#define world_matrix instances.data[instance_index].transform
#define projection_matrix scene_data.projection_matrix
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
@@ -787,13 +799,11 @@ LIGHT_SHADER_CODE
#ifndef USE_NO_SHADOWS
-// Produces cheap white noise, optimized for window-space
-// Comes from: https://www.shadertoy.com/view/4djSRW
-// Copyright: Dave Hoskins, MIT License
+// Interleaved Gradient Noise
+// http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
float quick_hash(vec2 pos) {
- vec3 p3 = fract(vec3(pos.xyx) * .1031);
- p3 += dot(p3, p3.yzx + 33.33);
- return fract((p3.x + p3.y) * p3.z);
+ const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);
+ return fract(magic.z * fract(dot(pos, magic.xy)));
}
float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
@@ -1770,7 +1780,7 @@ vec4 fog_process(vec3 vertex) {
}
}
- float fog_amount = 1.0 - exp(vertex.z * scene_data.fog_density);
+ float fog_amount = 1.0 - exp(min(0.0, vertex.z * scene_data.fog_density));
if (abs(scene_data.fog_height_density) > 0.001) {
float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y;
@@ -2083,7 +2093,7 @@ FRAGMENT_SHADER_CODE
#endif
uint decal_index = 32 * i + bit;
- if (!bool(decals.data[decal_index].mask & draw_call.layer_mask)) {
+ if (!bool(decals.data[decal_index].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
@@ -2210,8 +2220,8 @@ FRAGMENT_SHADER_CODE
#ifdef USE_LIGHTMAP
//lightmap
- if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
- uint index = draw_call.gi_offset;
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
+ uint index = instances.data[instance_index].gi_offset;
vec3 wnormal = mat3(scene_data.camera_matrix) * normal;
const float c1 = 0.429043;
@@ -2230,12 +2240,12 @@ FRAGMENT_SHADER_CODE
2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
- } else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
- bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
- uint ofs = draw_call.gi_offset & 0xFFFF;
+ } else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
+ bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
+ uint ofs = instances.data[instance_index].gi_offset & 0xFFFF;
vec3 uvw;
- uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy;
- uvw.z = float((draw_call.gi_offset >> 16) & 0xFFFF);
+ uvw.xy = uv2 * instances.data[instance_index].lightmap_uv_scale.zw + instances.data[instance_index].lightmap_uv_scale.xy;
+ uvw.z = float((instances.data[instance_index].gi_offset >> 16) & 0xFFFF);
if (uses_sh) {
uvw.z *= 4.0; //SH textures use 4 times more data
@@ -2244,7 +2254,7 @@ FRAGMENT_SHADER_CODE
vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
- uint idx = draw_call.gi_offset >> 20;
+ uint idx = instances.data[instance_index].gi_offset >> 20;
vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);
ambient_light += lm_light_l0 * 0.282095f;
@@ -2264,7 +2274,7 @@ FRAGMENT_SHADER_CODE
}
#elif defined(USE_FORWARD_GI)
- if (bool(draw_call.flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
//make vertex orientation the world one, but still align to camera
vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex;
@@ -2336,9 +2346,9 @@ FRAGMENT_SHADER_CODE
}
}
- if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
- uint index1 = draw_call.gi_offset & 0xFFFF;
+ uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
//find arbitrary tangent and bitangent, then build a matrix
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
@@ -2350,7 +2360,7 @@ FRAGMENT_SHADER_CODE
vec4 spec_accum = vec4(0.0);
gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
- uint index2 = draw_call.gi_offset >> 16;
+ uint index2 = instances.data[instance_index].gi_offset >> 16;
if (index2 != 0xFFFF) {
gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
@@ -2369,7 +2379,7 @@ FRAGMENT_SHADER_CODE
}
#elif !defined(LOW_END_MODE)
- if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
vec2 coord;
@@ -2448,7 +2458,7 @@ FRAGMENT_SHADER_CODE
#endif
uint reflection_index = 32 * i + bit;
- if (!bool(reflections.data[reflection_index].mask & draw_call.layer_mask)) {
+ if (!bool(reflections.data[reflection_index].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
@@ -2519,7 +2529,7 @@ FRAGMENT_SHADER_CODE
break;
}
- if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) {
+ if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
@@ -2838,7 +2848,7 @@ FRAGMENT_SHADER_CODE
break;
}
- if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) {
+ if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
@@ -2968,7 +2978,7 @@ FRAGMENT_SHADER_CODE
#endif
uint light_index = 32 * i + bit;
- if (!bool(omni_lights.data[light_index].mask & draw_call.layer_mask)) {
+ if (!bool(omni_lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
@@ -3041,7 +3051,7 @@ FRAGMENT_SHADER_CODE
uint light_index = 32 * i + bit;
- if (!bool(spot_lights.data[light_index].mask & draw_call.layer_mask)) {
+ if (!bool(spot_lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
@@ -3214,9 +3224,9 @@ FRAGMENT_SHADER_CODE
normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);
#ifdef MODE_RENDER_GIPROBE
- if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
- uint index1 = draw_call.gi_offset & 0xFFFF;
- uint index2 = draw_call.gi_offset >> 16;
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
+ uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
+ uint index2 = instances.data[instance_index].gi_offset >> 16;
giprobe_buffer.x = index1 & 0xFF;
giprobe_buffer.y = index2 & 0xFF;
} else {
@@ -3275,6 +3285,7 @@ FRAGMENT_SHADER_CODE
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
+ ;
#endif //MODE_MULTIPLE_RENDER_TARGETS
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index e9b79e1560..d78890fa9e 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -21,12 +21,10 @@
#endif
layout(push_constant, binding = 0, std430) uniform DrawCall {
- mat4 transform;
- uint flags;
- uint instance_uniforms_ofs; //base offset in global buffer for instance variables
- uint gi_offset; //GI information when using lightmapping (VCT or lightmap index)
- uint layer_mask;
- vec4 lightmap_uv_scale;
+ uint instance_index;
+ uint uv_offset;
+ uint pad0;
+ uint pad1;
}
draw_call;
@@ -45,96 +43,13 @@ draw_call;
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
-layout(set = 0, binding = 1) uniform sampler material_samplers[12];
-
-layout(set = 0, binding = 2) uniform sampler shadow_sampler;
-
#define SDFGI_MAX_CASCADES 8
-layout(set = 0, binding = 3, std140) uniform SceneData {
- mat4 projection_matrix;
- mat4 inv_projection_matrix;
-
- mat4 camera_matrix;
- mat4 inv_camera_matrix;
-
- vec2 viewport_size;
- vec2 screen_pixel_size;
-
- uint cluster_shift;
- uint cluster_width;
- uint cluster_type_size;
- uint max_cluster_element_count_div_32;
-
- //use vec4s because std140 doesnt play nice with vec2s, z and w are wasted
- vec4 directional_penumbra_shadow_kernel[32];
- vec4 directional_soft_shadow_kernel[32];
- vec4 penumbra_shadow_kernel[32];
- vec4 soft_shadow_kernel[32];
-
- uint directional_penumbra_shadow_samples;
- uint directional_soft_shadow_samples;
- uint penumbra_shadow_samples;
- uint soft_shadow_samples;
-
- vec4 ambient_light_color_energy;
+/* Set 1: Base Pass (never changes) */
- float ambient_color_sky_mix;
- bool use_ambient_light;
- bool use_ambient_cubemap;
- bool use_reflection_cubemap;
-
- mat3 radiance_inverse_xform;
-
- vec2 shadow_atlas_pixel_size;
- vec2 directional_shadow_pixel_size;
-
- uint directional_light_count;
- float dual_paraboloid_side;
- float z_far;
- float z_near;
-
- bool ssao_enabled;
- float ssao_light_affect;
- float ssao_ao_affect;
- bool roughness_limiter_enabled;
-
- float roughness_limiter_amount;
- float roughness_limiter_limit;
- uvec2 roughness_limiter_pad;
-
- vec4 ao_color;
-
- mat4 sdf_to_bounds;
-
- ivec3 sdf_offset;
- bool material_uv2_mode;
-
- ivec3 sdf_size;
- bool gi_upscale_for_msaa;
-
- bool volumetric_fog_enabled;
- float volumetric_fog_inv_length;
- float volumetric_fog_detail_spread;
- uint volumetric_fog_pad;
-
- bool fog_enabled;
- float fog_density;
- float fog_height;
- float fog_height_density;
-
- vec3 fog_light_color;
- float fog_sun_scatter;
-
- float fog_aerial_perspective;
-
- float time;
- float reflection_multiplier; // one normally, zero when rendering reflections
-
- bool pancake_shadows;
-}
+layout(set = 0, binding = 1) uniform sampler material_samplers[12];
-scene_data;
+layout(set = 0, binding = 2) uniform sampler shadow_sampler;
#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6)
#define INSTANCE_FLAGS_USE_SDFGI (1 << 7)
@@ -153,22 +68,22 @@ scene_data;
#define INSTANCE_FLAGS_SKELETON (1 << 19)
#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 20)
-layout(set = 0, binding = 4, std430) restrict readonly buffer OmniLights {
+layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
LightData data[];
}
omni_lights;
-layout(set = 0, binding = 5, std430) restrict readonly buffer SpotLights {
+layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights {
LightData data[];
}
spot_lights;
-layout(set = 0, binding = 6) buffer restrict readonly ReflectionProbeData {
+layout(set = 0, binding = 5) buffer restrict readonly ReflectionProbeData {
ReflectionData data[];
}
reflections;
-layout(set = 0, binding = 7, std140) uniform DirectionalLights {
+layout(set = 0, binding = 6, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
directional_lights;
@@ -180,7 +95,7 @@ struct Lightmap {
mat3 normal_xform;
};
-layout(set = 0, binding = 8, std140) restrict readonly buffer Lightmaps {
+layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
Lightmap data[];
}
lightmaps;
@@ -189,20 +104,20 @@ struct LightmapCapture {
vec4 sh[9];
};
-layout(set = 0, binding = 9, std140) restrict readonly buffer LightmapCaptures {
+layout(set = 0, binding = 8, std140) restrict readonly buffer LightmapCaptures {
LightmapCapture data[];
}
lightmap_captures;
-layout(set = 0, binding = 10) uniform texture2D decal_atlas;
-layout(set = 0, binding = 11) uniform texture2D decal_atlas_srgb;
+layout(set = 0, binding = 9) uniform texture2D decal_atlas;
+layout(set = 0, binding = 10) uniform texture2D decal_atlas_srgb;
-layout(set = 0, binding = 12, std430) restrict readonly buffer Decals {
+layout(set = 0, binding = 11, std430) restrict readonly buffer Decals {
DecalData data[];
}
decals;
-layout(set = 0, binding = 13, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 12, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
global_variables;
@@ -216,7 +131,7 @@ struct SDFGIProbeCascadeData {
float to_cell; // 1/bounds * grid_size
};
-layout(set = 0, binding = 14, std140) uniform SDFGI {
+layout(set = 0, binding = 13, std140) uniform SDFGI {
vec3 grid_size;
uint max_cascades;
@@ -246,47 +161,140 @@ sdfgi;
#endif //LOW_END_MODE
-// decal atlas
+/* Set 2: Render Pass (changes per render pass) */
-/* Set 1, Radiance */
+layout(set = 1, binding = 0, std140) uniform SceneData {
+ mat4 projection_matrix;
+ mat4 inv_projection_matrix;
+
+ mat4 camera_matrix;
+ mat4 inv_camera_matrix;
+
+ vec2 viewport_size;
+ vec2 screen_pixel_size;
+
+ uint cluster_shift;
+ uint cluster_width;
+ uint cluster_type_size;
+ uint max_cluster_element_count_div_32;
+
+ //use vec4s because std140 doesnt play nice with vec2s, z and w are wasted
+ vec4 directional_penumbra_shadow_kernel[32];
+ vec4 directional_soft_shadow_kernel[32];
+ vec4 penumbra_shadow_kernel[32];
+ vec4 soft_shadow_kernel[32];
+
+ uint directional_penumbra_shadow_samples;
+ uint directional_soft_shadow_samples;
+ uint penumbra_shadow_samples;
+ uint soft_shadow_samples;
+
+ vec4 ambient_light_color_energy;
+
+ float ambient_color_sky_mix;
+ bool use_ambient_light;
+ bool use_ambient_cubemap;
+ bool use_reflection_cubemap;
+
+ mat3 radiance_inverse_xform;
+
+ vec2 shadow_atlas_pixel_size;
+ vec2 directional_shadow_pixel_size;
+
+ uint directional_light_count;
+ float dual_paraboloid_side;
+ float z_far;
+ float z_near;
+
+ bool ssao_enabled;
+ float ssao_light_affect;
+ float ssao_ao_affect;
+ bool roughness_limiter_enabled;
+
+ float roughness_limiter_amount;
+ float roughness_limiter_limit;
+ uvec2 roughness_limiter_pad;
+
+ vec4 ao_color;
+
+ mat4 sdf_to_bounds;
+
+ ivec3 sdf_offset;
+ bool material_uv2_mode;
+
+ ivec3 sdf_size;
+ bool gi_upscale_for_msaa;
+
+ bool volumetric_fog_enabled;
+ float volumetric_fog_inv_length;
+ float volumetric_fog_detail_spread;
+ uint volumetric_fog_pad;
+
+ bool fog_enabled;
+ float fog_density;
+ float fog_height;
+ float fog_height_density;
+
+ vec3 fog_light_color;
+ float fog_sun_scatter;
+
+ float fog_aerial_perspective;
+
+ float time;
+ float reflection_multiplier; // one normally, zero when rendering reflections
+
+ bool pancake_shadows;
+}
+
+scene_data;
+
+struct InstanceData {
+ mat4 transform;
+ uint flags;
+ uint instance_uniforms_ofs; //base offset in global buffer for instance variables
+ uint gi_offset; //GI information when using lightmapping (VCT or lightmap index)
+ uint layer_mask;
+ vec4 lightmap_uv_scale;
+};
+
+layout(set = 1, binding = 1, std430) buffer restrict readonly InstanceDataBuffer {
+ InstanceData data[];
+}
+instances;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
-layout(set = 1, binding = 0) uniform textureCubeArray radiance_cubemap;
+layout(set = 1, binding = 2) uniform textureCubeArray radiance_cubemap;
#else
-layout(set = 1, binding = 0) uniform textureCube radiance_cubemap;
+layout(set = 1, binding = 2) uniform textureCube radiance_cubemap;
#endif
-/* Set 2, Reflection and Shadow Atlases (view dependent) */
-
-layout(set = 1, binding = 1) uniform textureCubeArray reflection_atlas;
+layout(set = 1, binding = 3) uniform textureCubeArray reflection_atlas;
-layout(set = 1, binding = 2) uniform texture2D shadow_atlas;
+layout(set = 1, binding = 4) uniform texture2D shadow_atlas;
-layout(set = 1, binding = 3) uniform texture2D directional_shadow_atlas;
+layout(set = 1, binding = 5) uniform texture2D directional_shadow_atlas;
-layout(set = 1, binding = 4) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
+layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
-#ifndef LOW_END_MODE
-layout(set = 1, binding = 5) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
+#ifndef LOW_END_MOD
+layout(set = 1, binding = 7) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
#endif
-layout(set = 1, binding = 6, std430) buffer restrict readonly ClusterBuffer {
+layout(set = 1, binding = 8, std430) buffer restrict readonly ClusterBuffer {
uint data[];
}
cluster_buffer;
-/* Set 3, Render Buffers */
-
#ifdef MODE_RENDER_SDF
-layout(r16ui, set = 1, binding = 7) uniform restrict writeonly uimage3D albedo_volume_grid;
-layout(r32ui, set = 1, binding = 8) uniform restrict writeonly uimage3D emission_grid;
-layout(r32ui, set = 1, binding = 9) uniform restrict writeonly uimage3D emission_aniso_grid;
-layout(r32ui, set = 1, binding = 10) uniform restrict uimage3D geom_facing_grid;
+layout(r16ui, set = 1, binding = 9) uniform restrict writeonly uimage3D albedo_volume_grid;
+layout(r32ui, set = 1, binding = 10) uniform restrict writeonly uimage3D emission_grid;
+layout(r32ui, set = 1, binding = 11) uniform restrict writeonly uimage3D emission_aniso_grid;
+layout(r32ui, set = 1, binding = 12) uniform restrict uimage3D geom_facing_grid;
//still need to be present for shaders that use it, so remap them to something
#define depth_buffer shadow_atlas
@@ -295,17 +303,17 @@ layout(r32ui, set = 1, binding = 10) uniform restrict uimage3D geom_facing_grid;
#else
-layout(set = 1, binding = 7) uniform texture2D depth_buffer;
-layout(set = 1, binding = 8) uniform texture2D color_buffer;
+layout(set = 1, binding = 9) uniform texture2D depth_buffer;
+layout(set = 1, binding = 10) uniform texture2D color_buffer;
#ifndef LOW_END_MODE
-layout(set = 1, binding = 9) uniform texture2D normal_roughness_buffer;
-layout(set = 1, binding = 10) uniform texture2D ao_buffer;
-layout(set = 1, binding = 11) uniform texture2D ambient_buffer;
-layout(set = 1, binding = 12) uniform texture2D reflection_buffer;
-layout(set = 1, binding = 13) uniform texture2DArray sdfgi_lightprobe_texture;
-layout(set = 1, binding = 14) uniform texture3D sdfgi_occlusion_cascades;
+layout(set = 1, binding = 11) uniform texture2D normal_roughness_buffer;
+layout(set = 1, binding = 12) uniform texture2D ao_buffer;
+layout(set = 1, binding = 13) uniform texture2D ambient_buffer;
+layout(set = 1, binding = 14) uniform texture2D reflection_buffer;
+layout(set = 1, binding = 15) uniform texture2DArray sdfgi_lightprobe_texture;
+layout(set = 1, binding = 16) uniform texture3D sdfgi_occlusion_cascades;
struct GIProbeData {
mat4 xform;
@@ -323,22 +331,22 @@ struct GIProbeData {
uint mipmaps;
};
-layout(set = 1, binding = 15, std140) uniform GIProbes {
+layout(set = 1, binding = 17, std140) uniform GIProbes {
GIProbeData data[MAX_GI_PROBES];
}
gi_probes;
-layout(set = 1, binding = 16) uniform texture3D volumetric_fog_texture;
+layout(set = 1, binding = 18) uniform texture3D volumetric_fog_texture;
#endif // LOW_END_MODE
#endif
-/* Set 4 Skeleton & Instancing (Multimesh) */
+/* Set 2 Skeleton & Instancing (can change per item) */
layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms {
vec4 data[];
}
transforms;
-/* Set 5 User Material */
+/* Set 3 User Material */
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
index bcdfe8cc85..dc7238abed 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
@@ -67,8 +67,8 @@ struct Light {
float attenuation;
uint type;
- float spot_angle;
- float spot_attenuation;
+ float cos_spot_angle;
+ float inv_spot_attenuation;
float radius;
vec4 shadow_color;
@@ -80,6 +80,7 @@ layout(set = 0, binding = 9, std140) buffer restrict readonly Lights {
lights;
layout(set = 0, binding = 10) uniform texture2DArray lightprobe_texture;
+layout(set = 0, binding = 11) uniform texture3D occlusion_texture;
layout(push_constant, binding = 0, std430) uniform Params {
vec3 grid_size;
@@ -91,9 +92,9 @@ layout(push_constant, binding = 0, std430) uniform Params {
uint process_increment;
int probe_axis_size;
- bool multibounce;
+ float bounce_feedback;
float y_mult;
- uint pad;
+ bool use_occlusion;
}
params;
@@ -159,7 +160,8 @@ void main() {
// Add indirect light first, in order to save computation resources
#ifdef MODE_PROCESS_DYNAMIC
- if (params.multibounce) {
+ if (params.bounce_feedback > 0.001) {
+ vec3 feedback = (params.bounce_feedback < 1.0) ? (albedo * params.bounce_feedback) : mix(albedo, vec3(1.0), params.bounce_feedback - 1.0);
vec3 pos = (vec3(positioni) + vec3(0.5)) * float(params.probe_axis_size - 1) / params.grid_size;
ivec3 probe_base_pos = ivec3(pos);
@@ -172,7 +174,7 @@ void main() {
vec3 base_tex_posf = vec3(tex_pos);
vec2 tex_pixel_size = 1.0 / vec2(ivec2((OCT_SIZE + 2) * params.probe_axis_size * params.probe_axis_size, (OCT_SIZE + 2) * params.probe_axis_size));
- vec3 probe_uv_offset = (ivec3(OCT_SIZE + 2, OCT_SIZE + 2, (OCT_SIZE + 2) * params.probe_axis_size)) * tex_pixel_size.xyx;
+ vec3 probe_uv_offset = vec3(ivec3(OCT_SIZE + 2, OCT_SIZE + 2, (OCT_SIZE + 2) * params.probe_axis_size)) * tex_pixel_size.xyx;
for (uint j = 0; j < 8; j++) {
ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
@@ -192,18 +194,35 @@ void main() {
for (uint k = 0; k < 6; k++) {
if (bool(valid_aniso & (1 << k))) {
vec3 n = aniso_dir[k];
- float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(n, probe_dir));
-
- vec3 tex_posf = base_tex_posf + vec3(octahedron_encode(n) * float(OCT_SIZE), 0.0);
- tex_posf.xy *= tex_pixel_size;
-
- vec3 pos_uvw = tex_posf;
- pos_uvw.xy += vec2(offset.xy) * probe_uv_offset.xy;
- pos_uvw.x += float(offset.z) * probe_uv_offset.z;
- vec3 indirect_light = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb;
-
- light_accum[k] += indirect_light * weight;
- weight_accum[k] += weight;
+ float weight = trilinear.x * trilinear.y * trilinear.z * max(0, dot(n, probe_dir));
+
+ if (weight > 0.0 && params.use_occlusion) {
+ ivec3 occ_indexv = abs((cascades.data[params.cascade].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4);
+ vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3)));
+
+ vec3 occ_pos = (vec3(positioni) + aniso_dir[k] + vec3(0.5)) / params.grid_size;
+ occ_pos.z += float(params.cascade);
+ if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures
+ occ_pos.x += 1.0;
+ }
+ occ_pos *= vec3(0.5, 1.0, 1.0 / float(params.max_cascades)); //renormalize
+ float occlusion = dot(textureLod(sampler3D(occlusion_texture, linear_sampler), occ_pos, 0.0), occ_mask);
+
+ weight *= occlusion;
+ }
+
+ if (weight > 0.0) {
+ vec3 tex_posf = base_tex_posf + vec3(octahedron_encode(n) * float(OCT_SIZE), 0.0);
+ tex_posf.xy *= tex_pixel_size;
+
+ vec3 pos_uvw = tex_posf;
+ pos_uvw.xy += vec2(offset.xy) * probe_uv_offset.xy;
+ pos_uvw.x += float(offset.z) * probe_uv_offset.z;
+ vec3 indirect_light = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb;
+
+ light_accum[k] += indirect_light * weight;
+ weight_accum[k] += weight;
+ }
}
}
}
@@ -211,7 +230,7 @@ void main() {
for (uint k = 0; k < 6; k++) {
if (weight_accum[k] > 0.0) {
light_accum[k] /= weight_accum[k];
- light_accum[k] *= albedo;
+ light_accum[k] *= feedback;
}
}
}
@@ -266,13 +285,16 @@ void main() {
rel_vec.y /= params.y_mult;
attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation);
- float angle = acos(dot(normalize(rel_vec), -lights.data[i].direction));
- if (angle > lights.data[i].spot_angle) {
- attenuation = 0.0;
- } else {
- float d = clamp(angle / lights.data[i].spot_angle, 0, 1);
- attenuation *= pow(1.0 - d, lights.data[i].spot_attenuation);
+ float cos_spot_angle = lights.data[i].cos_spot_angle;
+ float cos_angle = dot(-direction, lights.data[i].direction);
+
+ if (cos_angle < cos_spot_angle) {
+ continue;
}
+
+ float scos = max(cos_angle, cos_spot_angle);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle));
+ attenuation *= 1.0 - pow(spot_rim, lights.data[i].inv_spot_attenuation);
} break;
}
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl
index e4f6f4b7ea..007e4c113a 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl
@@ -244,20 +244,26 @@ void main() {
vec4 light;
if (hit) {
- const float EPSILON = 0.001;
- vec3 hit_normal = normalize(vec3(
- texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(EPSILON, 0.0, 0.0)).r,
- texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(0.0, EPSILON, 0.0)).r,
- texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(0.0, 0.0, EPSILON)).r));
-
- vec3 hit_light = texture(sampler3D(light_cascades[hit_cascade], linear_sampler), uvw).rgb;
- vec4 aniso0 = texture(sampler3D(aniso0_cascades[hit_cascade], linear_sampler), uvw);
- vec3 hit_aniso0 = aniso0.rgb;
- vec3 hit_aniso1 = vec3(aniso0.a, texture(sampler3D(aniso1_cascades[hit_cascade], linear_sampler), uvw).rg);
-
- //one liner magic
- light.rgb = hit_light * (dot(max(vec3(0.0), (hit_normal * hit_aniso0)), vec3(1.0)) + dot(max(vec3(0.0), (-hit_normal * hit_aniso1)), vec3(1.0)));
- light.a = 1.0;
+ //avoid reading different texture from different threads
+ for (uint j = params.cascade; j < params.max_cascades; j++) {
+ if (j == hit_cascade) {
+ const float EPSILON = 0.001;
+ vec3 hit_normal = normalize(vec3(
+ texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(EPSILON, 0.0, 0.0)).r,
+ texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(0.0, EPSILON, 0.0)).r,
+ texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(0.0, 0.0, EPSILON)).r));
+
+ vec3 hit_light = texture(sampler3D(light_cascades[hit_cascade], linear_sampler), uvw).rgb;
+ vec4 aniso0 = texture(sampler3D(aniso0_cascades[hit_cascade], linear_sampler), uvw);
+ vec3 hit_aniso0 = aniso0.rgb;
+ vec3 hit_aniso1 = vec3(aniso0.a, texture(sampler3D(aniso1_cascades[hit_cascade], linear_sampler), uvw).rg);
+
+ //one liner magic
+ light.rgb = hit_light * (dot(max(vec3(0.0), (hit_normal * hit_aniso0)), vec3(1.0)) + dot(max(vec3(0.0), (-hit_normal * hit_aniso1)), vec3(1.0)));
+ light.a = 1.0;
+ }
+ }
+
} else if (params.sky_mode == SKY_MODE_SKY) {
#ifdef USE_CUBEMAP_ARRAY
light.rgb = textureLod(samplerCubeArray(sky_irradiance, linear_sampler_mipmaps), vec4(ray_dir, 0.0), 2.0).rgb; //use second mipmap because we dont usually throw a lot of rays, so this compensates
diff --git a/servers/rendering/renderer_rd/shaders/shadow_reduce.glsl b/servers/rendering/renderer_rd/shaders/shadow_reduce.glsl
deleted file mode 100644
index 29443ae7db..0000000000
--- a/servers/rendering/renderer_rd/shaders/shadow_reduce.glsl
+++ /dev/null
@@ -1,105 +0,0 @@
-#[compute]
-
-#version 450
-
-VERSION_DEFINES
-
-#define BLOCK_SIZE 8
-
-layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
-
-#ifdef MODE_REDUCE
-
-shared float tmp_data[BLOCK_SIZE * BLOCK_SIZE];
-const uint swizzle_table[BLOCK_SIZE] = uint[](0, 4, 2, 6, 1, 5, 3, 7);
-const uint unswizzle_table[BLOCK_SIZE] = uint[](0, 0, 0, 1, 0, 2, 1, 3);
-
-#endif
-
-layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D source_depth;
-layout(r32f, set = 0, binding = 1) uniform restrict writeonly image2D dst_depth;
-
-layout(push_constant, binding = 1, std430) uniform Params {
- ivec2 source_size;
- ivec2 source_offset;
- uint min_size;
- uint gaussian_kernel_version;
- ivec2 filter_dir;
-}
-params;
-
-void main() {
-#ifdef MODE_REDUCE
-
- uvec2 pos = gl_LocalInvocationID.xy;
-
- ivec2 image_offset = params.source_offset;
- ivec2 image_pos = image_offset + ivec2(gl_GlobalInvocationID.xy);
- uint dst_t = swizzle_table[pos.y] * BLOCK_SIZE + swizzle_table[pos.x];
- tmp_data[dst_t] = imageLoad(source_depth, min(image_pos, params.source_size - ivec2(1))).r;
- ivec2 image_size = params.source_size;
-
- uint t = pos.y * BLOCK_SIZE + pos.x;
-
- //neighbours
- uint size = BLOCK_SIZE;
-
- do {
- groupMemoryBarrier();
- barrier();
-
- size >>= 1;
- image_size >>= 1;
- image_offset >>= 1;
-
- if (all(lessThan(pos, uvec2(size)))) {
- uint nx = t + size;
- uint ny = t + (BLOCK_SIZE * size);
- uint nxy = ny + size;
-
- tmp_data[t] += tmp_data[nx];
- tmp_data[t] += tmp_data[ny];
- tmp_data[t] += tmp_data[nxy];
- tmp_data[t] /= 4.0;
- }
-
- } while (size > params.min_size);
-
- if (all(lessThan(pos, uvec2(size)))) {
- image_pos = ivec2(unswizzle_table[size + pos.x], unswizzle_table[size + pos.y]);
- image_pos += image_offset + ivec2(gl_WorkGroupID.xy) * int(size);
-
- image_size = max(ivec2(1), image_size); //in case image size became 0
-
- if (all(lessThan(image_pos, uvec2(image_size)))) {
- imageStore(dst_depth, image_pos, vec4(tmp_data[t]));
- }
- }
-#endif
-
-#ifdef MODE_FILTER
-
- ivec2 image_pos = params.source_offset + ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThanEqual(image_pos, params.source_size))) {
- return;
- }
-
- ivec2 clamp_min = ivec2(params.source_offset);
- ivec2 clamp_max = ivec2(params.source_size) - 1;
-
- //gaussian kernel, size 9, sigma 4
- const int kernel_size = 9;
- const float gaussian_kernel[kernel_size * 3] = float[](
- 0.000229, 0.005977, 0.060598, 0.241732, 0.382928, 0.241732, 0.060598, 0.005977, 0.000229,
- 0.028532, 0.067234, 0.124009, 0.179044, 0.20236, 0.179044, 0.124009, 0.067234, 0.028532,
- 0.081812, 0.101701, 0.118804, 0.130417, 0.134535, 0.130417, 0.118804, 0.101701, 0.081812);
- float accum = 0.0;
- for (int i = 0; i < kernel_size; i++) {
- ivec2 ofs = clamp(image_pos + params.filter_dir * (i - kernel_size / 2), clamp_min, clamp_max);
- accum += imageLoad(source_depth, ofs).r * gaussian_kernel[params.gaussian_kernel_version + i];
- }
-
- imageStore(dst_depth, image_pos, vec4(accum));
-
-#endif
-}
diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl
index b19f5a9ad3..680d1045cd 100644
--- a/servers/rendering/renderer_rd/shaders/skeleton.glsl
+++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl
@@ -100,7 +100,7 @@ void main() {
for (uint i = 0; i < params.blend_shape_count; i++) {
float w = blend_shape_weights.data[i];
- if (w > 0.0001) {
+ if (abs(w) > 0.0001) {
uint base_offset = (params.vertex_count * i + index) * params.vertex_stride;
blend_vertex += uintBitsToFloat(uvec3(src_blend_shapes.data[base_offset + 0], src_blend_shapes.data[base_offset + 1], src_blend_shapes.data[base_offset + 2])) * w;
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
index aa32809a06..e7ba8feb80 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
@@ -168,13 +168,18 @@ layout(set = 0, binding = 14, std140) uniform Params {
uint cluster_shift;
uint cluster_width;
- uvec3 cluster_pad;
uint max_cluster_element_count_div_32;
+ bool use_temporal_reprojection;
+ uint temporal_frame;
+ float temporal_blend;
mat3x4 cam_rotation;
+ mat4 to_prev_view;
}
params;
+layout(set = 0, binding = 15) uniform texture3D prev_density_texture;
+
float get_depth_at_pos(float cell_depth_size, int z) {
float d = float(z) * cell_depth_size + cell_depth_size * 0.5; //center of voxels
d = pow(d, params.detail_spread);
@@ -213,6 +218,26 @@ uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) {
return bitfieldInsert(uint(0), uint(0xFFFFFFFF), local_min, mask_width);
}
+#define TEMPORAL_FRAMES 16
+
+const vec3 halton_map[TEMPORAL_FRAMES] = vec3[](
+ vec3(0.5, 0.33333333, 0.2),
+ vec3(0.25, 0.66666667, 0.4),
+ vec3(0.75, 0.11111111, 0.6),
+ vec3(0.125, 0.44444444, 0.8),
+ vec3(0.625, 0.77777778, 0.04),
+ vec3(0.375, 0.22222222, 0.24),
+ vec3(0.875, 0.55555556, 0.44),
+ vec3(0.0625, 0.88888889, 0.64),
+ vec3(0.5625, 0.03703704, 0.84),
+ vec3(0.3125, 0.37037037, 0.08),
+ vec3(0.8125, 0.7037037, 0.28),
+ vec3(0.1875, 0.14814815, 0.48),
+ vec3(0.6875, 0.48148148, 0.68),
+ vec3(0.4375, 0.81481481, 0.88),
+ vec3(0.9375, 0.25925926, 0.12),
+ vec3(0.03125, 0.59259259, 0.32));
+
void main() {
vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size);
@@ -241,6 +266,45 @@ void main() {
view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
view_pos.y = -view_pos.y;
+ vec4 reprojected_density = vec4(0.0);
+ float reproject_amount = 0.0;
+
+ if (params.use_temporal_reprojection) {
+ vec3 prev_view = (params.to_prev_view * vec4(view_pos, 1.0)).xyz;
+ //undo transform into prev view
+ prev_view.y = -prev_view.y;
+ //z back to unit size
+ prev_view.z /= -params.fog_frustum_end;
+ //xy back to unit size
+ prev_view.xy /= mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(prev_view.z));
+ prev_view.xy = prev_view.xy * 0.5 + 0.5;
+ //z back to unspread value
+ prev_view.z = pow(prev_view.z, 1.0 / params.detail_spread);
+
+ if (all(greaterThan(prev_view, vec3(0.0))) && all(lessThan(prev_view, vec3(1.0)))) {
+ //reprojectinon fits
+
+ reprojected_density = textureLod(sampler3D(prev_density_texture, linear_sampler), prev_view, 0.0);
+ reproject_amount = params.temporal_blend;
+
+ // Since we can reproject, now we must jitter the current view pos.
+ // This is done here because cells that can't reproject should not jitter.
+
+ fog_unit_pos = posf * fog_cell_size + fog_cell_size * halton_map[params.temporal_frame]; //center of voxels, offset by halton table
+
+ screen_pos = uvec2(fog_unit_pos.xy * params.screen_size);
+ cluster_pos = screen_pos >> params.cluster_shift;
+ cluster_offset = (params.cluster_width * cluster_pos.y + cluster_pos.x) * (params.max_cluster_element_count_div_32 + 32);
+ //positions in screen are too spread apart, no hopes for optimizing with subgroups
+
+ fog_unit_pos.z = pow(fog_unit_pos.z, params.detail_spread);
+
+ view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(fog_unit_pos.z));
+ view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
+ view_pos.y = -view_pos.y;
+ }
+ }
+
uint cluster_z = uint(clamp((abs(view_pos.z) / params.z_far) * 32.0, 0.0, 31.0));
vec3 total_light = params.light_color;
@@ -433,31 +497,31 @@ void main() {
uint light_index = 32 * i + bit;
- vec3 light_pos = omni_lights.data[light_index].position;
- vec3 light_rel_vec = omni_lights.data[light_index].position - view_pos;
+ vec3 light_pos = spot_lights.data[light_index].position;
+ vec3 light_rel_vec = spot_lights.data[light_index].position - view_pos;
float d = length(light_rel_vec);
float shadow_attenuation = 1.0;
- if (d * omni_lights.data[light_index].inv_radius < 1.0) {
- float attenuation = get_omni_attenuation(d, omni_lights.data[light_index].inv_radius, omni_lights.data[light_index].attenuation);
+ if (d * spot_lights.data[light_index].inv_radius < 1.0) {
+ float attenuation = get_omni_attenuation(d, spot_lights.data[light_index].inv_radius, spot_lights.data[light_index].attenuation);
- vec3 spot_dir = omni_lights.data[light_index].direction;
- float scos = max(dot(-normalize(light_rel_vec), spot_dir), omni_lights.data[light_index].cone_angle);
- float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - omni_lights.data[light_index].cone_angle));
- attenuation *= 1.0 - pow(spot_rim, omni_lights.data[light_index].cone_attenuation);
+ vec3 spot_dir = spot_lights.data[light_index].direction;
+ float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights.data[light_index].cone_angle);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights.data[light_index].cone_angle));
+ attenuation *= 1.0 - pow(spot_rim, spot_lights.data[light_index].cone_attenuation);
- vec3 light = omni_lights.data[light_index].color / M_PI;
+ vec3 light = spot_lights.data[light_index].color / M_PI;
- if (omni_lights.data[light_index].shadow_enabled) {
+ if (spot_lights.data[light_index].shadow_enabled) {
//has shadow
vec4 v = vec4(view_pos, 1.0);
- vec4 splane = (omni_lights.data[light_index].shadow_matrix * v);
+ vec4 splane = (spot_lights.data[light_index].shadow_matrix * v);
splane /= splane.w;
float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
- shadow_attenuation = exp(min(0.0, (depth - splane.z)) / omni_lights.data[light_index].inv_radius * omni_lights.data[light_index].shadow_volumetric_fog_fade);
+ shadow_attenuation = exp(min(0.0, (depth - splane.z)) / spot_lights.data[light_index].inv_radius * spot_lights.data[light_index].shadow_volumetric_fog_fade);
}
total_light += light * attenuation * shadow_attenuation;
@@ -565,7 +629,11 @@ void main() {
#endif
- imageStore(density_map, pos, vec4(total_light, total_density));
+ vec4 final_density = vec4(total_light, total_density);
+
+ final_density = mix(final_density, reprojected_density, reproject_amount);
+
+ imageStore(density_map, pos, final_density);
#endif
#ifdef MODE_FOG
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index d92642886c..b546001843 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -36,7 +36,8 @@
class RendererScene {
public:
- virtual RID camera_create() = 0;
+ virtual RID camera_allocate() = 0;
+ virtual void camera_initialize(RID p_rid) = 0;
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0;
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0;
@@ -48,7 +49,8 @@ public:
virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0;
virtual bool is_camera(RID p_camera) const = 0;
- virtual RID scenario_create() = 0;
+ virtual RID scenario_allocate() = 0;
+ virtual void scenario_initialize(RID p_rid) = 0;
virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) = 0;
virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0;
@@ -58,7 +60,8 @@ public:
virtual bool is_scenario(RID p_scenario) const = 0;
virtual RID scenario_get_environment(RID p_scenario) = 0;
- virtual RID instance_create() = 0;
+ virtual RID instance_allocate() = 0;
+ virtual void instance_initialize(RID p_rid) = 0;
virtual void instance_set_base(RID p_instance, RID p_base) = 0;
virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0;
@@ -99,7 +102,9 @@ public:
/* SKY API */
- virtual RID sky_create() = 0;
+ virtual RID sky_allocate() = 0;
+ virtual void sky_initialize(RID p_rid) = 0;
+
virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0;
virtual void sky_set_mode(RID p_sky, RS::SkyMode p_samples) = 0;
virtual void sky_set_material(RID p_sky, RID p_material) = 0;
@@ -107,7 +112,8 @@ public:
/* ENVIRONMENT API */
- virtual RID environment_create() = 0;
+ virtual RID environment_allocate() = 0;
+ virtual void environment_initialize(RID p_rid) = 0;
virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0;
virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
@@ -122,12 +128,10 @@ public:
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) = 0;
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
- virtual void environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) = 0;
- virtual void environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size) = 0;
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0;
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0;
@@ -136,7 +140,7 @@ public:
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
+ virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
@@ -161,7 +165,8 @@ public:
/* Camera Effects */
- virtual RID camera_effects_create() = 0;
+ virtual RID camera_effects_allocate() = 0;
+ virtual void camera_effects_initialize(RID p_rid) = 0;
virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) = 0;
virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) = 0;
@@ -179,6 +184,7 @@ public:
/* Render Buffers */
virtual RID render_buffers_create() = 0;
+
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index db601ba49c..e8155e4025 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -39,9 +39,11 @@
/* CAMERA API */
-RID RendererSceneCull::camera_create() {
- Camera *camera = memnew(Camera);
- return camera_owner.make_rid(camera);
+RID RendererSceneCull::camera_allocate() {
+ return camera_owner.allocate_rid();
+}
+void RendererSceneCull::camera_initialize(RID p_rid) {
+ camera_owner.initialize_rid(p_rid, memnew(Camera));
}
void RendererSceneCull::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) {
@@ -290,11 +292,12 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
}
}
-RID RendererSceneCull::scenario_create() {
+RID RendererSceneCull::scenario_allocate() {
+ return scenario_owner.allocate_rid();
+}
+void RendererSceneCull::scenario_initialize(RID p_rid) {
Scenario *scenario = memnew(Scenario);
- ERR_FAIL_COND_V(!scenario, RID());
- RID scenario_rid = scenario_owner.make_rid(scenario);
- scenario->self = scenario_rid;
+ scenario->self = p_rid;
scenario->reflection_probe_shadow_atlas = scene_render->shadow_atlas_create();
scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest
@@ -307,7 +310,7 @@ RID RendererSceneCull::scenario_create() {
scenario->instance_aabbs.set_page_pool(&instance_aabb_page_pool);
scenario->instance_data.set_page_pool(&instance_data_page_pool);
- return scenario_rid;
+ scenario_owner.initialize_rid(p_rid, scenario);
}
void RendererSceneCull::scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) {
@@ -367,14 +370,14 @@ void RendererSceneCull::_instance_queue_update(Instance *p_instance, bool p_upda
_instance_update_list.add(&p_instance->update_item);
}
-RID RendererSceneCull::instance_create() {
+RID RendererSceneCull::instance_allocate() {
+ return instance_owner.allocate_rid();
+}
+void RendererSceneCull::instance_initialize(RID p_rid) {
Instance *instance = memnew(Instance);
- ERR_FAIL_COND_V(!instance, RID());
+ instance->self = p_rid;
- RID instance_rid = instance_owner.make_rid(instance);
- instance->self = instance_rid;
-
- return instance_rid;
+ instance_owner.initialize_rid(p_rid, instance);
}
void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
@@ -1906,6 +1909,9 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
RS::LightOmniShadowMode shadow_mode = RSG::storage->light_omni_get_shadow_mode(p_instance->base);
if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !scene_render->light_instances_can_render_shadow_cube()) {
+ if (max_shadows_used + 2 > MAX_UPDATE_SHADOWS) {
+ return true;
+ }
for (int i = 0; i < 2; i++) {
//using this one ensures that raster deferred will have it
RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i));
@@ -1922,7 +1928,6 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
planes.write[5] = light_transform.xform(Plane(Vector3(0, 0, -z), 0));
- geometry_instances_to_shadow_render.clear();
instance_shadow_cull_result.clear();
Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());
@@ -1943,6 +1948,8 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
+ RendererSceneRender::RenderShadowData &shadow_data = render_shadow_data[max_shadows_used++];
+
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
@@ -1957,16 +1964,21 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
}
- geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
+ shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
RSG::storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
- scene_render->render_shadow(light->instance, p_shadow_atlas, i, geometry_instances_to_shadow_render);
+ shadow_data.light = light->instance;
+ shadow_data.pass = i;
}
} else { //shadow cube
+ if (max_shadows_used + 6 > MAX_UPDATE_SHADOWS) {
+ return true;
+ }
+
real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
CameraMatrix cm;
cm.set_perspective(90, 1, 0.01, radius);
@@ -1996,7 +2008,6 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
Vector<Plane> planes = cm.get_projection_planes(xform);
- geometry_instances_to_shadow_render.clear();
instance_shadow_cull_result.clear();
Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());
@@ -2015,7 +2026,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);
- Plane near_plane(xform.origin, -xform.basis.get_axis(2));
+ RendererSceneRender::RenderShadowData &shadow_data = render_shadow_data[max_shadows_used++];
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
@@ -2030,22 +2041,28 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
}
- geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
+ shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
RSG::storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
- scene_render->render_shadow(light->instance, p_shadow_atlas, i, geometry_instances_to_shadow_render);
+
+ shadow_data.light = light->instance;
+ shadow_data.pass = i;
}
//restore the regular DP matrix
- scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0);
+ //scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0);
}
} break;
case RS::LIGHT_SPOT: {
RENDER_TIMESTAMP("Culling Spot Light");
+ if (max_shadows_used + 1 > MAX_UPDATE_SHADOWS) {
+ return true;
+ }
+
real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
real_t angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
@@ -2054,7 +2071,6 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
Vector<Plane> planes = cm.get_projection_planes(light_transform);
- geometry_instances_to_shadow_render.clear();
instance_shadow_cull_result.clear();
Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());
@@ -2073,7 +2089,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);
- Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
+ RendererSceneRender::RenderShadowData &shadow_data = render_shadow_data[max_shadows_used++];
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
@@ -2088,13 +2104,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
- geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
+ shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
RSG::storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
- scene_render->render_shadow(light->instance, p_shadow_atlas, 0, geometry_instances_to_shadow_render);
+ shadow_data.light = light->instance;
+ shadow_data.pass = 0;
} break;
}
@@ -2147,14 +2164,13 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
RID environment = _render_get_environment(p_camera, p_scenario);
- _prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold);
- _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
+ _render_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
#endif
}
void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas) {
// render for AR/VR interface
-
+#if 0
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
@@ -2234,6 +2250,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_
// And render our scene...
_render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
+#endif
};
void RendererSceneCull::_frustum_cull_threaded(uint32_t p_thread, FrustumCullData *cull_data) {
@@ -2452,7 +2469,7 @@ void RendererSceneCull::_frustum_cull(FrustumCullData &cull_data, FrustumCullRes
}
}
-void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, float p_screen_lod_threshold, bool p_using_shadows) {
+void RendererSceneCull::_render_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows) {
// Note, in stereo rendering:
// - p_cam_transform will be a transform in the middle of our two eyes
// - p_cam_projection is a wider frustrum that encompasses both eyes
@@ -2466,6 +2483,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
scene_render->set_scene_pass(render_pass);
if (p_render_buffers.is_valid()) {
+ //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_cam_transform.origin); //update conditions for SDFGI (whether its used or not)
}
@@ -2596,62 +2614,28 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
//render shadows
- for (uint32_t i = 0; i < cull.shadow_count; i++) {
- for (uint32_t j = 0; j < cull.shadows[i].cascade_count; j++) {
- const Cull::Shadow::Cascade &c = cull.shadows[i].cascades[j];
- // print_line("shadow " + itos(i) + " cascade " + itos(j) + " elements: " + itos(c.cull_result.size()));
- scene_render->light_instance_set_shadow_transform(cull.shadows[i].light_instance, c.projection, c.transform, c.zfar, c.split, j, c.shadow_texel_size, c.bias_scale, c.range_begin, c.uv_scale);
- scene_render->render_shadow(cull.shadows[i].light_instance, p_shadow_atlas, j, frustum_cull_result.directional_shadows[i].cascade_geometry_instances[j], near_plane, p_cam_projection.get_lod_multiplier(), p_screen_lod_threshold);
- }
- }
+ max_shadows_used = 0;
- //render SDFGI
+ if (p_using_shadows) { //setup shadow maps
- {
- if (cull.sdfgi.region_count > 0) {
- //update regions
- for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {
- scene_render->render_sdfgi(p_render_buffers, i, frustum_cull_result.sdfgi_region_geometry_instances[i]);
- }
- //check if static lights were culled
- bool static_lights_culled = false;
- for (uint32_t i = 0; i < cull.sdfgi.cascade_light_count; i++) {
- if (frustum_cull_result.sdfgi_cascade_lights[i].size()) {
- static_lights_culled = true;
- break;
- }
- }
+ // Directional Shadows
- if (static_lights_culled) {
- scene_render->render_sdfgi_static_lights(p_render_buffers, cull.sdfgi.cascade_light_count, cull.sdfgi.cascade_light_index, frustum_cull_result.sdfgi_cascade_lights);
+ for (uint32_t i = 0; i < cull.shadow_count; i++) {
+ for (uint32_t j = 0; j < cull.shadows[i].cascade_count; j++) {
+ const Cull::Shadow::Cascade &c = cull.shadows[i].cascades[j];
+ // print_line("shadow " + itos(i) + " cascade " + itos(j) + " elements: " + itos(c.cull_result.size()));
+ scene_render->light_instance_set_shadow_transform(cull.shadows[i].light_instance, c.projection, c.transform, c.zfar, c.split, j, c.shadow_texel_size, c.bias_scale, c.range_begin, c.uv_scale);
+ if (max_shadows_used == MAX_UPDATE_SHADOWS) {
+ continue;
+ }
+ render_shadow_data[max_shadows_used].light = cull.shadows[i].light_instance;
+ render_shadow_data[max_shadows_used].pass = j;
+ render_shadow_data[max_shadows_used].instances.merge_unordered(frustum_cull_result.directional_shadows[i].cascade_geometry_instances[j]);
+ max_shadows_used++;
}
}
- if (p_render_buffers.is_valid()) {
- scene_render->sdfgi_update_probes(p_render_buffers, p_environment, directional_lights, scenario->dynamic_lights.ptr(), scenario->dynamic_lights.size());
- }
- }
-
- //light_samplers_culled=0;
-
- /*
- print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0));
- print_line("OTO: "+itos(p_scenario->octree.get_octant_count()));
- print_line("OTE: "+itos(p_scenario->octree.get_elem_count()));
- print_line("OTP: "+itos(p_scenario->octree.get_pair_count()));
- */
-
- /* STEP 3 - PROCESS PORTALS, VALIDATE ROOMS */
- //removed, will replace with culling
-
- /* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */
-
- /* STEP 5 - PROCESS POSITIONAL LIGHTS */
-
- if (p_using_shadows) { //setup shadow maps
-
- //SortArray<Instance*,_InstanceLightsort> sorter;
- //sorter.sort(light_cull_result,light_cull_count);
+ // Positional Shadowss
for (uint32_t i = 0; i < (uint32_t)frustum_cull_result.lights.size(); i++) {
Instance *ins = frustum_cull_result.lights[i];
@@ -2738,19 +2722,78 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
bool redraw = scene_render->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version);
- if (redraw) {
+ if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) {
//must redraw!
RENDER_TIMESTAMP(">Rendering Light " + itos(i));
light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
RENDER_TIMESTAMP("<Rendering Light " + itos(i));
+ } else {
+ light->shadow_dirty = redraw;
}
}
}
+ //render SDFGI
+
+ {
+ sdfgi_update_data.update_static = false;
+
+ if (cull.sdfgi.region_count > 0) {
+ //update regions
+ for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {
+ render_sdfgi_data[i].instances.merge_unordered(frustum_cull_result.sdfgi_region_geometry_instances[i]);
+ render_sdfgi_data[i].region = i;
+ }
+ //check if static lights were culled
+ bool static_lights_culled = false;
+ for (uint32_t i = 0; i < cull.sdfgi.cascade_light_count; i++) {
+ if (frustum_cull_result.sdfgi_cascade_lights[i].size()) {
+ static_lights_culled = true;
+ break;
+ }
+ }
+
+ if (static_lights_culled) {
+ sdfgi_update_data.static_cascade_count = cull.sdfgi.cascade_light_count;
+ sdfgi_update_data.static_cascade_indices = cull.sdfgi.cascade_light_index;
+ sdfgi_update_data.static_positional_lights = frustum_cull_result.sdfgi_cascade_lights;
+ sdfgi_update_data.update_static = true;
+ }
+ }
+
+ if (p_render_buffers.is_valid()) {
+ 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();
+ }
+ }
+
//append the directional lights to the lights culled
for (int i = 0; i < directional_lights.size(); i++) {
frustum_cull_result.light_instances.push_back(directional_lights[i]);
}
+
+ RID camera_effects;
+ if (p_force_camera_effects.is_valid()) {
+ camera_effects = p_force_camera_effects;
+ } else {
+ camera_effects = scenario->camera_effects;
+ }
+ /* PROCESS GEOMETRY AND DRAW SCENE */
+
+ RENDER_TIMESTAMP("Render Scene ");
+ scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, frustum_cull_result.geometry_instances, frustum_cull_result.light_instances, frustum_cull_result.reflections, frustum_cull_result.gi_probes, frustum_cull_result.decals, frustum_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data);
+
+ for (uint32_t i = 0; i < max_shadows_used; i++) {
+ render_shadow_data[i].instances.clear();
+ }
+ max_shadows_used = 0;
+
+ for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {
+ render_sdfgi_data[i].instances.clear();
+ }
+
+ // virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
}
RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
@@ -2774,21 +2817,6 @@ RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
return RID();
}
-void RendererSceneCull::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
- Scenario *scenario = scenario_owner.getornull(p_scenario);
-
- RID camera_effects;
- if (p_force_camera_effects.is_valid()) {
- camera_effects = p_force_camera_effects;
- } else {
- camera_effects = scenario->camera_effects;
- }
- /* PROCESS GEOMETRY AND DRAW SCENE */
-
- RENDER_TIMESTAMP("Render Scene ");
- scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, frustum_cull_result.geometry_instances, frustum_cull_result.light_instances, frustum_cull_result.reflections, frustum_cull_result.gi_probes, frustum_cull_result.decals, frustum_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold);
-}
-
void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
#ifndef _3D_DISABLED
@@ -2801,7 +2829,7 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
environment = scenario->fallback_environment;
}
RENDER_TIMESTAMP("Render Empty Scene ");
- scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0, 0);
+ scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
@@ -2864,8 +2892,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
}
RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step));
- _prepare_scene(xform, cm, false, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, lod_threshold, use_shadows);
- _render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step, lod_threshold);
+ _render_scene(xform, cm, false, false, RID(), RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step, lod_threshold, use_shadows);
} else {
//do roughness postprocess step until it believes it's done
@@ -3493,7 +3520,12 @@ RendererSceneCull::RendererSceneCull() {
instance_cull_result.set_page_pool(&instance_cull_page_pool);
instance_shadow_cull_result.set_page_pool(&instance_cull_page_pool);
- geometry_instances_to_shadow_render.set_page_pool(&geometry_instance_cull_page_pool);
+ for (uint32_t i = 0; i < MAX_UPDATE_SHADOWS; i++) {
+ render_shadow_data[i].instances.set_page_pool(&geometry_instance_cull_page_pool);
+ }
+ for (uint32_t i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {
+ render_sdfgi_data[i].instances.set_page_pool(&geometry_instance_cull_page_pool);
+ }
frustum_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
frustum_cull_result_threads.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
@@ -3501,8 +3533,8 @@ RendererSceneCull::RendererSceneCull() {
frustum_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
}
- indexer_update_iterations = GLOBAL_GET("rendering/spatial_indexer/update_iterations_per_frame");
- thread_cull_threshold = GLOBAL_GET("rendering/spatial_indexer/threaded_cull_minimum_instances");
+ indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame");
+ thread_cull_threshold = GLOBAL_GET("rendering/limits/spatial_indexer/threaded_cull_minimum_instances");
thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)RendererThreadPool::singleton->thread_work_pool.get_thread_count()); //make sure there is at least one thread per CPU
}
@@ -3510,7 +3542,12 @@ RendererSceneCull::~RendererSceneCull() {
instance_cull_result.reset();
instance_shadow_cull_result.reset();
- geometry_instances_to_shadow_render.reset();
+ for (uint32_t i = 0; i < MAX_UPDATE_SHADOWS; i++) {
+ render_shadow_data[i].instances.reset();
+ }
+ for (uint32_t i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {
+ render_sdfgi_data[i].instances.reset();
+ }
frustum_cull_result.reset();
for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 2ffaf48675..32f4334288 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -54,7 +54,8 @@ public:
enum {
SDFGI_MAX_CASCADES = 8,
SDFGI_MAX_REGIONS_PER_CASCADE = 3,
- MAX_INSTANCE_PAIRS = 32
+ MAX_INSTANCE_PAIRS = 32,
+ MAX_UPDATE_SHADOWS = 512
};
uint64_t render_pass;
@@ -93,9 +94,11 @@ public:
}
};
- mutable RID_PtrOwner<Camera> camera_owner;
+ mutable RID_PtrOwner<Camera, true> camera_owner;
+
+ virtual RID camera_allocate();
+ virtual void camera_initialize(RID p_rid);
- virtual RID camera_create();
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far);
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far);
virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far);
@@ -295,14 +298,15 @@ public:
int indexer_update_iterations = 0;
- mutable RID_PtrOwner<Scenario> scenario_owner;
+ mutable RID_PtrOwner<Scenario, true> scenario_owner;
static void _instance_pair(Instance *p_A, Instance *p_B);
static void _instance_unpair(Instance *p_A, Instance *p_B);
void _instance_update_mesh_instance(Instance *p_instance);
- virtual RID scenario_create();
+ virtual RID scenario_allocate();
+ virtual void scenario_initialize(RID p_rid);
virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode);
virtual void scenario_set_environment(RID p_scenario, RID p_environment);
@@ -696,7 +700,6 @@ public:
PagedArray<Instance *> instance_cull_result;
PagedArray<Instance *> instance_shadow_cull_result;
- PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances_to_shadow_render;
struct FrustumCullResult {
PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances;
@@ -816,13 +819,20 @@ public:
FrustumCullResult frustum_cull_result;
LocalVector<FrustumCullResult> frustum_cull_result_threads;
+ RendererSceneRender::RenderShadowData render_shadow_data[MAX_UPDATE_SHADOWS];
+ uint32_t max_shadows_used = 0;
+
+ RendererSceneRender::RenderSDFGIData render_sdfgi_data[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
+ RendererSceneRender::RenderSDFGIUpdateData sdfgi_update_data;
+
uint32_t thread_cull_threshold = 200;
- RID_PtrOwner<Instance> instance_owner;
+ RID_PtrOwner<Instance, true> instance_owner;
uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecesary on clustered
- virtual RID instance_create();
+ virtual RID instance_allocate();
+ virtual void instance_initialize(RID p_rid);
virtual void instance_set_base(RID p_instance, RID p_base);
virtual void instance_set_scenario(RID p_instance, RID p_scenario);
@@ -924,8 +934,7 @@ public:
void _frustum_cull(FrustumCullData &cull_data, FrustumCullResult &cull_result, uint64_t p_from, uint64_t p_to);
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
- void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, float p_screen_lod_threshold, bool p_using_shadows = true);
- void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
+ void _render_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows = true);
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas);
@@ -952,13 +961,16 @@ public:
/* SKY API */
- PASS0R(RID, sky_create)
+ PASS0R(RID, sky_allocate)
+ PASS1(sky_initialize, RID)
+
PASS2(sky_set_radiance_size, RID, int)
PASS2(sky_set_mode, RID, RS::SkyMode)
PASS2(sky_set_material, RID, RID)
PASS4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &)
- PASS0R(RID, environment_create)
+ PASS0R(RID, environment_allocate)
+ PASS1(environment_initialize, RID)
PASS1RC(bool, is_environment, RID)
@@ -986,14 +998,12 @@ public:
PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
- PASS9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, RS::EnvVolumetricFogShadowFilter)
+ PASS10(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, bool, float)
PASS2(environment_set_volumetric_fog_volume_size, int, int)
PASS1(environment_set_volumetric_fog_filter_active, bool)
- PASS1(environment_set_volumetric_fog_directional_shadow_shrink_size, int)
- PASS1(environment_set_volumetric_fog_positional_shadow_shrink_size, int)
- PASS11(environment_set_sdfgi, RID, bool, RS::EnvironmentSDFGICascades, float, RS::EnvironmentSDFGIYScale, bool, bool, bool, float, float, float)
+ PASS11(environment_set_sdfgi, RID, bool, RS::EnvironmentSDFGICascades, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
PASS1(environment_set_sdfgi_ray_count, RS::EnvironmentSDFGIRayCount)
PASS1(environment_set_sdfgi_frames_to_converge, RS::EnvironmentSDFGIFramesToConverge)
PASS1(environment_set_sdfgi_frames_to_update_light, RS::EnvironmentSDFGIFramesToUpdateLight)
@@ -1009,7 +1019,8 @@ public:
/* CAMERA EFFECTS */
- PASS0R(RID, camera_effects_create)
+ PASS0R(RID, camera_effects_allocate)
+ PASS1(camera_effects_initialize, RID)
PASS2(camera_effects_set_dof_blur_quality, RS::DOFBlurQuality, bool)
PASS1(camera_effects_set_dof_blur_bokeh_shape, RS::DOFBokehShape)
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index ecec03db94..1dea3580b6 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -71,8 +71,7 @@ public:
/* SHADOW ATLAS API */
- virtual RID
- shadow_atlas_create() = 0;
+ virtual RID shadow_atlas_create() = 0;
virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false) = 0;
virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0;
@@ -87,11 +86,12 @@ public:
virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0;
- virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const Vector<RID> &p_directional_lights, const RID *p_positional_light_instances, uint32_t p_positional_light_count) = 0;
/* SKY API */
- virtual RID sky_create() = 0;
+ virtual RID sky_allocate() = 0;
+ virtual void sky_initialize(RID p_rid) = 0;
+
virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0;
virtual void sky_set_mode(RID p_sky, RS::SkyMode p_samples) = 0;
virtual void sky_set_material(RID p_sky, RID p_material) = 0;
@@ -99,7 +99,8 @@ public:
/* ENVIRONMENT API */
- virtual RID environment_create() = 0;
+ virtual RID environment_allocate() = 0;
+ virtual void environment_initialize(RID p_rid) = 0;
virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0;
virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
@@ -118,12 +119,9 @@ public:
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) = 0;
-
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
- virtual void environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) = 0;
- virtual void environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size) = 0;
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0;
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0;
@@ -132,7 +130,7 @@ public:
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
+ virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
@@ -150,7 +148,8 @@ public:
virtual RS::EnvironmentBG environment_get_background(RID p_env) const = 0;
virtual int environment_get_canvas_max_layer(RID p_env) const = 0;
- virtual RID camera_effects_create() = 0;
+ virtual RID camera_effects_allocate() = 0;
+ virtual void camera_effects_initialize(RID p_rid) = 0;
virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) = 0;
virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) = 0;
@@ -195,12 +194,31 @@ public:
virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
- virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) = 0;
+ struct RenderShadowData {
+ RID light;
+ int pass = 0;
+ PagedArray<GeometryInstance *> instances;
+ };
+
+ struct RenderSDFGIData {
+ int region = 0;
+ PagedArray<GeometryInstance *> instances;
+ };
+
+ struct RenderSDFGIUpdateData {
+ bool update_static = false;
+ uint32_t static_cascade_count;
+ uint32_t *static_cascade_indices;
+ PagedArray<RID> *static_positional_lights;
+
+ const Vector<RID> *directional_lights;
+ const RID *positional_light_instances;
+ uint32_t positional_light_count;
+ };
+
+ virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) = 0;
- virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) = 0;
virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances) = 0;
- virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_lights) = 0;
virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
virtual void set_scene_pass(uint64_t p_pass) = 0;
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index 7a80c2b0bf..22cf6acb19 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -98,6 +98,7 @@ public:
while (to_clean_up.size()) {
to_clean_up.front()->get().first->instances.erase(to_clean_up.front()->get().second);
+ dependencies.erase(to_clean_up.front()->get().first);
to_clean_up.pop_front();
}
}
@@ -118,12 +119,15 @@ public:
Set<Dependency *> dependencies;
};
+ virtual bool can_create_resources_async() const = 0;
/* TEXTURE API */
- virtual RID texture_2d_create(const Ref<Image> &p_image) = 0;
- virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0;
- virtual RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
- virtual RID texture_proxy_create(RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
+ virtual RID texture_allocate() = 0;
+
+ virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0;
+ virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0;
+ virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
+ virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; //mostly used for video and streaming
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
@@ -131,9 +135,9 @@ public:
virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0;
//these two APIs can be used together or in combination with the others.
- virtual RID texture_2d_placeholder_create() = 0;
- virtual RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type) = 0;
- virtual RID texture_3d_placeholder_create() = 0;
+ virtual void texture_2d_placeholder_initialize(RID p_texture) = 0;
+ virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0;
+ virtual void texture_3d_placeholder_initialize(RID p_texture) = 0;
virtual Ref<Image> texture_2d_get(RID p_texture) const = 0;
virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0;
@@ -160,7 +164,9 @@ public:
/* CANVAS TEXTURE API */
- virtual RID canvas_texture_create() = 0;
+ virtual RID canvas_texture_allocate() = 0;
+ virtual void canvas_texture_initialize(RID p_rid) = 0;
+
virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0;
virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0;
@@ -169,7 +175,8 @@ public:
/* SHADER API */
- virtual RID shader_create() = 0;
+ virtual RID shader_allocate() = 0;
+ virtual void shader_initialize(RID p_rid) = 0;
virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
virtual String shader_get_code(RID p_shader) const = 0;
@@ -183,7 +190,8 @@ public:
/* COMMON MATERIAL API */
- virtual RID material_create() = 0;
+ virtual RID material_allocate() = 0;
+ virtual void material_initialize(RID p_rid) = 0;
virtual void material_set_render_priority(RID p_material, int priority) = 0;
virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0;
@@ -208,7 +216,8 @@ public:
/* MESH API */
- virtual RID mesh_create() = 0;
+ virtual RID mesh_allocate() = 0;
+ virtual void mesh_initialize(RID p_rid) = 0;
virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0;
@@ -250,9 +259,10 @@ public:
/* MULTIMESH API */
- virtual RID multimesh_create() = 0;
+ virtual RID multimesh_allocate() = 0;
+ virtual void multimesh_initialize(RID p_rid) = 0;
- virtual void multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
@@ -279,7 +289,9 @@ public:
/* IMMEDIATE API */
- virtual RID immediate_create() = 0;
+ virtual RID immediate_allocate() = 0;
+ virtual void immediate_initialize(RID p_rid) = 0;
+
virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) = 0;
virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0;
virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0;
@@ -295,8 +307,10 @@ public:
/* SKELETON API */
- virtual RID skeleton_create() = 0;
- virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
+ virtual RID skeleton_allocate() = 0;
+ virtual void skeleton_initialize(RID p_rid) = 0;
+
+ virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
virtual int skeleton_get_bone_count(RID p_skeleton) const = 0;
virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0;
virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
@@ -306,11 +320,14 @@ public:
/* Light API */
- virtual RID light_create(RS::LightType p_type) = 0;
+ virtual RID directional_light_allocate() = 0;
+ virtual void directional_light_initialize(RID p_rid) = 0;
- RID directional_light_create() { return light_create(RS::LIGHT_DIRECTIONAL); }
- RID omni_light_create() { return light_create(RS::LIGHT_OMNI); }
- RID spot_light_create() { return light_create(RS::LIGHT_SPOT); }
+ virtual RID omni_light_allocate() = 0;
+ virtual void omni_light_initialize(RID p_rid) = 0;
+
+ virtual RID spot_light_allocate() = 0;
+ virtual void spot_light_initialize(RID p_rid) = 0;
virtual void light_set_color(RID p_light, const Color &p_color) = 0;
virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) = 0;
@@ -348,7 +365,8 @@ public:
/* PROBE API */
- virtual RID reflection_probe_create() = 0;
+ virtual RID reflection_probe_allocate() = 0;
+ virtual void reflection_probe_initialize(RID p_rid) = 0;
virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0;
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
@@ -379,7 +397,9 @@ public:
/* DECAL API */
- virtual RID decal_create() = 0;
+ virtual RID decal_allocate() = 0;
+ virtual void decal_initialize(RID p_rid) = 0;
+
virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0;
virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0;
virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0;
@@ -394,9 +414,10 @@ public:
/* GI PROBE API */
- virtual RID gi_probe_create() = 0;
+ virtual RID gi_probe_allocate() = 0;
+ virtual void gi_probe_initialize(RID p_rid) = 0;
- virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
+ virtual void gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0;
virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0;
@@ -439,9 +460,10 @@ public:
virtual uint32_t gi_probe_get_version(RID p_probe) = 0;
- /* LIGHTMAP CAPTURE */
+ /* LIGHTMAP */
- virtual RID lightmap_create() = 0;
+ virtual RID lightmap_allocate() = 0;
+ virtual void lightmap_initialize(RID p_rid) = 0;
virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0;
virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0;
@@ -459,7 +481,8 @@ public:
/* PARTICLES */
- virtual RID particles_create() = 0;
+ virtual RID particles_allocate() = 0;
+ virtual void particles_initialize(RID p_rid) = 0;
virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0;
virtual bool particles_get_emitting(RID p_particles) = 0;
@@ -506,7 +529,9 @@ public:
/* PARTICLES COLLISION */
- virtual RID particles_collision_create() = 0;
+ virtual RID particles_collision_allocate() = 0;
+ virtual void particles_collision_initialize(RID p_rid) = 0;
+
virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0;
virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0;
virtual void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) = 0; //for spheres
@@ -583,7 +608,7 @@ public:
virtual void render_info_end_capture() = 0;
virtual int get_captured_render_info(RS::RenderInfo p_info) = 0;
- virtual int get_render_info(RS::RenderInfo p_info) = 0;
+ virtual uint64_t get_render_info(RS::RenderInfo p_info) = 0;
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index d52da5b331..a5d5033c18 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -457,7 +457,7 @@ void RendererViewport::draw_viewports() {
}
if (Engine::get_singleton()->is_editor_hint()) {
- set_default_clear_color(GLOBAL_GET("rendering/environment/default_clear_color"));
+ set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
}
//sort viewports
@@ -608,19 +608,20 @@ void RendererViewport::draw_viewports() {
}
}
-RID RendererViewport::viewport_create() {
- Viewport *viewport = memnew(Viewport);
-
- RID rid = viewport_owner.make_rid(viewport);
+RID RendererViewport::viewport_allocate() {
+ return viewport_owner.allocate_rid();
+}
- viewport->self = rid;
+void RendererViewport::viewport_initialize(RID p_rid) {
+ Viewport *viewport = memnew(Viewport);
+ viewport->self = p_rid;
viewport->hide_scenario = false;
viewport->hide_canvas = false;
viewport->render_target = RSG::storage->render_target_create();
viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
viewport->viewport_render_direct_to_screen = false;
- return rid;
+ viewport_owner.initialize_rid(p_rid, viewport);
}
void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
@@ -1019,5 +1020,10 @@ void RendererViewport::set_default_clear_color(const Color &p_color) {
RSG::storage->set_default_clear_color(p_color);
}
+//workaround for setting this on thread
+void RendererViewport::call_set_use_vsync(bool p_enable) {
+ DisplayServer::get_singleton()->_set_use_vsync(p_enable);
+}
+
RendererViewport::RendererViewport() {
}
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 979cbb095b..f5ed543e8d 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -165,7 +165,7 @@ public:
uint64_t draw_viewports_pass = 0;
- mutable RID_PtrOwner<Viewport> viewport_owner;
+ mutable RID_PtrOwner<Viewport, true> viewport_owner;
struct ViewportSort {
_FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const {
@@ -186,7 +186,8 @@ private:
void _draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_eye = XRInterface::EYE_MONO);
public:
- RID viewport_create();
+ RID viewport_allocate();
+ void viewport_initialize(RID p_rid);
void viewport_set_use_xr(RID p_viewport, bool p_use_xr);
@@ -249,6 +250,9 @@ public:
bool free(RID p_rid);
+ //workaround for setting this on thread
+ void call_set_use_vsync(bool p_enable);
+
RendererViewport();
virtual ~RendererViewport() {}
};
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 70497bcdb3..27a9353e4e 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -240,10 +240,6 @@ void RenderingDevice::_compute_list_set_push_constant(ComputeListID p_list, cons
compute_list_set_push_constant(p_list, p_data.ptr(), p_data_size);
}
-void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads, uint32_t p_x_local_group, uint32_t p_y_local_group, uint32_t p_z_local_group) {
- compute_list_dispatch(p_list, (p_x_threads - 1) / p_x_local_group + 1, (p_y_threads - 1) / p_y_local_group + 1, (p_z_threads - 1) / p_z_local_group + 1);
-}
-
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);
@@ -273,7 +269,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("index_buffer_create", "size_indices", "format", "data"), &RenderingDevice::index_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
+ 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);
ClassDB::bind_method(D_METHOD("shader_compile_from_source", "shader_source", "allow_cache"), &RenderingDevice::_shader_compile_from_source, DEFVAL(true));
@@ -319,7 +315,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_end", "post_barrier"), &RenderingDevice::draw_list_end, DEFVAL(BARRIER_MASK_ALL));
- ClassDB::bind_method(D_METHOD("compute_list_begin"), &RenderingDevice::compute_list_begin);
+ 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);
ClassDB::bind_method(D_METHOD("compute_list_set_push_constant", "compute_list", "buffer", "size_bytes"), &RenderingDevice::_compute_list_set_push_constant);
ClassDB::bind_method(D_METHOD("compute_list_bind_uniform_set", "compute_list", "uniform_set", "set_index"), &RenderingDevice::compute_list_bind_uniform_set);
@@ -352,10 +348,15 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_command_insert_label", "name", "color"), &RenderingDevice::draw_command_insert_label);
ClassDB::bind_method(D_METHOD("draw_command_end_label"), &RenderingDevice::draw_command_end_label);
+ ClassDB::bind_method(D_METHOD("get_device_vendor_name"), &RenderingDevice::get_device_vendor_name);
+ ClassDB::bind_method(D_METHOD("get_device_name"), &RenderingDevice::get_device_name);
+ ClassDB::bind_method(D_METHOD("get_device_pipeline_cache_uuid"), &RenderingDevice::get_device_pipeline_cache_uuid);
+
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(DATA_FORMAT_R4G4_UNORM_PACK8);
BIND_ENUM_CONSTANT(DATA_FORMAT_R4G4B4A4_UNORM_PACK16);
@@ -760,6 +761,7 @@ void RenderingDevice::_bind_methods() {
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)
+ BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION_CONTINUE); //continue rendering and clear the framebuffer (supply params)
BIND_ENUM_CONSTANT(INITIAL_ACTION_KEEP); //start rendering); but keep attached color texture contents (depth will be cleared)
BIND_ENUM_CONSTANT(INITIAL_ACTION_DROP); //start rendering); ignore what is there); just write above it
BIND_ENUM_CONSTANT(INITIAL_ACTION_CONTINUE); //continue rendering (framebuffer must have been left in "continue" state as final action previously)
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 47ef54cef7..9fbf58d131 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -343,6 +343,7 @@ public:
BARRIER_MASK_RASTER = 1,
BARRIER_MASK_COMPUTE = 2,
BARRIER_MASK_TRANSFER = 4,
+ BARRIER_MASK_NO_BARRIER = 8,
BARRIER_MASK_ALL = BARRIER_MASK_RASTER | BARRIER_MASK_COMPUTE | BARRIER_MASK_TRANSFER
};
@@ -944,6 +945,7 @@ public:
enum InitialAction {
INITIAL_ACTION_CLEAR, //start rendering and clear the whole framebuffer (region or not) (supply params)
INITIAL_ACTION_CLEAR_REGION, //start rendering and clear the framebuffer in the specified region (supply params)
+ INITIAL_ACTION_CLEAR_REGION_CONTINUE, //countinue rendering and clear the framebuffer in the specified region (supply params)
INITIAL_ACTION_KEEP, //start rendering, but keep attached color texture contents (depth will be cleared)
INITIAL_ACTION_DROP, //start rendering, ignore what is there, just write above it
INITIAL_ACTION_CONTINUE, //continue rendering (framebuffer must have been left in "continue" state as final action previously)
@@ -983,12 +985,12 @@ public:
typedef int64_t ComputeListID;
- virtual ComputeListID compute_list_begin() = 0;
+ virtual ComputeListID compute_list_begin(bool p_allow_draw_overlap = false) = 0;
virtual void compute_list_bind_compute_pipeline(ComputeListID p_list, RID p_compute_pipeline) = 0;
virtual void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index) = 0;
virtual void compute_list_set_push_constant(ComputeListID p_list, const void *p_data, uint32_t p_data_size) = 0;
virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) = 0;
- virtual void compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads, uint32_t p_x_local_group, uint32_t p_y_local_group, uint32_t p_z_local_group);
+ virtual void compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads) = 0;
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;
@@ -1078,6 +1080,10 @@ public:
virtual void draw_command_insert_label(String p_label_name, const Color p_color = Color(1, 1, 1, 1)) = 0;
virtual void draw_command_end_label() = 0;
+ virtual String get_device_vendor_name() const = 0;
+ virtual String get_device_name() const = 0;
+ virtual String get_device_pipeline_cache_uuid() const = 0;
+
static RenderingDevice *get_singleton();
RenderingDevice();
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 360b333454..c6fe6a07e0 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -64,7 +64,7 @@ void RenderingServerDefault::_draw_margins() {
/* FREE */
-void RenderingServerDefault::free(RID p_rid) {
+void RenderingServerDefault::_free(RID p_rid) {
if (RSG::storage->free(p_rid)) {
return;
}
@@ -91,7 +91,7 @@ void RenderingServerDefault::request_frame_drawn_callback(Object *p_where, const
frame_drawn_callbacks.push_back(fdc);
}
-void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
+void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
//needs to be done before changes is reset to 0, to not force the editor to redraw
RS::get_singleton()->emit_signal("frame_pre_draw");
@@ -213,18 +213,15 @@ float RenderingServerDefault::get_frame_setup_time_cpu() const {
return frame_setup_time;
}
-void RenderingServerDefault::sync() {
-}
-
bool RenderingServerDefault::has_changed() const {
return changes > 0;
}
-void RenderingServerDefault::init() {
+void RenderingServerDefault::_init() {
RSG::rasterizer->initialize();
}
-void RenderingServerDefault::finish() {
+void RenderingServerDefault::_finish() {
if (test_cube.is_valid()) {
free(test_cube);
}
@@ -232,9 +229,35 @@ void RenderingServerDefault::finish() {
RSG::rasterizer->finalize();
}
+void RenderingServerDefault::init() {
+ if (create_thread) {
+ print_verbose("RenderingServerWrapMT: Creating render thread");
+ DisplayServer::get_singleton()->release_rendering_thread();
+ if (create_thread) {
+ thread.start(_thread_callback, this);
+ print_verbose("RenderingServerWrapMT: Starting render thread");
+ }
+ while (!draw_thread_up.is_set()) {
+ OS::get_singleton()->delay_usec(1000);
+ }
+ print_verbose("RenderingServerWrapMT: Finished render thread");
+ } else {
+ _init();
+ }
+}
+
+void RenderingServerDefault::finish() {
+ if (create_thread) {
+ command_queue.push(this, &RenderingServerDefault::_thread_exit);
+ thread.wait_to_finish();
+ } else {
+ _finish();
+ }
+}
+
/* STATUS INFORMATION */
-int RenderingServerDefault::get_render_info(RenderInfo p_info) {
+uint64_t RenderingServerDefault::get_render_info(RenderInfo p_info) {
return RSG::storage->get_render_info(p_info);
}
@@ -297,10 +320,6 @@ void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
RSG::storage->set_debug_generate_wireframes(p_generate);
}
-void RenderingServerDefault::call_set_use_vsync(bool p_enable) {
- DisplayServer::get_singleton()->_set_use_vsync(p_enable);
-}
-
bool RenderingServerDefault::is_low_end() const {
// FIXME: Commented out when rebasing vulkan branch on master,
// causes a crash, it seems rasterizer is not initialized yet the
@@ -309,7 +328,74 @@ bool RenderingServerDefault::is_low_end() const {
return false;
}
-RenderingServerDefault::RenderingServerDefault() {
+void RenderingServerDefault::_thread_exit() {
+ exit.set();
+}
+
+void RenderingServerDefault::_thread_draw(bool p_swap_buffers, double frame_step) {
+ if (!draw_pending.decrement()) {
+ _draw(p_swap_buffers, frame_step);
+ }
+}
+
+void RenderingServerDefault::_thread_flush() {
+ draw_pending.decrement();
+}
+
+void RenderingServerDefault::_thread_callback(void *_instance) {
+ RenderingServerDefault *vsmt = reinterpret_cast<RenderingServerDefault *>(_instance);
+
+ vsmt->_thread_loop();
+}
+
+void RenderingServerDefault::_thread_loop() {
+ server_thread = Thread::get_caller_id();
+
+ DisplayServer::get_singleton()->make_rendering_thread();
+
+ _init();
+
+ draw_thread_up.set();
+ while (!exit.is_set()) {
+ // flush commands one by one, until exit is requested
+ command_queue.wait_and_flush_one();
+ }
+
+ command_queue.flush_all(); // flush all
+
+ _finish();
+}
+
+/* EVENT QUEUING */
+
+void RenderingServerDefault::sync() {
+ if (create_thread) {
+ draw_pending.increment();
+ command_queue.push_and_sync(this, &RenderingServerDefault::_thread_flush);
+ } else {
+ command_queue.flush_all(); //flush all pending from other threads
+ }
+}
+
+void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
+ if (create_thread) {
+ draw_pending.increment();
+ command_queue.push(this, &RenderingServerDefault::_thread_draw, p_swap_buffers, frame_step);
+ } else {
+ _draw(p_swap_buffers, frame_step);
+ }
+}
+
+RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
+ command_queue(p_create_thread) {
+ create_thread = p_create_thread;
+
+ if (!p_create_thread) {
+ server_thread = Thread::get_caller_id();
+ } else {
+ server_thread = 0;
+ }
+
RSG::canvas = memnew(RendererCanvasCull);
RSG::viewport = memnew(RendererViewport);
RendererSceneCull *sr = memnew(RendererSceneCull);
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 83afd9096d..e82d5cc3f8 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -32,6 +32,7 @@
#define RENDERING_SERVER_DEFAULT_H
#include "core/math/octree.h"
+#include "core/templates/command_queue_mt.h"
#include "core/templates/ordered_hash_map.h"
#include "renderer_canvas_cull.h"
#include "renderer_scene_cull.h"
@@ -39,6 +40,7 @@
#include "rendering_server_globals.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering_server.h"
+#include "servers/server_wrap_mt_common.h"
class RenderingServerDefault : public RenderingServer {
enum {
@@ -81,6 +83,31 @@ class RenderingServerDefault : public RenderingServer {
uint64_t print_frame_profile_ticks_from = 0;
uint32_t print_frame_profile_frame_count = 0;
+ mutable CommandQueueMT command_queue;
+
+ static void _thread_callback(void *_instance);
+ void _thread_loop();
+
+ Thread::ID server_thread;
+ SafeFlag exit;
+ Thread thread;
+ SafeFlag draw_thread_up;
+ bool create_thread;
+
+ SafeNumeric<uint64_t> draw_pending;
+ void _thread_draw(bool p_swap_buffers, double frame_step);
+ void _thread_flush();
+
+ void _thread_exit();
+
+ Mutex alloc_mutex;
+
+ void _draw(bool p_swap_buffers, double frame_step);
+ void _init();
+ void _finish();
+
+ void _free(RID p_rid);
+
public:
//if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed()
//#define DEBUG_CHANGES
@@ -97,809 +124,813 @@ public:
#else
_FORCE_INLINE_ static void redraw_request() { changes++; }
+#endif
-#define DISPLAY_CHANGED \
- changes++;
+#define WRITE_ACTION redraw_request();
+
+#ifdef DEBUG_SYNC
+#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__));
+#else
+#define SYNC_DEBUG
#endif
-#define BIND0R(m_r, m_name) \
- m_r m_name() { return BINDBASE->m_name(); }
-#define BIND0RC(m_r, m_name) \
- m_r m_name() const { return BINDBASE->m_name(); }
-#define BIND1R(m_r, m_name, m_type1) \
- m_r m_name(m_type1 arg1) { return BINDBASE->m_name(arg1); }
-#define BIND1RC(m_r, m_name, m_type1) \
- m_r m_name(m_type1 arg1) const { return BINDBASE->m_name(arg1); }
-#define BIND2R(m_r, m_name, m_type1, m_type2) \
- m_r m_name(m_type1 arg1, m_type2 arg2) { return BINDBASE->m_name(arg1, arg2); }
-#define BIND2RC(m_r, m_name, m_type1, m_type2) \
- m_r m_name(m_type1 arg1, m_type2 arg2) const { return BINDBASE->m_name(arg1, arg2); }
-#define BIND3R(m_r, m_name, m_type1, m_type2, m_type3) \
- m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { return BINDBASE->m_name(arg1, arg2, arg3); }
-#define BIND3RC(m_r, m_name, m_type1, m_type2, m_type3) \
- m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) const { return BINDBASE->m_name(arg1, arg2, arg3); }
-#define BIND4R(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \
- m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { return BINDBASE->m_name(arg1, arg2, arg3, arg4); }
-#define BIND4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \
- m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4); }
-#define BIND5R(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \
- m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5); }
-#define BIND5RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \
- m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5); }
-#define BIND6R(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
- m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); }
-#define BIND6RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
- m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); }
-
-#define BIND0(m_name) \
- void m_name() { DISPLAY_CHANGED BINDBASE->m_name(); }
-#define BIND1(m_name, m_type1) \
- void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); }
-#define BIND1C(m_name, m_type1) \
- void m_name(m_type1 arg1) const { DISPLAY_CHANGED BINDBASE->m_name(arg1); }
-#define BIND2(m_name, m_type1, m_type2) \
- void m_name(m_type1 arg1, m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2); }
-#define BIND2C(m_name, m_type1, m_type2) \
- void m_name(m_type1 arg1, m_type2 arg2) const { BINDBASE->m_name(arg1, arg2); }
-#define BIND3(m_name, m_type1, m_type2, m_type3) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3); }
-#define BIND4(m_name, m_type1, m_type2, m_type3, m_type4) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4); }
-#define BIND5(m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5); }
-#define BIND6(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); }
-#define BIND7(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
-#define BIND8(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
-#define BIND9(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); }
-#define BIND10(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); }
-#define BIND11(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); }
-#define BIND12(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); }
-#define BIND13(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); }
-#define BIND14(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); }
-#define BIND15(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14, m_type15) \
- void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14, m_type15 arg15) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); }
+#include "servers/server_wrap_mt_common.h"
//from now on, calls forwarded to this singleton
-#define BINDBASE RSG::storage
+#define ServerName RendererStorage
+#define server_name RSG::storage
/* TEXTURE API */
+#define FUNCRIDTEX0(m_type) \
+ virtual RID m_type##_create() override { \
+ RID ret = RSG::storage->texture_allocate(); \
+ if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
+ RSG::storage->m_type##_initialize(ret); \
+ } else { \
+ command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret); \
+ } \
+ return ret; \
+ }
+
+#define FUNCRIDTEX1(m_type, m_type1) \
+ virtual RID m_type##_create(m_type1 p1) override { \
+ RID ret = RSG::storage->texture_allocate(); \
+ if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
+ RSG::storage->m_type##_initialize(ret, p1); \
+ } else { \
+ command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1); \
+ } \
+ return ret; \
+ }
+
+#define FUNCRIDTEX2(m_type, m_type1, m_type2) \
+ virtual RID m_type##_create(m_type1 p1, m_type2 p2) override { \
+ RID ret = RSG::storage->texture_allocate(); \
+ if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
+ RSG::storage->m_type##_initialize(ret, p1, p2); \
+ } else { \
+ command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2); \
+ } \
+ return ret; \
+ }
+
+#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
+ virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \
+ RID ret = RSG::storage->texture_allocate(); \
+ if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
+ RSG::storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6); \
+ } else { \
+ command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6); \
+ } \
+ return ret; \
+ }
+
//these go pass-through, as they can be called from any thread
- BIND1R(RID, texture_2d_create, const Ref<Image> &)
- BIND2R(RID, texture_2d_layered_create, const Vector<Ref<Image>> &, TextureLayeredType)
- BIND6R(RID, texture_3d_create, Image::Format, int, int, int, bool, const Vector<Ref<Image>> &)
- BIND1R(RID, texture_proxy_create, RID)
+ FUNCRIDTEX1(texture_2d, const Ref<Image> &)
+ FUNCRIDTEX2(texture_2d_layered, const Vector<Ref<Image>> &, TextureLayeredType)
+ FUNCRIDTEX6(texture_3d, Image::Format, int, int, int, bool, const Vector<Ref<Image>> &)
+ FUNCRIDTEX1(texture_proxy, RID)
//goes pass-through
- BIND3(texture_2d_update_immediate, RID, const Ref<Image> &, int)
+ FUNC3(texture_2d_update_immediate, RID, const Ref<Image> &, int)
//these go through command queue if they are in another thread
- BIND3(texture_2d_update, RID, const Ref<Image> &, int)
- BIND2(texture_3d_update, RID, const Vector<Ref<Image>> &)
- BIND2(texture_proxy_update, RID, RID)
+ FUNC3(texture_2d_update, RID, const Ref<Image> &, int)
+ FUNC2(texture_3d_update, RID, const Vector<Ref<Image>> &)
+ FUNC2(texture_proxy_update, RID, RID)
//these also go pass-through
- BIND0R(RID, texture_2d_placeholder_create)
- BIND1R(RID, texture_2d_layered_placeholder_create, TextureLayeredType)
- BIND0R(RID, texture_3d_placeholder_create)
+ FUNCRIDTEX0(texture_2d_placeholder)
+ FUNCRIDTEX1(texture_2d_layered_placeholder, TextureLayeredType)
+ FUNCRIDTEX0(texture_3d_placeholder)
- BIND1RC(Ref<Image>, texture_2d_get, RID)
- BIND2RC(Ref<Image>, texture_2d_layer_get, RID, int)
- BIND1RC(Vector<Ref<Image>>, texture_3d_get, RID)
+ FUNC1RC(Ref<Image>, texture_2d_get, RID)
+ FUNC2RC(Ref<Image>, texture_2d_layer_get, RID, int)
+ FUNC1RC(Vector<Ref<Image>>, texture_3d_get, RID)
- BIND2(texture_replace, RID, RID)
+ FUNC2(texture_replace, RID, RID)
- BIND3(texture_set_size_override, RID, int, int)
+ FUNC3(texture_set_size_override, RID, int, int)
// FIXME: Disabled during Vulkan refactoring, should be ported.
#if 0
- BIND2(texture_bind, RID, uint32_t)
+ FUNC2(texture_bind, RID, uint32_t)
#endif
- BIND3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
- BIND3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *)
- BIND3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *)
+ FUNC3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
+ FUNC3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *)
+ FUNC3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *)
- BIND2(texture_set_path, RID, const String &)
- BIND1RC(String, texture_get_path, RID)
- BIND1(texture_debug_usage, List<TextureInfo> *)
+ FUNC2(texture_set_path, RID, const String &)
+ FUNC1RC(String, texture_get_path, RID)
+ FUNC1(texture_debug_usage, List<TextureInfo> *)
- BIND2(texture_set_force_redraw_if_visible, RID, bool)
+ FUNC2(texture_set_force_redraw_if_visible, RID, bool)
/* SHADER API */
- BIND0R(RID, shader_create)
+ FUNCRIDSPLIT(shader)
- BIND2(shader_set_code, RID, const String &)
- BIND1RC(String, shader_get_code, RID)
+ FUNC2(shader_set_code, RID, const String &)
+ FUNC1RC(String, shader_get_code, RID)
- BIND2C(shader_get_param_list, RID, List<PropertyInfo> *)
+ FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
- BIND3(shader_set_default_texture_param, RID, const StringName &, RID)
- BIND2RC(RID, shader_get_default_texture_param, RID, const StringName &)
- BIND2RC(Variant, shader_get_param_default, RID, const StringName &)
+ FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
+ FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
+ FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
- BIND1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
+ FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
/* COMMON MATERIAL API */
- BIND0R(RID, material_create)
+ FUNCRIDSPLIT(material)
- BIND2(material_set_shader, RID, RID)
+ FUNC2(material_set_shader, RID, RID)
- BIND3(material_set_param, RID, const StringName &, const Variant &)
- BIND2RC(Variant, material_get_param, RID, const StringName &)
+ FUNC3(material_set_param, RID, const StringName &, const Variant &)
+ FUNC2RC(Variant, material_get_param, RID, const StringName &)
- BIND2(material_set_render_priority, RID, int)
- BIND2(material_set_next_pass, RID, RID)
+ FUNC2(material_set_render_priority, RID, int)
+ FUNC2(material_set_next_pass, RID, RID)
/* MESH API */
- virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) {
- RID mesh = mesh_create();
- mesh_set_blend_shape_count(mesh, p_blend_shape_count);
- for (int i = 0; i < p_surfaces.size(); i++) {
- mesh_add_surface(mesh, p_surfaces[i]);
+ virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) override {
+ RID mesh = RSG::storage->mesh_allocate();
+
+ if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) {
+ if (Thread::get_caller_id() == server_thread) {
+ command_queue.flush_if_pending();
+ }
+ RSG::storage->mesh_initialize(mesh);
+ RSG::storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count);
+ for (int i = 0; i < p_surfaces.size(); i++) {
+ RSG::storage->mesh_add_surface(mesh, p_surfaces[i]);
+ }
+ } else {
+ command_queue.push(RSG::storage, &RendererStorage::mesh_initialize, mesh);
+ command_queue.push(RSG::storage, &RendererStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count);
+ for (int i = 0; i < p_surfaces.size(); i++) {
+ RSG::storage->mesh_add_surface(mesh, p_surfaces[i]);
+ command_queue.push(RSG::storage, &RendererStorage::mesh_add_surface, mesh, p_surfaces[i]);
+ }
}
+
return mesh;
}
- BIND2(mesh_set_blend_shape_count, RID, int)
+ FUNC2(mesh_set_blend_shape_count, RID, int)
- BIND0R(RID, mesh_create)
+ FUNCRIDSPLIT(mesh)
- BIND2(mesh_add_surface, RID, const SurfaceData &)
+ FUNC2(mesh_add_surface, RID, const SurfaceData &)
- BIND1RC(int, mesh_get_blend_shape_count, RID)
+ FUNC1RC(int, mesh_get_blend_shape_count, RID)
- BIND2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
- BIND1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
+ FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
+ FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
- BIND4(mesh_surface_update_region, RID, int, int, const Vector<uint8_t> &)
+ FUNC4(mesh_surface_update_region, RID, int, int, const Vector<uint8_t> &)
- BIND3(mesh_surface_set_material, RID, int, RID)
- BIND2RC(RID, mesh_surface_get_material, RID, int)
+ FUNC3(mesh_surface_set_material, RID, int, RID)
+ FUNC2RC(RID, mesh_surface_get_material, RID, int)
- BIND2RC(SurfaceData, mesh_get_surface, RID, int)
+ FUNC2RC(SurfaceData, mesh_get_surface, RID, int)
- BIND1RC(int, mesh_get_surface_count, RID)
+ FUNC1RC(int, mesh_get_surface_count, RID)
- BIND2(mesh_set_custom_aabb, RID, const AABB &)
- BIND1RC(AABB, mesh_get_custom_aabb, RID)
+ FUNC2(mesh_set_custom_aabb, RID, const AABB &)
+ FUNC1RC(AABB, mesh_get_custom_aabb, RID)
- BIND2(mesh_set_shadow_mesh, RID, RID)
+ FUNC2(mesh_set_shadow_mesh, RID, RID)
- BIND1(mesh_clear, RID)
+ FUNC1(mesh_clear, RID)
/* MULTIMESH API */
- BIND0R(RID, multimesh_create)
+ FUNCRIDSPLIT(multimesh)
- BIND5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool)
- BIND1RC(int, multimesh_get_instance_count, RID)
+ FUNC5(multimesh_allocate_data, RID, int, MultimeshTransformFormat, bool, bool)
+ FUNC1RC(int, multimesh_get_instance_count, RID)
- BIND2(multimesh_set_mesh, RID, RID)
- BIND3(multimesh_instance_set_transform, RID, int, const Transform &)
- BIND3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
- BIND3(multimesh_instance_set_color, RID, int, const Color &)
- BIND3(multimesh_instance_set_custom_data, RID, int, const Color &)
+ FUNC2(multimesh_set_mesh, RID, RID)
+ FUNC3(multimesh_instance_set_transform, RID, int, const Transform &)
+ FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
+ FUNC3(multimesh_instance_set_color, RID, int, const Color &)
+ FUNC3(multimesh_instance_set_custom_data, RID, int, const Color &)
- BIND1RC(RID, multimesh_get_mesh, RID)
- BIND1RC(AABB, multimesh_get_aabb, RID)
+ FUNC1RC(RID, multimesh_get_mesh, RID)
+ FUNC1RC(AABB, multimesh_get_aabb, RID)
- BIND2RC(Transform, multimesh_instance_get_transform, RID, int)
- BIND2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
- BIND2RC(Color, multimesh_instance_get_color, RID, int)
- BIND2RC(Color, multimesh_instance_get_custom_data, RID, int)
+ FUNC2RC(Transform, multimesh_instance_get_transform, RID, int)
+ FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
+ FUNC2RC(Color, multimesh_instance_get_color, RID, int)
+ FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int)
- BIND2(multimesh_set_buffer, RID, const Vector<float> &)
- BIND1RC(Vector<float>, multimesh_get_buffer, RID)
+ FUNC2(multimesh_set_buffer, RID, const Vector<float> &)
+ FUNC1RC(Vector<float>, multimesh_get_buffer, RID)
- BIND2(multimesh_set_visible_instances, RID, int)
- BIND1RC(int, multimesh_get_visible_instances, RID)
+ FUNC2(multimesh_set_visible_instances, RID, int)
+ FUNC1RC(int, multimesh_get_visible_instances, RID)
/* IMMEDIATE API */
- BIND0R(RID, immediate_create)
- BIND3(immediate_begin, RID, PrimitiveType, RID)
- BIND2(immediate_vertex, RID, const Vector3 &)
- BIND2(immediate_normal, RID, const Vector3 &)
- BIND2(immediate_tangent, RID, const Plane &)
- BIND2(immediate_color, RID, const Color &)
- BIND2(immediate_uv, RID, const Vector2 &)
- BIND2(immediate_uv2, RID, const Vector2 &)
- BIND1(immediate_end, RID)
- BIND1(immediate_clear, RID)
- BIND2(immediate_set_material, RID, RID)
- BIND1RC(RID, immediate_get_material, RID)
+ FUNCRIDSPLIT(immediate)
+ FUNC3(immediate_begin, RID, PrimitiveType, RID)
+ FUNC2(immediate_vertex, RID, const Vector3 &)
+ FUNC2(immediate_normal, RID, const Vector3 &)
+ FUNC2(immediate_tangent, RID, const Plane &)
+ FUNC2(immediate_color, RID, const Color &)
+ FUNC2(immediate_uv, RID, const Vector2 &)
+ FUNC2(immediate_uv2, RID, const Vector2 &)
+ FUNC1(immediate_end, RID)
+ FUNC1(immediate_clear, RID)
+ FUNC2(immediate_set_material, RID, RID)
+ FUNC1RC(RID, immediate_get_material, RID)
/* SKELETON API */
- BIND0R(RID, skeleton_create)
- BIND3(skeleton_allocate, RID, int, bool)
- BIND1RC(int, skeleton_get_bone_count, RID)
- BIND3(skeleton_bone_set_transform, RID, int, const Transform &)
- BIND2RC(Transform, skeleton_bone_get_transform, RID, int)
- BIND3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
- BIND2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
- BIND2(skeleton_set_base_transform_2d, RID, const Transform2D &)
+ FUNCRIDSPLIT(skeleton)
+ FUNC3(skeleton_allocate_data, RID, int, bool)
+ FUNC1RC(int, skeleton_get_bone_count, RID)
+ FUNC3(skeleton_bone_set_transform, RID, int, const Transform &)
+ FUNC2RC(Transform, skeleton_bone_get_transform, RID, int)
+ FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
+ FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
+ FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &)
/* Light API */
- BIND0R(RID, directional_light_create)
- BIND0R(RID, omni_light_create)
- BIND0R(RID, spot_light_create)
+ FUNCRIDSPLIT(directional_light)
+ FUNCRIDSPLIT(omni_light)
+ FUNCRIDSPLIT(spot_light)
- BIND2(light_set_color, RID, const Color &)
- BIND3(light_set_param, RID, LightParam, float)
- BIND2(light_set_shadow, RID, bool)
- BIND2(light_set_shadow_color, RID, const Color &)
- BIND2(light_set_projector, RID, RID)
- BIND2(light_set_negative, RID, bool)
- BIND2(light_set_cull_mask, RID, uint32_t)
- BIND2(light_set_reverse_cull_face_mode, RID, bool)
- BIND2(light_set_bake_mode, RID, LightBakeMode)
- BIND2(light_set_max_sdfgi_cascade, RID, uint32_t)
+ FUNC2(light_set_color, RID, const Color &)
+ FUNC3(light_set_param, RID, LightParam, float)
+ FUNC2(light_set_shadow, RID, bool)
+ FUNC2(light_set_shadow_color, RID, const Color &)
+ FUNC2(light_set_projector, RID, RID)
+ FUNC2(light_set_negative, RID, bool)
+ FUNC2(light_set_cull_mask, RID, uint32_t)
+ FUNC2(light_set_reverse_cull_face_mode, RID, bool)
+ FUNC2(light_set_bake_mode, RID, LightBakeMode)
+ FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t)
- BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
+ FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
- BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
- BIND2(light_directional_set_blend_splits, RID, bool)
- BIND2(light_directional_set_sky_only, RID, bool)
- BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
+ FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
+ FUNC2(light_directional_set_blend_splits, RID, bool)
+ FUNC2(light_directional_set_sky_only, RID, bool)
+ FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
/* PROBE API */
- BIND0R(RID, reflection_probe_create)
-
- BIND2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
- BIND2(reflection_probe_set_intensity, RID, float)
- BIND2(reflection_probe_set_ambient_color, RID, const Color &)
- BIND2(reflection_probe_set_ambient_energy, RID, float)
- BIND2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode)
- BIND2(reflection_probe_set_max_distance, RID, float)
- BIND2(reflection_probe_set_extents, RID, const Vector3 &)
- BIND2(reflection_probe_set_origin_offset, RID, const Vector3 &)
- BIND2(reflection_probe_set_as_interior, RID, bool)
- BIND2(reflection_probe_set_enable_box_projection, RID, bool)
- BIND2(reflection_probe_set_enable_shadows, RID, bool)
- BIND2(reflection_probe_set_cull_mask, RID, uint32_t)
- BIND2(reflection_probe_set_resolution, RID, int)
- BIND2(reflection_probe_set_lod_threshold, RID, float)
+ FUNCRIDSPLIT(reflection_probe)
+
+ FUNC2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
+ FUNC2(reflection_probe_set_intensity, RID, float)
+ FUNC2(reflection_probe_set_ambient_color, RID, const Color &)
+ FUNC2(reflection_probe_set_ambient_energy, RID, float)
+ FUNC2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode)
+ FUNC2(reflection_probe_set_max_distance, RID, float)
+ FUNC2(reflection_probe_set_extents, RID, const Vector3 &)
+ FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &)
+ FUNC2(reflection_probe_set_as_interior, RID, bool)
+ FUNC2(reflection_probe_set_enable_box_projection, RID, bool)
+ FUNC2(reflection_probe_set_enable_shadows, RID, bool)
+ FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
+ FUNC2(reflection_probe_set_resolution, RID, int)
+ FUNC2(reflection_probe_set_lod_threshold, RID, float)
/* DECAL API */
- BIND0R(RID, decal_create)
+ FUNCRIDSPLIT(decal)
- BIND2(decal_set_extents, RID, const Vector3 &)
- BIND3(decal_set_texture, RID, DecalTexture, RID)
- BIND2(decal_set_emission_energy, RID, float)
- BIND2(decal_set_albedo_mix, RID, float)
- BIND2(decal_set_modulate, RID, const Color &)
- BIND2(decal_set_cull_mask, RID, uint32_t)
- BIND4(decal_set_distance_fade, RID, bool, float, float)
- BIND3(decal_set_fade, RID, float, float)
- BIND2(decal_set_normal_fade, RID, float)
+ FUNC2(decal_set_extents, RID, const Vector3 &)
+ FUNC3(decal_set_texture, RID, DecalTexture, RID)
+ FUNC2(decal_set_emission_energy, RID, float)
+ FUNC2(decal_set_albedo_mix, RID, float)
+ FUNC2(decal_set_modulate, RID, const Color &)
+ FUNC2(decal_set_cull_mask, RID, uint32_t)
+ FUNC4(decal_set_distance_fade, RID, bool, float, float)
+ FUNC3(decal_set_fade, RID, float, float)
+ FUNC2(decal_set_normal_fade, RID, float)
/* BAKED LIGHT API */
- BIND0R(RID, gi_probe_create)
+ FUNCRIDSPLIT(gi_probe)
- BIND8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)
+ FUNC8(gi_probe_allocate_data, RID, const Transform &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)
- BIND1RC(AABB, gi_probe_get_bounds, RID)
- BIND1RC(Vector3i, gi_probe_get_octree_size, RID)
- BIND1RC(Vector<uint8_t>, gi_probe_get_octree_cells, RID)
- BIND1RC(Vector<uint8_t>, gi_probe_get_data_cells, RID)
- BIND1RC(Vector<uint8_t>, gi_probe_get_distance_field, RID)
- BIND1RC(Vector<int>, gi_probe_get_level_counts, RID)
- BIND1RC(Transform, gi_probe_get_to_cell_xform, RID)
+ FUNC1RC(AABB, gi_probe_get_bounds, RID)
+ FUNC1RC(Vector3i, gi_probe_get_octree_size, RID)
+ FUNC1RC(Vector<uint8_t>, gi_probe_get_octree_cells, RID)
+ FUNC1RC(Vector<uint8_t>, gi_probe_get_data_cells, RID)
+ FUNC1RC(Vector<uint8_t>, gi_probe_get_distance_field, RID)
+ FUNC1RC(Vector<int>, gi_probe_get_level_counts, RID)
+ FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID)
- BIND2(gi_probe_set_dynamic_range, RID, float)
- BIND1RC(float, gi_probe_get_dynamic_range, RID)
+ FUNC2(gi_probe_set_dynamic_range, RID, float)
+ FUNC1RC(float, gi_probe_get_dynamic_range, RID)
- BIND2(gi_probe_set_propagation, RID, float)
- BIND1RC(float, gi_probe_get_propagation, RID)
+ FUNC2(gi_probe_set_propagation, RID, float)
+ FUNC1RC(float, gi_probe_get_propagation, RID)
- BIND2(gi_probe_set_energy, RID, float)
- BIND1RC(float, gi_probe_get_energy, RID)
+ FUNC2(gi_probe_set_energy, RID, float)
+ FUNC1RC(float, gi_probe_get_energy, RID)
- BIND2(gi_probe_set_ao, RID, float)
- BIND1RC(float, gi_probe_get_ao, RID)
+ FUNC2(gi_probe_set_ao, RID, float)
+ FUNC1RC(float, gi_probe_get_ao, RID)
- BIND2(gi_probe_set_ao_size, RID, float)
- BIND1RC(float, gi_probe_get_ao_size, RID)
+ FUNC2(gi_probe_set_ao_size, RID, float)
+ FUNC1RC(float, gi_probe_get_ao_size, RID)
- BIND2(gi_probe_set_bias, RID, float)
- BIND1RC(float, gi_probe_get_bias, RID)
+ FUNC2(gi_probe_set_bias, RID, float)
+ FUNC1RC(float, gi_probe_get_bias, RID)
- BIND2(gi_probe_set_normal_bias, RID, float)
- BIND1RC(float, gi_probe_get_normal_bias, RID)
+ FUNC2(gi_probe_set_normal_bias, RID, float)
+ FUNC1RC(float, gi_probe_get_normal_bias, RID)
- BIND2(gi_probe_set_interior, RID, bool)
- BIND1RC(bool, gi_probe_is_interior, RID)
+ FUNC2(gi_probe_set_interior, RID, bool)
+ FUNC1RC(bool, gi_probe_is_interior, RID)
- BIND2(gi_probe_set_use_two_bounces, RID, bool)
- BIND1RC(bool, gi_probe_is_using_two_bounces, RID)
+ FUNC2(gi_probe_set_use_two_bounces, RID, bool)
+ FUNC1RC(bool, gi_probe_is_using_two_bounces, RID)
- BIND2(gi_probe_set_anisotropy_strength, RID, float)
- BIND1RC(float, gi_probe_get_anisotropy_strength, RID)
+ FUNC2(gi_probe_set_anisotropy_strength, RID, float)
+ FUNC1RC(float, gi_probe_get_anisotropy_strength, RID)
/* LIGHTMAP */
- BIND0R(RID, lightmap_create)
+ FUNCRIDSPLIT(lightmap)
- BIND3(lightmap_set_textures, RID, RID, bool)
- BIND2(lightmap_set_probe_bounds, RID, const AABB &)
- BIND2(lightmap_set_probe_interior, RID, bool)
- BIND5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
- BIND1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
- BIND1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
- BIND1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
- BIND1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
- BIND1(lightmap_set_probe_capture_update_speed, float)
+ FUNC3(lightmap_set_textures, RID, RID, bool)
+ FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
+ FUNC2(lightmap_set_probe_interior, RID, bool)
+ FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
+ FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
+ FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
+ FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
+ FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
+ FUNC1(lightmap_set_probe_capture_update_speed, float)
/* PARTICLES */
- BIND0R(RID, particles_create)
-
- BIND2(particles_set_emitting, RID, bool)
- BIND1R(bool, particles_get_emitting, RID)
- BIND2(particles_set_amount, RID, int)
- BIND2(particles_set_lifetime, RID, float)
- BIND2(particles_set_one_shot, RID, bool)
- BIND2(particles_set_pre_process_time, RID, float)
- BIND2(particles_set_explosiveness_ratio, RID, float)
- BIND2(particles_set_randomness_ratio, RID, float)
- BIND2(particles_set_custom_aabb, RID, const AABB &)
- BIND2(particles_set_speed_scale, RID, float)
- BIND2(particles_set_use_local_coordinates, RID, bool)
- BIND2(particles_set_process_material, RID, RID)
- BIND2(particles_set_fixed_fps, RID, int)
- BIND2(particles_set_fractional_delta, RID, bool)
- BIND1R(bool, particles_is_inactive, RID)
- BIND1(particles_request_process, RID)
- BIND1(particles_restart, RID)
- BIND6(particles_emit, RID, const Transform &, const Vector3 &, const Color &, const Color &, uint32_t)
- BIND2(particles_set_subemitter, RID, RID)
- BIND2(particles_set_collision_base_size, RID, float)
-
- BIND2(particles_set_draw_order, RID, RS::ParticlesDrawOrder)
-
- BIND2(particles_set_draw_passes, RID, int)
- BIND3(particles_set_draw_pass_mesh, RID, int, RID)
-
- BIND1R(AABB, particles_get_current_aabb, RID)
- BIND2(particles_set_emission_transform, RID, const Transform &)
+ FUNCRIDSPLIT(particles)
+
+ FUNC2(particles_set_emitting, RID, bool)
+ FUNC1R(bool, particles_get_emitting, RID)
+ FUNC2(particles_set_amount, RID, int)
+ FUNC2(particles_set_lifetime, RID, float)
+ FUNC2(particles_set_one_shot, RID, bool)
+ FUNC2(particles_set_pre_process_time, RID, float)
+ FUNC2(particles_set_explosiveness_ratio, RID, float)
+ FUNC2(particles_set_randomness_ratio, RID, float)
+ FUNC2(particles_set_custom_aabb, RID, const AABB &)
+ FUNC2(particles_set_speed_scale, RID, float)
+ FUNC2(particles_set_use_local_coordinates, RID, bool)
+ FUNC2(particles_set_process_material, RID, RID)
+ FUNC2(particles_set_fixed_fps, RID, int)
+ FUNC2(particles_set_fractional_delta, RID, bool)
+ FUNC1R(bool, particles_is_inactive, RID)
+ FUNC1(particles_request_process, RID)
+ FUNC1(particles_restart, RID)
+ FUNC6(particles_emit, RID, const Transform &, const Vector3 &, const Color &, const Color &, uint32_t)
+ FUNC2(particles_set_subemitter, RID, RID)
+ FUNC2(particles_set_collision_base_size, RID, float)
+
+ FUNC2(particles_set_draw_order, RID, RS::ParticlesDrawOrder)
+
+ FUNC2(particles_set_draw_passes, RID, int)
+ FUNC3(particles_set_draw_pass_mesh, RID, int, RID)
+
+ FUNC1R(AABB, particles_get_current_aabb, RID)
+ FUNC2(particles_set_emission_transform, RID, const Transform &)
/* PARTICLES COLLISION */
- BIND0R(RID, particles_collision_create)
-
- BIND2(particles_collision_set_collision_type, RID, ParticlesCollisionType)
- BIND2(particles_collision_set_cull_mask, RID, uint32_t)
- BIND2(particles_collision_set_sphere_radius, RID, float)
- BIND2(particles_collision_set_box_extents, RID, const Vector3 &)
- BIND2(particles_collision_set_attractor_strength, RID, float)
- BIND2(particles_collision_set_attractor_directionality, RID, float)
- BIND2(particles_collision_set_attractor_attenuation, RID, float)
- BIND2(particles_collision_set_field_texture, RID, RID)
- BIND1(particles_collision_height_field_update, RID)
- BIND2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
-
-#undef BINDBASE
+ FUNCRIDSPLIT(particles_collision)
+
+ FUNC2(particles_collision_set_collision_type, RID, ParticlesCollisionType)
+ FUNC2(particles_collision_set_cull_mask, RID, uint32_t)
+ FUNC2(particles_collision_set_sphere_radius, RID, float)
+ FUNC2(particles_collision_set_box_extents, RID, const Vector3 &)
+ FUNC2(particles_collision_set_attractor_strength, RID, float)
+ FUNC2(particles_collision_set_attractor_directionality, RID, float)
+ FUNC2(particles_collision_set_attractor_attenuation, RID, float)
+ FUNC2(particles_collision_set_field_texture, RID, RID)
+ FUNC1(particles_collision_height_field_update, RID)
+ FUNC2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
+
+#undef server_name
+#undef ServerName
//from now on, calls forwarded to this singleton
-#define BINDBASE RSG::scene
+#define ServerName RendererScene
+#define server_name RSG::scene
/* CAMERA API */
- BIND0R(RID, camera_create)
- BIND4(camera_set_perspective, RID, float, float, float)
- BIND4(camera_set_orthogonal, RID, float, float, float)
- BIND5(camera_set_frustum, RID, float, Vector2, float, float)
- BIND2(camera_set_transform, RID, const Transform &)
- BIND2(camera_set_cull_mask, RID, uint32_t)
- BIND2(camera_set_environment, RID, RID)
- BIND2(camera_set_camera_effects, RID, RID)
- BIND2(camera_set_use_vertical_aspect, RID, bool)
-
-#undef BINDBASE
+ FUNCRIDSPLIT(camera)
+ FUNC4(camera_set_perspective, RID, float, float, float)
+ FUNC4(camera_set_orthogonal, RID, float, float, float)
+ FUNC5(camera_set_frustum, RID, float, Vector2, float, float)
+ FUNC2(camera_set_transform, RID, const Transform &)
+ FUNC2(camera_set_cull_mask, RID, uint32_t)
+ FUNC2(camera_set_environment, RID, RID)
+ FUNC2(camera_set_camera_effects, RID, RID)
+ FUNC2(camera_set_use_vertical_aspect, RID, bool)
+
+#undef server_name
+#undef ServerName
//from now on, calls forwarded to this singleton
-#define BINDBASE RSG::viewport
+#define ServerName RendererViewport
+#define server_name RSG::viewport
/* VIEWPORT TARGET API */
- BIND0R(RID, viewport_create)
+ FUNCRIDSPLIT(viewport)
- BIND2(viewport_set_use_xr, RID, bool)
- BIND3(viewport_set_size, RID, int, int)
+ FUNC2(viewport_set_use_xr, RID, bool)
+ FUNC3(viewport_set_size, RID, int, int)
- BIND2(viewport_set_active, RID, bool)
- BIND2(viewport_set_parent_viewport, RID, RID)
+ FUNC2(viewport_set_active, RID, bool)
+ FUNC2(viewport_set_parent_viewport, RID, RID)
- BIND2(viewport_set_clear_mode, RID, ViewportClearMode)
+ FUNC2(viewport_set_clear_mode, RID, ViewportClearMode)
- BIND3(viewport_attach_to_screen, RID, const Rect2 &, int)
- BIND2(viewport_set_render_direct_to_screen, RID, bool)
+ FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int)
+ FUNC2(viewport_set_render_direct_to_screen, RID, bool)
- BIND2(viewport_set_update_mode, RID, ViewportUpdateMode)
- BIND2(viewport_set_vflip, RID, bool)
+ FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
- BIND1RC(RID, viewport_get_texture, RID)
+ FUNC1RC(RID, viewport_get_texture, RID)
- BIND2(viewport_set_hide_scenario, RID, bool)
- BIND2(viewport_set_hide_canvas, RID, bool)
- BIND2(viewport_set_disable_environment, RID, bool)
+ FUNC2(viewport_set_hide_scenario, RID, bool)
+ FUNC2(viewport_set_hide_canvas, RID, bool)
+ FUNC2(viewport_set_disable_environment, RID, bool)
- BIND2(viewport_attach_camera, RID, RID)
- BIND2(viewport_set_scenario, RID, RID)
- BIND2(viewport_attach_canvas, RID, RID)
+ FUNC2(viewport_attach_camera, RID, RID)
+ FUNC2(viewport_set_scenario, RID, RID)
+ FUNC2(viewport_attach_canvas, RID, RID)
- BIND2(viewport_remove_canvas, RID, RID)
- BIND3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
- BIND2(viewport_set_transparent_background, RID, bool)
- BIND2(viewport_set_snap_2d_transforms_to_pixel, RID, bool)
- BIND2(viewport_set_snap_2d_vertices_to_pixel, RID, bool)
+ FUNC2(viewport_remove_canvas, RID, RID)
+ FUNC3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
+ FUNC2(viewport_set_transparent_background, RID, bool)
+ FUNC2(viewport_set_snap_2d_transforms_to_pixel, RID, bool)
+ FUNC2(viewport_set_snap_2d_vertices_to_pixel, RID, bool)
- BIND2(viewport_set_default_canvas_item_texture_filter, RID, CanvasItemTextureFilter)
- BIND2(viewport_set_default_canvas_item_texture_repeat, RID, CanvasItemTextureRepeat)
+ FUNC2(viewport_set_default_canvas_item_texture_filter, RID, CanvasItemTextureFilter)
+ FUNC2(viewport_set_default_canvas_item_texture_repeat, RID, CanvasItemTextureRepeat)
- BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
- BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
- BIND3(viewport_set_shadow_atlas_size, RID, int, bool)
- BIND3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
- BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
- BIND2(viewport_set_msaa, RID, ViewportMSAA)
- BIND2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
- BIND2(viewport_set_use_debanding, RID, bool)
- BIND2(viewport_set_lod_threshold, RID, float)
+ FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
+ FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
+ FUNC3(viewport_set_shadow_atlas_size, RID, int, bool)
+ FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
+ FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
+ FUNC2(viewport_set_msaa, RID, ViewportMSAA)
+ FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
+ FUNC2(viewport_set_use_debanding, RID, bool)
+ FUNC2(viewport_set_lod_threshold, RID, float)
- BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo)
- BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw)
+ FUNC2R(int, viewport_get_render_info, RID, ViewportRenderInfo)
+ FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
- BIND2(viewport_set_measure_render_time, RID, bool)
- BIND1RC(float, viewport_get_measured_render_time_cpu, RID)
- BIND1RC(float, viewport_get_measured_render_time_gpu, RID)
+ FUNC2(viewport_set_measure_render_time, RID, bool)
+ FUNC1RC(float, viewport_get_measured_render_time_cpu, RID)
+ FUNC1RC(float, viewport_get_measured_render_time_gpu, RID)
+
+ FUNC1(call_set_use_vsync, bool)
/* ENVIRONMENT API */
-#undef BINDBASE
+#undef server_name
+#undef ServerName
//from now on, calls forwarded to this singleton
-#define BINDBASE RSG::scene
+#define ServerName RendererScene
+#define server_name RSG::scene
- BIND2(directional_shadow_atlas_set_size, int, bool)
- BIND1(gi_probe_set_quality, GIProbeQuality)
+ FUNC2(directional_shadow_atlas_set_size, int, bool)
+ FUNC1(gi_probe_set_quality, GIProbeQuality)
/* SKY API */
- BIND0R(RID, sky_create)
- BIND2(sky_set_radiance_size, RID, int)
- BIND2(sky_set_mode, RID, SkyMode)
- BIND2(sky_set_material, RID, RID)
- BIND4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &)
+ FUNCRIDSPLIT(sky)
+ FUNC2(sky_set_radiance_size, RID, int)
+ FUNC2(sky_set_mode, RID, SkyMode)
+ FUNC2(sky_set_material, RID, RID)
+ FUNC4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &)
- BIND0R(RID, environment_create)
+ FUNCRIDSPLIT(environment)
- BIND2(environment_set_background, RID, EnvironmentBG)
- BIND2(environment_set_sky, RID, RID)
- BIND2(environment_set_sky_custom_fov, RID, float)
- BIND2(environment_set_sky_orientation, RID, const Basis &)
- BIND2(environment_set_bg_color, RID, const Color &)
- BIND2(environment_set_bg_energy, RID, float)
- BIND2(environment_set_canvas_max_layer, RID, int)
- BIND7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &)
+ FUNC2(environment_set_background, RID, EnvironmentBG)
+ FUNC2(environment_set_sky, RID, RID)
+ FUNC2(environment_set_sky_custom_fov, RID, float)
+ FUNC2(environment_set_sky_orientation, RID, const Basis &)
+ FUNC2(environment_set_bg_color, RID, const Color &)
+ FUNC2(environment_set_bg_energy, RID, float)
+ FUNC2(environment_set_canvas_max_layer, RID, int)
+ FUNC7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &)
// FIXME: Disabled during Vulkan refactoring, should be ported.
#if 0
- BIND2(environment_set_camera_feed_id, RID, int)
+ FUNC2(environment_set_camera_feed_id, RID, int)
#endif
- BIND6(environment_set_ssr, RID, bool, int, float, float, float)
- BIND1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality)
+ FUNC6(environment_set_ssr, RID, bool, int, float, float, float)
+ FUNC1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality)
- BIND10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float)
- BIND6(environment_set_ssao_quality, EnvironmentSSAOQuality, bool, float, int, float, float)
+ FUNC10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float)
+ FUNC6(environment_set_ssao_quality, EnvironmentSSAOQuality, bool, float, int, float, float)
- BIND11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
- BIND1(environment_glow_set_use_bicubic_upscale, bool)
- BIND1(environment_glow_set_use_high_quality, bool)
+ FUNC11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
+ FUNC1(environment_glow_set_use_bicubic_upscale, bool)
+ FUNC1(environment_glow_set_use_high_quality, bool)
- BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
+ FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
- BIND7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
+ FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
- BIND9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
- BIND9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, EnvVolumetricFogShadowFilter)
+ FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
+ FUNC10(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, bool, float)
- BIND2(environment_set_volumetric_fog_volume_size, int, int)
- BIND1(environment_set_volumetric_fog_filter_active, bool)
- BIND1(environment_set_volumetric_fog_directional_shadow_shrink_size, int)
- BIND1(environment_set_volumetric_fog_positional_shadow_shrink_size, int)
+ FUNC2(environment_set_volumetric_fog_volume_size, int, int)
+ FUNC1(environment_set_volumetric_fog_filter_active, bool)
- BIND11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, bool, bool, float, float, float)
- BIND1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
- BIND1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
- BIND1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight)
+ FUNC11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
+ FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
+ FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
+ FUNC1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight)
- BIND3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
+ FUNC3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
- BIND3(screen_space_roughness_limiter_set_active, bool, float, float)
- BIND1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
- BIND2(sub_surface_scattering_set_scale, float, float)
+ FUNC3(screen_space_roughness_limiter_set_active, bool, float, float)
+ FUNC1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
+ FUNC2(sub_surface_scattering_set_scale, float, float)
/* CAMERA EFFECTS */
- BIND0R(RID, camera_effects_create)
+ FUNCRIDSPLIT(camera_effects)
- BIND2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool)
- BIND1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape)
+ FUNC2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool)
+ FUNC1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape)
- BIND8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
- BIND3(camera_effects_set_custom_exposure, RID, bool, float)
+ FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
+ FUNC3(camera_effects_set_custom_exposure, RID, bool, float)
- BIND1(shadows_quality_set, ShadowQuality);
- BIND1(directional_shadow_quality_set, ShadowQuality);
+ FUNC1(shadows_quality_set, ShadowQuality);
+ FUNC1(directional_shadow_quality_set, ShadowQuality);
/* SCENARIO API */
-#undef BINDBASE
-#define BINDBASE RSG::scene
+#undef server_name
+#undef ServerName
+
+#define ServerName RendererScene
+#define server_name RSG::scene
- BIND0R(RID, scenario_create)
+ FUNCRIDSPLIT(scenario)
- BIND2(scenario_set_debug, RID, ScenarioDebugMode)
- BIND2(scenario_set_environment, RID, RID)
- BIND2(scenario_set_camera_effects, RID, RID)
- BIND2(scenario_set_fallback_environment, RID, RID)
+ FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
+ FUNC2(scenario_set_environment, RID, RID)
+ FUNC2(scenario_set_camera_effects, RID, RID)
+ FUNC2(scenario_set_fallback_environment, RID, RID)
/* INSTANCING API */
- BIND0R(RID, instance_create)
+ FUNCRIDSPLIT(instance)
- BIND2(instance_set_base, RID, RID)
- BIND2(instance_set_scenario, RID, RID)
- BIND2(instance_set_layer_mask, RID, uint32_t)
- BIND2(instance_set_transform, RID, const Transform &)
- BIND2(instance_attach_object_instance_id, RID, ObjectID)
- BIND3(instance_set_blend_shape_weight, RID, int, float)
- BIND3(instance_set_surface_material, RID, int, RID)
- BIND2(instance_set_visible, RID, bool)
+ FUNC2(instance_set_base, RID, RID)
+ FUNC2(instance_set_scenario, RID, RID)
+ FUNC2(instance_set_layer_mask, RID, uint32_t)
+ FUNC2(instance_set_transform, RID, const Transform &)
+ FUNC2(instance_attach_object_instance_id, RID, ObjectID)
+ FUNC3(instance_set_blend_shape_weight, RID, int, float)
+ FUNC3(instance_set_surface_material, RID, int, RID)
+ FUNC2(instance_set_visible, RID, bool)
- BIND2(instance_set_custom_aabb, RID, AABB)
+ FUNC2(instance_set_custom_aabb, RID, AABB)
- BIND2(instance_attach_skeleton, RID, RID)
- BIND2(instance_set_exterior, RID, bool)
+ FUNC2(instance_attach_skeleton, RID, RID)
+ FUNC2(instance_set_exterior, RID, bool)
- BIND2(instance_set_extra_visibility_margin, RID, real_t)
+ FUNC2(instance_set_extra_visibility_margin, RID, real_t)
// don't use these in a game!
- BIND2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
- BIND3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
- BIND2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
+ FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
+ FUNC3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
+ FUNC2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
- BIND3(instance_geometry_set_flag, RID, InstanceFlags, bool)
- BIND2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
- BIND2(instance_geometry_set_material_override, RID, RID)
+ FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool)
+ FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
+ FUNC2(instance_geometry_set_material_override, RID, RID)
- BIND5(instance_geometry_set_draw_range, RID, float, float, float, float)
- BIND2(instance_geometry_set_as_instance_lod, RID, RID)
- BIND4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
- BIND2(instance_geometry_set_lod_bias, RID, float)
+ FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
+ FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
+ FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
+ FUNC2(instance_geometry_set_lod_bias, RID, float)
- BIND3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
- BIND2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
- BIND2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
- BIND2C(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
+ FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
+ FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
+ FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
+ FUNC2C(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
- BIND3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
+ FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
- BIND1(gi_set_use_half_resolution, bool)
+ FUNC1(gi_set_use_half_resolution, bool)
-#undef BINDBASE
+#undef server_name
+#undef ServerName
//from now on, calls forwarded to this singleton
-#define BINDBASE RSG::canvas
+#define ServerName RendererCanvasCull
+#define server_name RSG::canvas
/* CANVAS (2D) */
- BIND0R(RID, canvas_create)
- BIND3(canvas_set_item_mirroring, RID, RID, const Point2 &)
- BIND2(canvas_set_modulate, RID, const Color &)
- BIND3(canvas_set_parent, RID, RID, float)
- BIND1(canvas_set_disable_scale, bool)
-
- BIND0R(RID, canvas_texture_create)
- BIND3(canvas_texture_set_channel, RID, CanvasTextureChannel, RID)
- BIND3(canvas_texture_set_shading_parameters, RID, const Color &, float)
-
- BIND2(canvas_texture_set_texture_filter, RID, CanvasItemTextureFilter)
- BIND2(canvas_texture_set_texture_repeat, RID, CanvasItemTextureRepeat)
-
- BIND0R(RID, canvas_item_create)
- BIND2(canvas_item_set_parent, RID, RID)
-
- BIND2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter)
- BIND2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat)
-
- BIND2(canvas_item_set_visible, RID, bool)
- BIND2(canvas_item_set_light_mask, RID, int)
-
- BIND2(canvas_item_set_update_when_visible, RID, bool)
-
- BIND2(canvas_item_set_transform, RID, const Transform2D &)
- BIND2(canvas_item_set_clip, RID, bool)
- BIND2(canvas_item_set_distance_field_mode, RID, bool)
- BIND3(canvas_item_set_custom_rect, RID, bool, const Rect2 &)
- BIND2(canvas_item_set_modulate, RID, const Color &)
- BIND2(canvas_item_set_self_modulate, RID, const Color &)
-
- BIND2(canvas_item_set_draw_behind_parent, RID, bool)
-
- BIND5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
- BIND5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
- BIND4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
- BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
- BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
- BIND6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
- BIND7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
- BIND10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
- BIND6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
- BIND5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
- BIND9(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int)
- BIND5(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID)
- BIND3(canvas_item_add_multimesh, RID, RID, RID)
- BIND3(canvas_item_add_particles, RID, RID, RID)
- BIND2(canvas_item_add_set_transform, RID, const Transform2D &)
- BIND2(canvas_item_add_clip_ignore, RID, bool)
- BIND2(canvas_item_set_sort_children_by_y, RID, bool)
- BIND2(canvas_item_set_z_index, RID, int)
- BIND2(canvas_item_set_z_as_relative_to_parent, RID, bool)
- BIND3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &)
- BIND2(canvas_item_attach_skeleton, RID, RID)
-
- BIND1(canvas_item_clear, RID)
- BIND2(canvas_item_set_draw_index, RID, int)
-
- BIND2(canvas_item_set_material, RID, RID)
-
- BIND2(canvas_item_set_use_parent_material, RID, bool)
-
- BIND6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
-
- BIND0R(RID, canvas_light_create)
-
- BIND2(canvas_light_set_mode, RID, CanvasLightMode)
-
- BIND2(canvas_light_attach_to_canvas, RID, RID)
- BIND2(canvas_light_set_enabled, RID, bool)
- BIND2(canvas_light_set_texture_scale, RID, float)
- BIND2(canvas_light_set_transform, RID, const Transform2D &)
- BIND2(canvas_light_set_texture, RID, RID)
- BIND2(canvas_light_set_texture_offset, RID, const Vector2 &)
- BIND2(canvas_light_set_color, RID, const Color &)
- BIND2(canvas_light_set_height, RID, float)
- BIND2(canvas_light_set_energy, RID, float)
- BIND3(canvas_light_set_z_range, RID, int, int)
- BIND3(canvas_light_set_layer_range, RID, int, int)
- BIND2(canvas_light_set_item_cull_mask, RID, int)
- BIND2(canvas_light_set_item_shadow_cull_mask, RID, int)
- BIND2(canvas_light_set_directional_distance, RID, float)
-
- BIND2(canvas_light_set_blend_mode, RID, CanvasLightBlendMode)
-
- BIND2(canvas_light_set_shadow_enabled, RID, bool)
- BIND2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter)
- BIND2(canvas_light_set_shadow_color, RID, const Color &)
- BIND2(canvas_light_set_shadow_smooth, RID, float)
-
- BIND0R(RID, canvas_light_occluder_create)
- BIND2(canvas_light_occluder_attach_to_canvas, RID, RID)
- BIND2(canvas_light_occluder_set_enabled, RID, bool)
- BIND2(canvas_light_occluder_set_polygon, RID, RID)
- BIND2(canvas_light_occluder_set_as_sdf_collision, RID, bool)
- BIND2(canvas_light_occluder_set_transform, RID, const Transform2D &)
- BIND2(canvas_light_occluder_set_light_mask, RID, int)
-
- BIND0R(RID, canvas_occluder_polygon_create)
- BIND3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
-
- BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
-
- BIND1(canvas_set_shadow_texture_size, int)
+ FUNCRIDSPLIT(canvas)
+ FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &)
+ FUNC2(canvas_set_modulate, RID, const Color &)
+ FUNC3(canvas_set_parent, RID, RID, float)
+ FUNC1(canvas_set_disable_scale, bool)
+
+ FUNCRIDSPLIT(canvas_texture)
+ FUNC3(canvas_texture_set_channel, RID, CanvasTextureChannel, RID)
+ FUNC3(canvas_texture_set_shading_parameters, RID, const Color &, float)
+
+ FUNC2(canvas_texture_set_texture_filter, RID, CanvasItemTextureFilter)
+ FUNC2(canvas_texture_set_texture_repeat, RID, CanvasItemTextureRepeat)
+
+ FUNCRIDSPLIT(canvas_item)
+ FUNC2(canvas_item_set_parent, RID, RID)
+
+ FUNC2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter)
+ FUNC2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat)
+
+ FUNC2(canvas_item_set_visible, RID, bool)
+ FUNC2(canvas_item_set_light_mask, RID, int)
+
+ FUNC2(canvas_item_set_update_when_visible, RID, bool)
+
+ FUNC2(canvas_item_set_transform, RID, const Transform2D &)
+ FUNC2(canvas_item_set_clip, RID, bool)
+ FUNC2(canvas_item_set_distance_field_mode, RID, bool)
+ FUNC3(canvas_item_set_custom_rect, RID, bool, const Rect2 &)
+ FUNC2(canvas_item_set_modulate, RID, const Color &)
+ FUNC2(canvas_item_set_self_modulate, RID, const Color &)
+
+ FUNC2(canvas_item_set_draw_behind_parent, RID, bool)
+
+ FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
+ FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
+ FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
+ FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
+ 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)
+ 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)
+ FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
+ FUNC9(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int)
+ FUNC5(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID)
+ FUNC3(canvas_item_add_multimesh, RID, RID, RID)
+ FUNC3(canvas_item_add_particles, RID, RID, RID)
+ FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
+ FUNC2(canvas_item_add_clip_ignore, RID, bool)
+ FUNC2(canvas_item_set_sort_children_by_y, RID, bool)
+ FUNC2(canvas_item_set_z_index, RID, int)
+ FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool)
+ FUNC3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &)
+ FUNC2(canvas_item_attach_skeleton, RID, RID)
+
+ FUNC1(canvas_item_clear, RID)
+ FUNC2(canvas_item_set_draw_index, RID, int)
+
+ FUNC2(canvas_item_set_material, RID, RID)
+
+ FUNC2(canvas_item_set_use_parent_material, RID, bool)
+
+ FUNC6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
+
+ FUNCRIDSPLIT(canvas_light)
+
+ FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
+
+ FUNC2(canvas_light_attach_to_canvas, RID, RID)
+ FUNC2(canvas_light_set_enabled, RID, bool)
+ FUNC2(canvas_light_set_texture_scale, RID, float)
+ FUNC2(canvas_light_set_transform, RID, const Transform2D &)
+ FUNC2(canvas_light_set_texture, RID, RID)
+ FUNC2(canvas_light_set_texture_offset, RID, const Vector2 &)
+ FUNC2(canvas_light_set_color, RID, const Color &)
+ FUNC2(canvas_light_set_height, RID, float)
+ FUNC2(canvas_light_set_energy, RID, float)
+ FUNC3(canvas_light_set_z_range, RID, int, int)
+ FUNC3(canvas_light_set_layer_range, RID, int, int)
+ FUNC2(canvas_light_set_item_cull_mask, RID, int)
+ FUNC2(canvas_light_set_item_shadow_cull_mask, RID, int)
+ FUNC2(canvas_light_set_directional_distance, RID, float)
+
+ FUNC2(canvas_light_set_blend_mode, RID, CanvasLightBlendMode)
+
+ FUNC2(canvas_light_set_shadow_enabled, RID, bool)
+ FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter)
+ FUNC2(canvas_light_set_shadow_color, RID, const Color &)
+ FUNC2(canvas_light_set_shadow_smooth, RID, float)
+
+ FUNCRIDSPLIT(canvas_light_occluder)
+ FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID)
+ FUNC2(canvas_light_occluder_set_enabled, RID, bool)
+ FUNC2(canvas_light_occluder_set_polygon, RID, RID)
+ FUNC2(canvas_light_occluder_set_as_sdf_collision, RID, bool)
+ FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &)
+ FUNC2(canvas_light_occluder_set_light_mask, RID, int)
+
+ FUNCRIDSPLIT(canvas_occluder_polygon)
+ FUNC3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
+
+ FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
+
+ FUNC1(canvas_set_shadow_texture_size, int)
/* GLOBAL VARIABLES */
-#undef BINDBASE
+#undef server_name
+#undef ServerName
//from now on, calls forwarded to this singleton
-#define BINDBASE RSG::storage
+#define ServerName RendererStorage
+#define server_name RSG::storage
- BIND3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
- BIND1(global_variable_remove, const StringName &)
- BIND0RC(Vector<StringName>, global_variable_get_list)
- BIND2(global_variable_set, const StringName &, const Variant &)
- BIND2(global_variable_set_override, const StringName &, const Variant &)
- BIND1RC(GlobalVariableType, global_variable_get_type, const StringName &)
- BIND1RC(Variant, global_variable_get, const StringName &)
+ FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
+ FUNC1(global_variable_remove, const StringName &)
+ FUNC0RC(Vector<StringName>, global_variable_get_list)
+ FUNC2(global_variable_set, const StringName &, const Variant &)
+ FUNC2(global_variable_set_override, const StringName &, const Variant &)
+ FUNC1RC(GlobalVariableType, global_variable_get_type, const StringName &)
+ FUNC1RC(Variant, global_variable_get, const StringName &)
- BIND1(global_variables_load_settings, bool)
- BIND0(global_variables_clear)
+ FUNC1(global_variables_load_settings, bool)
+ FUNC0(global_variables_clear)
+
+#undef server_name
+#undef ServerName
+#undef WRITE_ACTION
+#undef SYNC_DEBUG
/* BLACK BARS */
- virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom);
- virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom);
+ virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) override;
+ virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) override;
/* FREE */
- virtual void free(RID p_rid); ///< free RIDs associated with the visual server
+ virtual void free(RID p_rid) override {
+ if (Thread::get_caller_id() == server_thread) {
+ command_queue.flush_if_pending();
+ _free(p_rid);
+ } else {
+ command_queue.push(this, &RenderingServerDefault::_free, p_rid);
+ }
+ }
/* EVENT QUEUING */
- virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata);
+ virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) override;
- virtual void draw(bool p_swap_buffers, double frame_step);
- virtual void sync();
- virtual bool has_changed() const;
- virtual void init();
- virtual void finish();
+ virtual void draw(bool p_swap_buffers, double frame_step) override;
+ virtual void sync() override;
+ virtual bool has_changed() const override;
+ virtual void init() override;
+ virtual void finish() override;
/* STATUS INFORMATION */
- virtual int get_render_info(RenderInfo p_info);
- virtual String get_video_adapter_name() const;
- virtual String get_video_adapter_vendor() const;
+ virtual uint64_t get_render_info(RenderInfo p_info) override;
+ virtual String get_video_adapter_name() const override;
+ virtual String get_video_adapter_vendor() const override;
- virtual void set_frame_profiling_enabled(bool p_enable);
- virtual Vector<FrameProfileArea> get_frame_profile();
- virtual uint64_t get_frame_profile_frame();
+ virtual void set_frame_profiling_enabled(bool p_enable) override;
+ virtual Vector<FrameProfileArea> get_frame_profile() override;
+ virtual uint64_t get_frame_profile_frame() override;
- virtual RID get_test_cube();
+ virtual RID get_test_cube() override;
/* TESTING */
- virtual float get_frame_setup_time_cpu() const;
-
- virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true);
- virtual void set_default_clear_color(const Color &p_color);
+ virtual float get_frame_setup_time_cpu() const override;
- virtual bool has_feature(Features p_feature) const;
+ virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override;
+ virtual void set_default_clear_color(const Color &p_color) override;
- virtual bool has_os_feature(const String &p_feature) const;
- virtual void set_debug_generate_wireframes(bool p_generate);
+ virtual bool has_feature(Features p_feature) const override;
- virtual void call_set_use_vsync(bool p_enable);
+ virtual bool has_os_feature(const String &p_feature) const override;
+ virtual void set_debug_generate_wireframes(bool p_generate) override;
- virtual bool is_low_end() const;
+ virtual bool is_low_end() const override;
- virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir);
+ virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override;
- virtual void set_print_gpu_profile(bool p_enable);
+ virtual void set_print_gpu_profile(bool p_enable) override;
- RenderingServerDefault();
+ RenderingServerDefault(bool p_create_thread = false);
~RenderingServerDefault();
-
-#undef DISPLAY_CHANGED
-
-#undef BIND0R
-#undef BIND1RC
-#undef BIND2RC
-#undef BIND3RC
-#undef BIND4RC
-
-#undef BIND1
-#undef BIND2
-#undef BIND3
-#undef BIND4
-#undef BIND5
-#undef BIND6
-#undef BIND7
-#undef BIND8
-#undef BIND9
-#undef BIND10
};
#endif
diff --git a/servers/rendering/rendering_server_wrap_mt.cpp b/servers/rendering/rendering_server_wrap_mt.cpp
deleted file mode 100644
index 9b8d35e5b3..0000000000
--- a/servers/rendering/rendering_server_wrap_mt.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/*************************************************************************/
-/* rendering_server_wrap_mt.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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 "rendering_server_wrap_mt.h"
-#include "core/config/project_settings.h"
-#include "core/os/os.h"
-#include "servers/display_server.h"
-
-void RenderingServerWrapMT::thread_exit() {
- exit = true;
-}
-
-void RenderingServerWrapMT::thread_draw(bool p_swap_buffers, double frame_step) {
- if (!atomic_decrement(&draw_pending)) {
- rendering_server->draw(p_swap_buffers, frame_step);
- }
-}
-
-void RenderingServerWrapMT::thread_flush() {
- atomic_decrement(&draw_pending);
-}
-
-void RenderingServerWrapMT::_thread_callback(void *_instance) {
- RenderingServerWrapMT *vsmt = reinterpret_cast<RenderingServerWrapMT *>(_instance);
-
- vsmt->thread_loop();
-}
-
-void RenderingServerWrapMT::thread_loop() {
- server_thread = Thread::get_caller_id();
-
- DisplayServer::get_singleton()->make_rendering_thread();
-
- rendering_server->init();
-
- exit = false;
- draw_thread_up = true;
- while (!exit) {
- // flush commands one by one, until exit is requested
- command_queue.wait_and_flush_one();
- }
-
- command_queue.flush_all(); // flush all
-
- rendering_server->finish();
-}
-
-/* EVENT QUEUING */
-
-void RenderingServerWrapMT::sync() {
- if (create_thread) {
- atomic_increment(&draw_pending);
- command_queue.push_and_sync(this, &RenderingServerWrapMT::thread_flush);
- } else {
- command_queue.flush_all(); //flush all pending from other threads
- }
-}
-
-void RenderingServerWrapMT::draw(bool p_swap_buffers, double frame_step) {
- if (create_thread) {
- atomic_increment(&draw_pending);
- command_queue.push(this, &RenderingServerWrapMT::thread_draw, p_swap_buffers, frame_step);
- } else {
- rendering_server->draw(p_swap_buffers, frame_step);
- }
-}
-
-void RenderingServerWrapMT::init() {
- if (create_thread) {
- print_verbose("RenderingServerWrapMT: Creating render thread");
- DisplayServer::get_singleton()->release_rendering_thread();
- if (create_thread) {
- thread.start(_thread_callback, this);
- print_verbose("RenderingServerWrapMT: Starting render thread");
- }
- while (!draw_thread_up) {
- OS::get_singleton()->delay_usec(1000);
- }
- print_verbose("RenderingServerWrapMT: Finished render thread");
- } else {
- rendering_server->init();
- }
-}
-
-void RenderingServerWrapMT::finish() {
- sky_free_cached_ids();
- shader_free_cached_ids();
- material_free_cached_ids();
- mesh_free_cached_ids();
- multimesh_free_cached_ids();
- immediate_free_cached_ids();
- skeleton_free_cached_ids();
- directional_light_free_cached_ids();
- omni_light_free_cached_ids();
- spot_light_free_cached_ids();
- reflection_probe_free_cached_ids();
- gi_probe_free_cached_ids();
- lightmap_free_cached_ids();
- particles_free_cached_ids();
- particles_collision_free_cached_ids();
- camera_free_cached_ids();
- viewport_free_cached_ids();
- environment_free_cached_ids();
- camera_effects_free_cached_ids();
- scenario_free_cached_ids();
- instance_free_cached_ids();
- canvas_free_cached_ids();
- canvas_item_free_cached_ids();
- canvas_light_occluder_free_cached_ids();
- canvas_occluder_polygon_free_cached_ids();
-
- if (create_thread) {
- command_queue.push(this, &RenderingServerWrapMT::thread_exit);
- thread.wait_to_finish();
- } else {
- rendering_server->finish();
- }
-}
-
-void RenderingServerWrapMT::set_use_vsync_callback(bool p_enable) {
- singleton_mt->call_set_use_vsync(p_enable);
-}
-
-RenderingServerWrapMT *RenderingServerWrapMT::singleton_mt = nullptr;
-
-RenderingServerWrapMT::RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread) :
- command_queue(p_create_thread) {
- singleton_mt = this;
- DisplayServer::switch_vsync_function = set_use_vsync_callback; //as this goes to another thread, make sure it goes properly
-
- rendering_server = p_contained;
- create_thread = p_create_thread;
- draw_pending = 0;
- draw_thread_up = false;
- pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
-
- if (!p_create_thread) {
- server_thread = Thread::get_caller_id();
- } else {
- server_thread = 0;
- }
-}
-
-RenderingServerWrapMT::~RenderingServerWrapMT() {
- memdelete(rendering_server);
- //finish();
-}
diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h
deleted file mode 100644
index f8e73654a0..0000000000
--- a/servers/rendering/rendering_server_wrap_mt.h
+++ /dev/null
@@ -1,810 +0,0 @@
-/*************************************************************************/
-/* rendering_server_wrap_mt.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef RENDERING_SERVER_WRAP_MT_H
-#define RENDERING_SERVER_WRAP_MT_H
-
-#include "core/os/thread.h"
-#include "core/templates/command_queue_mt.h"
-#include "servers/rendering_server.h"
-
-class RenderingServerWrapMT : public RenderingServer {
- // the real visual server
- mutable RenderingServer *rendering_server;
-
- mutable CommandQueueMT command_queue;
-
- static void _thread_callback(void *_instance);
- void thread_loop();
-
- Thread::ID server_thread;
- volatile bool exit;
- Thread thread;
- volatile bool draw_thread_up;
- bool create_thread;
-
- uint64_t draw_pending;
- void thread_draw(bool p_swap_buffers, double frame_step);
- void thread_flush();
-
- void thread_exit();
-
- Mutex alloc_mutex;
-
- int pool_max_size;
-
- //#define DEBUG_SYNC
-
- static RenderingServerWrapMT *singleton_mt;
-
-#ifdef DEBUG_SYNC
-#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__));
-#else
-#define SYNC_DEBUG
-#endif
-
-public:
-#define ServerName RenderingServer
-#define ServerNameWrapMT RenderingServerWrapMT
-#define server_name rendering_server
-#include "servers/server_wrap_mt_common.h"
-
- //these go pass-through, as they can be called from any thread
- virtual RID texture_2d_create(const Ref<Image> &p_image) { return rendering_server->texture_2d_create(p_image); }
- virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, TextureLayeredType p_layered_type) { return rendering_server->texture_2d_layered_create(p_layers, p_layered_type); }
- virtual RID texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { return rendering_server->texture_3d_create(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); }
- virtual RID texture_proxy_create(RID p_base) { return rendering_server->texture_proxy_create(p_base); }
-
- //goes pass-through
- virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) { rendering_server->texture_2d_update_immediate(p_texture, p_image, p_layer); }
- //these go through command queue if they are in another thread
- FUNC3(texture_2d_update, RID, const Ref<Image> &, int)
- FUNC2(texture_3d_update, RID, const Vector<Ref<Image>> &)
- FUNC2(texture_proxy_update, RID, RID)
-
- //these also go pass-through
- virtual RID texture_2d_placeholder_create() { return rendering_server->texture_2d_placeholder_create(); }
- virtual RID texture_2d_layered_placeholder_create(TextureLayeredType p_type) { return rendering_server->texture_2d_layered_placeholder_create(p_type); }
- virtual RID texture_3d_placeholder_create() { return rendering_server->texture_3d_placeholder_create(); }
-
- FUNC1RC(Ref<Image>, texture_2d_get, RID)
- FUNC2RC(Ref<Image>, texture_2d_layer_get, RID, int)
- FUNC1RC(Vector<Ref<Image>>, texture_3d_get, RID)
-
- FUNC2(texture_replace, RID, RID)
-
- FUNC3(texture_set_size_override, RID, int, int)
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
- FUNC2(texture_bind, RID, uint32_t)
-#endif
-
- FUNC3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
- FUNC3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *)
- FUNC3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *)
-
- FUNC2(texture_set_path, RID, const String &)
- FUNC1RC(String, texture_get_path, RID)
- FUNC1S(texture_debug_usage, List<TextureInfo> *)
-
- FUNC2(texture_set_force_redraw_if_visible, RID, bool)
-
- /* SHADER API */
-
- FUNCRID(shader)
-
- FUNC2(shader_set_code, RID, const String &)
- FUNC1RC(String, shader_get_code, RID)
-
- FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
-
- FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
- FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
- FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
-
- FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
-
- /* COMMON MATERIAL API */
-
- FUNCRID(material)
-
- FUNC2(material_set_shader, RID, RID)
-
- FUNC3(material_set_param, RID, const StringName &, const Variant &)
- FUNC2RC(Variant, material_get_param, RID, const StringName &)
-
- FUNC2(material_set_render_priority, RID, int)
- FUNC2(material_set_next_pass, RID, RID)
-
- /* MESH API */
-
- virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) {
- return rendering_server->mesh_create_from_surfaces(p_surfaces, p_blend_shape_count);
- }
-
- FUNC2(mesh_set_blend_shape_count, RID, int)
-
- FUNCRID(mesh)
-
- FUNC2(mesh_add_surface, RID, const SurfaceData &)
-
- FUNC1RC(int, mesh_get_blend_shape_count, RID)
-
- FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
- FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
-
- FUNC4(mesh_surface_update_region, RID, int, int, const Vector<uint8_t> &)
-
- FUNC3(mesh_surface_set_material, RID, int, RID)
- FUNC2RC(RID, mesh_surface_get_material, RID, int)
-
- FUNC2RC(SurfaceData, mesh_get_surface, RID, int)
-
- FUNC1RC(int, mesh_get_surface_count, RID)
-
- FUNC2(mesh_set_custom_aabb, RID, const AABB &)
- FUNC1RC(AABB, mesh_get_custom_aabb, RID)
-
- FUNC2(mesh_set_shadow_mesh, RID, RID)
- FUNC1(mesh_clear, RID)
-
- /* MULTIMESH API */
-
- FUNCRID(multimesh)
-
- FUNC5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool)
- FUNC1RC(int, multimesh_get_instance_count, RID)
-
- FUNC2(multimesh_set_mesh, RID, RID)
- FUNC3(multimesh_instance_set_transform, RID, int, const Transform &)
- FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
- FUNC3(multimesh_instance_set_color, RID, int, const Color &)
- FUNC3(multimesh_instance_set_custom_data, RID, int, const Color &)
-
- FUNC1RC(RID, multimesh_get_mesh, RID)
- FUNC1RC(AABB, multimesh_get_aabb, RID)
-
- FUNC2RC(Transform, multimesh_instance_get_transform, RID, int)
- FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
- FUNC2RC(Color, multimesh_instance_get_color, RID, int)
- FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int)
-
- FUNC2(multimesh_set_buffer, RID, const Vector<float> &)
- FUNC1RC(Vector<float>, multimesh_get_buffer, RID)
-
- FUNC2(multimesh_set_visible_instances, RID, int)
- FUNC1RC(int, multimesh_get_visible_instances, RID)
-
- /* IMMEDIATE API */
-
- FUNCRID(immediate)
- FUNC3(immediate_begin, RID, PrimitiveType, RID)
- FUNC2(immediate_vertex, RID, const Vector3 &)
- FUNC2(immediate_normal, RID, const Vector3 &)
- FUNC2(immediate_tangent, RID, const Plane &)
- FUNC2(immediate_color, RID, const Color &)
- FUNC2(immediate_uv, RID, const Vector2 &)
- FUNC2(immediate_uv2, RID, const Vector2 &)
- FUNC1(immediate_end, RID)
- FUNC1(immediate_clear, RID)
- FUNC2(immediate_set_material, RID, RID)
- FUNC1RC(RID, immediate_get_material, RID)
-
- /* SKELETON API */
-
- FUNCRID(skeleton)
- FUNC3(skeleton_allocate, RID, int, bool)
- FUNC1RC(int, skeleton_get_bone_count, RID)
- FUNC3(skeleton_bone_set_transform, RID, int, const Transform &)
- FUNC2RC(Transform, skeleton_bone_get_transform, RID, int)
- FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
- FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
- FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &)
-
- /* Light API */
-
- FUNCRID(directional_light)
- FUNCRID(omni_light)
- FUNCRID(spot_light)
-
- FUNC2(light_set_color, RID, const Color &)
- FUNC3(light_set_param, RID, LightParam, float)
- FUNC2(light_set_shadow, RID, bool)
- FUNC2(light_set_shadow_color, RID, const Color &)
- FUNC2(light_set_projector, RID, RID)
- FUNC2(light_set_negative, RID, bool)
- FUNC2(light_set_cull_mask, RID, uint32_t)
- FUNC2(light_set_reverse_cull_face_mode, RID, bool)
- FUNC2(light_set_bake_mode, RID, LightBakeMode)
- FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t)
-
- FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
-
- FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
- FUNC2(light_directional_set_blend_splits, RID, bool)
- FUNC2(light_directional_set_sky_only, RID, bool)
- FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
-
- /* PROBE API */
-
- FUNCRID(reflection_probe)
-
- FUNC2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
- FUNC2(reflection_probe_set_intensity, RID, float)
- FUNC2(reflection_probe_set_ambient_color, RID, const Color &)
- FUNC2(reflection_probe_set_ambient_energy, RID, float)
- FUNC2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode)
- FUNC2(reflection_probe_set_max_distance, RID, float)
- FUNC2(reflection_probe_set_extents, RID, const Vector3 &)
- FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &)
- FUNC2(reflection_probe_set_as_interior, RID, bool)
- FUNC2(reflection_probe_set_enable_box_projection, RID, bool)
- FUNC2(reflection_probe_set_enable_shadows, RID, bool)
- FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
- FUNC2(reflection_probe_set_resolution, RID, int)
- FUNC2(reflection_probe_set_lod_threshold, RID, float)
-
- /* DECAL API */
-
- FUNCRID(decal)
-
- FUNC2(decal_set_extents, RID, const Vector3 &)
- FUNC3(decal_set_texture, RID, DecalTexture, RID)
- FUNC2(decal_set_emission_energy, RID, float)
- FUNC2(decal_set_albedo_mix, RID, float)
- FUNC2(decal_set_modulate, RID, const Color &)
- FUNC2(decal_set_cull_mask, RID, uint32_t)
- FUNC4(decal_set_distance_fade, RID, bool, float, float)
- FUNC3(decal_set_fade, RID, float, float)
- FUNC2(decal_set_normal_fade, RID, float)
-
- /* BAKED LIGHT API */
-
- FUNCRID(gi_probe)
-
- FUNC8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)
-
- FUNC1RC(AABB, gi_probe_get_bounds, RID)
- FUNC1RC(Vector3i, gi_probe_get_octree_size, RID)
- FUNC1RC(Vector<uint8_t>, gi_probe_get_octree_cells, RID)
- FUNC1RC(Vector<uint8_t>, gi_probe_get_data_cells, RID)
- FUNC1RC(Vector<uint8_t>, gi_probe_get_distance_field, RID)
- FUNC1RC(Vector<int>, gi_probe_get_level_counts, RID)
- FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID)
-
- FUNC2(gi_probe_set_dynamic_range, RID, float)
- FUNC1RC(float, gi_probe_get_dynamic_range, RID)
-
- FUNC2(gi_probe_set_propagation, RID, float)
- FUNC1RC(float, gi_probe_get_propagation, RID)
-
- FUNC2(gi_probe_set_energy, RID, float)
- FUNC1RC(float, gi_probe_get_energy, RID)
-
- FUNC2(gi_probe_set_ao, RID, float)
- FUNC1RC(float, gi_probe_get_ao, RID)
-
- FUNC2(gi_probe_set_ao_size, RID, float)
- FUNC1RC(float, gi_probe_get_ao_size, RID)
-
- FUNC2(gi_probe_set_bias, RID, float)
- FUNC1RC(float, gi_probe_get_bias, RID)
-
- FUNC2(gi_probe_set_normal_bias, RID, float)
- FUNC1RC(float, gi_probe_get_normal_bias, RID)
-
- FUNC2(gi_probe_set_interior, RID, bool)
- FUNC1RC(bool, gi_probe_is_interior, RID)
-
- FUNC2(gi_probe_set_use_two_bounces, RID, bool)
- FUNC1RC(bool, gi_probe_is_using_two_bounces, RID)
-
- FUNC2(gi_probe_set_anisotropy_strength, RID, float)
- FUNC1RC(float, gi_probe_get_anisotropy_strength, RID)
-
- FUNC1(gi_probe_set_quality, GIProbeQuality)
-
- /* LIGHTMAP CAPTURE */
-
- FUNCRID(lightmap)
- FUNC3(lightmap_set_textures, RID, RID, bool)
- FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
- FUNC2(lightmap_set_probe_interior, RID, bool)
- FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
- FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
- FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
- FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
- FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
-
- FUNC1(lightmap_set_probe_capture_update_speed, float)
-
- /* PARTICLES */
-
- FUNCRID(particles)
-
- FUNC2(particles_set_emitting, RID, bool)
- FUNC1R(bool, particles_get_emitting, RID)
- FUNC2(particles_set_amount, RID, int)
- FUNC2(particles_set_lifetime, RID, float)
- FUNC2(particles_set_one_shot, RID, bool)
- FUNC2(particles_set_pre_process_time, RID, float)
- FUNC2(particles_set_explosiveness_ratio, RID, float)
- FUNC2(particles_set_randomness_ratio, RID, float)
- FUNC2(particles_set_custom_aabb, RID, const AABB &)
- FUNC2(particles_set_speed_scale, RID, float)
- FUNC2(particles_set_use_local_coordinates, RID, bool)
- FUNC2(particles_set_process_material, RID, RID)
- FUNC2(particles_set_fixed_fps, RID, int)
- FUNC2(particles_set_fractional_delta, RID, bool)
- FUNC2(particles_set_collision_base_size, RID, float)
-
- FUNC1R(bool, particles_is_inactive, RID)
- FUNC1(particles_request_process, RID)
- FUNC1(particles_restart, RID)
-
- FUNC6(particles_emit, RID, const Transform &, const Vector3 &, const Color &, const Color &, uint32_t)
-
- FUNC2(particles_set_draw_order, RID, RS::ParticlesDrawOrder)
-
- FUNC2(particles_set_draw_passes, RID, int)
- FUNC3(particles_set_draw_pass_mesh, RID, int, RID)
- FUNC2(particles_set_emission_transform, RID, const Transform &)
- FUNC2(particles_set_subemitter, RID, RID)
-
- FUNC1R(AABB, particles_get_current_aabb, RID)
-
- /* PARTICLES COLLISION */
-
- FUNCRID(particles_collision)
-
- FUNC2(particles_collision_set_collision_type, RID, ParticlesCollisionType)
- FUNC2(particles_collision_set_cull_mask, RID, uint32_t)
- FUNC2(particles_collision_set_sphere_radius, RID, float)
- FUNC2(particles_collision_set_box_extents, RID, const Vector3 &)
- FUNC2(particles_collision_set_attractor_strength, RID, float)
- FUNC2(particles_collision_set_attractor_directionality, RID, float)
- FUNC2(particles_collision_set_attractor_attenuation, RID, float)
- FUNC2(particles_collision_set_field_texture, RID, RID)
- FUNC1(particles_collision_height_field_update, RID)
- FUNC2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
-
- /* CAMERA API */
-
- FUNCRID(camera)
- FUNC4(camera_set_perspective, RID, float, float, float)
- FUNC4(camera_set_orthogonal, RID, float, float, float)
- FUNC5(camera_set_frustum, RID, float, Vector2, float, float)
- FUNC2(camera_set_transform, RID, const Transform &)
- FUNC2(camera_set_cull_mask, RID, uint32_t)
- FUNC2(camera_set_environment, RID, RID)
- FUNC2(camera_set_camera_effects, RID, RID)
- FUNC2(camera_set_use_vertical_aspect, RID, bool)
-
- /* VIEWPORT TARGET API */
-
- FUNCRID(viewport)
-
- FUNC2(viewport_set_use_xr, RID, bool)
-
- FUNC3(viewport_set_size, RID, int, int)
-
- FUNC2(viewport_set_active, RID, bool)
- FUNC2(viewport_set_parent_viewport, RID, RID)
-
- FUNC2(viewport_set_clear_mode, RID, ViewportClearMode)
-
- FUNC3(viewport_attach_to_screen, RID, const Rect2 &, DisplayServer::WindowID)
- FUNC2(viewport_set_render_direct_to_screen, RID, bool)
-
- FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
-
- FUNC1RC(RID, viewport_get_texture, RID)
-
- FUNC2(viewport_set_hide_scenario, RID, bool)
- FUNC2(viewport_set_hide_canvas, RID, bool)
- FUNC2(viewport_set_disable_environment, RID, bool)
-
- FUNC2(viewport_attach_camera, RID, RID)
- FUNC2(viewport_set_scenario, RID, RID)
- FUNC2(viewport_attach_canvas, RID, RID)
-
- FUNC2(viewport_remove_canvas, RID, RID)
- FUNC3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
- FUNC2(viewport_set_transparent_background, RID, bool)
- FUNC2(viewport_set_snap_2d_transforms_to_pixel, RID, bool)
- FUNC2(viewport_set_snap_2d_vertices_to_pixel, RID, bool)
-
- FUNC2(viewport_set_default_canvas_item_texture_filter, RID, CanvasItemTextureFilter)
- FUNC2(viewport_set_default_canvas_item_texture_repeat, RID, CanvasItemTextureRepeat)
-
- FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
- FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
- FUNC3(viewport_set_shadow_atlas_size, RID, int, bool)
- FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
-
- FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
- FUNC2(viewport_set_msaa, RID, ViewportMSAA)
- FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
- FUNC2(viewport_set_use_debanding, RID, bool)
-
- FUNC2(viewport_set_lod_threshold, RID, float)
-
- //this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport
- virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) {
- return rendering_server->viewport_get_render_info(p_viewport, p_info);
- }
-
- FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
-
- FUNC2(viewport_set_measure_render_time, RID, bool)
- virtual float viewport_get_measured_render_time_cpu(RID p_viewport) const {
- return rendering_server->viewport_get_measured_render_time_cpu(p_viewport);
- }
- virtual float viewport_get_measured_render_time_gpu(RID p_viewport) const {
- return rendering_server->viewport_get_measured_render_time_gpu(p_viewport);
- }
-
- FUNC2(directional_shadow_atlas_set_size, int, bool)
-
- /* SKY API */
-
- FUNCRID(sky)
- FUNC2(sky_set_radiance_size, RID, int)
- FUNC2(sky_set_mode, RID, SkyMode)
- FUNC2(sky_set_material, RID, RID)
- FUNC4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &)
-
- /* ENVIRONMENT API */
-
- FUNCRID(environment)
-
- FUNC2(environment_set_background, RID, EnvironmentBG)
- FUNC2(environment_set_sky, RID, RID)
- FUNC2(environment_set_sky_custom_fov, RID, float)
- FUNC2(environment_set_sky_orientation, RID, const Basis &)
- FUNC2(environment_set_bg_color, RID, const Color &)
- FUNC2(environment_set_bg_energy, RID, float)
- FUNC2(environment_set_canvas_max_layer, RID, int)
- FUNC7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &)
-
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
- FUNC2(environment_set_camera_feed_id, RID, int)
-#endif
- FUNC6(environment_set_ssr, RID, bool, int, float, float, float)
- FUNC1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality)
-
- FUNC10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float)
-
- FUNC6(environment_set_ssao_quality, EnvironmentSSAOQuality, bool, float, int, float, float)
-
- FUNC11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, bool, bool, float, float, float)
- FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
- FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
- FUNC1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight)
-
- FUNC11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
- FUNC1(environment_glow_set_use_bicubic_upscale, bool)
- FUNC1(environment_glow_set_use_high_quality, bool)
-
- FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
-
- FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
-
- FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
-
- FUNC9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, EnvVolumetricFogShadowFilter)
-
- FUNC2(environment_set_volumetric_fog_volume_size, int, int)
- FUNC1(environment_set_volumetric_fog_filter_active, bool)
- FUNC1(environment_set_volumetric_fog_directional_shadow_shrink_size, int)
- FUNC1(environment_set_volumetric_fog_positional_shadow_shrink_size, int)
-
- FUNC3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
-
- FUNC3(screen_space_roughness_limiter_set_active, bool, float, float)
- FUNC1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
- FUNC2(sub_surface_scattering_set_scale, float, float)
-
- FUNCRID(camera_effects)
-
- FUNC2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool)
- FUNC1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape)
-
- FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
- FUNC3(camera_effects_set_custom_exposure, RID, bool, float)
-
- FUNC1(shadows_quality_set, ShadowQuality);
- FUNC1(directional_shadow_quality_set, ShadowQuality);
-
- FUNCRID(scenario)
-
- FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
- FUNC2(scenario_set_environment, RID, RID)
- FUNC2(scenario_set_camera_effects, RID, RID)
- FUNC2(scenario_set_fallback_environment, RID, RID)
-
- /* INSTANCING API */
- FUNCRID(instance)
-
- FUNC2(instance_set_base, RID, RID)
- FUNC2(instance_set_scenario, RID, RID)
- FUNC2(instance_set_layer_mask, RID, uint32_t)
- FUNC2(instance_set_transform, RID, const Transform &)
- FUNC2(instance_attach_object_instance_id, RID, ObjectID)
- FUNC3(instance_set_blend_shape_weight, RID, int, float)
- FUNC3(instance_set_surface_material, RID, int, RID)
- FUNC2(instance_set_visible, RID, bool)
-
- FUNC2(instance_set_custom_aabb, RID, AABB)
-
- FUNC2(instance_attach_skeleton, RID, RID)
- FUNC2(instance_set_exterior, RID, bool)
-
- FUNC2(instance_set_extra_visibility_margin, RID, real_t)
-
- // don't use these in a game!
- FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
- FUNC3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
- FUNC2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
-
- FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool)
- FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
- FUNC2(instance_geometry_set_material_override, RID, RID)
-
- FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
- FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
- FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
- FUNC2(instance_geometry_set_lod_bias, RID, float)
-
- FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
- FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
- FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
- FUNC2SC(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
-
- /* BAKE */
-
- FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
-
- /* CANVAS (2D) */
-
- FUNCRID(canvas)
- FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &)
- FUNC2(canvas_set_modulate, RID, const Color &)
- FUNC3(canvas_set_parent, RID, RID, float)
- FUNC1(canvas_set_disable_scale, bool)
-
- FUNCRID(canvas_texture)
- FUNC3(canvas_texture_set_channel, RID, CanvasTextureChannel, RID)
- FUNC3(canvas_texture_set_shading_parameters, RID, const Color &, float)
-
- FUNC2(canvas_texture_set_texture_filter, RID, CanvasItemTextureFilter)
- FUNC2(canvas_texture_set_texture_repeat, RID, CanvasItemTextureRepeat)
-
- FUNCRID(canvas_item)
- FUNC2(canvas_item_set_parent, RID, RID)
-
- FUNC2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter)
- FUNC2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat)
-
- FUNC2(canvas_item_set_visible, RID, bool)
- FUNC2(canvas_item_set_light_mask, RID, int)
-
- FUNC2(canvas_item_set_update_when_visible, RID, bool)
-
- FUNC2(canvas_item_set_transform, RID, const Transform2D &)
- FUNC2(canvas_item_set_clip, RID, bool)
- FUNC2(canvas_item_set_distance_field_mode, RID, bool)
- FUNC3(canvas_item_set_custom_rect, RID, bool, const Rect2 &)
- FUNC2(canvas_item_set_modulate, RID, const Color &)
- FUNC2(canvas_item_set_self_modulate, RID, const Color &)
-
- FUNC2(canvas_item_set_draw_behind_parent, RID, bool)
-
- FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
- FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
- FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
- FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
- 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)
- 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)
- FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
- FUNC9(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int)
- FUNC5(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID)
- FUNC3(canvas_item_add_multimesh, RID, RID, RID)
- FUNC3(canvas_item_add_particles, RID, RID, RID)
- FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
- FUNC2(canvas_item_add_clip_ignore, RID, bool)
- FUNC2(canvas_item_set_sort_children_by_y, RID, bool)
- FUNC2(canvas_item_set_z_index, RID, int)
- FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool)
- FUNC3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &)
- FUNC2(canvas_item_attach_skeleton, RID, RID)
-
- FUNC1(canvas_item_clear, RID)
- FUNC2(canvas_item_set_draw_index, RID, int)
-
- FUNC2(canvas_item_set_material, RID, RID)
-
- FUNC2(canvas_item_set_use_parent_material, RID, bool)
-
- FUNC6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
-
- FUNC0R(RID, canvas_light_create)
-
- FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
-
- FUNC2(canvas_light_attach_to_canvas, RID, RID)
- FUNC2(canvas_light_set_enabled, RID, bool)
- FUNC2(canvas_light_set_texture_scale, RID, float)
- FUNC2(canvas_light_set_transform, RID, const Transform2D &)
- FUNC2(canvas_light_set_texture, RID, RID)
- FUNC2(canvas_light_set_texture_offset, RID, const Vector2 &)
- FUNC2(canvas_light_set_color, RID, const Color &)
- FUNC2(canvas_light_set_height, RID, float)
- FUNC2(canvas_light_set_energy, RID, float)
- FUNC3(canvas_light_set_z_range, RID, int, int)
- FUNC3(canvas_light_set_layer_range, RID, int, int)
- FUNC2(canvas_light_set_item_cull_mask, RID, int)
- FUNC2(canvas_light_set_item_shadow_cull_mask, RID, int)
- FUNC2(canvas_light_set_directional_distance, RID, float)
-
- FUNC2(canvas_light_set_blend_mode, RID, CanvasLightBlendMode)
-
- FUNC2(canvas_light_set_shadow_enabled, RID, bool)
- FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter)
- FUNC2(canvas_light_set_shadow_color, RID, const Color &)
- FUNC2(canvas_light_set_shadow_smooth, RID, float)
-
- FUNCRID(canvas_light_occluder)
- FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID)
- FUNC2(canvas_light_occluder_set_enabled, RID, bool)
- FUNC2(canvas_light_occluder_set_polygon, RID, RID)
- FUNC2(canvas_light_occluder_set_as_sdf_collision, RID, bool)
- FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &)
- FUNC2(canvas_light_occluder_set_light_mask, RID, int)
-
- FUNCRID(canvas_occluder_polygon)
- FUNC3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
-
- FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
-
- FUNC1(canvas_set_shadow_texture_size, int)
-
- /* GLOBAL VARIABLES */
-
- FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
- FUNC1(global_variable_remove, const StringName &)
- FUNC0RC(Vector<StringName>, global_variable_get_list)
- FUNC2(global_variable_set, const StringName &, const Variant &)
- FUNC2(global_variable_set_override, const StringName &, const Variant &)
- FUNC1RC(GlobalVariableType, global_variable_get_type, const StringName &)
- FUNC1RC(Variant, global_variable_get, const StringName &)
- FUNC1(global_variables_load_settings, bool)
- FUNC0(global_variables_clear)
-
- /* BLACK BARS */
-
- FUNC4(black_bars_set_margins, int, int, int, int)
- FUNC4(black_bars_set_images, RID, RID, RID, RID)
-
- /* FREE */
-
- FUNC1(free, RID)
-
- /* EVENT QUEUING */
-
- FUNC3(request_frame_drawn_callback, Object *, const StringName &, const Variant &)
-
- virtual void init();
- virtual void finish();
- virtual void draw(bool p_swap_buffers, double frame_step);
- virtual void sync();
- FUNC0RC(bool, has_changed)
-
- /* RENDER INFO */
-
- //this passes directly to avoid stalling
- virtual int get_render_info(RenderInfo p_info) {
- return rendering_server->get_render_info(p_info);
- }
-
- virtual String get_video_adapter_name() const {
- return rendering_server->get_video_adapter_name();
- }
-
- virtual String get_video_adapter_vendor() const {
- return rendering_server->get_video_adapter_vendor();
- }
-
- FUNC1(gi_set_use_half_resolution, bool)
-
- FUNC4(set_boot_image, const Ref<Image> &, const Color &, bool, bool)
- FUNC1(set_default_clear_color, const Color &)
-
- FUNC0R(RID, get_test_cube)
-
- FUNC1(set_debug_generate_wireframes, bool)
-
- virtual bool has_feature(Features p_feature) const {
- return rendering_server->has_feature(p_feature);
- }
- virtual bool has_os_feature(const String &p_feature) const {
- return rendering_server->has_os_feature(p_feature);
- }
-
- FUNC1(call_set_use_vsync, bool)
-
- static void set_use_vsync_callback(bool p_enable);
-
- virtual bool is_low_end() const {
- return rendering_server->is_low_end();
- }
-
- virtual uint64_t get_frame_profile_frame() {
- return rendering_server->get_frame_profile_frame();
- }
-
- virtual void set_frame_profiling_enabled(bool p_enabled) {
- rendering_server->set_frame_profiling_enabled(p_enabled);
- }
-
- virtual Vector<FrameProfileArea> get_frame_profile() {
- return rendering_server->get_frame_profile();
- }
-
- virtual float get_frame_setup_time_cpu() const {
- return rendering_server->get_frame_setup_time_cpu();
- }
-
- virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) {
- rendering_server->sdfgi_set_debug_probe_select(p_position, p_dir);
- }
-
- virtual void set_print_gpu_profile(bool p_enable) {
- rendering_server->set_print_gpu_profile(p_enable);
- }
-
- RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread);
- ~RenderingServerWrapMT();
-
-#undef ServerName
-#undef ServerNameWrapMT
-#undef server_name
-};
-
-#ifdef DEBUG_SYNC
-#undef DEBUG_SYNC
-#endif
-#undef SYNC_DEBUG
-
-#endif
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index e6415c0258..df1a7d58d0 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -558,13 +558,13 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_ERROR, "Invalid numeric constant");
}
hexa_found = true;
- } else if (GETCHAR(i) == 'e') {
- if (hexa_found || exponent_found || float_suffix_found) {
+ } else if (GETCHAR(i) == 'e' && !hexa_found) {
+ if (exponent_found || float_suffix_found) {
return _make_token(TK_ERROR, "Invalid numeric constant");
}
exponent_found = true;
- } else if (GETCHAR(i) == 'f') {
- if (hexa_found || exponent_found) {
+ } else if (GETCHAR(i) == 'f' && !hexa_found) {
+ if (exponent_found) {
return _make_token(TK_ERROR, "Invalid numeric constant");
}
float_suffix_found = true;
@@ -3102,6 +3102,72 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
return false;
}
+bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message) {
+ if (current_function == String("light")) {
+ *r_message = RTR("Varying may not be assigned in the 'light' function.");
+ return false;
+ }
+ switch (p_varying.stage) {
+ case ShaderNode::Varying::STAGE_UNKNOWN: // first assign
+ if (current_function == String("vertex")) {
+ p_varying.stage = ShaderNode::Varying::STAGE_VERTEX;
+ } else if (current_function == String("fragment")) {
+ p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_VERTEX:
+ if (current_function == String("fragment")) {
+ *r_message = RTR("Varyings which assigned in 'vertex' function may not be reassigned in 'fragment' or 'light'.");
+ return false;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_FRAGMENT:
+ if (current_function == String("vertex")) {
+ *r_message = RTR("Varyings which assigned in 'fragment' function may not be reassigned in 'vertex' or 'light'.");
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, String *r_message) {
+ switch (p_varying.stage) {
+ case ShaderNode::Varying::STAGE_UNKNOWN:
+ *r_message = RTR("Varying must be assigned before using!");
+ return false;
+ case ShaderNode::Varying::STAGE_VERTEX:
+ if (current_function == String("fragment")) {
+ p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT;
+ } else if (current_function == String("light")) {
+ p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_FRAGMENT:
+ if (current_function == String("light")) {
+ p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT:
+ if (current_function == String("light")) {
+ *r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
+ return false;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT:
+ if (current_function == String("fragment")) {
+ *r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message) {
if (p_node->type == Node::TYPE_OPERATOR) {
OperatorNode *op = static_cast<OperatorNode *>(p_node);
@@ -3142,13 +3208,6 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
return false;
}
- if (shader->varyings.has(var->name) && current_function != String("vertex")) {
- if (r_message) {
- *r_message = RTR("Varyings can only be assigned in vertex function.");
- }
- return false;
- }
-
if (shader->constants.has(var->name) || var->is_const) {
if (r_message) {
*r_message = RTR("Constants cannot be modified.");
@@ -3169,13 +3228,6 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
return false;
}
- if (shader->varyings.has(arr->name) && current_function != String("vertex")) {
- if (r_message) {
- *r_message = RTR("Varyings can only be assigned in vertex function.");
- }
- return false;
- }
-
return true;
}
@@ -3761,6 +3813,23 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Unknown identifier in expression: " + String(identifier));
return nullptr;
}
+ if (ident_type == IDENTIFIER_VARYING) {
+ TkPos prev_pos = _get_tkpos();
+ Token next_token = _get_token();
+ _set_tkpos(prev_pos);
+ String error;
+ if (next_token.type == TK_OP_ASSIGN) {
+ if (!_validate_varying_assign(shader->varyings[identifier], &error)) {
+ _set_error(error);
+ return nullptr;
+ }
+ } else {
+ if (!_validate_varying_using(shader->varyings[identifier], &error)) {
+ _set_error(error);
+ return nullptr;
+ }
+ }
+ }
last_const = is_const;
if (ident_type == IDENTIFIER_FUNCTION) {
@@ -3786,10 +3855,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Constants cannot be modified.");
return nullptr;
}
- if (shader->varyings.has(identifier) && current_function != String("vertex")) {
- _set_error("Varyings can only be assigned in vertex function.");
- return nullptr;
- }
assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size);
if (!assign_expression) {
return nullptr;
@@ -5796,6 +5861,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_BUG;
}
+ String return_struct_name = String(b->parent_function->return_struct_name);
+
ControlFlowNode *flow = alloc_node<ControlFlowNode>();
flow->flow_op = FLOW_OP_RETURN;
@@ -5804,7 +5871,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type == TK_SEMICOLON) {
//all is good
if (b->parent_function->return_type != TYPE_VOID) {
- _set_error("Expected return with expression of type '" + get_datatype_name(b->parent_function->return_type) + "'");
+ _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + "'");
return ERR_PARSE_ERROR;
}
} else {
@@ -5814,8 +5881,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
- if (b->parent_function->return_type != expr->get_datatype()) {
- _set_error("Expected return expression of type '" + get_datatype_name(b->parent_function->return_type) + "'");
+ if (b->parent_function->return_type != expr->get_datatype() || return_struct_name != expr->get_datatype_name()) {
+ _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + "'");
return ERR_PARSE_ERROR;
}
@@ -5859,15 +5926,15 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
pos = _get_tkpos();
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
- //all is good
_set_error("Expected ';' after discard");
+ return ERR_PARSE_ERROR;
}
p_block->statements.push_back(flow);
} else if (tk.type == TK_CF_BREAK) {
if (!p_can_break) {
- //all is good
- _set_error("Breaking is not allowed here");
+ _set_error("'break' is not allowed outside of a loop or 'switch' statement");
+ return ERR_PARSE_ERROR;
}
ControlFlowNode *flow = alloc_node<ControlFlowNode>();
@@ -5876,8 +5943,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
pos = _get_tkpos();
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
- //all is good
_set_error("Expected ';' after break");
+ return ERR_PARSE_ERROR;
}
p_block->statements.push_back(flow);
@@ -5892,8 +5959,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
} else if (tk.type == TK_CF_CONTINUE) {
if (!p_can_continue) {
- //all is good
- _set_error("Continuing is not allowed here");
+ _set_error("'continue' is not allowed outside of a loop");
+ return ERR_PARSE_ERROR;
}
ControlFlowNode *flow = alloc_node<ControlFlowNode>();
@@ -5904,6 +5971,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type != TK_SEMICOLON) {
//all is good
_set_error("Expected ';' after continue");
+ return ERR_PARSE_ERROR;
}
p_block->statements.push_back(flow);
@@ -6068,6 +6136,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_IDENTIFIER) {
st.name = tk.text;
+ if (shader->structs.has(st.name)) {
+ _set_error("Redefinition of '" + String(st.name) + "'");
+ return ERR_PARSE_ERROR;
+ }
tk = _get_token();
if (tk.type != TK_CURLY_BRACKET_OPEN) {
_set_error("Expected '{'");
@@ -6260,6 +6332,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
+ TkPos name_pos = _get_tkpos();
name = tk.text;
if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
@@ -6541,11 +6614,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Expected ';'");
return ERR_PARSE_ERROR;
}
- } else {
+ } else { // varying
ShaderNode::Varying varying;
varying.type = type;
varying.precision = precision;
varying.interpolation = interpolation;
+ varying.tkpos = name_pos;
tk = _get_token();
if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
@@ -7158,6 +7232,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
+ for (Map<StringName, ShaderNode::Varying>::Element *E = shader->varyings.front(); E; E = E->next()) {
+ if (E->get().stage == ShaderNode::Varying::STAGE_VERTEX || E->get().stage == ShaderNode::Varying::STAGE_FRAGMENT) {
+ _set_tkpos(E->get().tkpos);
+ _set_error(RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'"));
+ return ERR_PARSE_ERROR;
+ }
+ }
+
return OK;
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 27767378f9..14594b039c 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -41,6 +41,11 @@
class ShaderLanguage {
public:
+ struct TkPos {
+ int char_idx;
+ int tk_line;
+ };
+
enum TokenType {
TK_EMPTY,
TK_IDENTIFIER,
@@ -598,10 +603,21 @@ public:
};
struct Varying {
+ enum Stage {
+ STAGE_UNKNOWN,
+ STAGE_VERTEX, // transition stage to STAGE_VERTEX_TO_FRAGMENT or STAGE_VERTEX_TO_LIGHT, emits error if they are not used
+ STAGE_FRAGMENT, // transition stage to STAGE_FRAGMENT_TO_LIGHT, emits error if it's not used
+ STAGE_VERTEX_TO_FRAGMENT,
+ STAGE_VERTEX_TO_LIGHT,
+ STAGE_FRAGMENT_TO_LIGHT,
+ };
+
+ Stage stage = STAGE_UNKNOWN;
DataType type = TYPE_VOID;
DataInterpolation interpolation = INTERPOLATION_FLAT;
DataPrecision precision = PRECISION_DEFAULT;
int array_size = 0;
+ TkPos tkpos;
Varying() {}
};
@@ -780,11 +796,6 @@ private:
StringName current_function;
bool last_const = false;
- struct TkPos {
- int char_idx;
- int tk_line;
- };
-
TkPos _get_tkpos() {
TkPos tkp;
tkp.char_idx = char_idx;
@@ -864,6 +875,8 @@ private:
bool _parse_function_arguments(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, int *r_complete_arg = nullptr);
bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat);
bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin);
+ bool _validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message);
+ bool _validate_varying_using(ShaderNode::Varying &p_varying, String *r_message);
Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size);
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 7059045a5d..809343114c 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -1489,7 +1489,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &RenderingServer::mesh_clear);
ClassDB::bind_method(D_METHOD("multimesh_create"), &RenderingServer::multimesh_create);
- ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &RenderingServer::multimesh_allocate, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("multimesh_allocate_data", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &RenderingServer::multimesh_allocate_data, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &RenderingServer::multimesh_get_instance_count);
ClassDB::bind_method(D_METHOD("multimesh_set_mesh", "multimesh", "mesh"), &RenderingServer::multimesh_set_mesh);
ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform", "multimesh", "index", "transform"), &RenderingServer::multimesh_instance_set_transform);
@@ -1523,7 +1523,7 @@ void RenderingServer::_bind_methods() {
#endif
ClassDB::bind_method(D_METHOD("skeleton_create"), &RenderingServer::skeleton_create);
- ClassDB::bind_method(D_METHOD("skeleton_allocate", "skeleton", "bones", "is_2d_skeleton"), &RenderingServer::skeleton_allocate, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("skeleton_allocate_data", "skeleton", "bones", "is_2d_skeleton"), &RenderingServer::skeleton_allocate_data, DEFVAL(false));
ClassDB::bind_method(D_METHOD("skeleton_get_bone_count", "skeleton"), &RenderingServer::skeleton_get_bone_count);
ClassDB::bind_method(D_METHOD("skeleton_bone_set_transform", "skeleton", "bone", "transform"), &RenderingServer::skeleton_bone_set_transform);
ClassDB::bind_method(D_METHOD("skeleton_bone_get_transform", "skeleton", "bone"), &RenderingServer::skeleton_bone_get_transform);
@@ -2259,134 +2259,130 @@ RenderingServer::RenderingServer() {
thread_pool = memnew(RendererThreadPool);
singleton = this;
- GLOBAL_DEF_RST("rendering/vram_compression/import_bptc", false);
- GLOBAL_DEF_RST("rendering/vram_compression/import_s3tc", true);
- GLOBAL_DEF_RST("rendering/vram_compression/import_etc", false);
- GLOBAL_DEF_RST("rendering/vram_compression/import_etc2", true);
- GLOBAL_DEF_RST("rendering/vram_compression/import_pvrtc", false);
+ GLOBAL_DEF_RST("rendering/textures/vram_compression/import_bptc", false);
+ GLOBAL_DEF_RST("rendering/textures/vram_compression/import_s3tc", true);
+ GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc", false);
+ GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc2", true);
+ GLOBAL_DEF_RST("rendering/textures/vram_compression/import_pvrtc", false);
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"));
- GLOBAL_DEF("rendering/quality/directional_shadow/size", 4096);
- GLOBAL_DEF("rendering/quality/directional_shadow/size.mobile", 2048);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/quality/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384"));
- GLOBAL_DEF("rendering/quality/directional_shadow/soft_shadow_quality", 2);
- GLOBAL_DEF("rendering/quality/directional_shadow/soft_shadow_quality.mobile", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/directional_shadow/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/quality/directional_shadow/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
- GLOBAL_DEF("rendering/quality/directional_shadow/16_bits", true);
-
- GLOBAL_DEF("rendering/quality/shadows/soft_shadow_quality", 2);
- GLOBAL_DEF("rendering/quality/shadows/soft_shadow_quality.mobile", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadows/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/quality/shadows/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
-
- GLOBAL_DEF("rendering/quality/2d_shadow_atlas/size", 2048);
-
- GLOBAL_DEF("rendering/quality/rd_renderer/use_low_end_renderer", false);
- GLOBAL_DEF("rendering/quality/rd_renderer/use_low_end_renderer.mobile", true);
-
- GLOBAL_DEF("rendering/quality/reflections/roughness_layers", 8);
- GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections", true);
- GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections.mobile", false);
- GLOBAL_DEF("rendering/quality/reflections/ggx_samples", 1024);
- GLOBAL_DEF("rendering/quality/reflections/ggx_samples.mobile", 128);
- GLOBAL_DEF("rendering/quality/reflections/fast_filter_high_quality", false);
- GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size", 256);
- GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size.mobile", 128);
- GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_count", 64);
-
- GLOBAL_DEF("rendering/quality/gi/use_half_resolution", false);
-
- GLOBAL_DEF("rendering/quality/gi_probes/anisotropic", false);
- GLOBAL_DEF("rendering/quality/gi_probes/quality", 1);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/quality/gi_probes/quality", PROPERTY_HINT_ENUM, "Low (4 Cones - Fast),High (6 Cones - Slow)"));
-
- GLOBAL_DEF("rendering/quality/shading/force_vertex_shading", false);
- GLOBAL_DEF("rendering/quality/shading/force_vertex_shading.mobile", true);
- GLOBAL_DEF("rendering/quality/shading/force_lambert_over_burley", false);
- GLOBAL_DEF("rendering/quality/shading/force_lambert_over_burley.mobile", true);
- GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx", false);
- GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx.mobile", true);
-
- GLOBAL_DEF("rendering/quality/depth_prepass/enable", true);
- GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
-
- GLOBAL_DEF("rendering/quality/texture_filters/use_nearest_mipmap_filter", false);
- GLOBAL_DEF("rendering/quality/texture_filters/anisotropic_filtering_level", 2);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/texture_filters/anisotropic_filtering_level", PropertyInfo(Variant::INT, "rendering/quality/texture_filters/anisotropic_filtering_level", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Faster),4x (Fast),8x (Average),16x (Slow)"));
-
- GLOBAL_DEF("rendering/quality/depth_of_field/depth_of_field_bokeh_shape", 1);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/depth_of_field/depth_of_field_bokeh_shape", PropertyInfo(Variant::INT, "rendering/quality/depth_of_field/depth_of_field_bokeh_shape", PROPERTY_HINT_ENUM, "Box (Fast),Hexagon (Average),Circle (Slow)"));
- GLOBAL_DEF("rendering/quality/depth_of_field/depth_of_field_bokeh_quality", 2);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/depth_of_field/depth_of_field_bokeh_quality", PropertyInfo(Variant::INT, "rendering/quality/depth_of_field/depth_of_field_bokeh_quality", PROPERTY_HINT_ENUM, "Very Low (Fastest),Low (Fast),Medium (Average),High (Slow)"));
- GLOBAL_DEF("rendering/quality/depth_of_field/depth_of_field_use_jitter", false);
-
- GLOBAL_DEF("rendering/quality/ssao/quality", 2);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/ssao/quality", PropertyInfo(Variant::INT, "rendering/quality/ssao/quality", PROPERTY_HINT_ENUM, "Very Low (Fast),Low (Fast),Medium (Average),High (Slow),Ultra (Custom)"));
- GLOBAL_DEF("rendering/quality/ssao/half_size", false);
- GLOBAL_DEF("rendering/quality/ssao/half_size.mobile", true);
- GLOBAL_DEF("rendering/quality/ssao/adaptive_target", 0.5);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/ssao/adaptive_target", PropertyInfo(Variant::FLOAT, "rendering/quality/ssao/adaptive_target", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"));
- GLOBAL_DEF("rendering/quality/ssao/blur_passes", 2);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/ssao/blur_passes", PropertyInfo(Variant::INT, "rendering/quality/ssao/blur_passes", PROPERTY_HINT_RANGE, "0,6"));
- GLOBAL_DEF("rendering/quality/ssao/fadeout_from", 50.0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/ssao/fadeout_from", PropertyInfo(Variant::FLOAT, "rendering/quality/ssao/fadeout_from", PROPERTY_HINT_RANGE, "0.0,512,0.1,or_greater"));
- GLOBAL_DEF("rendering/quality/ssao/fadeout_to", 300.0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/ssao/fadeout_to", PropertyInfo(Variant::FLOAT, "rendering/quality/ssao/fadeout_to", PROPERTY_HINT_RANGE, "64,65536,0.1,or_greater"));
-
- GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter_enabled", true);
- GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter_amount", 0.25);
- GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter_limit", 0.18);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_roughness_limiter_amount", PropertyInfo(Variant::FLOAT, "rendering/quality/screen_filters/screen_space_roughness_limiter_amount", PROPERTY_HINT_RANGE, "0.01,4.0,0.01"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_roughness_limiter_limit", PropertyInfo(Variant::FLOAT, "rendering/quality/screen_filters/screen_space_roughness_limiter_limit", PROPERTY_HINT_RANGE, "0.01,1.0,0.01"));
-
- GLOBAL_DEF("rendering/quality/glow/upscale_mode", 1);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/glow/upscale_mode", PropertyInfo(Variant::INT, "rendering/quality/glow/upscale_mode", PROPERTY_HINT_ENUM, "Linear (Fast),Bicubic (Slow)"));
- GLOBAL_DEF("rendering/quality/glow/upscale_mode.mobile", 0);
- GLOBAL_DEF("rendering/quality/glow/use_high_quality", false);
-
- GLOBAL_DEF("rendering/quality/screen_space_reflection/roughness_quality", 1);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_space_reflection/roughness_quality", PropertyInfo(Variant::INT, "rendering/quality/screen_space_reflection/roughness_quality", PROPERTY_HINT_ENUM, "Disabled (Fastest),Low (Fast),Medium (Average),High (Slow)"));
-
- GLOBAL_DEF("rendering/quality/subsurface_scattering/subsurface_scattering_quality", 1);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/subsurface_scattering_quality", PropertyInfo(Variant::INT, "rendering/quality/subsurface_scattering/subsurface_scattering_quality", PROPERTY_HINT_ENUM, "Disabled (Fastest),Low (Fast),Medium (Average),High (Slow)"));
- GLOBAL_DEF("rendering/quality/subsurface_scattering/subsurface_scattering_scale", 0.05);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/subsurface_scattering_scale", PropertyInfo(Variant::FLOAT, "rendering/quality/subsurface_scattering/subsurface_scattering_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"));
- GLOBAL_DEF("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", 0.01);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", PropertyInfo(Variant::FLOAT, "rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"));
-
- GLOBAL_DEF("rendering/high_end/global_shader_variables_buffer_size", 65536);
-
- GLOBAL_DEF("rendering/lightmapper/probe_capture_update_speed", 15);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/lightmapper/probe_capture_update_speed", PropertyInfo(Variant::FLOAT, "rendering/lightmapper/probe_capture_update_speed", PROPERTY_HINT_RANGE, "0.001,256,0.001"));
-
- GLOBAL_DEF("rendering/sdfgi/probe_ray_count", 1);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/sdfgi/probe_ray_count", PropertyInfo(Variant::INT, "rendering/sdfgi/probe_ray_count", PROPERTY_HINT_ENUM, "8 (Fastest),16,32,64,96,128 (Slowest)"));
- GLOBAL_DEF("rendering/sdfgi/frames_to_converge", 4);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/sdfgi/frames_to_converge", PropertyInfo(Variant::INT, "rendering/sdfgi/frames_to_converge", PROPERTY_HINT_ENUM, "5 (Less Latency but Lower Quality),10,15,20,25,30 (More Latency but Higher Quality)"));
- GLOBAL_DEF("rendering/sdfgi/frames_to_update_lights", 2);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/sdfgi/frames_to_update_lights", PropertyInfo(Variant::INT, "rendering/sdfgi/frames_to_update_lights", PROPERTY_HINT_ENUM, "1 (Slower),2,4,8,16 (Faster)"));
-
- GLOBAL_DEF("rendering/volumetric_fog/volume_size", 64);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/volumetric_fog/volume_size", PropertyInfo(Variant::INT, "rendering/volumetric_fog/volume_size", PROPERTY_HINT_RANGE, "16,512,1"));
- GLOBAL_DEF("rendering/volumetric_fog/volume_depth", 128);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/volumetric_fog/volume_depth", PropertyInfo(Variant::INT, "rendering/volumetric_fog/volume_depth", PROPERTY_HINT_RANGE, "16,512,1"));
- GLOBAL_DEF("rendering/volumetric_fog/use_filter", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/volumetric_fog/use_filter", PropertyInfo(Variant::INT, "rendering/volumetric_fog/use_filter", PROPERTY_HINT_ENUM, "No (Faster),Yes (Higher Quality)"));
- GLOBAL_DEF("rendering/volumetric_fog/directional_shadow_shrink", 512);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/volumetric_fog/directional_shadow_shrink", PropertyInfo(Variant::INT, "rendering/volumetric_fog/directional_shadow_shrink", PROPERTY_HINT_RANGE, "32,2048,1"));
- GLOBAL_DEF("rendering/volumetric_fog/positional_shadow_shrink", 512);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/volumetric_fog/positional_shadow_shrink", PropertyInfo(Variant::INT, "rendering/volumetric_fog/positional_shadow_shrink", PROPERTY_HINT_RANGE, "32,2048,1"));
-
- GLOBAL_DEF("rendering/spatial_indexer/update_iterations_per_frame", 10);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/spatial_indexer/update_iterations_per_frame", PropertyInfo(Variant::INT, "rendering/spatial_indexer/update_iterations_per_frame", PROPERTY_HINT_RANGE, "0,1024,1"));
- GLOBAL_DEF("rendering/spatial_indexer/threaded_cull_minimum_instances", 1000);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/spatial_indexer/threaded_cull_minimum_instances", PropertyInfo(Variant::INT, "rendering/spatial_indexer/threaded_cull_minimum_instances", PROPERTY_HINT_RANGE, "32,65536,1"));
- GLOBAL_DEF("rendering/forward_renderer/threaded_render_minimum_instances", 500);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/forward_renderer/threaded_render_minimum_instances", PropertyInfo(Variant::INT, "rendering/forward_renderer/threaded_render_minimum_instances", PROPERTY_HINT_RANGE, "32,65536,1"));
-
- GLOBAL_DEF("rendering/cluster_builder/max_clustered_elements", 512);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/cluster_builder/max_clustered_elements", PropertyInfo(Variant::FLOAT, "rendering/cluster_builder/max_clustered_elements", PROPERTY_HINT_RANGE, "32,8192,1"));
+ GLOBAL_DEF("rendering/shadows/directional_shadow/size", 4096);
+ GLOBAL_DEF("rendering/shadows/directional_shadow/size.mobile", 2048);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384"));
+ GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality", 2);
+ GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality.mobile", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
+ GLOBAL_DEF("rendering/shadows/directional_shadow/16_bits", true);
+
+ GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality", 2);
+ GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality.mobile", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadows/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/shadows/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
+
+ GLOBAL_DEF("rendering/2d/shadow_atlas/size", 2048);
+
+ GLOBAL_DEF("rendering/driver/rd_renderer/use_low_end_renderer", false);
+ GLOBAL_DEF("rendering/driver/rd_renderer/use_low_end_renderer.mobile", true);
+
+ GLOBAL_DEF("rendering/reflections/sky_reflections/roughness_layers", 8);
+ GLOBAL_DEF("rendering/reflections/sky_reflections/texture_array_reflections", true);
+ GLOBAL_DEF("rendering/reflections/sky_reflections/texture_array_reflections.mobile", false);
+ GLOBAL_DEF("rendering/reflections/sky_reflections/ggx_samples", 1024);
+ GLOBAL_DEF("rendering/reflections/sky_reflections/ggx_samples.mobile", 128);
+ GLOBAL_DEF("rendering/reflections/sky_reflections/fast_filter_high_quality", false);
+ GLOBAL_DEF("rendering/reflections/reflection_atlas/reflection_size", 256);
+ GLOBAL_DEF("rendering/reflections/reflection_atlas/reflection_size.mobile", 128);
+ GLOBAL_DEF("rendering/reflections/reflection_atlas/reflection_count", 64);
+
+ GLOBAL_DEF("rendering/global_illumination/gi/use_half_resolution", false);
+
+ GLOBAL_DEF("rendering/global_illumination/gi_probes/anisotropic", false);
+ GLOBAL_DEF("rendering/global_illumination/gi_probes/quality", 1);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/global_illumination/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/global_illumination/gi_probes/quality", PROPERTY_HINT_ENUM, "Low (4 Cones - Fast),High (6 Cones - Slow)"));
+
+ GLOBAL_DEF("rendering/shading/overrides/force_vertex_shading", false);
+ GLOBAL_DEF("rendering/shading/overrides/force_vertex_shading.mobile", true);
+ GLOBAL_DEF("rendering/shading/overrides/force_lambert_over_burley", false);
+ GLOBAL_DEF("rendering/shading/overrides/force_lambert_over_burley.mobile", true);
+ GLOBAL_DEF("rendering/shading/overrides/force_blinn_over_ggx", false);
+ GLOBAL_DEF("rendering/shading/overrides/force_blinn_over_ggx.mobile", true);
+
+ GLOBAL_DEF("rendering/driver/depth_prepass/enable", true);
+ GLOBAL_DEF("rendering/driver/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
+
+ GLOBAL_DEF("rendering/textures/default_filters/use_nearest_mipmap_filter", false);
+ GLOBAL_DEF("rendering/textures/default_filters/anisotropic_filtering_level", 2);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/default_filters/anisotropic_filtering_level", PropertyInfo(Variant::INT, "rendering/textures/default_filters/anisotropic_filtering_level", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Faster),4x (Fast),8x (Average),16x (Slow)"));
+
+ GLOBAL_DEF("rendering/camera/depth_of_field/depth_of_field_bokeh_shape", 1);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/camera/depth_of_field/depth_of_field_bokeh_shape", PropertyInfo(Variant::INT, "rendering/camera/depth_of_field/depth_of_field_bokeh_shape", PROPERTY_HINT_ENUM, "Box (Fast),Hexagon (Average),Circle (Slow)"));
+ GLOBAL_DEF("rendering/camera/depth_of_field/depth_of_field_bokeh_quality", 2);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/camera/depth_of_field/depth_of_field_bokeh_quality", PropertyInfo(Variant::INT, "rendering/camera/depth_of_field/depth_of_field_bokeh_quality", PROPERTY_HINT_ENUM, "Very Low (Fastest),Low (Fast),Medium (Average),High (Slow)"));
+ GLOBAL_DEF("rendering/camera/depth_of_field/depth_of_field_use_jitter", false);
+
+ GLOBAL_DEF("rendering/environment/ssao/quality", 2);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssao/quality", PropertyInfo(Variant::INT, "rendering/environment/ssao/quality", PROPERTY_HINT_ENUM, "Very Low (Fast),Low (Fast),Medium (Average),High (Slow),Ultra (Custom)"));
+ GLOBAL_DEF("rendering/environment/ssao/half_size", false);
+ GLOBAL_DEF("rendering/environment/ssao/half_size.mobile", true);
+ GLOBAL_DEF("rendering/environment/ssao/adaptive_target", 0.5);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssao/adaptive_target", PropertyInfo(Variant::FLOAT, "rendering/environment/ssao/adaptive_target", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"));
+ GLOBAL_DEF("rendering/environment/ssao/blur_passes", 2);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssao/blur_passes", PropertyInfo(Variant::INT, "rendering/environment/ssao/blur_passes", PROPERTY_HINT_RANGE, "0,6"));
+ GLOBAL_DEF("rendering/environment/ssao/fadeout_from", 50.0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssao/fadeout_from", PropertyInfo(Variant::FLOAT, "rendering/environment/ssao/fadeout_from", PROPERTY_HINT_RANGE, "0.0,512,0.1,or_greater"));
+ GLOBAL_DEF("rendering/environment/ssao/fadeout_to", 300.0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssao/fadeout_to", PropertyInfo(Variant::FLOAT, "rendering/environment/ssao/fadeout_to", PROPERTY_HINT_RANGE, "64,65536,0.1,or_greater"));
+
+ GLOBAL_DEF("rendering/anti_aliasing/screen_space_roughness_limiter/enabled", true);
+ GLOBAL_DEF("rendering/anti_aliasing/screen_space_roughness_limiter/amount", 0.25);
+ GLOBAL_DEF("rendering/anti_aliasing/screen_space_roughness_limiter/limit", 0.18);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/amount", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/amount", PROPERTY_HINT_RANGE, "0.01,4.0,0.01"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/limit", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/limit", PROPERTY_HINT_RANGE, "0.01,1.0,0.01"));
+
+ 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)"));
+
+ GLOBAL_DEF("rendering/environment/subsurface_scattering/subsurface_scattering_quality", 1);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/subsurface_scattering/subsurface_scattering_quality", PropertyInfo(Variant::INT, "rendering/environment/subsurface_scattering/subsurface_scattering_quality", PROPERTY_HINT_ENUM, "Disabled (Fastest),Low (Fast),Medium (Average),High (Slow)"));
+ GLOBAL_DEF("rendering/environment/subsurface_scattering/subsurface_scattering_scale", 0.05);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/subsurface_scattering/subsurface_scattering_scale", PropertyInfo(Variant::FLOAT, "rendering/environment/subsurface_scattering/subsurface_scattering_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"));
+ GLOBAL_DEF("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale", 0.01);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale", PropertyInfo(Variant::FLOAT, "rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"));
+
+ GLOBAL_DEF("rendering/limits/global_shader_variables/buffer_size", 65536);
+
+ GLOBAL_DEF("rendering/lightmapping/probe_capture/update_speed", 15);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/lightmapping/probe_capture/update_speed", PropertyInfo(Variant::FLOAT, "rendering/lightmapping/probe_capture/update_speed", PROPERTY_HINT_RANGE, "0.001,256,0.001"));
+
+ GLOBAL_DEF("rendering/global_illumination/sdfgi/probe_ray_count", 1);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/global_illumination/sdfgi/probe_ray_count", PropertyInfo(Variant::INT, "rendering/global_illumination/sdfgi/probe_ray_count", PROPERTY_HINT_ENUM, "8 (Fastest),16,32,64,96,128 (Slowest)"));
+ GLOBAL_DEF("rendering/global_illumination/sdfgi/frames_to_converge", 4);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/global_illumination/sdfgi/frames_to_converge", PropertyInfo(Variant::INT, "rendering/global_illumination/sdfgi/frames_to_converge", PROPERTY_HINT_ENUM, "5 (Less Latency but Lower Quality),10,15,20,25,30 (More Latency but Higher Quality)"));
+ GLOBAL_DEF("rendering/global_illumination/sdfgi/frames_to_update_lights", 2);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/global_illumination/sdfgi/frames_to_update_lights", PropertyInfo(Variant::INT, "rendering/global_illumination/sdfgi/frames_to_update_lights", PROPERTY_HINT_ENUM, "1 (Slower),2,4,8,16 (Faster)"));
+
+ GLOBAL_DEF("rendering/environment/volumetric_fog/volume_size", 64);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/volumetric_fog/volume_size", PropertyInfo(Variant::INT, "rendering/environment/volumetric_fog/volume_size", PROPERTY_HINT_RANGE, "16,512,1"));
+ GLOBAL_DEF("rendering/environment/volumetric_fog/volume_depth", 128);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/volumetric_fog/volume_depth", PropertyInfo(Variant::INT, "rendering/environment/volumetric_fog/volume_depth", PROPERTY_HINT_RANGE, "16,512,1"));
+ GLOBAL_DEF("rendering/environment/volumetric_fog/use_filter", 1);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/volumetric_fog/use_filter", PropertyInfo(Variant::INT, "rendering/environment/volumetric_fog/use_filter", PROPERTY_HINT_ENUM, "No (Faster),Yes (Higher Quality)"));
+
+ GLOBAL_DEF("rendering/limits/spatial_indexer/update_iterations_per_frame", 10);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/spatial_indexer/update_iterations_per_frame", PropertyInfo(Variant::INT, "rendering/limits/spatial_indexer/update_iterations_per_frame", PROPERTY_HINT_RANGE, "0,1024,1"));
+ GLOBAL_DEF("rendering/limits/spatial_indexer/threaded_cull_minimum_instances", 1000);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/spatial_indexer/threaded_cull_minimum_instances", PropertyInfo(Variant::INT, "rendering/limits/spatial_indexer/threaded_cull_minimum_instances", PROPERTY_HINT_RANGE, "32,65536,1"));
+ GLOBAL_DEF("rendering/limits/forward_renderer/threaded_render_minimum_instances", 500);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/forward_renderer/threaded_render_minimum_instances", PropertyInfo(Variant::INT, "rendering/limits/forward_renderer/threaded_render_minimum_instances", PROPERTY_HINT_RANGE, "32,65536,1"));
+
+ GLOBAL_DEF("rendering/limits/cluster_builder/max_clustered_elements", 512);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/cluster_builder/max_clustered_elements", PropertyInfo(Variant::FLOAT, "rendering/limits/cluster_builder/max_clustered_elements", PROPERTY_HINT_RANGE, "32,8192,1"));
}
RenderingServer::~RenderingServer() {
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index fd8d8cd21d..6a8bb83ec1 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -367,7 +367,7 @@ public:
MULTIMESH_TRANSFORM_3D,
};
- virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
@@ -409,7 +409,7 @@ public:
/* SKELETON API */
virtual RID skeleton_create() = 0;
- virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
+ virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
virtual int skeleton_get_bone_count(RID p_skeleton) const = 0;
virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0;
virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
@@ -552,7 +552,7 @@ public:
virtual RID gi_probe_create() = 0;
- virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
+ virtual void gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0;
virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0;
@@ -985,7 +985,7 @@ public:
ENV_SDFGI_Y_SCALE_50_PERCENT
};
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, EnvironmentSDFGICascades p_cascades, float p_min_cell_size, EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
+ virtual void environment_set_sdfgi(RID p_env, bool p_enable, EnvironmentSDFGICascades p_cascades, float p_min_cell_size, EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
enum EnvironmentSDFGIRayCount {
ENV_SDFGI_RAY_COUNT_4,
@@ -1025,18 +1025,9 @@ public:
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0;
- enum EnvVolumetricFogShadowFilter {
- ENV_VOLUMETRIC_FOG_SHADOW_FILTER_DISABLED,
- ENV_VOLUMETRIC_FOG_SHADOW_FILTER_LOW,
- ENV_VOLUMETRIC_FOG_SHADOW_FILTER_MEDIUM,
- ENV_VOLUMETRIC_FOG_SHADOW_FILTER_HIGH,
- };
-
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, EnvVolumetricFogShadowFilter p_shadow_filter) = 0;
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
- virtual void environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) = 0;
- virtual void environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size) = 0;
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0;
@@ -1428,7 +1419,7 @@ public:
INFO_VERTEX_MEM_USED,
};
- virtual int get_render_info(RenderInfo p_info) = 0;
+ virtual uint64_t get_render_info(RenderInfo p_info) = 0;
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h
index 5e18dc1e6d..95d2e2254e 100644
--- a/servers/server_wrap_mt_common.h
+++ b/servers/server_wrap_mt_common.h
@@ -29,245 +29,89 @@
/*************************************************************************/
#define FUNC0R(m_r, m_type) \
- virtual m_r m_type() { \
+ virtual m_r m_type() override { \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(); \
} \
}
-#define FUNCRID(m_type) \
- List<RID> m_type##_id_pool; \
- int m_type##allocn() { \
- for (int i = 0; i < pool_max_size; i++) { \
- m_type##_id_pool.push_back(server_name->m_type##_create()); \
- } \
- return 0; \
- } \
- void m_type##_free_cached_ids() { \
- while (m_type##_id_pool.size()) { \
- server_name->free(m_type##_id_pool.front()->get()); \
- m_type##_id_pool.pop_front(); \
- } \
- } \
- virtual RID m_type##_create() { \
- if (Thread::get_caller_id() != server_thread) { \
- RID rid; \
- MutexLock lock(alloc_mutex); \
- if (m_type##_id_pool.size() == 0) { \
- int ret; \
- command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, &ret); \
- SYNC_DEBUG \
- } \
- rid = m_type##_id_pool.front()->get(); \
- m_type##_id_pool.pop_front(); \
- return rid; \
- } else { \
- return server_name->m_type##_create(); \
- } \
- }
-
-#define FUNC1RID(m_type, m_arg1) \
- int m_type##allocn() { \
- for (int i = 0; i < m_type##_pool_max_size; i++) { \
- m_type##_id_pool.push_back(server_name->m_type##_create()); \
- } \
- return 0; \
- } \
- void m_type##_free_cached_ids() { \
- while (m_type##_id_pool.size()) { \
- free(m_type##_id_pool.front()->get()); \
- m_type##_id_pool.pop_front(); \
- } \
- } \
- virtual RID m_type##_create(m_arg1 p1) { \
- if (Thread::get_caller_id() != server_thread) { \
- RID rid; \
- MutexLock lock(alloc_mutex); \
- if (m_type##_id_pool.size() == 0) { \
- int ret; \
- command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, p1, &ret); \
- SYNC_DEBUG \
- } \
- rid = m_type##_id_pool.front()->get(); \
- m_type##_id_pool.pop_front(); \
- return rid; \
- } else { \
- return server_name->m_type##_create(p1); \
- } \
- }
-
-#define FUNC2RID(m_type, m_arg1, m_arg2) \
- int m_type##allocn() { \
- for (int i = 0; i < m_type##_pool_max_size; i++) { \
- m_type##_id_pool.push_back(server_name->m_type##_create()); \
- } \
- return 0; \
- } \
- void m_type##_free_cached_ids() { \
- while (m_type##_id_pool.size()) { \
- free(m_type##_id_pool.front()->get()); \
- m_type##_id_pool.pop_front(); \
- } \
- } \
- virtual RID m_type##_create(m_arg1 p1, m_arg2 p2) { \
- if (Thread::get_caller_id() != server_thread) { \
- RID rid; \
- MutexLock lock(alloc_mutex); \
- if (m_type##_id_pool.size() == 0) { \
- int ret; \
- command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, p1, p2, &ret); \
- SYNC_DEBUG \
- } \
- rid = m_type##_id_pool.front()->get(); \
- m_type##_id_pool.pop_front(); \
- return rid; \
- } else { \
- return server_name->m_type##_create(p1, p2); \
- } \
- }
-
-#define FUNC3RID(m_type, m_arg1, m_arg2, m_arg3) \
- int m_type##allocn() { \
- for (int i = 0; i < m_type##_pool_max_size; i++) { \
- m_type##_id_pool.push_back(server_name->m_type##_create()); \
- } \
- return 0; \
- } \
- void m_type##_free_cached_ids() { \
- while (m_type##_id_pool.size()) { \
- free(m_type##_id_pool.front()->get()); \
- m_type##_id_pool.pop_front(); \
- } \
- } \
- virtual RID m_type##_create(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \
- if (Thread::get_caller_id() != server_thread) { \
- RID rid; \
- MutexLock lock(alloc_mutex); \
- if (m_type##_id_pool.size() == 0) { \
- int ret; \
- command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, p1, p2, p3, &ret); \
- SYNC_DEBUG \
- } \
- rid = m_type##_id_pool.front()->get(); \
- m_type##_id_pool.pop_front(); \
- return rid; \
- } else { \
- return server_name->m_type##_create(p1, p2, p3); \
- } \
- }
-
-#define FUNC4RID(m_type, m_arg1, m_arg2, m_arg3, m_arg4) \
- int m_type##allocn() { \
- for (int i = 0; i < m_type##_pool_max_size; i++) { \
- m_type##_id_pool.push_back(server_name->m_type##_create()); \
- } \
- return 0; \
- } \
- void m_type##_free_cached_ids() { \
- while (m_type##_id_pool.size()) { \
- free(m_type##_id_pool.front()->get()); \
- m_type##_id_pool.pop_front(); \
- } \
- } \
- virtual RID m_type##_create(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \
- if (Thread::get_caller_id() != server_thread) { \
- RID rid; \
- MutexLock lock(alloc_mutex); \
- if (m_type##_id_pool.size() == 0) { \
- int ret; \
- command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, p1, p2, p3, p4, &ret); \
- SYNC_DEBUG \
- } \
- rid = m_type##_id_pool.front()->get(); \
- m_type##_id_pool.pop_front(); \
- return rid; \
- } else { \
- return server_name->m_type##_create(p1, p2, p3, p4); \
- } \
+#define FUNCRIDSPLIT(m_type) \
+ virtual RID m_type##_create() override { \
+ RID ret = server_name->m_type##_allocate(); \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type##_initialize, ret); \
+ } else { \
+ server_name->m_type##_initialize(ret); \
+ } \
+ return ret; \
}
-#define FUNC5RID(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5) \
- List<RID> m_type##_id_pool; \
- int m_type##allocn(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \
- for (int i = 0; i < pool_max_size; i++) { \
- m_type##_id_pool.push_back(server_name->m_type##_create(p1, p2, p3, p4, p5)); \
- } \
- return 0; \
- } \
- void m_type##_free_cached_ids() { \
- while (m_type##_id_pool.size()) { \
- free(m_type##_id_pool.front()->get()); \
- m_type##_id_pool.pop_front(); \
- } \
- } \
- virtual RID m_type##_create(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \
- if (Thread::get_caller_id() != server_thread) { \
- RID rid; \
- MutexLock lock(alloc_mutex); \
- if (m_type##_id_pool.size() == 0) { \
- int ret; \
- command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, p1, p2, p3, p4, p5, &ret); \
- SYNC_DEBUG \
- } \
- rid = m_type##_id_pool.front()->get(); \
- m_type##_id_pool.pop_front(); \
- return rid; \
- } else { \
- return server_name->m_type##_create(p1, p2, p3, p4, p5); \
- } \
+//RID now returns directly, ensure thread safety yourself
+#define FUNCRID(m_type) \
+ virtual RID m_type##_create() override { \
+ return server_name->m_type##_create(); \
}
#define FUNC0RC(m_r, m_type) \
- virtual m_r m_type() const { \
+ virtual m_r m_type() const override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(); \
} \
}
#define FUNC0(m_type) \
- virtual void m_type() { \
+ virtual void m_type() override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push(server_name, &ServerName::m_type); \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(); \
} \
}
#define FUNC0C(m_type) \
- virtual void m_type() const { \
+ virtual void m_type() const override { \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push(server_name, &ServerName::m_type); \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(); \
} \
}
#define FUNC0S(m_type) \
- virtual void m_type() { \
+ virtual void m_type() override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push_and_sync(server_name, &ServerName::m_type); \
SYNC_DEBUG \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(); \
} \
}
#define FUNC0SC(m_type) \
- virtual void m_type() const { \
+ virtual void m_type() const override { \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push_and_sync(server_name, &ServerName::m_type); \
SYNC_DEBUG \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(); \
} \
}
@@ -275,560 +119,646 @@
///////////////////////////////////////////////
#define FUNC1R(m_r, m_type, m_arg1) \
- virtual m_r m_type(m_arg1 p1) { \
+ virtual m_r m_type(m_arg1 p1) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(p1); \
} \
}
#define FUNC1RC(m_r, m_type, m_arg1) \
- virtual m_r m_type(m_arg1 p1) const { \
+ virtual m_r m_type(m_arg1 p1) const override { \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(p1); \
} \
}
#define FUNC1S(m_type, m_arg1) \
- virtual void m_type(m_arg1 p1) { \
+ virtual void m_type(m_arg1 p1) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push_and_sync(server_name, &ServerName::m_type, p1); \
SYNC_DEBUG \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1); \
} \
}
#define FUNC1SC(m_type, m_arg1) \
- virtual void m_type(m_arg1 p1) const { \
+ virtual void m_type(m_arg1 p1) const override { \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push_and_sync(server_name, &ServerName::m_type, p1); \
SYNC_DEBUG \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1); \
} \
}
#define FUNC1(m_type, m_arg1) \
- virtual void m_type(m_arg1 p1) { \
+ virtual void m_type(m_arg1 p1) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push(server_name, &ServerName::m_type, p1); \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1); \
} \
}
#define FUNC1C(m_type, m_arg1) \
- virtual void m_type(m_arg1 p1) const { \
+ virtual void m_type(m_arg1 p1) const override { \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push(server_name, &ServerName::m_type, p1); \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1); \
} \
}
#define FUNC2R(m_r, m_type, m_arg1, m_arg2) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2) { \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(p1, p2); \
} \
}
#define FUNC2RC(m_r, m_type, m_arg1, m_arg2) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2) const { \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2) const override { \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(p1, p2); \
} \
}
#define FUNC2S(m_type, m_arg1, m_arg2) \
- virtual void m_type(m_arg1 p1, m_arg2 p2) { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2); \
SYNC_DEBUG \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2); \
} \
}
#define FUNC2SC(m_type, m_arg1, m_arg2) \
- virtual void m_type(m_arg1 p1, m_arg2 p2) const { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2) const override { \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2); \
SYNC_DEBUG \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2); \
} \
}
#define FUNC2(m_type, m_arg1, m_arg2) \
- virtual void m_type(m_arg1 p1, m_arg2 p2) { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push(server_name, &ServerName::m_type, p1, p2); \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2); \
} \
}
#define FUNC2C(m_type, m_arg1, m_arg2) \
- virtual void m_type(m_arg1 p1, m_arg2 p2) const { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2) const override { \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push(server_name, &ServerName::m_type, p1, p2); \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2); \
} \
}
#define FUNC3R(m_r, m_type, m_arg1, m_arg2, m_arg3) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(p1, p2, p3); \
} \
}
#define FUNC3RC(m_r, m_type, m_arg1, m_arg2, m_arg3) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const override { \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(p1, p2, p3); \
} \
}
#define FUNC3S(m_type, m_arg1, m_arg2, m_arg3) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3); \
SYNC_DEBUG \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2, p3); \
} \
}
#define FUNC3SC(m_type, m_arg1, m_arg2, m_arg3) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const override { \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3); \
SYNC_DEBUG \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2, p3); \
} \
}
#define FUNC3(m_type, m_arg1, m_arg2, m_arg3) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push(server_name, &ServerName::m_type, p1, p2, p3); \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2, p3); \
} \
}
#define FUNC3C(m_type, m_arg1, m_arg2, m_arg3) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const override { \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push(server_name, &ServerName::m_type, p1, p2, p3); \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2, p3); \
} \
}
#define FUNC4R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(p1, p2, p3, p4); \
} \
}
#define FUNC4RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const override { \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(p1, p2, p3, p4); \
} \
}
#define FUNC4S(m_type, m_arg1, m_arg2, m_arg3, m_arg4) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4); \
SYNC_DEBUG \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2, p3, p4); \
} \
}
#define FUNC4SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const override { \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4); \
SYNC_DEBUG \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2, p3, p4); \
} \
}
#define FUNC4(m_type, m_arg1, m_arg2, m_arg3, m_arg4) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4); \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2, p3, p4); \
} \
}
-#define FUNC4C(m_type, m_arg1, m_arg2, m_arg3, m_arg4) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4); \
- } else { \
- server_name->m_type(p1, p2, p3, p4); \
- } \
+#define FUNC4C(m_type, m_arg1, m_arg2, m_arg3, m_arg4) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4); \
+ } \
}
#define FUNC5R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5) \
virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(p1, p2, p3, p4, p5); \
} \
}
#define FUNC5RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const override { \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(p1, p2, p3, p4, p5); \
} \
}
#define FUNC5S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) override { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
SYNC_DEBUG \
} else { \
+ command_queue.flush_if_pending(); \
server_name->m_type(p1, p2, p3, p4, p5); \
} \
}
-#define FUNC5SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
- SYNC_DEBUG \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5); \
- } \
+#define FUNC5SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
+ SYNC_DEBUG \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5); \
+ } \
}
-#define FUNC5(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5); \
- } \
+#define FUNC5(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5); \
+ } \
}
-#define FUNC5C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5); \
- } \
+#define FUNC5C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5); \
+ } \
}
#define FUNC6R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6) \
virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \
+ WRITE_ACTION \
if (Thread::get_caller_id() != server_thread) { \
m_r ret; \
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret); \
SYNC_DEBUG \
return ret; \
} else { \
+ command_queue.flush_if_pending(); \
return server_name->m_type(p1, p2, p3, p4, p5, p6); \
} \
}
-#define FUNC6RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \
- if (Thread::get_caller_id() != server_thread) { \
- m_r ret; \
- command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret); \
- SYNC_DEBUG \
- return ret; \
- } else { \
- return server_name->m_type(p1, p2, p3, p4, p5, p6); \
- } \
+#define FUNC6RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6) \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ m_r ret; \
+ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret); \
+ SYNC_DEBUG \
+ return ret; \
+ } else { \
+ command_queue.flush_if_pending(); \
+ return server_name->m_type(p1, p2, p3, p4, p5, p6); \
+ } \
+ }
+
+#define FUNC6S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
+ SYNC_DEBUG \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6); \
+ } \
+ }
+
+#define FUNC6SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
+ SYNC_DEBUG \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6); \
+ } \
}
-#define FUNC6S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
- SYNC_DEBUG \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6); \
- } \
+#define FUNC6(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6); \
+ } \
}
-#define FUNC6SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
- SYNC_DEBUG \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6); \
- } \
+#define FUNC6C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6); \
+ } \
}
-#define FUNC6(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6); \
- } \
+#define FUNC7R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ m_r ret; \
+ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \
+ SYNC_DEBUG \
+ return ret; \
+ } else { \
+ command_queue.flush_if_pending(); \
+ return server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
+ } \
}
-#define FUNC6C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6); \
- } \
- }
-
-#define FUNC7R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \
- if (Thread::get_caller_id() != server_thread) { \
- m_r ret; \
- command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \
- SYNC_DEBUG \
- return ret; \
- } else { \
- return server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
- } \
- }
-
-#define FUNC7RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \
- if (Thread::get_caller_id() != server_thread) { \
- m_r ret; \
- command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \
- SYNC_DEBUG \
- return ret; \
- } else { \
- return server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
- } \
- }
-
-#define FUNC7S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
- SYNC_DEBUG \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
- } \
- }
-
-#define FUNC7SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
- SYNC_DEBUG \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
- } \
- }
-
-#define FUNC7(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
- } \
- }
-
-#define FUNC7C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
- } \
- }
-
-#define FUNC8R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) { \
- if (Thread::get_caller_id() != server_thread) { \
- m_r ret; \
- command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret); \
- SYNC_DEBUG \
- return ret; \
- } else { \
- return server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
- } \
- }
-
-#define FUNC8RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
- virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const { \
- if (Thread::get_caller_id() != server_thread) { \
- m_r ret; \
- command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret); \
- SYNC_DEBUG \
- return ret; \
- } else { \
- return server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
- } \
- }
-
-#define FUNC8S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
- SYNC_DEBUG \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
- } \
- }
-
-#define FUNC8SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
- SYNC_DEBUG \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
- } \
- }
-
-#define FUNC8(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
- } \
- }
-
-#define FUNC8C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
- } \
- }
-
-#define FUNC9(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9); \
- } \
- }
-
-#define FUNC10(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); \
- } \
- }
-
-#define FUNC11(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); \
- } \
- }
-
-#define FUNC12(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \
- } \
- }
-
-#define FUNC13(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); \
- } \
- }
-
-#define FUNC14(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13, m_arg14) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13, m_arg14 p14) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); \
- } \
- }
-
-#define FUNC15(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13, m_arg14, m_arg15) \
- virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13, m_arg14 p14, m_arg15 p15) { \
- if (Thread::get_caller_id() != server_thread) { \
- command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); \
- } else { \
- server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); \
- } \
+#define FUNC7RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ m_r ret; \
+ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \
+ SYNC_DEBUG \
+ return ret; \
+ } else { \
+ command_queue.flush_if_pending(); \
+ return server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
+ } \
+ }
+
+#define FUNC7S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
+ SYNC_DEBUG \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
+ } \
+ }
+
+#define FUNC7SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
+ SYNC_DEBUG \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
+ } \
+ }
+
+#define FUNC7(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
+ } \
+ }
+
+#define FUNC7C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
+ } \
+ }
+
+#define FUNC8R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ m_r ret; \
+ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret); \
+ SYNC_DEBUG \
+ return ret; \
+ } else { \
+ command_queue.flush_if_pending(); \
+ return server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
+ } \
+ }
+
+#define FUNC8RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
+ virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ m_r ret; \
+ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret); \
+ SYNC_DEBUG \
+ return ret; \
+ } else { \
+ command_queue.flush_if_pending(); \
+ return server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
+ } \
+ }
+
+#define FUNC8S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
+ SYNC_DEBUG \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
+ } \
+ }
+
+#define FUNC8SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
+ SYNC_DEBUG \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
+ } \
+ }
+
+#define FUNC8(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
+ } \
+ }
+
+#define FUNC8C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const override { \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
+ } \
+ }
+
+#define FUNC9(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9); \
+ } \
+ }
+
+#define FUNC10(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); \
+ } \
+ }
+
+#define FUNC11(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); \
+ } \
+ }
+
+#define FUNC12(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \
+ } \
+ }
+
+#define FUNC13(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); \
+ } \
+ }
+
+#define FUNC14(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13, m_arg14) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13, m_arg14 p14) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); \
+ } \
+ }
+
+#define FUNC15(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13, m_arg14, m_arg15) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13, m_arg14 p14, m_arg15 p15) override { \
+ WRITE_ACTION \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); \
+ } else { \
+ command_queue.flush_if_pending(); \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); \
+ } \
}
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index da68ceb128..d6d3c11cfb 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -219,6 +219,11 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_font_system", "name", "base_size"), &TextServer::create_font_system, DEFVAL(16));
ClassDB::bind_method(D_METHOD("create_font_resource", "filename", "base_size"), &TextServer::create_font_resource, DEFVAL(16));
ClassDB::bind_method(D_METHOD("create_font_memory", "data", "type", "base_size"), &TextServer::_create_font_memory, DEFVAL(16));
+ ClassDB::bind_method(D_METHOD("create_font_bitmap", "height", "ascent", "base_size"), &TextServer::create_font_bitmap);
+
+ ClassDB::bind_method(D_METHOD("font_bitmap_add_texture", "font", "texture"), &TextServer::font_bitmap_add_texture);
+ ClassDB::bind_method(D_METHOD("font_bitmap_add_char", "font", "char", "texture_idx", "rect", "align", "advance"), &TextServer::font_bitmap_add_char);
+ ClassDB::bind_method(D_METHOD("font_bitmap_add_kerning_pair", "font", "A", "B", "kerning"), &TextServer::font_bitmap_add_kerning_pair);
ClassDB::bind_method(D_METHOD("font_get_height", "font", "size"), &TextServer::font_get_height);
ClassDB::bind_method(D_METHOD("font_get_ascent", "font", "size"), &TextServer::font_get_ascent);
@@ -227,6 +232,12 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_get_underline_position", "font", "size"), &TextServer::font_get_underline_position);
ClassDB::bind_method(D_METHOD("font_get_underline_thickness", "font", "size"), &TextServer::font_get_underline_thickness);
+ ClassDB::bind_method(D_METHOD("font_get_spacing_space", "font"), &TextServer::font_get_spacing_space);
+ ClassDB::bind_method(D_METHOD("font_set_spacing_space", "font", "value"), &TextServer::font_set_spacing_space);
+
+ ClassDB::bind_method(D_METHOD("font_get_spacing_glyph", "font"), &TextServer::font_get_spacing_glyph);
+ ClassDB::bind_method(D_METHOD("font_set_spacing_glyph", "font", "value"), &TextServer::font_set_spacing_glyph);
+
ClassDB::bind_method(D_METHOD("font_set_antialiased", "font", "antialiased"), &TextServer::font_set_antialiased);
ClassDB::bind_method(D_METHOD("font_get_antialiased", "font"), &TextServer::font_get_antialiased);
@@ -284,7 +295,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_shaped_text", "direction", "orientation"), &TextServer::create_shaped_text, DEFVAL(DIRECTION_AUTO), DEFVAL(ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("shaped_text_clear"), &TextServer::shaped_text_clear);
+ ClassDB::bind_method(D_METHOD("shaped_text_clear", "rid"), &TextServer::shaped_text_clear);
ClassDB::bind_method(D_METHOD("shaped_text_set_direction", "shaped", "direction"), &TextServer::shaped_text_set_direction, DEFVAL(DIRECTION_AUTO));
ClassDB::bind_method(D_METHOD("shaped_text_get_direction", "shaped"), &TextServer::shaped_text_get_direction);
diff --git a/servers/text_server.h b/servers/text_server.h
index 23367de4c8..e1429da1d1 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -192,18 +192,6 @@ public:
Vector<TextServer::Glyph> glyphs_logical;
};
- struct BitmapFontData {
- int height = 0;
- int ascent = 0;
- int charcount = 0;
- const int *char_rects = nullptr;
- int kerning_count = 0;
- const int *kernings = nullptr;
- int w = 0;
- int h = 0;
- const unsigned char *img = nullptr;
- };
-
protected:
static void _bind_methods();
@@ -236,11 +224,22 @@ public:
virtual RID create_font_system(const String &p_name, int p_base_size = 16) = 0;
virtual RID create_font_resource(const String &p_filename, int p_base_size = 16) = 0;
virtual RID create_font_memory(const uint8_t *p_data, size_t p_size, const String &p_type, int p_base_size = 16) = 0;
+ virtual RID create_font_bitmap(float p_height, float p_ascent, int p_base_size = 16) = 0;
+
+ virtual void font_bitmap_add_texture(RID p_font, const Ref<Texture> &p_texture) = 0;
+ virtual void font_bitmap_add_char(RID p_font, char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) = 0;
+ virtual void font_bitmap_add_kerning_pair(RID p_font, char32_t p_A, char32_t p_B, int p_kerning) = 0;
virtual float font_get_height(RID p_font, int p_size) const = 0;
virtual float font_get_ascent(RID p_font, int p_size) const = 0;
virtual float font_get_descent(RID p_font, int p_size) const = 0;
+ virtual int font_get_spacing_space(RID p_font) const = 0;
+ virtual void font_set_spacing_space(RID p_font, int p_value) = 0;
+
+ virtual int font_get_spacing_glyph(RID p_font) const = 0;
+ virtual void font_set_spacing_glyph(RID p_font, int p_value) = 0;
+
virtual float font_get_underline_position(RID p_font, int p_size) const = 0;
virtual float font_get_underline_thickness(RID p_font, int p_size) const = 0;
diff --git a/tests/data/images/icon.bmp b/tests/data/images/icon.bmp
new file mode 100644
index 0000000000..e006f7ebdd
--- /dev/null
+++ b/tests/data/images/icon.bmp
Binary files differ
diff --git a/tests/data/images/icon.jpg b/tests/data/images/icon.jpg
new file mode 100644
index 0000000000..b45bfa8d9b
--- /dev/null
+++ b/tests/data/images/icon.jpg
Binary files differ
diff --git a/tests/data/images/icon.png b/tests/data/images/icon.png
new file mode 100644
index 0000000000..45aaaf584f
--- /dev/null
+++ b/tests/data/images/icon.png
Binary files differ
diff --git a/tests/data/images/icon.tga b/tests/data/images/icon.tga
new file mode 100644
index 0000000000..dcacdc5c67
--- /dev/null
+++ b/tests/data/images/icon.tga
Binary files differ
diff --git a/tests/data/images/icon.webp b/tests/data/images/icon.webp
new file mode 100644
index 0000000000..6c4707e858
--- /dev/null
+++ b/tests/data/images/icon.webp
Binary files differ
diff --git a/tests/test_array.h b/tests/test_array.h
new file mode 100644
index 0000000000..52da256860
--- /dev/null
+++ b/tests/test_array.h
@@ -0,0 +1,186 @@
+/*************************************************************************/
+/* test_array.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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_ARRAY_H
+#define TEST_ARRAY_H
+
+#include "core/object/class_db.h"
+#include "core/object/script_language.h"
+#include "core/templates/hashfuncs.h"
+#include "core/templates/vector.h"
+#include "core/variant/array.h"
+#include "core/variant/container_type_validate.h"
+#include "core/variant/variant.h"
+#include "tests/test_macros.h"
+
+namespace TestArray {
+
+TEST_CASE("[Array] size(), clear(), and is_empty()") {
+ Array arr;
+ CHECK(arr.size() == 0);
+ CHECK(arr.is_empty());
+ arr.push_back(1);
+ CHECK(arr.size() == 1);
+ arr.clear();
+ CHECK(arr.is_empty());
+ CHECK(arr.size() == 0);
+}
+
+TEST_CASE("[Array] Assignment and comparison operators") {
+ Array arr1;
+ Array arr2;
+ arr1.push_back(1);
+ CHECK(arr1 != arr2);
+ CHECK(arr1 > arr2);
+ CHECK(arr1 >= arr2);
+ arr2.push_back(2);
+ CHECK(arr1 != arr2);
+ CHECK(arr1 < arr2);
+ CHECK(arr1 <= arr2);
+ CHECK(arr2 > arr1);
+ CHECK(arr2 >= arr1);
+ Array arr3 = arr2;
+ CHECK(arr3 == arr2);
+}
+
+TEST_CASE("[Array] append_array()") {
+ Array arr1;
+ Array arr2;
+ arr1.push_back(1);
+ arr1.append_array(arr2);
+ CHECK(arr1.size() == 1);
+ arr2.push_back(2);
+ arr1.append_array(arr2);
+ CHECK(arr1.size() == 2);
+ CHECK(int(arr1[0]) == 1);
+ CHECK(int(arr1[1]) == 2);
+}
+
+TEST_CASE("[Array] resize(), insert(), and erase()") {
+ Array arr;
+ arr.resize(2);
+ CHECK(arr.size() == 2);
+ arr.insert(0, 1);
+ CHECK(int(arr[0]) == 1);
+ arr.insert(0, 2);
+ CHECK(int(arr[0]) == 2);
+ arr.erase(2);
+ CHECK(int(arr[0]) == 1);
+}
+
+TEST_CASE("[Array] front() and back()") {
+ Array arr;
+ arr.push_back(1);
+ CHECK(int(arr.front()) == 1);
+ CHECK(int(arr.back()) == 1);
+ arr.push_back(3);
+ CHECK(int(arr.front()) == 1);
+ CHECK(int(arr.back()) == 3);
+}
+
+TEST_CASE("[Array] has() and count()") {
+ Array arr;
+ arr.push_back(1);
+ arr.push_back(1);
+ CHECK(arr.has(1));
+ CHECK(!arr.has(2));
+ CHECK(arr.count(1) == 2);
+ CHECK(arr.count(2) == 0);
+}
+
+TEST_CASE("[Array] remove()") {
+ Array arr;
+ arr.push_back(1);
+ arr.push_back(2);
+ arr.remove(0);
+ CHECK(arr.size() == 1);
+ CHECK(int(arr[0]) == 2);
+ arr.remove(0);
+ CHECK(arr.size() == 0);
+
+ // The array is now empty; try to use `remove()` again.
+ // Normally, this prints an error message so we silence it.
+ ERR_PRINT_OFF;
+ arr.remove(0);
+ ERR_PRINT_ON;
+
+ CHECK(arr.size() == 0);
+}
+
+TEST_CASE("[Array] get()") {
+ Array arr;
+ arr.push_back(1);
+ CHECK(int(arr.get(0)) == 1);
+}
+
+TEST_CASE("[Array] sort()") {
+ Array arr;
+
+ arr.push_back(3);
+ arr.push_back(4);
+ arr.push_back(2);
+ arr.push_back(1);
+ arr.sort();
+ int val = 1;
+ for (int i = 0; i < arr.size(); i++) {
+ CHECK(int(arr[i]) == val);
+ val++;
+ }
+}
+
+TEST_CASE("[Array] push_front(), pop_front(), pop_back()") {
+ Array arr;
+ arr.push_front(1);
+ arr.push_front(2);
+ CHECK(int(arr[0]) == 2);
+ arr.pop_front();
+ CHECK(int(arr[0]) == 1);
+ CHECK(arr.size() == 1);
+ arr.push_front(2);
+ arr.push_front(3);
+ arr.pop_back();
+ CHECK(int(arr[1]) == 2);
+ CHECK(arr.size() == 2);
+}
+
+TEST_CASE("[Array] max() and min()") {
+ Array arr;
+ arr.push_back(3);
+ arr.push_front(4);
+ arr.push_back(5);
+ arr.push_back(2);
+ int max = int(arr.max());
+ int min = int(arr.min());
+ CHECK(max == 5);
+ CHECK(min == 2);
+}
+} // namespace TestArray
+
+#endif // TEST_ARRAY_H
diff --git a/tests/test_class_db.h b/tests/test_class_db.h
index b1440b83ef..9ef4569c14 100644
--- a/tests/test_class_db.h
+++ b/tests/test_class_db.h
@@ -340,7 +340,14 @@ void validate_property(const Context &p_context, const ExposedClass &p_class, co
if (prop_class) {
TEST_COND(prop_class->is_singleton,
"Property type is a singleton: '", p_class.name, ".", String(p_prop.name), "'.");
+
+ if (p_class.api_type == ClassDB::API_CORE) {
+ TEST_COND(prop_class->api_type == ClassDB::API_EDITOR,
+ "Property '", p_class.name, ".", p_prop.name, "' has type '", prop_class->name,
+ "' from the editor API. Core API cannot have dependencies on the editor API.");
+ }
} else {
+ // Look for types that don't inherit Object
TEST_FAIL_COND(!p_context.has_type(prop_type_ref),
"Property type '", prop_type_ref.name, "' not found: '", p_class.name, ".", String(p_prop.name), "'.");
}
@@ -370,10 +377,22 @@ void validate_property(const Context &p_context, const ExposedClass &p_class, co
}
void validate_method(const Context &p_context, const ExposedClass &p_class, const MethodData &p_method) {
- const ExposedClass *return_class = p_context.find_exposed_class(p_method.return_type);
- if (return_class) {
- TEST_COND(return_class->is_singleton,
- "Method return type is a singleton: '", p_class.name, ".", p_method.name, "'.");
+ if (p_method.return_type.name != StringName()) {
+ const ExposedClass *return_class = p_context.find_exposed_class(p_method.return_type);
+ if (return_class) {
+ TEST_COND(return_class->is_singleton,
+ "Method return type is a singleton: '", p_class.name, ".", p_method.name, "'.");
+
+ if (p_class.api_type == ClassDB::API_CORE) {
+ TEST_COND(return_class->api_type == ClassDB::API_EDITOR,
+ "Method '", p_class.name, ".", p_method.name, "' has return type '", return_class->name,
+ "' from the editor API. Core API cannot have dependencies on the editor API.");
+ }
+ } else {
+ // Look for types that don't inherit Object
+ TEST_FAIL_COND(!p_context.has_type(p_method.return_type),
+ "Method return type '", p_method.return_type.name, "' not found: '", p_class.name, ".", p_method.name, "'.");
+ }
}
for (const List<ArgumentData>::Element *F = p_method.arguments.front(); F; F = F->next()) {
@@ -383,7 +402,14 @@ void validate_method(const Context &p_context, const ExposedClass &p_class, cons
if (arg_class) {
TEST_COND(arg_class->is_singleton,
"Argument type is a singleton: '", arg.name, "' of method '", p_class.name, ".", p_method.name, "'.");
+
+ if (p_class.api_type == ClassDB::API_CORE) {
+ TEST_COND(arg_class->api_type == ClassDB::API_EDITOR,
+ "Argument '", arg.name, "' of method '", p_class.name, ".", p_method.name, "' has type '",
+ arg_class->name, "' from the editor API. Core API cannot have dependencies on the editor API.");
+ }
} else {
+ // Look for types that don't inherit Object
TEST_FAIL_COND(!p_context.has_type(arg.type),
"Argument type '", arg.type.name, "' not found: '", arg.name, "' of method", p_class.name, ".", p_method.name, "'.");
}
@@ -407,8 +433,15 @@ void validate_signal(const Context &p_context, const ExposedClass &p_class, cons
const ExposedClass *arg_class = p_context.find_exposed_class(arg.type);
if (arg_class) {
TEST_COND(arg_class->is_singleton,
- "Argument class is a singleton: '", arg.name, "' of signal", p_class.name, ".", p_signal.name, "'.");
+ "Argument class is a singleton: '", arg.name, "' of signal '", p_class.name, ".", p_signal.name, "'.");
+
+ if (p_class.api_type == ClassDB::API_CORE) {
+ TEST_COND(arg_class->api_type == ClassDB::API_EDITOR,
+ "Argument '", arg.name, "' of signal '", p_class.name, ".", p_signal.name, "' has type '",
+ arg_class->name, "' from the editor API. Core API cannot have dependencies on the editor API.");
+ }
} else {
+ // Look for types that don't inherit Object
TEST_FAIL_COND(!p_context.has_type(arg.type),
"Argument type '", arg.type.name, "' not found: '", arg.name, "' of signal", p_class.name, ".", p_signal.name, "'.");
}
diff --git a/tests/test_geometry_3d.h b/tests/test_geometry_3d.h
new file mode 100644
index 0000000000..2b2a424b2b
--- /dev/null
+++ b/tests/test_geometry_3d.h
@@ -0,0 +1,417 @@
+/*************************************************************************/
+/* test_geometry_3d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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_3D_GEOMETRY_H
+#define TEST_3D_GEOMETRY_H
+
+#include "core/math/geometry_3d.h"
+#include "core/math/plane.h"
+#include "core/math/random_number_generator.h"
+#include "core/math/vector3.h"
+#include "tests/test_macros.h"
+#include "vector"
+
+namespace Test3DGeometry {
+TEST_CASE("[Geometry3D] Closest Points Between Segments") {
+ struct Case {
+ Vector3 p_1, p_2, p_3, p_4;
+ Vector3 got_1, got_2;
+ Vector3 want_1, want_2;
+ Case(){};
+ Case(Vector3 p_p_1, Vector3 p_p_2, Vector3 p_p_3, Vector3 p_p_4, Vector3 p_want_1, Vector3 p_want_2) :
+ p_1(p_p_1), p_2(p_p_2), p_3(p_p_3), p_4(p_p_4), want_1(p_want_1), want_2(p_want_2){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(Vector3(1, -1, 1), Vector3(1, 1, -1), Vector3(-1, -2, -1), Vector3(-1, 1, 1), Vector3(1, -0.2, 0.2), Vector3(-1, -0.2, 0.2)));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ Geometry3D::get_closest_points_between_segments(current_case.p_1, current_case.p_2, current_case.p_3, current_case.p_4, current_case.got_1, current_case.got_2);
+ CHECK(current_case.got_1.is_equal_approx(current_case.want_1));
+ CHECK(current_case.got_2.is_equal_approx(current_case.want_2));
+ }
+}
+TEST_CASE("[Geometry3D] Closest Distance Between Segments") {
+ struct Case {
+ Vector3 p_1, p_2, p_3, p_4;
+ float want;
+ Case(){};
+ Case(Vector3 p_p_1, Vector3 p_p_2, Vector3 p_p_3, Vector3 p_p_4, float p_want) :
+ p_1(p_p_1), p_2(p_p_2), p_3(p_p_3), p_4(p_p_4), want(p_want){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(Vector3(1, -2, 0), Vector3(1, 2, 0), Vector3(-1, 2, 0), Vector3(-1, -2, 0), 0.0f));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ float out = Geometry3D::get_closest_distance_between_segments(current_case.p_1, current_case.p_2, current_case.p_3, current_case.p_4);
+ CHECK(out == current_case.want);
+ }
+}
+TEST_CASE("[Geometry3D] Build Box Planes") {
+ const Vector3 extents = Vector3(5, 5, 20);
+ Vector<Plane> box = Geometry3D::build_box_planes(extents);
+ CHECK(box.size() == 6);
+ CHECK(extents.x == box[0].d);
+ CHECK(box[0].normal == Vector3(1, 0, 0));
+ CHECK(extents.x == box[1].d);
+ CHECK(box[1].normal == Vector3(-1, 0, 0));
+ CHECK(extents.y == box[2].d);
+ CHECK(box[2].normal == Vector3(0, 1, 0));
+ CHECK(extents.y == box[3].d);
+ CHECK(box[3].normal == Vector3(0, -1, 0));
+ CHECK(extents.z == box[4].d);
+ CHECK(box[4].normal == Vector3(0, 0, 1));
+ CHECK(extents.z == box[5].d);
+ CHECK(box[5].normal == Vector3(0, 0, -1));
+}
+TEST_CASE("[Geometry3D] Build Capsule Planes") {
+ struct Case {
+ real_t radius, height;
+ int sides, lats;
+ Vector3::Axis axis;
+ int want_size;
+ Case(){};
+ Case(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis, int p_want) :
+ radius(p_radius), height(p_height), sides(p_sides), lats(p_lats), axis(p_axis), want_size(p_want){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(10, 20, 6, 10, Vector3::Axis(), 126));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ Vector<Plane> capsule = Geometry3D::build_capsule_planes(current_case.radius, current_case.height, current_case.sides, current_case.lats, current_case.axis);
+ // Should equal (p_sides * p_lats) * 2 + p_sides
+ CHECK(capsule.size() == current_case.want_size);
+ }
+}
+TEST_CASE("[Geometry3D] Build Cylinder Planes") {
+ struct Case {
+ real_t radius, height;
+ int sides;
+ Vector3::Axis axis;
+ int want_size;
+ Case(){};
+ Case(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis, int p_want) :
+ radius(p_radius), height(p_height), sides(p_sides), axis(p_axis), want_size(p_want){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(3.0f, 10.0f, 10, Vector3::Axis(), 12));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ Vector<Plane> planes = Geometry3D::build_cylinder_planes(current_case.radius, current_case.height, current_case.sides, current_case.axis);
+ CHECK(planes.size() == current_case.want_size);
+ }
+}
+TEST_CASE("[Geometry3D] Build Sphere Planes") {
+ struct Case {
+ real_t radius;
+ int lats, lons;
+ Vector3::Axis axis;
+ int want_size;
+ Case(){};
+ Case(real_t p_radius, int p_lat, int p_lons, Vector3::Axis p_axis, int p_want) :
+ radius(p_radius), lats(p_lat), lons(p_lons), axis(p_axis), want_size(p_want){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(10.0f, 10, 3, Vector3::Axis(), 63));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ Vector<Plane> planes = Geometry3D::build_sphere_planes(current_case.radius, current_case.lats, current_case.lons, current_case.axis);
+ CHECK(planes.size() == 63);
+ }
+}
+TEST_CASE("[Geometry3D] Build Convex Mesh") {
+ struct Case {
+ Vector<Plane> object;
+ int want_faces, want_edges, want_vertices;
+ Case(){};
+ Case(Vector<Plane> p_object, int p_want_faces, int p_want_edges, int p_want_vertices) :
+ object(p_object), want_faces(p_want_faces), want_edges(p_want_edges), want_vertices(p_want_vertices){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(Geometry3D::build_box_planes(Vector3(5, 10, 5)), 6, 12, 8));
+ tt.push_back(Case(Geometry3D::build_capsule_planes(5, 5, 20, 20, Vector3::Axis()), 820, 7603, 6243));
+ tt.push_back(Case(Geometry3D::build_cylinder_planes(5, 5, 20, Vector3::Axis()), 22, 100, 80));
+ tt.push_back(Case(Geometry3D::build_sphere_planes(5, 5, 20), 220, 1011, 522));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ Geometry3D::MeshData mesh = Geometry3D::build_convex_mesh(current_case.object);
+ CHECK(mesh.faces.size() == current_case.want_faces);
+ CHECK(mesh.edges.size() == current_case.want_edges);
+ CHECK(mesh.vertices.size() == current_case.want_vertices);
+ }
+}
+TEST_CASE("[Geometry3D] Clip Polygon") {
+ struct Case {
+ Plane clipping_plane;
+ Vector<Vector3> polygon;
+ bool want;
+ Case(){};
+ Case(Plane p_clipping_plane, Vector<Vector3> p_polygon, bool p_want) :
+ clipping_plane(p_clipping_plane), polygon(p_polygon), want(p_want){};
+ };
+ Vector<Case> tt;
+ Vector<Plane> box_planes = Geometry3D::build_box_planes(Vector3(5, 10, 5));
+ Vector<Vector3> box = Geometry3D::compute_convex_mesh_points(&box_planes[0], box_planes.size());
+ tt.push_back(Case(Plane(), box, true));
+ tt.push_back(Case(Plane(Vector3(0, 3, 0), Vector3(0, 1, 0)), box, false));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ Vector<Vector3> output = Geometry3D::clip_polygon(current_case.polygon, current_case.clipping_plane);
+ if (current_case.want) {
+ CHECK(output == current_case.polygon);
+ } else {
+ CHECK(output != current_case.polygon);
+ }
+ }
+}
+TEST_CASE("[Geometry3D] Compute Convex Mesh Points") {
+ struct Case {
+ Vector<Plane> mesh;
+ Vector<Vector3> want;
+ Case(){};
+ Case(Vector<Plane> p_mesh, Vector<Vector3> p_want) :
+ mesh(p_mesh), want(p_want){};
+ };
+ Vector<Case> tt;
+ Vector<Vector3> cube;
+ cube.push_back(Vector3(-5, -5, -5));
+ cube.push_back(Vector3(5, -5, -5));
+ cube.push_back(Vector3(-5, 5, -5));
+ cube.push_back(Vector3(5, 5, -5));
+ cube.push_back(Vector3(-5, -5, 5));
+ cube.push_back(Vector3(5, -5, 5));
+ cube.push_back(Vector3(-5, 5, 5));
+ cube.push_back(Vector3(5, 5, 5));
+ tt.push_back(Case(Geometry3D::build_box_planes(Vector3(5, 5, 5)), cube));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ Vector<Vector3> vectors = Geometry3D::compute_convex_mesh_points(&current_case.mesh[0], current_case.mesh.size());
+ CHECK(vectors == current_case.want);
+ }
+}
+TEST_CASE("[Geometry3D] Get Closest Point To Segment") {
+ struct Case {
+ Vector3 point;
+ Vector<Vector3> segment;
+ Vector3 want;
+ Case(){};
+ Case(Vector3 p_point, Vector<Vector3> p_segment, Vector3 p_want) :
+ point(p_point), segment(p_segment), want(p_want){};
+ };
+ Vector<Case> tt;
+ Vector<Vector3> test_segment;
+ test_segment.push_back(Vector3(1, 1, 1));
+ test_segment.push_back(Vector3(5, 5, 5));
+ tt.push_back(Case(Vector3(2, 1, 4), test_segment, Vector3(2.33333, 2.33333, 2.33333)));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ Vector3 output = Geometry3D::get_closest_point_to_segment(current_case.point, &current_case.segment[0]);
+ CHECK(output.is_equal_approx(current_case.want));
+ }
+}
+TEST_CASE("[Geometry3D] Plane and Box Overlap") {
+ struct Case {
+ Vector3 normal, max_box;
+ float d;
+ bool want;
+ Case(){};
+ Case(Vector3 p_normal, float p_d, Vector3 p_max_box, bool p_want) :
+ normal(p_normal), max_box(p_max_box), d(p_d), want(p_want){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(Vector3(3, 4, 2), 5, Vector3(5, 5, 5), true));
+ tt.push_back(Case(Vector3(0, 1, 0), -10, Vector3(5, 5, 5), false));
+ tt.push_back(Case(Vector3(1, 0, 0), -6, Vector3(5, 5, 5), false));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ bool overlap = Geometry3D::planeBoxOverlap(current_case.normal, current_case.d, current_case.max_box);
+ CHECK(overlap == current_case.want);
+ }
+}
+TEST_CASE("[Geometry3D] Is Point in Projected Triangle") {
+ struct Case {
+ Vector3 point, v_1, v_2, v_3;
+ bool want;
+ Case(){};
+ Case(Vector3 p_point, Vector3 p_v_1, Vector3 p_v_2, Vector3 p_v_3, bool p_want) :
+ point(p_point), v_1(p_v_1), v_2(p_v_2), v_3(p_v_3), want(p_want){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(Vector3(1, 1, 0), Vector3(3, 0, 0), Vector3(0, 3, 0), Vector3(-3, 0, 0), true));
+ tt.push_back(Case(Vector3(5, 1, 0), Vector3(3, 0, 0), Vector3(0, 3, 0), Vector3(-3, 0, 0), false));
+ tt.push_back(Case(Vector3(3, 0, 0), Vector3(3, 0, 0), Vector3(0, 3, 0), Vector3(-3, 0, 0), true));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ bool output = Geometry3D::point_in_projected_triangle(current_case.point, current_case.v_1, current_case.v_2, current_case.v_3);
+ CHECK(output == current_case.want);
+ }
+}
+TEST_CASE("[Geometry3D] Does Ray Intersect Triangle") {
+ struct Case {
+ Vector3 from, direction, v_1, v_2, v_3;
+ Vector3 *result;
+ bool want;
+ Case(){};
+ Case(Vector3 p_from, Vector3 p_direction, Vector3 p_v_1, Vector3 p_v_2, Vector3 p_v_3, bool p_want) :
+ from(p_from), direction(p_direction), v_1(p_v_1), v_2(p_v_2), v_3(p_v_3), result(nullptr), want(p_want){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(Vector3(0, 1, 1), Vector3(0, 0, -10), Vector3(0, 3, 0), Vector3(-3, 0, 0), Vector3(3, 0, 0), true));
+ tt.push_back(Case(Vector3(5, 10, 1), Vector3(0, 0, -10), Vector3(0, 3, 0), Vector3(-3, 0, 0), Vector3(3, 0, 0), false));
+ tt.push_back(Case(Vector3(0, 1, 1), Vector3(0, 0, 10), Vector3(0, 3, 0), Vector3(-3, 0, 0), Vector3(3, 0, 0), false));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ bool output = Geometry3D::ray_intersects_triangle(current_case.from, current_case.direction, current_case.v_1, current_case.v_2, current_case.v_3, current_case.result);
+ CHECK(output == current_case.want);
+ }
+}
+TEST_CASE("[Geometry3D] Does Segment Intersect Convex") {
+ struct Case {
+ Vector3 from, to;
+ Vector<Plane> planes;
+ Vector3 *result, *normal;
+ bool want;
+ Case(){};
+ Case(Vector3 p_from, Vector3 p_to, Vector<Plane> p_planes, bool p_want) :
+ from(p_from), to(p_to), planes(p_planes), result(nullptr), normal(nullptr), want(p_want){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(Vector3(10, 10, 10), Vector3(0, 0, 0), Geometry3D::build_box_planes(Vector3(5, 5, 5)), true));
+ tt.push_back(Case(Vector3(10, 10, 10), Vector3(5, 5, 5), Geometry3D::build_box_planes(Vector3(5, 5, 5)), true));
+ tt.push_back(Case(Vector3(10, 10, 10), Vector3(6, 5, 5), Geometry3D::build_box_planes(Vector3(5, 5, 5)), false));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ bool output = Geometry3D::segment_intersects_convex(current_case.from, current_case.to, &current_case.planes[0], current_case.planes.size(), current_case.result, current_case.normal);
+ CHECK(output == current_case.want);
+ }
+}
+TEST_CASE("[Geometry3D] Segment Intersects Cylinder") {
+ struct Case {
+ Vector3 from, to;
+ real_t height, radius;
+ Vector3 *result, *normal;
+ bool want;
+ Case(){};
+ Case(Vector3 p_from, Vector3 p_to, real_t p_height, real_t p_radius, bool p_want) :
+ from(p_from), to(p_to), height(p_height), radius(p_radius), result(nullptr), normal(nullptr), want(p_want){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(Vector3(10, 10, 10), Vector3(0, 0, 0), 5, 5, true));
+ tt.push_back(Case(Vector3(10, 10, 10), Vector3(6, 6, 6), 5, 5, false));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ bool output = Geometry3D::segment_intersects_cylinder(current_case.from, current_case.to, current_case.height, current_case.radius, current_case.result, current_case.normal);
+ CHECK(output == current_case.want);
+ }
+}
+TEST_CASE("[Geometry3D] Segment Intersects Cylinder") {
+ struct Case {
+ Vector3 from, to, sphere_pos;
+ real_t radius;
+ Vector3 *result, *normal;
+ bool want;
+ Case(){};
+ Case(Vector3 p_from, Vector3 p_to, Vector3 p_sphere_pos, real_t p_radius, bool p_want) :
+ from(p_from), to(p_to), sphere_pos(p_sphere_pos), radius(p_radius), result(nullptr), normal(nullptr), want(p_want){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(Vector3(10, 10, 10), Vector3(0, 0, 0), Vector3(0, 0, 0), 5, true));
+ tt.push_back(Case(Vector3(10, 10, 10), Vector3(0, 0, 2.5), Vector3(0, 0, 0), 5, true));
+ tt.push_back(Case(Vector3(10, 10, 10), Vector3(5, 5, 5), Vector3(0, 0, 0), 5, false));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ bool output = Geometry3D::segment_intersects_sphere(current_case.from, current_case.to, current_case.sphere_pos, current_case.radius, current_case.result, current_case.normal);
+ CHECK(output == current_case.want);
+ }
+}
+TEST_CASE("[Geometry3D] Segment Intersects Triangle") {
+ struct Case {
+ Vector3 from, to, v_1, v_2, v_3, *result;
+ bool want;
+ Case(){};
+ Case(Vector3 p_from, Vector3 p_to, Vector3 p_v_1, Vector3 p_v_2, Vector3 p_v_3, bool p_want) :
+ from(p_from), to(p_to), v_1(p_v_1), v_2(p_v_2), v_3(p_v_3), result(nullptr), want(p_want){};
+ };
+ Vector<Case> tt;
+ tt.push_back(Case(Vector3(1, 1, 1), Vector3(-1, -1, -1), Vector3(-3, 0, 0), Vector3(0, 3, 0), Vector3(3, 0, 0), true));
+ tt.push_back(Case(Vector3(1, 1, 1), Vector3(3, 0, 0), Vector3(-3, 0, 0), Vector3(0, 3, 0), Vector3(3, 0, 0), true));
+ tt.push_back(Case(Vector3(1, 1, 1), Vector3(10, -1, -1), Vector3(-3, 0, 0), Vector3(0, 3, 0), Vector3(3, 0, 0), false));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ bool output = Geometry3D::segment_intersects_triangle(current_case.from, current_case.to, current_case.v_1, current_case.v_2, current_case.v_3, current_case.result);
+ CHECK(output == current_case.want);
+ }
+}
+TEST_CASE("[Geometry3D] Triangle and Box Overlap") {
+ struct Case {
+ Vector3 box_centre;
+ Vector3 box_half_size;
+ Vector3 *tri_verts;
+ bool want;
+ Case(){};
+ Case(Vector3 p_centre, Vector3 p_half_size, Vector3 *p_verts, bool p_want) :
+ box_centre(p_centre), box_half_size(p_half_size), tri_verts(p_verts), want(p_want){};
+ };
+ Vector<Case> tt;
+ Vector3 GoodTriangle[3] = { Vector3(3, 2, 3), Vector3(2, 2, 1), Vector3(2, 1, 1) };
+ tt.push_back(Case(Vector3(0, 0, 0), Vector3(5, 5, 5), GoodTriangle, true));
+ Vector3 BadTriangle[3] = { Vector3(100, 100, 100), Vector3(-100, -100, -100), Vector3(10, 10, 10) };
+ tt.push_back(Case(Vector3(1000, 1000, 1000), Vector3(1, 1, 1), BadTriangle, false));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ bool output = Geometry3D::triangle_box_overlap(current_case.box_centre, current_case.box_half_size, current_case.tri_verts);
+ CHECK(output == current_case.want);
+ }
+}
+TEST_CASE("[Geometry3D] Triangle and Sphere Intersect") {
+ struct Case {
+ Vector<Vector3> triangle;
+ Vector3 normal, sphere_pos, triangle_contact, sphere_contact;
+ real_t sphere_radius;
+ bool want;
+ Case(){};
+ Case(Vector<Vector3> p_triangle, Vector3 p_normal, Vector3 p_sphere_pos, real_t p_sphere_radius, bool p_want) :
+ triangle(p_triangle), normal(p_normal), sphere_pos(p_sphere_pos), triangle_contact(Vector3()), sphere_contact(Vector3()), sphere_radius(p_sphere_radius), want(p_want){};
+ };
+ Vector<Case> tt;
+ Vector<Vector3> triangle;
+ triangle.push_back(Vector3(3, 0, 0));
+ triangle.push_back(Vector3(-3, 0, 0));
+ triangle.push_back(Vector3(0, 3, 0));
+ tt.push_back(Case(triangle, Vector3(0, -1, 0), Vector3(0, 0, 0), 5, true));
+ tt.push_back(Case(triangle, Vector3(0, 1, 0), Vector3(0, 0, 0), 5, true));
+ tt.push_back(Case(triangle, Vector3(0, 1, 0), Vector3(20, 0, 0), 5, false));
+ for (int i = 0; i < tt.size(); ++i) {
+ Case current_case = tt[i];
+ bool output = Geometry3D::triangle_sphere_intersection_test(&current_case.triangle[0], current_case.normal, current_case.sphere_pos, current_case.sphere_radius, current_case.triangle_contact, current_case.sphere_contact);
+ CHECK(output == current_case.want);
+ }
+}
+} // namespace Test3DGeometry
+#endif
diff --git a/tests/test_hashing_context.h b/tests/test_hashing_context.h
new file mode 100644
index 0000000000..728a5f2cfa
--- /dev/null
+++ b/tests/test_hashing_context.h
@@ -0,0 +1,165 @@
+/*************************************************************************/
+/* test_hashing_context.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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_HASHING_CONTEXT_H
+#define TEST_HASHING_CONTEXT_H
+
+#include "core/crypto/hashing_context.h"
+
+#include "tests/test_macros.h"
+
+namespace TestHashingContext {
+
+TEST_CASE("[HashingContext] Default - MD5/SHA1/SHA256") {
+ HashingContext ctx;
+
+ static const uint8_t md5_expected[] = {
+ 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
+ };
+ static const uint8_t sha1_expected[] = {
+ 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
+ 0xaf, 0xd8, 0x07, 0x09
+ };
+ static const uint8_t sha256_expected[] = {
+ 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
+ 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
+ };
+
+ CHECK(ctx.start(HashingContext::HASH_MD5) == OK);
+ PackedByteArray result = ctx.finish();
+ REQUIRE(result.size() == 16);
+ CHECK(memcmp(result.ptr(), md5_expected, 16) == 0);
+
+ CHECK(ctx.start(HashingContext::HASH_SHA1) == OK);
+ result = ctx.finish();
+ REQUIRE(result.size() == 20);
+ CHECK(memcmp(result.ptr(), sha1_expected, 20) == 0);
+
+ CHECK(ctx.start(HashingContext::HASH_SHA256) == OK);
+ result = ctx.finish();
+ REQUIRE(result.size() == 32);
+ CHECK(memcmp(result.ptr(), sha256_expected, 32) == 0);
+}
+
+TEST_CASE("[HashingContext] Multiple updates - MD5/SHA1/SHA256") {
+ HashingContext ctx;
+ const String s = "xyz";
+
+ const PackedByteArray s_byte_parts[] = {
+ String("x").to_ascii_buffer(),
+ String("y").to_ascii_buffer(),
+ String("z").to_ascii_buffer()
+ };
+
+ static const uint8_t md5_expected[] = {
+ 0xd1, 0x6f, 0xb3, 0x6f, 0x09, 0x11, 0xf8, 0x78, 0x99, 0x8c, 0x13, 0x61, 0x91, 0xaf, 0x70, 0x5e
+ };
+ static const uint8_t sha1_expected[] = {
+ 0x66, 0xb2, 0x74, 0x17, 0xd3, 0x7e, 0x02, 0x4c, 0x46, 0x52, 0x6c, 0x2f, 0x6d, 0x35, 0x8a, 0x75,
+ 0x4f, 0xc5, 0x52, 0xf3
+ };
+ static const uint8_t sha256_expected[] = {
+ 0x36, 0x08, 0xbc, 0xa1, 0xe4, 0x4e, 0xa6, 0xc4, 0xd2, 0x68, 0xeb, 0x6d, 0xb0, 0x22, 0x60, 0x26,
+ 0x98, 0x92, 0xc0, 0xb4, 0x2b, 0x86, 0xbb, 0xf1, 0xe7, 0x7a, 0x6f, 0xa1, 0x6c, 0x3c, 0x92, 0x82
+ };
+
+ CHECK(ctx.start(HashingContext::HASH_MD5) == OK);
+ CHECK(ctx.update(s_byte_parts[0]) == OK);
+ CHECK(ctx.update(s_byte_parts[1]) == OK);
+ CHECK(ctx.update(s_byte_parts[2]) == OK);
+ PackedByteArray result = ctx.finish();
+ REQUIRE(result.size() == 16);
+ CHECK(memcmp(result.ptr(), md5_expected, 16) == 0);
+
+ CHECK(ctx.start(HashingContext::HASH_SHA1) == OK);
+ CHECK(ctx.update(s_byte_parts[0]) == OK);
+ CHECK(ctx.update(s_byte_parts[1]) == OK);
+ CHECK(ctx.update(s_byte_parts[2]) == OK);
+ result = ctx.finish();
+ REQUIRE(result.size() == 20);
+ CHECK(memcmp(result.ptr(), sha1_expected, 20) == 0);
+
+ CHECK(ctx.start(HashingContext::HASH_SHA256) == OK);
+ CHECK(ctx.update(s_byte_parts[0]) == OK);
+ CHECK(ctx.update(s_byte_parts[1]) == OK);
+ CHECK(ctx.update(s_byte_parts[2]) == OK);
+ result = ctx.finish();
+ REQUIRE(result.size() == 32);
+ CHECK(memcmp(result.ptr(), sha256_expected, 32) == 0);
+}
+
+TEST_CASE("[HashingContext] Invalid use of start") {
+ HashingContext ctx;
+
+ ERR_PRINT_OFF;
+ CHECK_MESSAGE(
+ ctx.start(static_cast<HashingContext::HashType>(-1)) == ERR_UNAVAILABLE,
+ "Using invalid hash types should fail.");
+ ERR_PRINT_ON;
+
+ REQUIRE(ctx.start(HashingContext::HASH_MD5) == OK);
+
+ ERR_PRINT_OFF;
+ CHECK_MESSAGE(
+ ctx.start(HashingContext::HASH_MD5) == ERR_ALREADY_IN_USE,
+ "Calling 'start' twice before 'finish' should fail.");
+ ERR_PRINT_ON;
+}
+
+TEST_CASE("[HashingContext] Invalid use of update") {
+ HashingContext ctx;
+
+ ERR_PRINT_OFF;
+ CHECK_MESSAGE(
+ ctx.update(PackedByteArray()) == ERR_UNCONFIGURED,
+ "Calling 'update' before 'start' should fail.");
+ ERR_PRINT_ON;
+
+ REQUIRE(ctx.start(HashingContext::HASH_MD5) == OK);
+
+ ERR_PRINT_OFF;
+ CHECK_MESSAGE(
+ ctx.update(PackedByteArray()) == FAILED,
+ "Calling 'update' with an empty byte array should fail.");
+ ERR_PRINT_ON;
+}
+
+TEST_CASE("[HashingContext] Invalid use of finish") {
+ HashingContext ctx;
+
+ ERR_PRINT_OFF;
+ CHECK_MESSAGE(
+ ctx.finish() == PackedByteArray(),
+ "Calling 'finish' before 'start' should return an empty byte array.");
+ ERR_PRINT_ON;
+}
+} // namespace TestHashingContext
+
+#endif // TEST_HASHING_CONTEXT_H
diff --git a/tests/test_image.h b/tests/test_image.h
new file mode 100644
index 0000000000..d73717f5b7
--- /dev/null
+++ b/tests/test_image.h
@@ -0,0 +1,259 @@
+/*************************************************************************/
+/* test_image.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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_IMAGE_H
+#define TEST_IMAGE_H
+
+#include "core/io/file_access_pack.h"
+#include "core/io/image.h"
+#include "test_utils.h"
+
+#include "thirdparty/doctest/doctest.h"
+
+namespace TestImage {
+
+TEST_CASE("[Image] Instantiation") {
+ Ref<Image> image = memnew(Image(8, 4, false, Image::FORMAT_RGBA8));
+ CHECK_MESSAGE(
+ !image->is_empty(),
+ "An image created with specified size and format should not be empty at first.");
+ CHECK_MESSAGE(
+ image->is_invisible(),
+ "A newly created image should be invisible.");
+ CHECK_MESSAGE(
+ !image->is_compressed(),
+ "A newly created image should not be compressed.");
+ CHECK(!image->has_mipmaps());
+
+ Ref<Image> image_copy = memnew(Image());
+ CHECK_MESSAGE(
+ image_copy->is_empty(),
+ "An image created without any specified size and format be empty at first.");
+ image_copy->copy_internals_from(image);
+
+ CHECK_MESSAGE(
+ image->get_data() == image_copy->get_data(),
+ "Duplicated images should have the same data.");
+
+ PackedByteArray image_data = image->get_data();
+ Ref<Image> image_from_data = memnew(Image(8, 4, false, Image::FORMAT_RGBA8, image_data));
+ CHECK_MESSAGE(
+ image->get_data() == image_from_data->get_data(),
+ "An image created from data of another image should have the same data of the original image.");
+}
+
+TEST_CASE("[Image] Saving and loading") {
+ Ref<Image> image = memnew(Image(4, 4, false, Image::FORMAT_RGBA8));
+ const String save_path_png = OS::get_singleton()->get_cache_path().plus_file("image.png");
+ const String save_path_exr = OS::get_singleton()->get_cache_path().plus_file("image.exr");
+
+ // Save PNG
+ Error err;
+ err = image->save_png(save_path_png);
+ CHECK_MESSAGE(
+ err == OK,
+ "The image should be saved successfully as a .png file.");
+
+ // Save EXR
+ err = image->save_exr(save_path_exr, false);
+ CHECK_MESSAGE(
+ err == OK,
+ "The image should be saved successfully as an .exr file.");
+
+ // Load using load()
+ Ref<Image> image_load = memnew(Image());
+ err = image_load->load(save_path_png);
+ CHECK_MESSAGE(
+ err == OK,
+ "The image should load successfully using load().");
+ CHECK_MESSAGE(
+ image->get_data() == image_load->get_data(),
+ "The loaded image should have the same data as the one that got saved.");
+
+ // Load BMP
+ Ref<Image> image_bmp = memnew(Image());
+ FileAccessRef f_bmp = FileAccess::open(TestUtils::get_data_path("images/icon.bmp"), FileAccess::READ, &err);
+ PackedByteArray data_bmp;
+ data_bmp.resize(f_bmp->get_len() + 1);
+ f_bmp->get_buffer(data_bmp.ptrw(), f_bmp->get_len());
+ CHECK_MESSAGE(
+ image_bmp->load_bmp_from_buffer(data_bmp) == OK,
+ "The BMP image should load successfully.");
+
+ // Load JPG
+ Ref<Image> image_jpg = memnew(Image());
+ FileAccessRef f_jpg = FileAccess::open(TestUtils::get_data_path("images/icon.jpg"), FileAccess::READ, &err);
+ PackedByteArray data_jpg;
+ data_jpg.resize(f_jpg->get_len() + 1);
+ f_jpg->get_buffer(data_jpg.ptrw(), f_jpg->get_len());
+ CHECK_MESSAGE(
+ image_jpg->load_jpg_from_buffer(data_jpg) == OK,
+ "The JPG image should load successfully.");
+
+ // Load WEBP
+ Ref<Image> image_webp = memnew(Image());
+ FileAccessRef f_webp = FileAccess::open(TestUtils::get_data_path("images/icon.webp"), FileAccess::READ, &err);
+ PackedByteArray data_webp;
+ data_webp.resize(f_webp->get_len() + 1);
+ f_webp->get_buffer(data_webp.ptrw(), f_webp->get_len());
+ CHECK_MESSAGE(
+ image_webp->load_webp_from_buffer(data_webp) == OK,
+ "The WEBP image should load successfully.");
+
+ // Load PNG
+ Ref<Image> image_png = memnew(Image());
+ FileAccessRef f_png = FileAccess::open(TestUtils::get_data_path("images/icon.png"), FileAccess::READ, &err);
+ PackedByteArray data_png;
+ data_png.resize(f_png->get_len() + 1);
+ f_png->get_buffer(data_png.ptrw(), f_png->get_len());
+ CHECK_MESSAGE(
+ image_png->load_png_from_buffer(data_png) == OK,
+ "The PNG image should load successfully.");
+
+ // Load TGA
+ Ref<Image> image_tga = memnew(Image());
+ FileAccessRef f_tga = FileAccess::open(TestUtils::get_data_path("images/icon.tga"), FileAccess::READ, &err);
+ PackedByteArray data_tga;
+ data_tga.resize(f_tga->get_len() + 1);
+ f_tga->get_buffer(data_tga.ptrw(), f_tga->get_len());
+ CHECK_MESSAGE(
+ image_tga->load_tga_from_buffer(data_tga) == OK,
+ "The TGA image should load successfully.");
+}
+
+TEST_CASE("[Image] Basic getters") {
+ Ref<Image> image = memnew(Image(8, 4, false, Image::FORMAT_LA8));
+ CHECK(image->get_width() == 8);
+ CHECK(image->get_height() == 4);
+ CHECK(image->get_size() == Vector2(8, 4));
+ CHECK(image->get_format() == Image::FORMAT_LA8);
+ CHECK(image->get_used_rect() == Rect2(0, 0, 0, 0));
+ Ref<Image> image_get_rect = image->get_rect(Rect2(0, 0, 2, 1));
+ CHECK(image_get_rect->get_size() == Vector2(2, 1));
+}
+
+TEST_CASE("[Image] Resizing") {
+ Ref<Image> image = memnew(Image(8, 8, false, Image::FORMAT_RGBA8));
+ // Crop
+ image->crop(4, 4);
+ CHECK_MESSAGE(
+ image->get_size() == Vector2(4, 4),
+ "get_size() should return the correct size after cropping.");
+ image->set_pixel(0, 0, Color(1, 1, 1, 1));
+
+ // Resize
+ for (int i = 0; i < 5; i++) {
+ Ref<Image> image_resized = memnew(Image());
+ image_resized->copy_internals_from(image);
+ Image::Interpolation interpolation = static_cast<Image::Interpolation>(i);
+ image_resized->resize(8, 8, interpolation);
+ CHECK_MESSAGE(
+ image_resized->get_size() == Vector2(8, 8),
+ "get_size() should return the correct size after resizing.");
+ CHECK_MESSAGE(
+ image_resized->get_pixel(1, 1).a > 0,
+ "Resizing an image should also affect its content.");
+ }
+
+ // shrink_x2()
+ image->shrink_x2();
+ CHECK_MESSAGE(
+ image->get_size() == Vector2(2, 2),
+ "get_size() should return the correct size after shrink_x2().");
+
+ // resize_to_po2()
+ Ref<Image> image_po_2 = memnew(Image(14, 28, false, Image::FORMAT_RGBA8));
+ image_po_2->resize_to_po2();
+ CHECK_MESSAGE(
+ image_po_2->get_size() == Vector2(16, 32),
+ "get_size() should return the correct size after resize_to_po2().");
+}
+
+TEST_CASE("[Image] Modifying pixels of an image") {
+ Ref<Image> image = memnew(Image(3, 3, false, Image::FORMAT_RGBA8));
+ image->set_pixel(0, 0, Color(1, 1, 1, 1));
+ CHECK_MESSAGE(
+ !image->is_invisible(),
+ "Image should not be invisible after drawing on it.");
+ CHECK_MESSAGE(
+ image->get_pixelv(Vector2(0, 0)).is_equal_approx(Color(1, 1, 1, 1)),
+ "Image's get_pixel() should return the same color value as the one being set with set_pixel() in the same position.");
+ CHECK_MESSAGE(
+ image->get_used_rect() == Rect2(0, 0, 1, 1),
+ "Image's get_used_rect should return the expected value, larger than Rect2(0, 0, 0, 0) if it's visible.");
+
+ image->set_pixelv(Vector2(0, 0), Color(0.5, 0.5, 0.5, 0.5));
+ Ref<Image> image2 = memnew(Image(3, 3, false, Image::FORMAT_RGBA8));
+
+ // Fill image with color
+ image2->fill(Color(0.5, 0.5, 0.5, 0.5));
+ for (int x = 0; x < image2->get_width(); x++) {
+ for (int y = 0; y < image2->get_height(); y++) {
+ CHECK_MESSAGE(
+ image2->get_pixel(x, y).r > 0.49,
+ "fill() should colorize all pixels of the image.");
+ }
+ }
+
+ // Blend two images together
+ image->blend_rect(image2, Rect2(Vector2(0, 0), image2->get_size()), Vector2(0, 0));
+ CHECK_MESSAGE(
+ image->get_pixel(0, 0).a > 0.7,
+ "blend_rect() should blend the alpha values of the two images.");
+ CHECK_MESSAGE(
+ image->get_used_rect().size == image->get_size(),
+ "get_used_rect() should return the expected value, its Rect size should be the same as get_size() if there are no transparent pixels.");
+
+ Ref<Image> image3 = memnew(Image(2, 2, false, Image::FORMAT_RGBA8));
+ image3->set_pixel(0, 0, Color(0, 1, 0, 1));
+
+ //blit_rect() two images together
+ image->blit_rect(image3, Rect2(Vector2(0, 0), image3->get_size()), Vector2(0, 0));
+ CHECK_MESSAGE(
+ image->get_pixel(0, 0).is_equal_approx(Color(0, 1, 0, 1)),
+ "blit_rect() should replace old colors and not blend them.");
+ CHECK_MESSAGE(
+ !image->get_pixel(2, 2).is_equal_approx(Color(0, 1, 0, 1)),
+ "blit_rect() should not affect the area of the image that is outside src_rect.");
+
+ // Flip image
+ image3->flip_x();
+ CHECK(image3->get_pixel(1, 0).is_equal_approx(Color(0, 1, 0, 1)));
+ CHECK_MESSAGE(
+ image3->get_pixel(0, 0).is_equal_approx(Color(0, 0, 0, 0)),
+ "flip_x() should not leave old pixels behind.");
+ image3->flip_y();
+ CHECK(image3->get_pixel(1, 1).is_equal_approx(Color(0, 1, 0, 1)));
+ CHECK_MESSAGE(
+ image3->get_pixel(1, 0).is_equal_approx(Color(0, 0, 0, 0)),
+ "flip_y() should not leave old pixels behind.");
+}
+} // namespace TestImage
+#endif // TEST_IMAGE_H
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index 5c635de25c..f2a546de9b 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -33,6 +33,7 @@
#include "core/templates/list.h"
#include "test_aabb.h"
+#include "test_array.h"
#include "test_astar.h"
#include "test_basis.h"
#include "test_class_db.h"
@@ -44,8 +45,11 @@
#include "test_expression.h"
#include "test_file_access.h"
#include "test_geometry_2d.h"
+#include "test_geometry_3d.h"
#include "test_gradient.h"
#include "test_gui.h"
+#include "test_hashing_context.h"
+#include "test_image.h"
#include "test_json.h"
#include "test_list.h"
#include "test_local_vector.h"
@@ -64,11 +68,13 @@
#include "test_random_number_generator.h"
#include "test_rect2.h"
#include "test_render.h"
+#include "test_resource.h"
#include "test_shader_lang.h"
#include "test_string.h"
#include "test_text_server.h"
#include "test_validate_testing.h"
#include "test_variant.h"
+#include "test_xml_parser.h"
#include "modules/modules_tests.gen.h"
diff --git a/tests/test_path_follow_2d.h b/tests/test_path_follow_2d.h
new file mode 100644
index 0000000000..388b690060
--- /dev/null
+++ b/tests/test_path_follow_2d.h
@@ -0,0 +1,241 @@
+/*************************************************************************/
+/* test_path_follow_2d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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_PATH_FOLLOW_2D_H
+#define TEST_PATH_FOLLOW_2D_H
+
+#include "scene/2d/path_2d.h"
+#include "scene/resources/curve.h"
+
+#include "tests/test_macros.h"
+
+namespace TestPathFollow2D {
+
+TEST_CASE("[PathFollow2D] Sampling with unit offset") {
+ const Ref<Curve2D> &curve = memnew(Curve2D());
+ curve->add_point(Vector2(0, 0));
+ curve->add_point(Vector2(100, 0));
+ curve->add_point(Vector2(100, 100));
+ curve->add_point(Vector2(0, 100));
+ curve->add_point(Vector2(0, 0));
+ const Path2D *path = memnew(Path2D);
+ path->set_curve(curve);
+ const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
+ path->add_child(path_follow_2d);
+
+ path_follow_2d->set_unit_offset(0);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
+
+ path_follow_2d->set_unit_offset(0.125);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
+
+ path_follow_2d->set_unit_offset(0.25);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
+
+ path_follow_2d->set_unit_offset(0.375);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 50)));
+
+ path_follow_2d->set_unit_offset(0.5);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 100)));
+
+ path_follow_2d->set_unit_offset(0.625);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 100)));
+
+ path_follow_2d->set_unit_offset(0.75);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 100)));
+
+ path_follow_2d->set_unit_offset(0.875);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 50)));
+
+ path_follow_2d->set_unit_offset(1);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
+
+ memdelete(path);
+}
+
+TEST_CASE("[PathFollow2D] Sampling with offset") {
+ const Ref<Curve2D> &curve = memnew(Curve2D());
+ curve->add_point(Vector2(0, 0));
+ curve->add_point(Vector2(100, 0));
+ curve->add_point(Vector2(100, 100));
+ curve->add_point(Vector2(0, 100));
+ curve->add_point(Vector2(0, 0));
+ const Path2D *path = memnew(Path2D);
+ path->set_curve(curve);
+ const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
+ path->add_child(path_follow_2d);
+
+ path_follow_2d->set_offset(0);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
+
+ path_follow_2d->set_offset(50);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
+
+ path_follow_2d->set_offset(100);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
+
+ path_follow_2d->set_offset(150);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 50)));
+
+ path_follow_2d->set_offset(200);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 100)));
+
+ path_follow_2d->set_offset(250);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 100)));
+
+ path_follow_2d->set_offset(300);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 100)));
+
+ path_follow_2d->set_offset(350);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 50)));
+
+ path_follow_2d->set_offset(400);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
+
+ memdelete(path);
+}
+
+TEST_CASE("[PathFollow2D] Removal of a point in curve") {
+ const Ref<Curve2D> &curve = memnew(Curve2D());
+ curve->add_point(Vector2(0, 0));
+ curve->add_point(Vector2(100, 0));
+ curve->add_point(Vector2(100, 100));
+ const Path2D *path = memnew(Path2D);
+ path->set_curve(curve);
+ const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
+ path->add_child(path_follow_2d);
+
+ path_follow_2d->set_unit_offset(0.5);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
+
+ curve->remove_point(1);
+
+ CHECK_MESSAGE(
+ path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 50)),
+ "Path follow's position should be updated after removing a point from the curve");
+
+ memdelete(path);
+}
+
+TEST_CASE("[PathFollow2D] Setting h_offset and v_offset") {
+ const Ref<Curve2D> &curve = memnew(Curve2D());
+ curve->add_point(Vector2(0, 0));
+ curve->add_point(Vector2(100, 0));
+ const Path2D *path = memnew(Path2D);
+ path->set_curve(curve);
+ const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
+ path->add_child(path_follow_2d);
+
+ path_follow_2d->set_unit_offset(0.5);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
+
+ path_follow_2d->set_h_offset(25);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(75, 0)));
+
+ path_follow_2d->set_v_offset(25);
+ CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(75, 25)));
+
+ memdelete(path);
+}
+
+TEST_CASE("[PathFollow2D] Unit offset out of range") {
+ const Ref<Curve2D> &curve = memnew(Curve2D());
+ curve->add_point(Vector2(0, 0));
+ curve->add_point(Vector2(100, 0));
+ const Path2D *path = memnew(Path2D);
+ path->set_curve(curve);
+ const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
+ path->add_child(path_follow_2d);
+
+ path_follow_2d->set_loop(true);
+
+ path_follow_2d->set_unit_offset(-0.3);
+ CHECK_MESSAGE(
+ path_follow_2d->get_unit_offset() == 0.7,
+ "Unit Offset should loop back from the end in the opposite direction");
+
+ path_follow_2d->set_unit_offset(1.3);
+ CHECK_MESSAGE(
+ path_follow_2d->get_unit_offset() == 0.3,
+ "Unit Offset should loop back from the end in the opposite direction");
+
+ path_follow_2d->set_loop(false);
+
+ path_follow_2d->set_unit_offset(-0.3);
+ CHECK_MESSAGE(
+ path_follow_2d->get_unit_offset() == 0,
+ "Unit Offset should be clamped at 0");
+
+ path_follow_2d->set_unit_offset(1.3);
+ CHECK_MESSAGE(
+ path_follow_2d->get_unit_offset() == 1,
+ "Unit Offset should be clamped at 1");
+
+ memdelete(path);
+}
+
+TEST_CASE("[PathFollow2D] Offset out of range") {
+ const Ref<Curve2D> &curve = memnew(Curve2D());
+ curve->add_point(Vector2(0, 0));
+ curve->add_point(Vector2(100, 0));
+ const Path2D *path = memnew(Path2D);
+ path->set_curve(curve);
+ const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
+ path->add_child(path_follow_2d);
+
+ path_follow_2d->set_loop(true);
+
+ path_follow_2d->set_offset(-50);
+ CHECK_MESSAGE(
+ path_follow_2d->get_offset() == 50,
+ "Offset should loop back from the end in the opposite direction");
+
+ path_follow_2d->set_offset(150);
+ CHECK_MESSAGE(
+ path_follow_2d->get_offset() == 50,
+ "Offset should loop back from the end in the opposite direction");
+
+ path_follow_2d->set_loop(false);
+
+ path_follow_2d->set_offset(-50);
+ CHECK_MESSAGE(
+ path_follow_2d->get_offset() == 0,
+ "Offset should be clamped at 0");
+
+ path_follow_2d->set_offset(150);
+ CHECK_MESSAGE(
+ path_follow_2d->get_offset() == 100,
+ "Offset should be clamped at 1");
+
+ memdelete(path);
+}
+} // namespace TestPathFollow2D
+
+#endif // TEST_PATH_FOLLOW_2D_H
diff --git a/tests/test_path_follow_3d.h b/tests/test_path_follow_3d.h
new file mode 100644
index 0000000000..b6b4c88222
--- /dev/null
+++ b/tests/test_path_follow_3d.h
@@ -0,0 +1,220 @@
+/*************************************************************************/
+/* test_path_follow_3d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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_PATH_FOLLOW_3D_H
+#define TEST_PATH_FOLLOW_3D_H
+
+#include "scene/3d/path_3d.h"
+#include "scene/resources/curve.h"
+
+#include "tests/test_macros.h"
+
+namespace TestPathFollow3D {
+
+TEST_CASE("[PathFollow3D] Sampling with unit offset") {
+ const Ref<Curve3D> &curve = memnew(Curve3D());
+ curve->add_point(Vector3(0, 0, 0));
+ curve->add_point(Vector3(100, 0, 0));
+ curve->add_point(Vector3(100, 100, 0));
+ curve->add_point(Vector3(100, 100, 100));
+ curve->add_point(Vector3(100, 0, 100));
+ const Path3D *path = memnew(Path3D);
+ path->set_curve(curve);
+ const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
+ path->add_child(path_follow_3d);
+
+ path_follow_3d->set_unit_offset(0);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(0, 0, 0));
+
+ path_follow_3d->set_unit_offset(0.125);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(50, 0, 0));
+
+ path_follow_3d->set_unit_offset(0.25);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 0);
+
+ path_follow_3d->set_unit_offset(0.375);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 0)));
+
+ path_follow_3d->set_unit_offset(0.5);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 0)));
+
+ path_follow_3d->set_unit_offset(0.625);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 50)));
+
+ path_follow_3d->set_unit_offset(0.75);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 100)));
+
+ path_follow_3d->set_unit_offset(0.875);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 100)));
+
+ path_follow_3d->set_unit_offset(1);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 100)));
+
+ memdelete(path);
+}
+
+TEST_CASE("[PathFollow3D] Sampling with offset") {
+ const Ref<Curve3D> &curve = memnew(Curve3D());
+ curve->add_point(Vector3(0, 0, 0));
+ curve->add_point(Vector3(100, 0, 0));
+ curve->add_point(Vector3(100, 100, 0));
+ curve->add_point(Vector3(100, 100, 100));
+ curve->add_point(Vector3(100, 0, 100));
+ const Path3D *path = memnew(Path3D);
+ path->set_curve(curve);
+ const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
+ path->add_child(path_follow_3d);
+
+ path_follow_3d->set_offset(0);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(0, 0, 0));
+
+ path_follow_3d->set_offset(50);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(50, 0, 0));
+
+ path_follow_3d->set_offset(100);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 0);
+
+ path_follow_3d->set_offset(150);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 0)));
+
+ path_follow_3d->set_offset(200);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 0)));
+
+ path_follow_3d->set_offset(250);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 50)));
+
+ path_follow_3d->set_offset(300);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 100)));
+
+ path_follow_3d->set_offset(350);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 100)));
+
+ path_follow_3d->set_offset(400);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 100)));
+
+ memdelete(path);
+}
+
+TEST_CASE("[PathFollow3D] Removal of a point in curve") {
+ const Ref<Curve3D> &curve = memnew(Curve3D());
+ curve->add_point(Vector3(0, 0, 0));
+ curve->add_point(Vector3(100, 0, 0));
+ curve->add_point(Vector3(100, 100, 0));
+ const Path3D *path = memnew(Path3D);
+ path->set_curve(curve);
+ const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
+ path->add_child(path_follow_3d);
+
+ path_follow_3d->set_unit_offset(0.5);
+ CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector2(100, 0, 0)));
+
+ curve->remove_point(1);
+
+ CHECK_MESSAGE(
+ path_follow_3d->get_transform().get_origin().is_equal_approx(Vector2(50, 50, 0)),
+ "Path follow's position should be updated after removing a point from the curve");
+
+ memdelete(path);
+}
+
+TEST_CASE("[PathFollow3D] Unit offset out of range") {
+ const Ref<Curve3D> &curve = memnew(Curve3D());
+ curve->add_point(Vector3(0, 0, 0));
+ curve->add_point(Vector3(100, 0, 0));
+ const Path3D *path = memnew(Path3D);
+ path->set_curve(curve);
+ const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
+ path->add_child(path_follow_3d);
+
+ path_follow_3d->set_loop(true);
+
+ path_follow_3d->set_unit_offset(-0.3);
+ CHECK_MESSAGE(
+ path_follow_3d->get_unit_offset() == 0.7,
+ "Unit Offset should loop back from the end in the opposite direction");
+
+ path_follow_3d->set_unit_offset(1.3);
+ CHECK_MESSAGE(
+ path_follow_3d->get_unit_offset() == 0.3,
+ "Unit Offset should loop back from the end in the opposite direction");
+
+ path_follow_3d->set_loop(false);
+
+ path_follow_3d->set_unit_offset(-0.3);
+ CHECK_MESSAGE(
+ path_follow_3d->get_unit_offset() == 0,
+ "Unit Offset should be clamped at 0");
+
+ path_follow_3d->set_unit_offset(1.3);
+ CHECK_MESSAGE(
+ path_follow_3d->get_unit_offset() == 1,
+ "Unit Offset should be clamped at 1");
+
+ memdelete(path);
+}
+
+TEST_CASE("[PathFollow3D] Offset out of range") {
+ const Ref<Curve3D> &curve = memnew(Curve3D());
+ curve->add_point(Vector3(0, 0, 0));
+ curve->add_point(Vector3(100, 0, 0));
+ const Path3D *path = memnew(Path3D);
+ path->set_curve(curve);
+ const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
+ path->add_child(path_follow_3d);
+
+ path_follow_3d->set_loop(true);
+
+ path_follow_3d->set_offset(-50);
+ CHECK_MESSAGE(
+ path_follow_3d->get_offset() == 50,
+ "Offset should loop back from the end in the opposite direction");
+
+ path_follow_3d->set_offset(150);
+ CHECK_MESSAGE(
+ path_follow_3d->get_offset() == 50,
+ "Offset should loop back from the end in the opposite direction");
+
+ path_follow_3d->set_loop(false);
+
+ path_follow_3d->set_offset(-50);
+ CHECK_MESSAGE(
+ path_follow_3d->get_offset() == 0,
+ "Offset should be clamped at 0");
+
+ path_follow_3d->set_offset(150);
+ CHECK_MESSAGE(
+ path_follow_3d->get_offset() == 100,
+ "Offset should be clamped at max value of curve");
+
+ memdelete(path);
+}
+} // namespace TestPathFollow3D
+
+#endif // TEST_PATH_FOLLOW_3D_H
diff --git a/tests/test_physics_2d.cpp b/tests/test_physics_2d.cpp
index 570e1897d6..047697e314 100644
--- a/tests/test_physics_2d.cpp
+++ b/tests/test_physics_2d.cpp
@@ -216,10 +216,10 @@ protected:
if (mm.is_valid()) {
Point2 p = mm->get_position();
- if (mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
ray_to = p;
_do_ray_query();
- } else if (mm->get_button_mask() & BUTTON_MASK_RIGHT) {
+ } else if (mm->get_button_mask() & MOUSE_BUTTON_MASK_RIGHT) {
ray_from = p;
_do_ray_query();
}
diff --git a/tests/test_physics_3d.cpp b/tests/test_physics_3d.cpp
index f991fd7c86..bb324d8ffe 100644
--- a/tests/test_physics_3d.cpp
+++ b/tests/test_physics_3d.cpp
@@ -86,7 +86,9 @@ protected:
PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
RID mesh_instance = vs->instance_create2(type_mesh_map[p_shape], scenario);
- RID body = ps->body_create(p_body, !p_active_default);
+ RID body = ps->body_create();
+ ps->body_set_mode(body, p_body);
+ ps->body_set_state(body, PhysicsServer3D::BODY_STATE_SLEEPING, !p_active_default);
ps->body_set_space(body, space);
ps->body_set_param(body, PhysicsServer3D::BODY_PARAM_BOUNCE, 0.0);
//todo set space
@@ -108,7 +110,9 @@ protected:
RID world_margin_shape = ps->shape_create(PhysicsServer3D::SHAPE_PLANE);
ps->shape_set_data(world_margin_shape, p_plane);
- RID b = ps->body_create(PhysicsServer3D::BODY_MODE_STATIC);
+ RID b = ps->body_create();
+ ps->body_set_mode(b, PhysicsServer3D::BODY_MODE_STATIC);
+
ps->body_set_space(b, space);
//todo set space
ps->body_add_shape(b, world_margin_shape);
@@ -183,8 +187,10 @@ protected:
RenderingServer *vs = RenderingServer::get_singleton();
PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
RID trimesh_shape = ps->shape_create(PhysicsServer3D::SHAPE_CONCAVE_POLYGON);
- ps->shape_set_data(trimesh_shape, p_faces);
- p_faces = ps->shape_get_data(trimesh_shape); // optimized one
+ Dictionary trimesh_params;
+ trimesh_params["faces"] = p_faces;
+ trimesh_params["backface_collision"] = false;
+ ps->shape_set_data(trimesh_shape, trimesh_params);
Vector<Vector3> normals; // for drawing
for (int i = 0; i < p_faces.size() / 3; i++) {
Plane p(p_faces[i * 3 + 0], p_faces[i * 3 + 1], p_faces[i * 3 + 2]);
@@ -202,7 +208,8 @@ protected:
RID triins = vs->instance_create2(trimesh_mesh, scenario);
- RID tribody = ps->body_create(PhysicsServer3D::BODY_MODE_STATIC);
+ RID tribody = ps->body_create();
+ ps->body_set_mode(tribody, PhysicsServer3D::BODY_MODE_STATIC);
ps->body_set_space(tribody, space);
//todo set space
ps->body_add_shape(tribody, trimesh_shape);
@@ -358,7 +365,8 @@ public:
ps->shape_set_data(capsule_shape, capsule_params);
RID mesh_instance = vs->instance_create2(capsule_mesh, scenario);
- character = ps->body_create(PhysicsServer3D::BODY_MODE_CHARACTER);
+ character = ps->body_create();
+ ps->body_set_mode(character, PhysicsServer3D::BODY_MODE_CHARACTER);
ps->body_set_space(character, space);
//todo add space
ps->body_add_shape(character, capsule_shape);
diff --git a/tests/test_render.cpp b/tests/test_render.cpp
index 2a4ae8bd73..72b2840098 100644
--- a/tests/test_render.cpp
+++ b/tests/test_render.cpp
@@ -183,8 +183,8 @@ public:
//vs->light_set_shadow( lightaux, true );
light = vs->instance_create2(lightaux, scenario);
Transform lla;
- //lla.set_look_at(Vector3(),Vector3(1,-1,1),Vector3(0,1,0));
- lla.set_look_at(Vector3(), Vector3(-0.000000, -0.836026, -0.548690), Vector3(0, 1, 0));
+ //lla.set_look_at(Vector3(),Vector3(1, -1, 1));
+ lla.set_look_at(Vector3(), Vector3(0.0, -0.836026, -0.548690));
vs->instance_set_transform(light, lla);
diff --git a/tests/test_resource.h b/tests/test_resource.h
new file mode 100644
index 0000000000..cee3281995
--- /dev/null
+++ b/tests/test_resource.h
@@ -0,0 +1,114 @@
+/*************************************************************************/
+/* test_resource.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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_RESOURCE
+#define TEST_RESOURCE
+
+#include "core/io/resource.h"
+#include "core/io/resource_loader.h"
+#include "core/io/resource_saver.h"
+#include "core/os/os.h"
+
+#include "thirdparty/doctest/doctest.h"
+
+namespace TestResource {
+
+TEST_CASE("[Resource] Duplication") {
+ Ref<Resource> resource = memnew(Resource);
+ resource->set_name("Hello world");
+ Ref<Resource> child_resource = memnew(Resource);
+ child_resource->set_name("I'm a child resource");
+ resource->set_meta("other_resource", child_resource);
+
+ Ref<Resource> resource_dupe = resource->duplicate();
+ const Ref<Resource> &resource_dupe_reference = resource_dupe;
+ resource_dupe->set_name("Changed name");
+ child_resource->set_name("My name was changed too");
+
+ CHECK_MESSAGE(
+ resource_dupe->get_name() == "Changed name",
+ "Duplicated resource should have the new name.");
+ CHECK_MESSAGE(
+ resource_dupe_reference->get_name() == "Changed name",
+ "Reference to the duplicated resource should have the new name.");
+ CHECK_MESSAGE(
+ resource->get_name() == "Hello world",
+ "Original resource name should not be affected after editing the duplicate's name.");
+ CHECK_MESSAGE(
+ Ref<Resource>(resource_dupe->get_meta("other_resource"))->get_name() == "My name was changed too",
+ "Duplicated resource should share its child resource with the original.");
+}
+
+TEST_CASE("[Resource] Saving and loading") {
+ Ref<Resource> resource = memnew(Resource);
+ resource->set_name("Hello world");
+ resource->set_meta(" ExampleMetadata ", Vector2i(40, 80));
+ resource->set_meta("string", "The\nstring\nwith\nunnecessary\nline\n\t\\\nbreaks");
+ Ref<Resource> child_resource = memnew(Resource);
+ child_resource->set_name("I'm a child resource");
+ resource->set_meta("other_resource", child_resource);
+ const String save_path_binary = OS::get_singleton()->get_cache_path().plus_file("resource.res");
+ const String save_path_text = OS::get_singleton()->get_cache_path().plus_file("resource.tres");
+ ResourceSaver::save(save_path_binary, resource);
+ ResourceSaver::save(save_path_text, resource);
+
+ const Ref<Resource> &loaded_resource_binary = ResourceLoader::load(save_path_binary);
+ CHECK_MESSAGE(
+ loaded_resource_binary->get_name() == "Hello world",
+ "The loaded resource name should be equal to the expected value.");
+ CHECK_MESSAGE(
+ loaded_resource_binary->get_meta(" ExampleMetadata ") == Vector2i(40, 80),
+ "The loaded resource metadata should be equal to the expected value.");
+ CHECK_MESSAGE(
+ loaded_resource_binary->get_meta("string") == "The\nstring\nwith\nunnecessary\nline\n\t\\\nbreaks",
+ "The loaded resource metadata should be equal to the expected value.");
+ const Ref<Resource> &loaded_child_resource_binary = loaded_resource_binary->get_meta("other_resource");
+ CHECK_MESSAGE(
+ loaded_child_resource_binary->get_name() == "I'm a child resource",
+ "The loaded child resource name should be equal to the expected value.");
+
+ const Ref<Resource> &loaded_resource_text = ResourceLoader::load(save_path_text);
+ CHECK_MESSAGE(
+ loaded_resource_text->get_name() == "Hello world",
+ "The loaded resource name should be equal to the expected value.");
+ CHECK_MESSAGE(
+ loaded_resource_text->get_meta(" ExampleMetadata ") == Vector2i(40, 80),
+ "The loaded resource metadata should be equal to the expected value.");
+ CHECK_MESSAGE(
+ loaded_resource_text->get_meta("string") == "The\nstring\nwith\nunnecessary\nline\n\t\\\nbreaks",
+ "The loaded resource metadata should be equal to the expected value.");
+ const Ref<Resource> &loaded_child_resource_text = loaded_resource_text->get_meta("other_resource");
+ CHECK_MESSAGE(
+ loaded_child_resource_text->get_name() == "I'm a child resource",
+ "The loaded child resource name should be equal to the expected value.");
+}
+} // namespace TestResource
+
+#endif // TEST_RESOURCE
diff --git a/tests/test_string.h b/tests/test_string.h
index cc3152203e..6febf22765 100644
--- a/tests/test_string.h
+++ b/tests/test_string.h
@@ -1166,6 +1166,52 @@ TEST_CASE("[String] xml_escape/unescape") {
CHECK(s.xml_escape(false).xml_unescape() == s);
}
+TEST_CASE("[String] xml_unescape") {
+ // Named entities
+ String input = "&quot;&amp;&apos;&lt;&gt;";
+ CHECK(input.xml_unescape() == "\"&\'<>");
+
+ // Numeric entities
+ input = "&#x41;&#66;";
+ CHECK(input.xml_unescape() == "AB");
+
+ input = "&#0;&x#0;More text";
+ String result = input.xml_unescape();
+ // Didn't put in a leading NUL and terminate the string
+ CHECK(input.length() > 0);
+ CHECK(input[0] != '\0');
+ // Entity should be left as-is if invalid
+ CHECK(input.xml_unescape() == input);
+
+ // Check near char32_t range
+ input = "&#xFFFFFFFF;";
+ result = input.xml_unescape();
+ CHECK(result.length() == 1);
+ CHECK(result[0] == 0xFFFFFFFF);
+ input = "&#4294967295;";
+ result = input.xml_unescape();
+ CHECK(result.length() == 1);
+ CHECK(result[0] == 0xFFFFFFFF);
+
+ // Check out of range of char32_t
+ input = "&#xFFFFFFFFF;";
+ CHECK(input.xml_unescape() == input);
+ input = "&#4294967296;";
+ CHECK(input.xml_unescape() == input);
+
+ // Shouldn't consume without ending in a ';'
+ input = "&#66";
+ CHECK(input.xml_unescape() == input);
+ input = "&#x41";
+ CHECK(input.xml_unescape() == input);
+
+ // Invalid characters should make the entity ignored
+ input = "&#x41SomeIrrelevantText;";
+ CHECK(input.xml_unescape() == input);
+ input = "&#66SomeIrrelevantText;";
+ CHECK(input.xml_unescape() == input);
+}
+
TEST_CASE("[String] Strip escapes") {
String s = "\t\tTest Test\r\n Test";
CHECK(s.strip_escapes() == "Test Test Test");
@@ -1272,6 +1318,20 @@ TEST_CASE("[String] humanize_size") {
CHECK(String::humanize_size(100523550) == "95.86 MiB");
CHECK(String::humanize_size(5345555000) == "4.97 GiB");
}
+
+TEST_CASE("[String] validate_node_name") {
+ String numeric_only = "12345";
+ CHECK(numeric_only.validate_node_name() == "12345");
+
+ String name_with_spaces = "Name with spaces";
+ CHECK(name_with_spaces.validate_node_name() == "Name with spaces");
+
+ String name_with_kana = "Name with kana ゴドツ";
+ CHECK(name_with_kana.validate_node_name() == "Name with kana ゴドツ");
+
+ String name_with_invalid_chars = "Name with invalid characters :.@removed!";
+ CHECK(name_with_invalid_chars.validate_node_name() == "Name with invalid characters removed!");
+}
} // namespace TestString
#endif // TEST_STRING_H
diff --git a/tests/test_text_server.h b/tests/test_text_server.h
index b0b40447fe..3d700f8ec4 100644
--- a/tests/test_text_server.h
+++ b/tests/test_text_server.h
@@ -28,6 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifdef TOOLS_ENABLED
+
#ifndef TEST_TEXT_SERVER_H
#define TEST_TEXT_SERVER_H
@@ -247,3 +249,4 @@ TEST_SUITE("[[TextServer]") {
}; // namespace TestTextServer
#endif // TEST_TEXT_SERVER_H
+#endif // TOOLS_ENABLED
diff --git a/tests/test_variant.h b/tests/test_variant.h
index f8fa852bf4..dfc72b512c 100644
--- a/tests/test_variant.h
+++ b/tests/test_variant.h
@@ -105,6 +105,600 @@ TEST_CASE("[Variant] Writer and parser float") {
CHECK_MESSAGE(b64_float_parsed == 340282001837565597733306976381245063168.0, "Should not overflow.");
}
+
+TEST_CASE("[Variant] Assignment To Bool from Int,Float,String,Vec2,Vec2i,Vec3,Vec3i and Color") {
+ Variant int_v = 0;
+ Variant bool_v = true;
+ int_v = bool_v; // int_v is now a bool
+ CHECK(int_v == Variant(true));
+ bool_v = false;
+ int_v = bool_v;
+ CHECK(int_v.get_type() == Variant::BOOL);
+
+ Variant float_v = 0.0f;
+ bool_v = true;
+ float_v = bool_v;
+ CHECK(float_v == Variant(true));
+ bool_v = false;
+ float_v = bool_v;
+ CHECK(float_v.get_type() == Variant::BOOL);
+
+ Variant string_v = "";
+ bool_v = true;
+ string_v = bool_v;
+ CHECK(string_v == Variant(true));
+ bool_v = false;
+ string_v = bool_v;
+ CHECK(string_v.get_type() == Variant::BOOL);
+
+ Variant vec2_v = Vector2(0, 0);
+ bool_v = true;
+ vec2_v = bool_v;
+ CHECK(vec2_v == Variant(true));
+ bool_v = false;
+ vec2_v = bool_v;
+ CHECK(vec2_v.get_type() == Variant::BOOL);
+
+ Variant vec2i_v = Vector2i(0, 0);
+ bool_v = true;
+ vec2i_v = bool_v;
+ CHECK(vec2i_v == Variant(true));
+ bool_v = false;
+ vec2i_v = bool_v;
+ CHECK(vec2i_v.get_type() == Variant::BOOL);
+
+ Variant vec3_v = Vector3(0, 0, 0);
+ bool_v = true;
+ vec3_v = bool_v;
+ CHECK(vec3_v == Variant(true));
+ bool_v = false;
+ vec3_v = bool_v;
+ CHECK(vec3_v.get_type() == Variant::BOOL);
+
+ Variant vec3i_v = Vector3i(0, 0, 0);
+ bool_v = true;
+ vec3i_v = bool_v;
+ CHECK(vec3i_v == Variant(true));
+ bool_v = false;
+ vec3i_v = bool_v;
+ CHECK(vec3i_v.get_type() == Variant::BOOL);
+
+ Variant col_v = Color(0.5f, 0.2f, 0.75f);
+ bool_v = true;
+ col_v = bool_v;
+ CHECK(col_v == Variant(true));
+ bool_v = false;
+ col_v = bool_v;
+ CHECK(col_v.get_type() == Variant::BOOL);
+}
+
+TEST_CASE("[Variant] Assignment To Int from Bool,Float,String,Vec2,Vec2i,Vec3,Vec3i and Color") {
+ Variant bool_v = false;
+ Variant int_v = 2;
+ bool_v = int_v; // Now bool_v is int
+ CHECK(bool_v == Variant(2));
+ int_v = -3;
+ bool_v = int_v;
+ CHECK(bool_v.get_type() == Variant::INT);
+
+ Variant float_v = 0.0f;
+ int_v = 2;
+ float_v = int_v;
+ CHECK(float_v == Variant(2));
+ int_v = -3;
+ float_v = int_v;
+ CHECK(float_v.get_type() == Variant::INT);
+
+ Variant string_v = "";
+ int_v = 2;
+ string_v = int_v;
+ CHECK(string_v == Variant(2));
+ int_v = -3;
+ string_v = int_v;
+ CHECK(string_v.get_type() == Variant::INT);
+
+ Variant vec2_v = Vector2(0, 0);
+ int_v = 2;
+ vec2_v = int_v;
+ CHECK(vec2_v == Variant(2));
+ int_v = -3;
+ vec2_v = int_v;
+ CHECK(vec2_v.get_type() == Variant::INT);
+
+ Variant vec2i_v = Vector2i(0, 0);
+ int_v = 2;
+ vec2i_v = int_v;
+ CHECK(vec2i_v == Variant(2));
+ int_v = -3;
+ vec2i_v = int_v;
+ CHECK(vec2i_v.get_type() == Variant::INT);
+
+ Variant vec3_v = Vector3(0, 0, 0);
+ int_v = 2;
+ vec3_v = int_v;
+ CHECK(vec3_v == Variant(2));
+ int_v = -3;
+ vec3_v = int_v;
+ CHECK(vec3_v.get_type() == Variant::INT);
+
+ Variant vec3i_v = Vector3i(0, 0, 0);
+ int_v = 2;
+ vec3i_v = int_v;
+ CHECK(vec3i_v == Variant(2));
+ int_v = -3;
+ vec3i_v = int_v;
+ CHECK(vec3i_v.get_type() == Variant::INT);
+
+ Variant col_v = Color(0.5f, 0.2f, 0.75f);
+ int_v = 2;
+ col_v = int_v;
+ CHECK(col_v == Variant(2));
+ int_v = -3;
+ col_v = int_v;
+ CHECK(col_v.get_type() == Variant::INT);
+}
+
+TEST_CASE("[Variant] Assignment To Float from Bool,Int,String,Vec2,Vec2i,Vec3,Vec3i and Color") {
+ Variant bool_v = false;
+ Variant float_v = 1.5f;
+ bool_v = float_v; // Now bool_v is float
+ CHECK(bool_v == Variant(1.5f));
+ float_v = -4.6f;
+ bool_v = float_v;
+ CHECK(bool_v.get_type() == Variant::FLOAT);
+
+ Variant int_v = 1;
+ float_v = 1.5f;
+ int_v = float_v;
+ CHECK(int_v == Variant(1.5f));
+ float_v = -4.6f;
+ int_v = float_v;
+ CHECK(int_v.get_type() == Variant::FLOAT);
+
+ Variant string_v = "";
+ float_v = 1.5f;
+ string_v = float_v;
+ CHECK(string_v == Variant(1.5f));
+ float_v = -4.6f;
+ string_v = float_v;
+ CHECK(string_v.get_type() == Variant::FLOAT);
+
+ Variant vec2_v = Vector2(0, 0);
+ float_v = 1.5f;
+ vec2_v = float_v;
+ CHECK(vec2_v == Variant(1.5f));
+ float_v = -4.6f;
+ vec2_v = float_v;
+ CHECK(vec2_v.get_type() == Variant::FLOAT);
+
+ Variant vec2i_v = Vector2i(0, 0);
+ float_v = 1.5f;
+ vec2i_v = float_v;
+ CHECK(vec2i_v == Variant(1.5f));
+ float_v = -4.6f;
+ vec2i_v = float_v;
+ CHECK(vec2i_v.get_type() == Variant::FLOAT);
+
+ Variant vec3_v = Vector3(0, 0, 0);
+ float_v = 1.5f;
+ vec3_v = float_v;
+ CHECK(vec3_v == Variant(1.5f));
+ float_v = -4.6f;
+ vec3_v = float_v;
+ CHECK(vec3_v.get_type() == Variant::FLOAT);
+
+ Variant vec3i_v = Vector3i(0, 0, 0);
+ float_v = 1.5f;
+ vec3i_v = float_v;
+ CHECK(vec3i_v == Variant(1.5f));
+ float_v = -4.6f;
+ vec3i_v = float_v;
+ CHECK(vec3i_v.get_type() == Variant::FLOAT);
+
+ Variant col_v = Color(0.5f, 0.2f, 0.75f);
+ float_v = 1.5f;
+ col_v = float_v;
+ CHECK(col_v == Variant(1.5f));
+ float_v = -4.6f;
+ col_v = float_v;
+ CHECK(col_v.get_type() == Variant::FLOAT);
+}
+
+TEST_CASE("[Variant] Assignment To String from Bool,Int,Float,Vec2,Vec2i,Vec3,Vec3i and Color") {
+ Variant bool_v = false;
+ Variant string_v = "Hello";
+ bool_v = string_v; // Now bool_v is string
+ CHECK(bool_v == Variant("Hello"));
+ string_v = "Hello there";
+ bool_v = string_v;
+ CHECK(bool_v.get_type() == Variant::STRING);
+
+ Variant int_v = 0;
+ string_v = "Hello";
+ int_v = string_v;
+ CHECK(int_v == Variant("Hello"));
+ string_v = "Hello there";
+ int_v = string_v;
+ CHECK(int_v.get_type() == Variant::STRING);
+
+ Variant float_v = 0.0f;
+ string_v = "Hello";
+ float_v = string_v;
+ CHECK(float_v == Variant("Hello"));
+ string_v = "Hello there";
+ float_v = string_v;
+ CHECK(float_v.get_type() == Variant::STRING);
+
+ Variant vec2_v = Vector2(0, 0);
+ string_v = "Hello";
+ vec2_v = string_v;
+ CHECK(vec2_v == Variant("Hello"));
+ string_v = "Hello there";
+ vec2_v = string_v;
+ CHECK(vec2_v.get_type() == Variant::STRING);
+
+ Variant vec2i_v = Vector2i(0, 0);
+ string_v = "Hello";
+ vec2i_v = string_v;
+ CHECK(vec2i_v == Variant("Hello"));
+ string_v = "Hello there";
+ vec2i_v = string_v;
+ CHECK(vec2i_v.get_type() == Variant::STRING);
+
+ Variant vec3_v = Vector3(0, 0, 0);
+ string_v = "Hello";
+ vec3_v = string_v;
+ CHECK(vec3_v == Variant("Hello"));
+ string_v = "Hello there";
+ vec3_v = string_v;
+ CHECK(vec3_v.get_type() == Variant::STRING);
+
+ Variant vec3i_v = Vector3i(0, 0, 0);
+ string_v = "Hello";
+ vec3i_v = string_v;
+ CHECK(vec3i_v == Variant("Hello"));
+ string_v = "Hello there";
+ vec3i_v = string_v;
+ CHECK(vec3i_v.get_type() == Variant::STRING);
+
+ Variant col_v = Color(0.5f, 0.2f, 0.75f);
+ string_v = "Hello";
+ col_v = string_v;
+ CHECK(col_v == Variant("Hello"));
+ string_v = "Hello there";
+ col_v = string_v;
+ CHECK(col_v.get_type() == Variant::STRING);
+}
+
+TEST_CASE("[Variant] Assignment To Vec2 from Bool,Int,Float,String,Vec2i,Vec3,Vec3i and Color") {
+ Variant bool_v = false;
+ Variant vec2_v = Vector2(2.2f, 3.5f);
+ bool_v = vec2_v; // Now bool_v is Vector2
+ CHECK(bool_v == Variant(Vector2(2.2f, 3.5f)));
+ vec2_v = Vector2(-5.4f, -7.9f);
+ bool_v = vec2_v;
+ CHECK(bool_v.get_type() == Variant::VECTOR2);
+
+ Variant int_v = 0;
+ vec2_v = Vector2(2.2f, 3.5f);
+ int_v = vec2_v;
+ CHECK(int_v == Variant(Vector2(2.2f, 3.5f)));
+ vec2_v = Vector2(-5.4f, -7.9f);
+ int_v = vec2_v;
+ CHECK(int_v.get_type() == Variant::VECTOR2);
+
+ Variant float_v = 0.0f;
+ vec2_v = Vector2(2.2f, 3.5f);
+ float_v = vec2_v;
+ CHECK(float_v == Variant(Vector2(2.2f, 3.5f)));
+ vec2_v = Vector2(-5.4f, -7.9f);
+ float_v = vec2_v;
+ CHECK(float_v.get_type() == Variant::VECTOR2);
+
+ Variant string_v = "";
+ vec2_v = Vector2(2.2f, 3.5f);
+ string_v = vec2_v;
+ CHECK(string_v == Variant(Vector2(2.2f, 3.5f)));
+ vec2_v = Vector2(-5.4f, -7.9f);
+ string_v = vec2_v;
+ CHECK(string_v.get_type() == Variant::VECTOR2);
+
+ Variant vec2i_v = Vector2i(0, 0);
+ vec2_v = Vector2(2.2f, 3.5f);
+ vec2i_v = vec2_v;
+ CHECK(vec2i_v == Variant(Vector2(2.2f, 3.5f)));
+ vec2_v = Vector2(-5.4f, -7.9f);
+ vec2i_v = vec2_v;
+ CHECK(vec2i_v.get_type() == Variant::VECTOR2);
+
+ Variant vec3_v = Vector3(0, 0, 0);
+ vec2_v = Vector2(2.2f, 3.5f);
+ vec3_v = vec2_v;
+ CHECK(vec3_v == Variant(Vector2(2.2f, 3.5f)));
+ vec2_v = Vector2(-5.4f, -7.9f);
+ vec3_v = vec2_v;
+ CHECK(vec3_v.get_type() == Variant::VECTOR2);
+
+ Variant vec3i_v = Vector3i(0, 0, 0);
+ vec2_v = Vector2(2.2f, 3.5f);
+ vec3i_v = vec2_v;
+ CHECK(vec3i_v == Variant(Vector2(2.2f, 3.5f)));
+ vec2_v = Vector2(-5.4f, -7.9f);
+ vec3i_v = vec2_v;
+ CHECK(vec3i_v.get_type() == Variant::VECTOR2);
+
+ Variant col_v = Color(0.5f, 0.2f, 0.75f);
+ vec2_v = Vector2(2.2f, 3.5f);
+ col_v = vec2_v;
+ CHECK(col_v == Variant(Vector2(2.2f, 3.5f)));
+ vec2_v = Vector2(-5.4f, -7.9f);
+ col_v = vec2_v;
+ CHECK(col_v.get_type() == Variant::VECTOR2);
+}
+
+TEST_CASE("[Variant] Assignment To Vec2i from Bool,Int,Float,String,Vec2,Vec3,Vec3i and Color") {
+ Variant bool_v = false;
+ Variant vec2i_v = Vector2i(2, 3);
+ bool_v = vec2i_v; // Now bool_v is Vector2i
+ CHECK(bool_v == Variant(Vector2i(2, 3)));
+ vec2i_v = Vector2i(-5, -7);
+ bool_v = vec2i_v;
+ CHECK(bool_v.get_type() == Variant::VECTOR2I);
+
+ Variant int_v = 0;
+ vec2i_v = Vector2i(2, 3);
+ int_v = vec2i_v;
+ CHECK(int_v == Variant(Vector2i(2, 3)));
+ vec2i_v = Vector2i(-5, -7);
+ int_v = vec2i_v;
+ CHECK(int_v.get_type() == Variant::VECTOR2I);
+
+ Variant float_v = 0.0f;
+ vec2i_v = Vector2i(2, 3);
+ float_v = vec2i_v;
+ CHECK(float_v == Variant(Vector2i(2, 3)));
+ vec2i_v = Vector2i(-5, -7);
+ float_v = vec2i_v;
+ CHECK(float_v.get_type() == Variant::VECTOR2I);
+
+ Variant string_v = "";
+ vec2i_v = Vector2i(2, 3);
+ string_v = vec2i_v;
+ CHECK(string_v == Variant(Vector2i(2, 3)));
+ vec2i_v = Vector2i(-5, -7);
+ string_v = vec2i_v;
+ CHECK(string_v.get_type() == Variant::VECTOR2I);
+
+ Variant vec2_v = Vector2(0, 0);
+ vec2i_v = Vector2i(2, 3);
+ vec2_v = vec2i_v;
+ CHECK(vec2_v == Variant(Vector2i(2, 3)));
+ vec2i_v = Vector2i(-5, -7);
+ vec2_v = vec2i_v;
+ CHECK(vec2i_v.get_type() == Variant::VECTOR2I);
+
+ Variant vec3_v = Vector3(0, 0, 0);
+ vec2i_v = Vector2i(2, 3);
+ vec3_v = vec2i_v;
+ CHECK(vec3_v == Variant(Vector2i(2, 3)));
+ vec2i_v = Vector2i(-5, -7);
+ vec3_v = vec2i_v;
+ CHECK(vec3_v.get_type() == Variant::VECTOR2I);
+
+ Variant vec3i_v = Vector3i(0, 0, 0);
+ vec2i_v = Vector2i(2, 3);
+ vec3i_v = vec2i_v;
+ CHECK(vec3i_v == Variant(Vector2i(2, 3)));
+ vec2i_v = Vector2i(-5, -7);
+ vec3i_v = vec2i_v;
+ CHECK(vec3i_v.get_type() == Variant::VECTOR2I);
+
+ Variant col_v = Color(0.5f, 0.2f, 0.75f);
+ vec2i_v = Vector2i(2, 3);
+ col_v = vec2i_v;
+ CHECK(col_v == Variant(Vector2i(2, 3)));
+ vec2i_v = Vector2i(-5, -7);
+ col_v = vec2i_v;
+ CHECK(col_v.get_type() == Variant::VECTOR2I);
+}
+
+TEST_CASE("[Variant] Assignment To Vec3 from Bool,Int,Float,String,Vec2,Vec2i,Vec3i and Color") {
+ Variant bool_v = false;
+ Variant vec3_v = Vector3(2.2f, 3.5f, 5.3f);
+ bool_v = vec3_v; // Now bool_v is Vector3
+ CHECK(bool_v == Variant(Vector3(2.2f, 3.5f, 5.3f)));
+ vec3_v = Vector3(-5.4f, -7.9f, -2.1f);
+ bool_v = vec3_v;
+ CHECK(bool_v.get_type() == Variant::VECTOR3);
+
+ Variant int_v = 0;
+ vec3_v = Vector3(2.2f, 3.5f, 5.3f);
+ int_v = vec3_v;
+ CHECK(int_v == Variant(Vector3(2.2f, 3.5f, 5.3f)));
+ vec3_v = Vector3(-5.4f, -7.9f, -2.1f);
+ int_v = vec3_v;
+ CHECK(int_v.get_type() == Variant::VECTOR3);
+
+ Variant float_v = 0.0f;
+ vec3_v = Vector3(2.2f, 3.5f, 5.3f);
+ float_v = vec3_v;
+ CHECK(float_v == Variant(Vector3(2.2f, 3.5f, 5.3f)));
+ vec3_v = Vector3(-5.4f, -7.9f, -2.1f);
+ float_v = vec3_v;
+ CHECK(float_v.get_type() == Variant::VECTOR3);
+
+ Variant string_v = "";
+ vec3_v = Vector3(2.2f, 3.5f, 5.3f);
+ string_v = vec3_v;
+ CHECK(string_v == Variant(Vector3(2.2f, 3.5f, 5.3f)));
+ vec3_v = Vector3(-5.4f, -7.9f, -2.1f);
+ string_v = vec3_v;
+ CHECK(string_v.get_type() == Variant::VECTOR3);
+
+ Variant vec2_v = Vector2(0, 0);
+ vec3_v = Vector3(2.2f, 3.5f, 5.3f);
+ vec2_v = vec3_v;
+ CHECK(vec2_v == Variant(Vector3(2.2f, 3.5f, 5.3f)));
+ vec3_v = Vector3(-5.4f, -7.9f, -2.1f);
+ vec2_v = vec3_v;
+ CHECK(vec2_v.get_type() == Variant::VECTOR3);
+
+ Variant vec2i_v = Vector2i(0, 0);
+ vec3_v = Vector3(2.2f, 3.5f, 5.3f);
+ vec2i_v = vec3_v;
+ CHECK(vec2i_v == Variant(Vector3(2.2f, 3.5f, 5.3f)));
+ vec3_v = Vector3(-5.4f, -7.9f, -2.1f);
+ vec2i_v = vec3_v;
+ CHECK(vec2i_v.get_type() == Variant::VECTOR3);
+
+ Variant vec3i_v = Vector3i(0, 0, 0);
+ vec3_v = Vector3(2.2f, 3.5f, 5.3f);
+ vec3i_v = vec3_v;
+ CHECK(vec3i_v == Variant(Vector3(2.2f, 3.5f, 5.3f)));
+ vec3_v = Vector3(-5.4f, -7.9f, -2.1f);
+ vec3i_v = vec3_v;
+ CHECK(vec3i_v.get_type() == Variant::VECTOR3);
+
+ Variant col_v = Color(0.5f, 0.2f, 0.75f);
+ vec3_v = Vector3(2.2f, 3.5f, 5.3f);
+ col_v = vec3_v;
+ CHECK(col_v == Variant(Vector3(2.2f, 3.5f, 5.3f)));
+ vec3_v = Vector3(-5.4f, -7.9f, -2.1f);
+ col_v = vec3_v;
+ CHECK(col_v.get_type() == Variant::VECTOR3);
+}
+
+TEST_CASE("[Variant] Assignment To Vec3i from Bool,Int,Float,String,Vec2,Vec2i,Vec3 and Color") {
+ Variant bool_v = false;
+ Variant vec3i_v = Vector3i(2, 3, 5);
+ bool_v = vec3i_v; // Now bool_v is Vector3i
+ CHECK(bool_v == Variant(Vector3i(2, 3, 5)));
+ vec3i_v = Vector3i(-5, -7, -2);
+ bool_v = vec3i_v;
+ CHECK(bool_v.get_type() == Variant::VECTOR3I);
+
+ Variant int_v = 0;
+ vec3i_v = Vector3i(2, 3, 5);
+ int_v = vec3i_v;
+ CHECK(int_v == Variant(Vector3i(2, 3, 5)));
+ vec3i_v = Vector3i(-5, -7, -2);
+ int_v = vec3i_v;
+ CHECK(int_v.get_type() == Variant::VECTOR3I);
+
+ Variant float_v = 0.0f;
+ vec3i_v = Vector3i(2, 3, 5);
+ float_v = vec3i_v;
+ CHECK(float_v == Variant(Vector3i(2, 3, 5)));
+ vec3i_v = Vector3i(-5, -7, -2);
+ float_v = vec3i_v;
+ CHECK(float_v.get_type() == Variant::VECTOR3I);
+
+ Variant string_v = "";
+ vec3i_v = Vector3i(2, 3, 5);
+ string_v = vec3i_v;
+ CHECK(string_v == Variant(Vector3i(2, 3, 5)));
+ vec3i_v = Vector3i(-5, -7, -2);
+ string_v = vec3i_v;
+ CHECK(string_v.get_type() == Variant::VECTOR3I);
+
+ Variant vec2_v = Vector2(0, 0);
+ vec3i_v = Vector3i(2, 3, 5);
+ vec2_v = vec3i_v;
+ CHECK(vec2_v == Variant(Vector3i(2, 3, 5)));
+ vec3i_v = Vector3i(-5, -7, -2);
+ vec2_v = vec3i_v;
+ CHECK(vec2_v.get_type() == Variant::VECTOR3I);
+
+ Variant vec2i_v = Vector2i(0, 0);
+ vec3i_v = Vector3i(2, 3, 5);
+ vec2i_v = vec3i_v;
+ CHECK(vec2i_v == Variant(Vector3i(2, 3, 5)));
+ vec3i_v = Vector3i(-5, -7, -2);
+ vec2i_v = vec3i_v;
+ CHECK(vec2i_v.get_type() == Variant::VECTOR3I);
+
+ Variant vec3_v = Vector3(0, 0, 0);
+ vec3i_v = Vector3i(2, 3, 5);
+ vec3_v = vec3i_v;
+ CHECK(vec3_v == Variant(Vector3i(2, 3, 5)));
+ vec3i_v = Vector3i(-5, -7, -2);
+ vec3_v = vec3i_v;
+ CHECK(vec3_v.get_type() == Variant::VECTOR3I);
+
+ Variant col_v = Color(0.5f, 0.2f, 0.75f);
+ vec3i_v = Vector3i(2, 3, 5);
+ col_v = vec3i_v;
+ CHECK(col_v == Variant(Vector3i(2, 3, 5)));
+ vec3i_v = Vector3i(-5, -7, -2);
+ col_v = vec3i_v;
+ CHECK(col_v.get_type() == Variant::VECTOR3I);
+}
+
+TEST_CASE("[Variant] Assignment To Color from Bool,Int,Float,String,Vec2,Vec2i,Vec3 and Vec3i") {
+ Variant bool_v = false;
+ Variant col_v = Color(0.25f, 0.4f, 0.78f);
+ bool_v = col_v; // Now bool_v is Color
+ CHECK(bool_v == Variant(Color(0.25f, 0.4f, 0.78f)));
+ col_v = Color(0.33f, 0.75f, 0.21f);
+ bool_v = col_v;
+ CHECK(bool_v.get_type() == Variant::COLOR);
+
+ Variant int_v = 0;
+ col_v = Color(0.25f, 0.4f, 0.78f);
+ int_v = col_v;
+ CHECK(int_v == Variant(Color(0.25f, 0.4f, 0.78f)));
+ col_v = Color(0.33f, 0.75f, 0.21f);
+ int_v = col_v;
+ CHECK(int_v.get_type() == Variant::COLOR);
+
+ Variant float_v = 0.0f;
+ col_v = Color(0.25f, 0.4f, 0.78f);
+ float_v = col_v;
+ CHECK(float_v == Variant(Color(0.25f, 0.4f, 0.78f)));
+ col_v = Color(0.33f, 0.75f, 0.21f);
+ float_v = col_v;
+ CHECK(float_v.get_type() == Variant::COLOR);
+
+ Variant string_v = "";
+ col_v = Color(0.25f, 0.4f, 0.78f);
+ string_v = col_v;
+ CHECK(string_v == Variant(Color(0.25f, 0.4f, 0.78f)));
+ col_v = Color(0.33f, 0.75f, 0.21f);
+ string_v = col_v;
+ CHECK(string_v.get_type() == Variant::COLOR);
+
+ Variant vec2_v = Vector2(0, 0);
+ col_v = Color(0.25f, 0.4f, 0.78f);
+ vec2_v = col_v;
+ CHECK(vec2_v == Variant(Color(0.25f, 0.4f, 0.78f)));
+ col_v = Color(0.33f, 0.75f, 0.21f);
+ vec2_v = col_v;
+ CHECK(vec2_v.get_type() == Variant::COLOR);
+
+ Variant vec2i_v = Vector2i(0, 0);
+ col_v = Color(0.25f, 0.4f, 0.78f);
+ vec2i_v = col_v;
+ CHECK(vec2i_v == Variant(Color(0.25f, 0.4f, 0.78f)));
+ col_v = Color(0.33f, 0.75f, 0.21f);
+ vec2i_v = col_v;
+ CHECK(vec2i_v.get_type() == Variant::COLOR);
+
+ Variant vec3_v = Vector3(0, 0, 0);
+ col_v = Color(0.25f, 0.4f, 0.78f);
+ vec3_v = col_v;
+ CHECK(vec3_v == Variant(Color(0.25f, 0.4f, 0.78f)));
+ col_v = Color(0.33f, 0.75f, 0.21f);
+ vec3_v = col_v;
+ CHECK(vec3_v.get_type() == Variant::COLOR);
+
+ Variant vec3i_v = Vector3i(0, 0, 0);
+ col_v = Color(0.25f, 0.4f, 0.78f);
+ vec3i_v = col_v;
+ CHECK(vec3i_v == Variant(Color(0.25f, 0.4f, 0.78f)));
+ col_v = Color(0.33f, 0.75f, 0.21f);
+ vec3i_v = col_v;
+ CHECK(vec3i_v.get_type() == Variant::COLOR);
+}
} // namespace TestVariant
#endif // TEST_VARIANT_H
diff --git a/modules/mono/editor/script_class_parser.h b/tests/test_xml_parser.h
index 75a46bb4e5..55de048d6a 100644
--- a/modules/mono/editor/script_class_parser.h
+++ b/tests/test_xml_parser.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* script_class_parser.h */
+/* test_xml_parser.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,81 +28,47 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SCRIPT_CLASS_PARSER_H
-#define SCRIPT_CLASS_PARSER_H
+#ifndef TEST_XML_PARSER_H
+#define TEST_XML_PARSER_H
-#include "core/string/ustring.h"
-#include "core/templates/vector.h"
-#include "core/variant/variant.h"
-
-class ScriptClassParser {
-public:
- struct NameDecl {
- enum Type {
- NAMESPACE_DECL,
- CLASS_DECL,
- STRUCT_DECL
- };
-
- String name;
- Type type = NAMESPACE_DECL;
- };
+#include <inttypes.h>
- struct ClassDecl {
- String name;
- String namespace_;
- Vector<String> base;
- bool nested = false;
- };
-
-private:
- String code;
- int idx = 0;
- int line = 0;
- String error_str;
- bool error = false;
- Variant value;
-
- Vector<ClassDecl> classes;
+#include "core/io/xml_parser.h"
+#include "core/string/ustring.h"
- enum Token {
- TK_BRACKET_OPEN,
- TK_BRACKET_CLOSE,
- TK_CURLY_BRACKET_OPEN,
- TK_CURLY_BRACKET_CLOSE,
- TK_PERIOD,
- TK_COLON,
- TK_COMMA,
- TK_SYMBOL,
- TK_IDENTIFIER,
- TK_STRING,
- TK_NUMBER,
- TK_OP_LESS,
- TK_OP_GREATER,
- TK_EOF,
- TK_ERROR,
- TK_MAX
- };
+#include "tests/test_macros.h"
- static const char *token_names[TK_MAX];
- static String get_token_name(Token p_token);
+namespace TestXMLParser {
+TEST_CASE("[XMLParser] End-to-end") {
+ String source = "<?xml version = \"1.0\" encoding=\"UTF-8\" ?>\
+<top attr=\"attr value\">\
+ Text&lt;&#65;&#x42;&gt;\
+</top>";
+ Vector<uint8_t> buff = source.to_utf8_buffer();
- Token get_token();
+ XMLParser parser;
+ parser.open_buffer(buff);
- Error _skip_generic_type_params();
+ // <?xml ...?> gets parsed as NODE_UNKNOWN
+ CHECK(parser.read() == OK);
+ CHECK(parser.get_node_type() == XMLParser::NodeType::NODE_UNKNOWN);
- Error _parse_type_full_name(String &r_full_name);
- Error _parse_class_base(Vector<String> &r_base);
- Error _parse_type_constraints();
- Error _parse_namespace_name(String &r_name, int &r_curly_stack);
+ CHECK(parser.read() == OK);
+ CHECK(parser.get_node_type() == XMLParser::NodeType::NODE_ELEMENT);
+ CHECK(parser.get_node_name() == "top");
+ CHECK(parser.has_attribute("attr"));
+ CHECK(parser.get_attribute_value("attr") == "attr value");
-public:
- Error parse(const String &p_code);
- Error parse_file(const String &p_filepath);
+ CHECK(parser.read() == OK);
+ CHECK(parser.get_node_type() == XMLParser::NodeType::NODE_TEXT);
+ CHECK(parser.get_node_data().lstrip(" \t") == "Text<AB>");
- String get_error();
+ CHECK(parser.read() == OK);
+ CHECK(parser.get_node_type() == XMLParser::NodeType::NODE_ELEMENT_END);
+ CHECK(parser.get_node_name() == "top");
- Vector<ClassDecl> get_classes();
-};
+ parser.close();
+}
+} // namespace TestXMLParser
-#endif // SCRIPT_CLASS_PARSER_H
+#endif // TEST_XML_PARSER_H
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 3803e87fea..b05f074bd6 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -174,7 +174,7 @@ Files extracted from upstream source:
## harfbuzz
- Upstream: https://github.com/harfbuzz/harfbuzz
-- Version: 2.7.4 (7236c7e29cef1c2d76c7a284c5081ff4d3aa1127, 2020)
+- Version: 2.8.0 (03538e872a0610a65fad692b33d3646f387cf578, 2021)
- License: MIT
Files extracted from upstream source:
@@ -324,7 +324,7 @@ changes are marked with `// -- GODOT --` comments.
## mbedtls
- Upstream: https://tls.mbed.org/
-- Version: 2.16.9 (3fac0bae4a50113989b3d015cd2d948f51a6d9ac, 2020)
+- Version: 2.16.10 (d61fa61bef06b64132e3490543c81b8ee40fbee3, 2021)
- License: Apache 2.0
File extracted from upstream release tarball:
@@ -355,18 +355,20 @@ Files extracted from upstream repository:
## miniupnpc
-- Upstream: https://github.com/miniupnp/miniupnp/tree/master/miniupnpc
-- Version: git (44366328661826603982d1e0d7ebb4062c5f2bfc, 2020)
+- Upstream: https://github.com/miniupnp/miniupnp
+- Version: 2.2.2 (81029a860baf1f727903e5b85307903b3f40cbc8, 2021)
- License: BSD-3-Clause
Files extracted from upstream source:
- All `*.c` and `*.h` files from `miniupnpc` to `thirdparty/miniupnpc/miniupnpc`
-- Remove `test*`, `minihttptestserver.c` and `wingenminiupnpcstrings.c`
+- Remove the following test or sample files:
+ `listdevices.c minihttptestserver.c miniupnpcmodule.c upnpc.c upnperrors.* test* wingenminiupnpcstrings.c`
+- `LICENSE`
-The patch `windows_fix.diff` is applied to `minissdpc.c` to fix an upstream issue.
-The only modified file is miniupnpcstrings.h, which was created for Godot
-(it is usually autogenerated by cmake).
+The only modified file is `miniupnpcstrings.h`, which was created for Godot
+(it is usually autogenerated by cmake). Bump the version number for miniupnpc in that
+file when upgrading.
## minizip
diff --git a/thirdparty/harfbuzz/NEWS b/thirdparty/harfbuzz/NEWS
index f09c2fafd1..321c550188 100644
--- a/thirdparty/harfbuzz/NEWS
+++ b/thirdparty/harfbuzz/NEWS
@@ -1,3 +1,18 @@
+Overview of changes leading to 2.8.0
+Tuesday, March 16, 2021
+====================================
+- Shape joining scripts other than Arabic/Syriac using the Universal Shaping Engine.
+ Previously these were shaped using the generalized Arabic shaper. (David Corbett)
+- Fix regression in shaping of U+0B55 ORIYA SIGN OVERLINE. (David Corbett)
+- Update language tags. (David Corbett)
+- Variations: reduce error: do not round each interpolated delta. (Just van Rossum)
+- Documentation improvements. (Khaled Hosny, Nathan Willis)
+- Subsetter improvements: subsets most, if not all, lookup types now. (Garret Rieger, Qunxin Liu)
+- Fuzzer-found fixes and other improvements when memory failures happen. (Behdad)
+- Removed most atomic implementations now that we have C++11 atomic impl. (Behdad)
+- General codebase upkeep; using more C++11 features: constexpr constructors, etc. (Behdad)
+
+
Overview of changes leading to 2.7.4
Sunday, December 27, 2020
====================================
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
index 75d523f5fc..98ed20d8eb 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
@@ -510,7 +510,7 @@ struct StateTable
const Entry<Extra> &get_entry (int state, unsigned int klass) const
{
if (unlikely (klass >= nClasses))
- klass = StateTable<Types, Entry<Extra>>::CLASS_OUT_OF_BOUNDS;
+ klass = StateTable::CLASS_OUT_OF_BOUNDS;
const HBUSHORT *states = (this+stateArrayTable).arrayZ;
const Entry<Extra> *entries = (this+entryTable).arrayZ;
@@ -576,7 +576,7 @@ struct StateTable
if (unlikely (stop > states))
return_trace (false);
for (const HBUSHORT *p = states; stop < p; p--)
- num_entries = hb_max (num_entries, *(p - 1) + 1);
+ num_entries = hb_max (num_entries, *(p - 1) + 1u);
state_neg = min_state;
}
}
@@ -597,7 +597,7 @@ struct StateTable
if (unlikely (stop < states))
return_trace (false);
for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
- num_entries = hb_max (num_entries, *p + 1);
+ num_entries = hb_max (num_entries, *p + 1u);
state_pos = max_state + 1;
}
}
@@ -729,7 +729,10 @@ struct ExtendedTypes
template <typename Types, typename EntryData>
struct StateTableDriver
{
- StateTableDriver (const StateTable<Types, EntryData> &machine_,
+ using StateTableT = StateTable<Types, EntryData>;
+ using EntryT = Entry<EntryData>;
+
+ StateTableDriver (const StateTableT &machine_,
hb_buffer_t *buffer_,
hb_face_t *face_) :
machine (machine_),
@@ -742,59 +745,101 @@ struct StateTableDriver
if (!c->in_place)
buffer->clear_output ();
- int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT;
+ int state = StateTableT::STATE_START_OF_TEXT;
for (buffer->idx = 0; buffer->successful;)
{
unsigned int klass = buffer->idx < buffer->len ?
machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
- (unsigned) StateTable<Types, EntryData>::CLASS_END_OF_TEXT;
+ (unsigned) StateTableT::CLASS_END_OF_TEXT;
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
- const Entry<EntryData> &entry = machine.get_entry (state, klass);
+ const EntryT &entry = machine.get_entry (state, klass);
+ const int next_state = machine.new_state (entry.newState);
- /* Unsafe-to-break before this if not in state 0, as things might
- * go differently if we start from state 0 here.
+ /* Conditions under which it's guaranteed safe-to-break before current glyph:
*
- * Ugh. The indexing here is ugly... */
- if (state && buffer->backtrack_len () && buffer->idx < buffer->len)
- {
- /* If there's no action and we're just epsilon-transitioning to state 0,
- * safe to break. */
- if (c->is_actionable (this, entry) ||
- !(entry.newState == StateTable<Types, EntryData>::STATE_START_OF_TEXT &&
- entry.flags == context_t::DontAdvance))
- buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
- }
-
- /* Unsafe-to-break if end-of-text would kick in here. */
- if (buffer->idx + 2 <= buffer->len)
- {
- const Entry<EntryData> &end_entry = machine.get_entry (state, StateTable<Types, EntryData>::CLASS_END_OF_TEXT);
- if (c->is_actionable (this, end_entry))
- buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
- }
+ * 1. There was no action in this transition; and
+ *
+ * 2. If we break before current glyph, the results will be the same. That
+ * is guaranteed if:
+ *
+ * 2a. We were already in start-of-text state; or
+ *
+ * 2b. We are epsilon-transitioning to start-of-text state; or
+ *
+ * 2c. Starting from start-of-text state seeing current glyph:
+ *
+ * 2c'. There won't be any actions; and
+ *
+ * 2c". We would end up in the same state that we were going to end up
+ * in now, including whether epsilon-transitioning.
+ *
+ * and
+ *
+ * 3. If we break before current glyph, there won't be any end-of-text action
+ * after previous glyph.
+ *
+ * This triples the transitions we need to look up, but is worth returning
+ * granular unsafe-to-break results. See eg.:
+ *
+ * https://github.com/harfbuzz/harfbuzz/issues/2860
+ */
+ const EntryT *wouldbe_entry;
+ bool safe_to_break =
+ /* 1. */
+ !c->is_actionable (this, entry)
+ &&
+ /* 2. */
+ (
+ /* 2a. */
+ state == StateTableT::STATE_START_OF_TEXT
+ ||
+ /* 2b. */
+ (
+ (entry.flags & context_t::DontAdvance) &&
+ next_state == StateTableT::STATE_START_OF_TEXT
+ )
+ ||
+ /* 2c. */
+ (
+ wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
+ ,
+ /* 2c'. */
+ !c->is_actionable (this, *wouldbe_entry)
+ &&
+ /* 2c". */
+ (
+ next_state == machine.new_state (wouldbe_entry->newState)
+ &&
+ (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
+ )
+ )
+ )
+ &&
+ /* 3. */
+ !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
+ ;
+
+ if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
+ buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
c->transition (this, entry);
- state = machine.new_state (entry.newState);
+ state = next_state;
DEBUG_MSG (APPLY, nullptr, "s%d", state);
- if (buffer->idx == buffer->len)
+ if (buffer->idx == buffer->len || unlikely (!buffer->successful))
break;
if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
}
if (!c->in_place)
- {
- for (; buffer->successful && buffer->idx < buffer->len;)
- buffer->next_glyph ();
buffer->swap_buffers ();
- }
}
public:
- const StateTable<Types, EntryData> &machine;
+ const StateTableT &machine;
hb_buffer_t *buffer;
unsigned int num_glyphs;
};
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
index 04027a61be..e3bc268d26 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
@@ -337,9 +337,9 @@ struct ContextualSubtable
const EntryData &data = entries[i].data;
if (data.markIndex != 0xFFFF)
- num_lookups = hb_max (num_lookups, 1 + data.markIndex);
+ num_lookups = hb_max (num_lookups, 1u + data.markIndex);
if (data.currentIndex != 0xFFFF)
- num_lookups = hb_max (num_lookups, 1 + data.currentIndex);
+ num_lookups = hb_max (num_lookups, 1u + data.currentIndex);
}
return_trace (substitutionTables.sanitize (c, this, num_lookups));
@@ -499,7 +499,7 @@ struct LigatureSubtable
}
DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1);
- buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]);
+ if (unlikely (!buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]))) return;
if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
action = *actionData;
@@ -525,25 +525,25 @@ struct LigatureSubtable
hb_codepoint_t lig = ligatureData;
DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
- buffer->replace_glyph (lig);
+ if (unlikely (!buffer->replace_glyph (lig))) return;
unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u;
/* Now go and delete all subsequent components. */
while (match_length - 1u > cursor)
{
DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
- buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]);
- buffer->replace_glyph (DELETED_GLYPH);
+ if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return;
+ if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return;
}
- buffer->move_to (lig_end);
+ if (unlikely (!buffer->move_to (lig_end))) return;
buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len);
}
actionData++;
}
while (!(action & LigActionLast));
- buffer->move_to (end);
+ if (unlikely (!buffer->move_to (end))) return;
}
}
@@ -733,17 +733,16 @@ struct InsertionSubtable
bool before = flags & MarkedInsertBefore;
unsigned int end = buffer->out_len;
- buffer->move_to (mark);
+ if (unlikely (!buffer->move_to (mark))) return;
if (buffer->idx < buffer->len && !before)
- buffer->copy_glyph ();
+ if (unlikely (!buffer->copy_glyph ())) return;
/* TODO We ignore KashidaLike setting. */
- for (unsigned int i = 0; i < count; i++)
- buffer->output_glyph (glyphs[i]);
+ if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
if (buffer->idx < buffer->len && !before)
buffer->skip_glyph ();
- buffer->move_to (end + count);
+ if (unlikely (!buffer->move_to (end + count))) return;
buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len));
}
@@ -764,10 +763,9 @@ struct InsertionSubtable
unsigned int end = buffer->out_len;
if (buffer->idx < buffer->len && !before)
- buffer->copy_glyph ();
+ if (unlikely (!buffer->copy_glyph ())) return;
/* TODO We ignore KashidaLike setting. */
- for (unsigned int i = 0; i < count; i++)
- buffer->output_glyph (glyphs[i]);
+ if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
if (buffer->idx < buffer->len && !before)
buffer->skip_glyph ();
@@ -786,7 +784,7 @@ struct InsertionSubtable
*
* https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417
*/
- buffer->move_to ((flags & DontAdvance) ? end : end + count);
+ if (unlikely (!buffer->move_to ((flags & DontAdvance) ? end : end + count))) return;
}
}
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout.cc b/thirdparty/harfbuzz/src/hb-aat-layout.cc
index 74ebaa64ec..0e9f2b4954 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-aat-layout.cc
@@ -227,7 +227,7 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
*
* <note>Note: does not examine the `GSUB` table.</note>
*
- * Return value: true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 2.3.0
*/
@@ -294,7 +294,7 @@ hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
*
* <note>Note: does not examine the `GPOS` table.</note>
*
- * Return value: true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 2.3.0
*/
@@ -325,7 +325,7 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
* Tests whether the specified face includes any tracking information
* in the `trak` table.
*
- * Return value: true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 2.3.0
*/
@@ -350,7 +350,7 @@ hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
* hb_aat_layout_get_feature_types:
* @face: #hb_face_t to work upon
* @start_offset: offset of the first feature type to retrieve
- * @feature_count: (inout) (allow-none): Input = the maximum number of feature types to return;
+ * @feature_count: (inout) (optional): Input = the maximum number of feature types to return;
* Output = the actual number of feature types returned (may be zero)
* @features: (out caller-allocates) (array length=feature_count): Array of feature types found
*
@@ -374,9 +374,9 @@ hb_aat_layout_get_feature_types (hb_face_t *face,
* @face: #hb_face_t to work upon
* @feature_type: The #hb_aat_layout_feature_type_t of the requested feature type
*
- * Fetches the name ID of the specified feature type in the face's `name` table.
+ * Fetches the name identifier of the specified feature type in the face's `name` table.
*
- * Return value: Name ID of the requested feature type
+ * Return value: Name identifier of the requested feature type
*
* Since: 2.2.0
*/
@@ -388,15 +388,15 @@ hb_aat_layout_feature_type_get_name_id (hb_face_t *face,
}
/**
- * hb_aat_layout_feature_type_get_selectors:
+ * hb_aat_layout_feature_type_get_selector_infos:
* @face: #hb_face_t to work upon
* @feature_type: The #hb_aat_layout_feature_type_t of the requested feature type
* @start_offset: offset of the first feature type to retrieve
- * @selector_count: (inout) (allow-none): Input = the maximum number of selectors to return;
+ * @selector_count: (inout) (optional): Input = the maximum number of selectors to return;
* Output = the actual number of selectors returned (may be zero)
- * @selectors: (out caller-allocates) (array length=selector_count): A buffer pointer.
- * The selectors available for the feature type queries.
- * @default_index: (out) (allow-none): The index of the feature's default selector, if any
+ * @selectors: (out caller-allocates) (array length=selector_count) (optional):
+ * A buffer pointer. The selectors available for the feature type queries.
+ * @default_index: (out) (optional): The index of the feature's default selector, if any
*
* Fetches a list of the selectors available for the specified feature in the given face.
*
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout.h b/thirdparty/harfbuzz/src/hb-aat-layout.h
index dc1bf96573..9af2740088 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout.h
+++ b/thirdparty/harfbuzz/src/hb-aat-layout.h
@@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-#ifndef HB_AAT_H_IN
+#if !defined(HB_AAT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-aat.h> instead."
#endif
@@ -38,47 +38,47 @@ HB_BEGIN_DECLS
/**
* hb_aat_layout_feature_type_t:
* @HB_AAT_LAYOUT_FEATURE_TYPE_INVALID: Initial, unset feature type
- * @HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE:
- * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE:
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC: [All Typographic Features](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type0)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES: [Ligatures](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type1)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION: [Cursive Connection](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type2)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE: [Letter Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type3)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION: [Vertical Substitution](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type4)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT: [Linguistic Rearrangement](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type5)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING: [Number Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type6)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE: [Smart Swash](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type8)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE: [Diacritics](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type9)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION: [Vertical Position](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type10)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS: [Fractions](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type11)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE: [Overlapping Characters](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type13)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS: [Typographic Extras](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type14)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS: [Mathematical Extras](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type15)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE: [Ornament Sets](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type16)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES: [Character Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type17)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE: [Design Complexity](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type18)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS: [Style Options](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type19)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE: [Character Shape](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type20)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE: [Number Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type21)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING: [Text Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type22)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION: [Transliteration](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type23)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE: [Annotation](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type24)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE: [Kana Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type25)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE: [Ideographic Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type26)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE: [Unicode Decomposition](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type27)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA: [Ruby Kana](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type28)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE: [CJK Symbol Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type29)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE: [Ideographic Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type30)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE: [CJK Vertical Roman Placement](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type31)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN: [Italic CJK Roman](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type32)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT: [Case Sensitive Layout](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type33)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA: [Alternate Kana](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type34)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES: [Stylistic Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type35)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES: [Contextual Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type36)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE: [Lower Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type37)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE: [Upper Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type38)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE: [Language Tag](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type39)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE: [CJK Roman Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type103)
*
- * The possible feature types defined for AAT shaping.
+ * The possible feature types defined for AAT shaping, from Apple [Font Feature Registry](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html).
*
* Since: 2.2.0
*/
@@ -732,6 +732,14 @@ HB_EXTERN hb_ot_name_id_t
hb_aat_layout_feature_type_get_name_id (hb_face_t *face,
hb_aat_layout_feature_type_t feature_type);
+/**
+ * hb_aat_layout_feature_selector_info_t:
+ * @name_id: The selector's name identifier
+ * @enable: The value to turn the selector on
+ * @disable: The value to turn the selector off
+ *
+ * Structure representing a setting for an #hb_aat_layout_feature_type_t.
+ */
typedef struct hb_aat_layout_feature_selector_info_t {
hb_ot_name_id_t name_id;
hb_aat_layout_feature_selector_t enable;
diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh
index 98de61f3e8..bc170b0546 100644
--- a/thirdparty/harfbuzz/src/hb-algs.hh
+++ b/thirdparty/harfbuzz/src/hb-algs.hh
@@ -35,6 +35,132 @@
#include "hb-number.hh"
+/*
+ * Flags
+ */
+
+/* Enable bitwise ops on enums marked as flags_t */
+/* To my surprise, looks like the function resolver is happy to silently cast
+ * one enum to another... So this doesn't provide the type-checking that I
+ * originally had in mind... :(.
+ *
+ * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
+ */
+#ifdef _MSC_VER
+# pragma warning(disable:4200)
+# pragma warning(disable:4800)
+#endif
+#define HB_MARK_AS_FLAG_T(T) \
+ extern "C++" { \
+ static inline constexpr T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
+ static inline constexpr T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
+ static inline constexpr T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
+ static inline constexpr T operator ~ (T r) { return T (~(unsigned int) r); } \
+ static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
+ static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
+ static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
+ } \
+ static_assert (true, "")
+
+/* Useful for set-operations on small enums.
+ * For example, for testing "x ∈ {x1, x2, x3}" use:
+ * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
+ */
+#define FLAG(x) (static_assert_expr ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
+#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
+#define FLAG_RANGE(x,y) (static_assert_expr ((x) < (y)) + FLAG(y+1) - FLAG(x))
+#define FLAG64(x) (static_assert_expr ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
+#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
+
+
+/*
+ * Big-endian integers.
+ */
+
+/* Endian swap, used in Windows related backends */
+static inline constexpr uint16_t hb_uint16_swap (uint16_t v)
+{ return (v >> 8) | (v << 8); }
+static inline constexpr uint32_t hb_uint32_swap (uint32_t v)
+{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
+
+template <typename Type, int Bytes = sizeof (Type)>
+struct BEInt;
+template <typename Type>
+struct BEInt<Type, 1>
+{
+ public:
+ BEInt () = default;
+ constexpr BEInt (Type V) : v {uint8_t (V)} {}
+ constexpr operator Type () const { return v; }
+ private: uint8_t v;
+};
+template <typename Type>
+struct BEInt<Type, 2>
+{
+ public:
+ BEInt () = default;
+ constexpr BEInt (Type V) : v {uint8_t ((V >> 8) & 0xFF),
+ uint8_t ((V ) & 0xFF)} {}
+
+ struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
+ constexpr operator Type () const
+ {
+#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
+ defined(__BYTE_ORDER) && \
+ (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
+ /* Spoon-feed the compiler a big-endian integer with alignment 1.
+ * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ return __builtin_bswap16 (((packed_uint16_t *) this)->v);
+#else /* __BYTE_ORDER == __BIG_ENDIAN */
+ return ((packed_uint16_t *) this)->v;
+#endif
+#else
+ return (v[0] << 8)
+ + (v[1] );
+#endif
+ }
+ private: uint8_t v[2];
+};
+template <typename Type>
+struct BEInt<Type, 3>
+{
+ static_assert (!hb_is_signed (Type), "");
+ public:
+ BEInt () = default;
+ constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF),
+ uint8_t ((V >> 8) & 0xFF),
+ uint8_t ((V ) & 0xFF)} {}
+
+ constexpr operator Type () const { return (v[0] << 16)
+ + (v[1] << 8)
+ + (v[2] ); }
+ private: uint8_t v[3];
+};
+template <typename Type>
+struct BEInt<Type, 4>
+{
+ public:
+ BEInt () = default;
+ constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF),
+ uint8_t ((V >> 16) & 0xFF),
+ uint8_t ((V >> 8) & 0xFF),
+ uint8_t ((V ) & 0xFF)} {}
+ constexpr operator Type () const { return (v[0] << 24)
+ + (v[1] << 16)
+ + (v[2] << 8)
+ + (v[3] ); }
+ private: uint8_t v[4];
+};
+
+/* Floats. */
+
+/* We want our rounding towards +infinity. */
+static inline float
+_hb_roundf (float x) { return floorf (x + .5f); }
+#define roundf(x) _hb_roundf(x)
+
+
/* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits,
* values will be truncated / overlap, and might not decode exactly. */
#define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
@@ -48,6 +174,7 @@
#define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300)
#define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu)
+
struct
{
/* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
@@ -215,7 +342,9 @@ struct
template <typename Pred, typename Val> auto
impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
- (hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v)))
+ (
+ hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v))
+ )
template <typename Pred, typename Val> auto
impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
@@ -269,7 +398,9 @@ struct
template <typename Proj, typename Val> auto
impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
- (hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v)))
+ (
+ hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v))
+ )
template <typename Proj, typename Val> auto
impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
@@ -296,6 +427,40 @@ struct
}
HB_FUNCOBJ (hb_get);
+struct
+{
+ private:
+
+ template <typename T1, typename T2> auto
+ impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN
+ (
+ hb_forward<T2> (v2).cmp (hb_forward<T1> (v1)) == 0
+ )
+
+ template <typename T1, typename T2> auto
+ impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN
+ (
+ hb_forward<T1> (v1).cmp (hb_forward<T2> (v2)) == 0
+ )
+
+ template <typename T1, typename T2> auto
+ impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN
+ (
+ hb_forward<T1> (v1) == hb_forward<T2> (v2)
+ )
+
+ public:
+
+ template <typename T1, typename T2> auto
+ operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN
+ (
+ impl (hb_forward<T1> (v1),
+ hb_forward<T2> (v2),
+ hb_prioritize)
+ )
+}
+HB_FUNCOBJ (hb_equal);
+
template <typename T1, typename T2>
struct hb_pair_t
@@ -375,7 +540,7 @@ HB_FUNCOBJ (hb_clamp);
/* Return the number of 1 bits in v. */
template <typename T>
-static inline HB_CONST_FUNC unsigned int
+static inline unsigned int
hb_popcount (T v)
{
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
@@ -416,7 +581,7 @@ hb_popcount (T v)
/* Returns the number of bits needed to store number */
template <typename T>
-static inline HB_CONST_FUNC unsigned int
+static inline unsigned int
hb_bit_storage (T v)
{
if (unlikely (!v)) return 0;
@@ -490,7 +655,7 @@ hb_bit_storage (T v)
/* Returns the number of zero bits in the least significant side of v */
template <typename T>
-static inline HB_CONST_FUNC unsigned int
+static inline unsigned int
hb_ctz (T v)
{
if (unlikely (!v)) return 8 * sizeof (T);
@@ -988,32 +1153,24 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
struct hb_bitwise_and
{ HB_PARTIALIZE(2);
- static constexpr bool passthru_left = false;
- static constexpr bool passthru_right = false;
template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
}
HB_FUNCOBJ (hb_bitwise_and);
struct hb_bitwise_or
{ HB_PARTIALIZE(2);
- static constexpr bool passthru_left = true;
- static constexpr bool passthru_right = true;
template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
}
HB_FUNCOBJ (hb_bitwise_or);
struct hb_bitwise_xor
{ HB_PARTIALIZE(2);
- static constexpr bool passthru_left = true;
- static constexpr bool passthru_right = true;
template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
}
HB_FUNCOBJ (hb_bitwise_xor);
struct hb_bitwise_sub
{ HB_PARTIALIZE(2);
- static constexpr bool passthru_left = true;
- static constexpr bool passthru_right = false;
template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
}
diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh
index 568cd02c79..02bd8d81c2 100644
--- a/thirdparty/harfbuzz/src/hb-array.hh
+++ b/thirdparty/harfbuzz/src/hb-array.hh
@@ -142,7 +142,7 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
bool lfind (const T &x, unsigned *pos = nullptr) const
{
for (unsigned i = 0; i < length; ++i)
- if (!this->arrayZ[i].cmp (x))
+ if (hb_equal (x, this->arrayZ[i]))
{
if (pos)
*pos = i;
diff --git a/thirdparty/harfbuzz/src/hb-atomic.hh b/thirdparty/harfbuzz/src/hb-atomic.hh
index b3fb296b4e..93265f655f 100644
--- a/thirdparty/harfbuzz/src/hb-atomic.hh
+++ b/thirdparty/harfbuzz/src/hb-atomic.hh
@@ -52,7 +52,7 @@
#elif !defined(HB_NO_MT) && defined(__ATOMIC_ACQUIRE)
-/* C++11-style GCC primitives. */
+/* C++11-style GCC primitives. We prefer these as they don't require linking to libstdc++ / libc++. */
#define _hb_memory_barrier() __sync_synchronize ()
@@ -73,7 +73,8 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
}
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
-#elif !defined(HB_NO_MT) && __cplusplus >= 201103L
+
+#elif !defined(HB_NO_MT)
/* C++11 atomics. */
@@ -101,117 +102,6 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
-#elif !defined(HB_NO_MT) && defined(_WIN32)
-
-#include <windows.h>
-
-static inline void _hb_memory_barrier ()
-{
-#if !defined(MemoryBarrier) && !defined(__MINGW32_VERSION)
- /* MinGW has a convoluted history of supporting MemoryBarrier. */
- LONG dummy = 0;
- InterlockedExchange (&dummy, 1);
-#else
- MemoryBarrier ();
-#endif
-}
-#define _hb_memory_barrier() _hb_memory_barrier ()
-
-#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd ((LONG *) (AI), (V))
-static_assert ((sizeof (LONG) == sizeof (int)), "");
-
-#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((P), (N), (O)) == (O))
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
-
-#define _hb_memory_barrier() __sync_synchronize ()
-
-#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add ((AI), (V))
-
-#define hb_atomic_ptr_impl_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N))
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
-
-#include <atomic.h>
-#include <mbarrier.h>
-
-#define _hb_memory_r_barrier() __machine_r_barrier ()
-#define _hb_memory_w_barrier() __machine_w_barrier ()
-#define _hb_memory_barrier() __machine_rw_barrier ()
-
-static inline int _hb_fetch_and_add (int *AI, int V)
-{
- _hb_memory_w_barrier ();
- int result = atomic_add_int_nv ((uint_t *) AI, V) - V;
- _hb_memory_r_barrier ();
- return result;
-}
-static inline bool _hb_compare_and_swap_ptr (void **P, void *O, void *N)
-{
- _hb_memory_w_barrier ();
- bool result = atomic_cas_ptr (P, O, N) == O;
- _hb_memory_r_barrier ();
- return result;
-}
-
-#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
-
-#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swap_ptr ((P), (O), (N))
-
-
-#elif !defined(HB_NO_MT) && defined(__APPLE__)
-
-#include <libkern/OSAtomic.h>
-#ifdef __MAC_OS_X_MIN_REQUIRED
-#include <AvailabilityMacros.h>
-#elif defined(__IPHONE_OS_MIN_REQUIRED)
-#include <Availability.h>
-#endif
-
-#define _hb_memory_barrier() OSMemoryBarrier ()
-
-#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), (AI)) - (V))
-
-#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
-#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((O), (N), (P))
-#else
-#if __ppc64__ || __x86_64__ || __aarch64__
-#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
-#else
-#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
-#endif
-#endif
-
-
-#elif !defined(HB_NO_MT) && defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__))
-
-#include <builtins.h>
-
-#define _hb_memory_barrier() __lwsync ()
-
-static inline int _hb_fetch_and_add (int *AI, int V)
-{
- _hb_memory_barrier ();
- int result = __fetch_and_add (AI, V);
- _hb_memory_barrier ();
- return result;
-}
-static inline bool _hb_compare_and_swaplp (long *P, long O, long N)
-{
- _hb_memory_barrier ();
- bool result = __compare_and_swaplp (P, &O, N);
- _hb_memory_barrier ();
- return result;
-}
-
-#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
-
-#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N))
-static_assert ((sizeof (long) == sizeof (void *)), "");
-
-
#elif defined(HB_NO_MT)
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
@@ -259,9 +149,11 @@ inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory
#endif
-#define HB_ATOMIC_INT_INIT(V) {V}
struct hb_atomic_int_t
{
+ hb_atomic_int_t () = default;
+ constexpr hb_atomic_int_t (int v) : v (v) {}
+
void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
void set (int v_) { hb_atomic_int_impl_set (&v, v_); }
int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
@@ -269,16 +161,17 @@ struct hb_atomic_int_t
int inc () { return hb_atomic_int_impl_add (&v, 1); }
int dec () { return hb_atomic_int_impl_add (&v, -1); }
- int v;
+ int v = 0;
};
-
-#define HB_ATOMIC_PTR_INIT(V) {V}
template <typename P>
struct hb_atomic_ptr_t
{
typedef hb_remove_pointer<P> T;
+ hb_atomic_ptr_t () = default;
+ constexpr hb_atomic_ptr_t (T* v) : v (v) {}
+
void init (T* v_ = nullptr) { set_relaxed (v_); }
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
@@ -288,7 +181,7 @@ struct hb_atomic_ptr_t
T * operator -> () const { return get (); }
template <typename C> operator C * () const { return get (); }
- T *v;
+ T *v = nullptr;
};
diff --git a/thirdparty/harfbuzz/src/hb-blob.cc b/thirdparty/harfbuzz/src/hb-blob.cc
index e340bc346d..71b1b1fc4f 100644
--- a/thirdparty/harfbuzz/src/hb-blob.cc
+++ b/thirdparty/harfbuzz/src/hb-blob.cc
@@ -35,9 +35,6 @@
#include <sys/mman.h>
#endif /* HAVE_SYS_MMAN_H */
-#include <stdio.h>
-#include <stdlib.h>
-
/**
* SECTION: hb-blob
@@ -58,7 +55,7 @@
* @length: Length of @data in bytes.
* @mode: Memory mode for @data.
* @user_data: Data parameter to pass to @destroy.
- * @destroy: (optional): Callback to call when @data is not needed anymore.
+ * @destroy: (nullable): Callback to call when @data is not needed anymore.
*
* Creates a new "blob" object wrapping @data. The @mode parameter is used
* to negotiate ownership and lifecycle of @data.
@@ -116,7 +113,7 @@ _hb_blob_destroy (void *data)
* @length: Length of sub-blob.
*
* Returns a blob that represents a range of bytes in @parent. The new
- * blob is always created with %HB_MEMORY_MODE_READONLY, meaning that it
+ * blob is always created with #HB_MEMORY_MODE_READONLY, meaning that it
* will never modify data in the parent blob. The parent data is not
* expected to be modified, and will result in undefined behavior if it
* is.
@@ -237,7 +234,7 @@ hb_blob_destroy (hb_blob_t *blob)
* @blob: An #hb_blob_t
* @key: The user-data key to set
* @data: A pointer to the user data to set
- * @destroy: (optional): A callback to call when @data is not needed anymore
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the specified blob.
@@ -299,7 +296,7 @@ hb_blob_make_immutable (hb_blob_t *blob)
*
* Tests whether a blob is immutable.
*
- * Return value: %true if @blob is immutable, false otherwise
+ * Return value: %true if @blob is immutable, %false otherwise
*
* Since: 0.9.2
**/
@@ -365,16 +362,14 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length)
char *
hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length)
{
- if (!blob->try_make_writable ()) {
- if (length)
- *length = 0;
-
+ if (hb_object_is_immutable (blob) ||
+ !blob->try_make_writable ())
+ {
+ if (length) *length = 0;
return nullptr;
}
- if (length)
- *length = blob->length;
-
+ if (length) *length = blob->length;
return const_cast<char *> (blob->data);
}
@@ -440,8 +435,8 @@ hb_blob_t::try_make_writable_inplace ()
bool
hb_blob_t::try_make_writable ()
{
- if (hb_object_is_immutable (this))
- return false;
+ if (unlikely (!length))
+ mode = HB_MEMORY_MODE_WRITABLE;
if (this->mode == HB_MEMORY_MODE_WRITABLE)
return true;
diff --git a/thirdparty/harfbuzz/src/hb-blob.h b/thirdparty/harfbuzz/src/hb-blob.h
index 00e41f3ce3..86f12788d2 100644
--- a/thirdparty/harfbuzz/src/hb-blob.h
+++ b/thirdparty/harfbuzz/src/hb-blob.h
@@ -24,7 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
@@ -38,10 +38,12 @@ HB_BEGIN_DECLS
/**
* hb_memory_mode_t:
- * @HB_MEMORY_MODE_DUPLICATE
- * @HB_MEMORY_MODE_READONLY
- * @HB_MEMORY_MODE_WRITABLE
- * @HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE
+ * @HB_MEMORY_MODE_DUPLICATE: HarfBuzz immediately makes a copy of the data.
+ * @HB_MEMORY_MODE_READONLY: HarfBuzz client will never modify the data,
+ * and HarfBuzz will never modify the data.
+ * @HB_MEMORY_MODE_WRITABLE: HarfBuzz client made a copy of the data solely
+ * for HarfBuzz, so HarfBuzz may modify the data.
+ * @HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE: See above
*
* Data type holding the memory modes available to
* client programs.
diff --git a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
index f65bad45bb..6539b89640 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
@@ -400,8 +400,8 @@ _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf.
- * @font: (allow-none): the #hb_font_t used to shape this buffer, needed to
+ * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
+ * @font: (nullable): the #hb_font_t used to shape this buffer, needed to
* read glyph names and extents. If %NULL, and empty font will be used.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
@@ -514,8 +514,10 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf.
+ * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
+ * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
+ * to serialize.
*
* Serializes @buffer into a textual representation of its content,
* when the buffer contains Unicode codepoints (i.e., before shaping). This is
@@ -635,8 +637,8 @@ _hb_buffer_serialize_invalid (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf.
- * @font: (allow-none): the #hb_font_t used to shape this buffer, needed to
+ * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
+ * @font: (nullable): the #hb_font_t used to shape this buffer, needed to
* read glyph names and extents. If %NULL, and empty font will be used.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
@@ -724,15 +726,17 @@ parse_hex (const char *pp, const char *end, uint32_t *pv)
/**
* hb_buffer_deserialize_glyphs:
* @buffer: an #hb_buffer_t buffer.
- * @buf: (array length=buf_len):
- * @buf_len:
- * @end_ptr: (out):
- * @font:
- * @format:
- *
+ * @buf: (array length=buf_len): string to deserialize
+ * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
+ * @end_ptr: (out) (optional): output pointer to the character after last
+ * consumed one.
+ * @font: (nullable): font for getting glyph IDs
+ * @format: the #hb_buffer_serialize_format_t of the input @buf
*
+ * Deserializes glyphs @buffer from textual representation in the format
+ * produced by hb_buffer_serialize_glyphs().
*
- * Return value:
+ * Return value: %true if @buf is not fully consumed, %false otherwise.
*
* Since: 0.9.7
**/
@@ -795,14 +799,16 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
/**
* hb_buffer_deserialize_unicode:
* @buffer: an #hb_buffer_t buffer.
- * @buf: (array length=buf_len):
- * @buf_len:
- * @end_ptr: (out):
- * @format:
- *
+ * @buf: (array length=buf_len): string to deserialize
+ * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
+ * @end_ptr: (out) (optional): output pointer to the character after last
+ * consumed one.
+ * @format: the #hb_buffer_serialize_format_t of the input @buf
*
+ * Deserializes Unicode @buffer from textual representation in the format
+ * produced by hb_buffer_serialize_unicode().
*
- * Return value:
+ * Return value: %true if @buf is not fully consumed, %false otherwise.
*
* Since: 2.7.3
**/
diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc
index 10063db050..8cad6ab8e6 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer.cc
@@ -218,9 +218,6 @@ hb_buffer_t::get_scratch_buffer (unsigned int *size)
void
hb_buffer_t::reset ()
{
- if (unlikely (hb_object_is_immutable (this)))
- return;
-
hb_unicode_funcs_destroy (unicode);
unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ());
flags = HB_BUFFER_FLAG_DEFAULT;
@@ -233,9 +230,6 @@ hb_buffer_t::reset ()
void
hb_buffer_t::clear ()
{
- if (unlikely (hb_object_is_immutable (this)))
- return;
-
hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
props = default_props;
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
@@ -290,9 +284,6 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
void
hb_buffer_t::remove_output ()
{
- if (unlikely (hb_object_is_immutable (this)))
- return;
-
have_output = false;
have_positions = false;
@@ -303,9 +294,6 @@ hb_buffer_t::remove_output ()
void
hb_buffer_t::clear_output ()
{
- if (unlikely (hb_object_is_immutable (this)))
- return;
-
have_output = true;
have_positions = false;
@@ -316,9 +304,6 @@ hb_buffer_t::clear_output ()
void
hb_buffer_t::clear_positions ()
{
- if (unlikely (hb_object_is_immutable (this)))
- return;
-
have_output = false;
have_positions = true;
@@ -333,15 +318,19 @@ hb_buffer_t::swap_buffers ()
{
if (unlikely (!successful)) return;
+ assert (idx <= len);
+ if (unlikely (!next_glyphs (len - idx))) return;
+
assert (have_output);
have_output = false;
if (out_info != info)
{
- hb_glyph_info_t *tmp_string;
- tmp_string = info;
+ hb_glyph_info_t *tmp;
+ tmp = info;
info = out_info;
- out_info = tmp_string;
+ out_info = tmp;
+
pos = (hb_glyph_position_t *) out_info;
}
@@ -353,31 +342,6 @@ hb_buffer_t::swap_buffers ()
idx = 0;
}
-
-void
-hb_buffer_t::replace_glyphs (unsigned int num_in,
- unsigned int num_out,
- const uint32_t *glyph_data)
-{
- if (unlikely (!make_room_for (num_in, num_out))) return;
-
- assert (idx + num_in <= len);
-
- merge_clusters (idx, idx + num_in);
-
- hb_glyph_info_t orig_info = info[idx];
- hb_glyph_info_t *pinfo = &out_info[out_len];
- for (unsigned int i = 0; i < num_out; i++)
- {
- *pinfo = orig_info;
- pinfo->codepoint = glyph_data[i];
- pinfo++;
- }
-
- idx += num_in;
- out_len += num_out;
-}
-
bool
hb_buffer_t::move_to (unsigned int i)
{
@@ -768,7 +732,7 @@ hb_buffer_destroy (hb_buffer_t *buffer)
* @buffer: An #hb_buffer_t
* @key: The user-data key
* @data: A pointer to the user data
- * @destroy: (optional): A callback to call when @data is not needed anymore
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the specified buffer.
@@ -795,7 +759,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer,
* Fetches the user data associated with the specified key,
* attached to the specified buffer.
*
- * Return value: (transfer-none): A pointer to the user data
+ * Return value: (transfer none): A pointer to the user data
*
* Since: 0.9.2
**/
@@ -1137,7 +1101,7 @@ hb_buffer_get_cluster_level (hb_buffer_t *buffer)
* Sets the #hb_codepoint_t that replaces invalid entries for a given encoding
* when adding text to @buffer.
*
- * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT.
+ * Default is #HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT.
*
* Since: 0.9.31
**/
@@ -1222,6 +1186,9 @@ hb_buffer_get_invisible_glyph (hb_buffer_t *buffer)
void
hb_buffer_reset (hb_buffer_t *buffer)
{
+ if (unlikely (hb_object_is_immutable (buffer)))
+ return;
+
buffer->reset ();
}
@@ -1237,6 +1204,9 @@ hb_buffer_reset (hb_buffer_t *buffer)
void
hb_buffer_clear_contents (hb_buffer_t *buffer)
{
+ if (unlikely (hb_object_is_immutable (buffer)))
+ return;
+
buffer->clear ();
}
@@ -1321,7 +1291,7 @@ hb_buffer_set_length (hb_buffer_t *buffer,
if (unlikely (hb_object_is_immutable (buffer)))
return length == 0;
- if (!buffer->ensure (length))
+ if (unlikely (!buffer->ensure (length)))
return false;
/* Wipe the new space */
@@ -1501,20 +1471,20 @@ hb_buffer_reverse_clusters (hb_buffer_t *buffer)
*
* Sets unset buffer segment properties based on buffer Unicode
* contents. If buffer is not empty, it must have content type
- * %HB_BUFFER_CONTENT_TYPE_UNICODE.
+ * #HB_BUFFER_CONTENT_TYPE_UNICODE.
*
- * If buffer script is not set (ie. is %HB_SCRIPT_INVALID), it
+ * If buffer script is not set (ie. is #HB_SCRIPT_INVALID), it
* will be set to the Unicode script of the first character in
- * the buffer that has a script other than %HB_SCRIPT_COMMON,
- * %HB_SCRIPT_INHERITED, and %HB_SCRIPT_UNKNOWN.
+ * the buffer that has a script other than #HB_SCRIPT_COMMON,
+ * #HB_SCRIPT_INHERITED, and #HB_SCRIPT_UNKNOWN.
*
- * Next, if buffer direction is not set (ie. is %HB_DIRECTION_INVALID),
+ * Next, if buffer direction is not set (ie. is #HB_DIRECTION_INVALID),
* it will be set to the natural horizontal direction of the
* buffer script as returned by hb_script_get_horizontal_direction().
- * If hb_script_get_horizontal_direction() returns %HB_DIRECTION_INVALID,
- * then %HB_DIRECTION_LTR is used.
+ * If hb_script_get_horizontal_direction() returns #HB_DIRECTION_INVALID,
+ * then #HB_DIRECTION_LTR is used.
*
- * Finally, if buffer language is not set (ie. is %HB_LANGUAGE_INVALID),
+ * Finally, if buffer language is not set (ie. is #HB_LANGUAGE_INVALID),
* it will be set to the process's default language as returned by
* hb_language_get_default(). This may change in the future by
* taking buffer script into consideration when choosing a language.
@@ -1551,7 +1521,10 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
if (item_length == -1)
item_length = text_length - item_offset;
- buffer->ensure (buffer->len + item_length * sizeof (T) / 4);
+ if (unlikely (item_length < 0 ||
+ item_length > INT_MAX / 8 ||
+ !buffer->ensure (buffer->len + item_length * sizeof (T) / 4)))
+ return;
/* If buffer is empty and pre-context provided, install it.
* This check is written this way, to make sure people can
@@ -1768,11 +1741,6 @@ hb_buffer_append (hb_buffer_t *buffer,
if (start == end)
return;
- if (!buffer->len)
- buffer->content_type = source->content_type;
- if (!buffer->have_positions && source->have_positions)
- buffer->clear_positions ();
-
if (buffer->len + (end - start) < buffer->len) /* Overflows. */
{
buffer->successful = false;
@@ -1784,6 +1752,11 @@ hb_buffer_append (hb_buffer_t *buffer,
if (unlikely (!buffer->successful))
return;
+ if (!orig_len)
+ buffer->content_type = source->content_type;
+ if (!buffer->have_positions && source->have_positions)
+ buffer->clear_positions ();
+
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]));
@@ -1902,8 +1875,8 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g
* @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1.
* @position_fuzz: allowed absolute difference in position values.
*
- * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
- * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most
+ * If dottedcircle_glyph is (hb_codepoint_t) -1 then #HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
+ * and #HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most
* callers if just comparing two buffers is needed.
*
* Since: 1.5.0
@@ -1994,11 +1967,11 @@ hb_buffer_diff (hb_buffer_t *buffer,
/**
* hb_buffer_set_message_func:
* @buffer: An #hb_buffer_t
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
+ * @func: (closure user_data) (destroy destroy) (scope notified): Callback function
+ * @user_data: (nullable): Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
+ * Sets the implementation function for #hb_buffer_message_func_t.
*
* Since: 1.1.3
**/
diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h
index b13757e68f..865ccb2273 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.h
+++ b/thirdparty/harfbuzz/src/hb-buffer.h
@@ -27,7 +27,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
@@ -90,6 +90,8 @@ typedef struct hb_glyph_info_t {
* breaking point only.
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
*
+ * Flags for #hb_glyph_info_t.
+ *
* Since: 1.5.0
*/
typedef enum { /*< flags >*/
@@ -150,6 +152,11 @@ typedef struct hb_segment_properties_t {
void *reserved2;
} hb_segment_properties_t;
+/**
+ * HB_SEGMENT_PROPERTIES_DEFAULT:
+ *
+ * The default #hb_segment_properties_t of of freshly created #hb_buffer_t.
+ */
#define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \
HB_SCRIPT_INVALID, \
HB_LANGUAGE_INVALID, \
@@ -203,6 +210,8 @@ hb_buffer_get_user_data (hb_buffer_t *buffer,
* @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer.
* @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping).
* @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping).
+ *
+ * The type of #hb_buffer_t contents.
*/
typedef enum {
HB_BUFFER_CONTENT_TYPE_INVALID = 0,
@@ -288,6 +297,8 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
* not be inserted in the rendering of incorrect
* character sequences (such at <0905 093E>). Since: 2.4
*
+ * Flags for #hb_buffer_t.
+ *
* Since: 0.9.20
*/
typedef enum { /*< flags >*/
@@ -579,6 +590,35 @@ hb_buffer_deserialize_unicode (hb_buffer_t *buffer,
* Compare buffers
*/
+/**
+ * hb_buffer_diff_flags_t:
+ * @HB_BUFFER_DIFF_FLAG_EQUAL: equal buffers.
+ * @HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH: buffers with different
+ * #hb_buffer_content_type_t.
+ * @HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH: buffers with differing length.
+ * @HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT: `.notdef` glyph is present in the
+ * reference buffer.
+ * @HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT: dotted circle glyph is present
+ * in the reference buffer.
+ * @HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH: difference in #hb_glyph_info_t.codepoint
+ * @HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH: difference in #hb_glyph_info_t.cluster
+ * @HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH: difference in #hb_glyph_flags_t.
+ * @HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH: difference in #hb_glyph_position_t.
+ *
+ * Flags from comparing two #hb_buffer_t's.
+ *
+ * Buffer with different #hb_buffer_content_type_t cannot be meaningfully
+ * compared in any further detail.
+ *
+ * For buffers with differing length, the per-glyph comparison is not
+ * attempted, though we do still scan reference buffer for dotted circle and
+ * `.notdef` glyphs.
+ *
+ * If the buffers have the same length, we compare them glyph-by-glyph and
+ * report which aspect(s) of the glyph info/position are different.
+ *
+ * Since: 1.5.0
+ */
typedef enum { /*< flags >*/
HB_BUFFER_DIFF_FLAG_EQUAL = 0x0000,
@@ -618,6 +658,23 @@ hb_buffer_diff (hb_buffer_t *buffer,
* Debugging.
*/
+/**
+ * hb_buffer_message_func_t:
+ * @buffer: An #hb_buffer_t to work upon
+ * @font: The #hb_font_t the @buffer is shaped with
+ * @message: %NULL-terminated message passed to the function
+ * @user_data: User data pointer passed by the caller
+ *
+ * A callback method for #hb_buffer_t. The method gets called with the
+ * #hb_buffer_t it was set on, the #hb_font_t the buffer is shaped with and a
+ * message describing what step of the shaping process will be performed.
+ * Returning %false from this method will skip this shaping step and move to
+ * the next one.
+ *
+ * Return value: %true to perform the shaping step, %false to skip it.
+ *
+ * Since: 1.1.3
+ */
typedef hb_bool_t (*hb_buffer_message_func_t) (hb_buffer_t *buffer,
hb_font_t *font,
const char *message,
diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh
index 9cad5206e2..8b432b5f96 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.hh
+++ b/thirdparty/harfbuzz/src/hb-buffer.hh
@@ -139,7 +139,7 @@ struct hb_buffer_t
/* Methods */
- bool in_error () const { return !successful; }
+ HB_NODISCARD bool in_error () const { return !successful; }
void allocate_var (unsigned int start, unsigned int count)
{
@@ -186,7 +186,7 @@ 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]; }
- bool has_separate_output () const { return info != out_info; }
+ HB_NODISCARD bool has_separate_output () const { return info != out_info; }
HB_INTERNAL void reset ();
@@ -210,86 +210,89 @@ struct hb_buffer_t
HB_INTERNAL void clear_output ();
HB_INTERNAL void clear_positions ();
- HB_INTERNAL void replace_glyphs (unsigned int num_in,
- unsigned int num_out,
- const hb_codepoint_t *glyph_data);
-
- void replace_glyph (hb_codepoint_t glyph_index)
+ template <typename T>
+ HB_NODISCARD bool replace_glyphs (unsigned int num_in,
+ unsigned int num_out,
+ const T *glyph_data)
{
- if (unlikely (out_info != info || out_len != idx)) {
- if (unlikely (!make_room_for (1, 1))) return;
- out_info[out_len] = info[idx];
- }
- out_info[out_len].codepoint = glyph_index;
+ if (unlikely (!make_room_for (num_in, num_out))) return false;
- idx++;
- out_len++;
- }
- /* Makes a copy of the glyph at idx to output and replace glyph_index */
- hb_glyph_info_t & output_glyph (hb_codepoint_t glyph_index)
- {
- if (unlikely (!make_room_for (0, 1))) return Crap (hb_glyph_info_t);
+ assert (idx + num_in <= len);
- if (unlikely (idx == len && !out_len))
- return Crap (hb_glyph_info_t);
+ merge_clusters (idx, idx + num_in);
- out_info[out_len] = idx < len ? info[idx] : out_info[out_len - 1];
- out_info[out_len].codepoint = glyph_index;
+ hb_glyph_info_t &orig_info = idx < len ? cur() : prev();
- out_len++;
+ hb_glyph_info_t *pinfo = &out_info[out_len];
+ for (unsigned int i = 0; i < num_out; i++)
+ {
+ *pinfo = orig_info;
+ pinfo->codepoint = glyph_data[i];
+ pinfo++;
+ }
- return out_info[out_len - 1];
+ idx += num_in;
+ out_len += num_out;
+ return true;
}
- void output_info (const hb_glyph_info_t &glyph_info)
+
+ HB_NODISCARD bool replace_glyph (hb_codepoint_t glyph_index)
+ { return replace_glyphs (1, 1, &glyph_index); }
+
+ /* Makes a copy of the glyph at idx to output and replace glyph_index */
+ HB_NODISCARD bool output_glyph (hb_codepoint_t glyph_index)
+ { return replace_glyphs (0, 1, &glyph_index); }
+
+ HB_NODISCARD bool output_info (const hb_glyph_info_t &glyph_info)
{
- if (unlikely (!make_room_for (0, 1))) return;
+ if (unlikely (!make_room_for (0, 1))) return false;
out_info[out_len] = glyph_info;
out_len++;
+ return true;
}
/* Copies glyph at idx to output but doesn't advance idx */
- void copy_glyph ()
+ HB_NODISCARD bool copy_glyph ()
{
- if (unlikely (!make_room_for (0, 1))) return;
-
- out_info[out_len] = info[idx];
-
- out_len++;
+ /* Extra copy because cur()'s return can be freed within
+ * output_info() call if buffer reallocates. */
+ return output_info (hb_glyph_info_t (cur()));
}
+
/* Copies glyph at idx to output and advance idx.
* If there's no output, just advance idx. */
- void
- next_glyph ()
+ HB_NODISCARD bool next_glyph ()
{
if (have_output)
{
if (out_info != info || out_len != idx)
{
- if (unlikely (!make_room_for (1, 1))) return;
+ if (unlikely (!make_room_for (1, 1))) return false;
out_info[out_len] = info[idx];
}
out_len++;
}
idx++;
+ return true;
}
/* Copies n glyphs at idx to output and advance idx.
* If there's no output, just advance idx. */
- void
- next_glyphs (unsigned int n)
+ HB_NODISCARD bool next_glyphs (unsigned int n)
{
if (have_output)
{
if (out_info != info || out_len != idx)
{
- if (unlikely (!make_room_for (n, n))) return;
+ if (unlikely (!make_room_for (n, n))) return false;
memmove (out_info + out_len, info + idx, n * sizeof (out_info[0]));
}
out_len += n;
}
idx += n;
+ return true;
}
/* Advance idx without copying to output. */
void skip_glyph () { idx++; }
@@ -329,14 +332,14 @@ struct hb_buffer_t
/* Internal methods */
- HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
+ HB_NODISCARD HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
- HB_INTERNAL bool enlarge (unsigned int size);
+ HB_NODISCARD HB_INTERNAL bool enlarge (unsigned int size);
- bool ensure (unsigned int size)
+ HB_NODISCARD bool ensure (unsigned int size)
{ return likely (!size || size < allocated) ? true : enlarge (size); }
- bool ensure_inplace (unsigned int size)
+ HB_NODISCARD bool ensure_inplace (unsigned int size)
{ return likely (!size || size < allocated); }
void assert_glyphs ()
@@ -349,7 +352,7 @@ struct hb_buffer_t
assert ((content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) ||
(!len && (content_type == HB_BUFFER_CONTENT_TYPE_INVALID)));
}
- bool ensure_glyphs ()
+ HB_NODISCARD bool ensure_glyphs ()
{
if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS))
{
@@ -360,7 +363,7 @@ struct hb_buffer_t
}
return true;
}
- bool ensure_unicode ()
+ HB_NODISCARD bool ensure_unicode ()
{
if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_UNICODE))
{
@@ -372,8 +375,8 @@ struct hb_buffer_t
return true;
}
- HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
- HB_INTERNAL bool shift_forward (unsigned int count);
+ HB_NODISCARD HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
+ HB_NODISCARD HB_INTERNAL bool shift_forward (unsigned int count);
typedef long scratch_buffer_t;
HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc
index ddbcaa064c..7bb878b217 100644
--- a/thirdparty/harfbuzz/src/hb-common.cc
+++ b/thirdparty/harfbuzz/src/hb-common.cc
@@ -675,8 +675,8 @@ hb_version_string ()
* Tests the library version against a minimum value,
* as three integer components.
*
- * Return value: True if the library is equal to or greater than
- * the test value, false otherwise
+ * Return value: %true if the library is equal to or greater than
+ * the test value, %false otherwise
*
* Since: 0.9.30
**/
@@ -1003,6 +1003,21 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation
/**
* hb_variation_from_string:
+ * @str: (array length=len) (element-type uint8_t): a string to parse
+ * @len: length of @str, or -1 if string is %NULL terminated
+ * @variation: (out): the #hb_variation_t to initialize with the parsed values
+ *
+ * Parses a string into a #hb_variation_t.
+ *
+ * The format for specifying variation settings follows. All valid CSS
+ * font-variation-settings values other than 'normal' and 'inherited' are also
+ * accepted, though, not documented below.
+ *
+ * The format is a tag, optionally followed by an equals sign, followed by a
+ * number. For example `wght=500`, or `slnt=-7.5`.
+ *
+ * Return value:
+ * %true if @str is successfully parsed, %false otherwise
*
* Since: 1.4.2
*/
@@ -1029,6 +1044,13 @@ hb_variation_from_string (const char *str, int len,
/**
* hb_variation_to_string:
+ * @variation: an #hb_variation_t to convert
+ * @buf: (array length=size) (out): output string
+ * @size: the allocated size of @buf
+ *
+ * Converts an #hb_variation_t into a %NULL-terminated string in the format
+ * understood by hb_variation_from_string(). The client in responsible for
+ * allocating big enough size for @buf, 128 bytes is more than enough.
*
* Since: 1.4.2
*/
@@ -1055,9 +1077,11 @@ hb_variation_to_string (hb_variation_t *variation,
/**
* hb_color_get_alpha:
- * color: a #hb_color_t we are interested in its channels.
+ * @color: an #hb_color_t we are interested in its channels.
*
- * Return value: Alpha channel value of the given color
+ * Fetches the alpha channel of the given @color.
+ *
+ * Return value: Alpha channel value
*
* Since: 2.1.0
*/
@@ -1069,9 +1093,11 @@ uint8_t
/**
* hb_color_get_red:
- * color: a #hb_color_t we are interested in its channels.
+ * @color: an #hb_color_t we are interested in its channels.
+ *
+ * Fetches the red channel of the given @color.
*
- * Return value: Red channel value of the given color
+ * Return value: Red channel value
*
* Since: 2.1.0
*/
@@ -1083,9 +1109,11 @@ uint8_t
/**
* hb_color_get_green:
- * color: a #hb_color_t we are interested in its channels.
+ * @color: an #hb_color_t we are interested in its channels.
*
- * Return value: Green channel value of the given color
+ * Fetches the green channel of the given @color.
+ *
+ * Return value: Green channel value
*
* Since: 2.1.0
*/
@@ -1097,9 +1125,11 @@ uint8_t
/**
* hb_color_get_blue:
- * color: a #hb_color_t we are interested in its channels.
+ * @color: an #hb_color_t we are interested in its channels.
+ *
+ * Fetches the blue channel of the given @color.
*
- * Return value: Blue channel value of the given color
+ * Return value: Blue channel value
*
* Since: 2.1.0
*/
diff --git a/thirdparty/harfbuzz/src/hb-common.h b/thirdparty/harfbuzz/src/hb-common.h
index efe185cdfd..532fd428cb 100644
--- a/thirdparty/harfbuzz/src/hb-common.h
+++ b/thirdparty/harfbuzz/src/hb-common.h
@@ -26,7 +26,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
@@ -135,7 +135,7 @@ typedef union _hb_var_int_t {
/**
* hb_tag_t:
- *
+ *
* Data type for tag identifiers. Tags are four
* byte integers, each byte representing a character.
*
@@ -148,22 +148,48 @@ typedef uint32_t hb_tag_t;
/**
* HB_TAG:
+ * @c1: 1st character of the tag
+ * @c2: 2nd character of the tag
+ * @c3: 3rd character of the tag
+ * @c4: 4th character of the tag
*
- * Constructs an #hb_tag_t from four characters.
+ * Constructs an #hb_tag_t from four character literals.
*
**/
#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF)))
/**
* HB_UNTAG:
+ * @tag: an #hb_tag_t
+ *
+ * Extracts four character literals from an #hb_tag_t.
*
- * Extracts the characters from an #hb_tag_t.
+ * Since: 0.6.0
*
**/
#define HB_UNTAG(tag) (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&0xFF)
+/**
+ * HB_TAG_NONE:
+ *
+ * Unset #hb_tag_t.
+ */
#define HB_TAG_NONE HB_TAG(0,0,0,0)
+/**
+ * HB_TAG_MAX:
+ *
+ * Maximum possible unsigned #hb_tag_t.
+ *
+ * Since: 0.9.26
+ */
#define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
+/**
+ * HB_TAG_MAX_SIGNED:
+ *
+ * Maximum possible signed #hb_tag_t.
+ *
+ * Since: 0.9.33
+ */
#define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff)
/* len=-1 means str is NUL-terminated. */
@@ -263,6 +289,13 @@ hb_direction_to_string (hb_direction_t direction);
/* hb_language_t */
+/**
+ * hb_language_t:
+ *
+ * Data type for languages. Each #hb_language_t corresponds to a BCP 47
+ * language tag.
+ *
+ */
typedef const struct hb_language_impl_t *hb_language_t;
HB_EXTERN hb_language_t
@@ -271,6 +304,13 @@ hb_language_from_string (const char *str, int len);
HB_EXTERN const char *
hb_language_to_string (hb_language_t language);
+/**
+ * HB_LANGUAGE_INVALID:
+ *
+ * An unset #hb_language_t.
+ *
+ * Since: 0.6.0
+ */
#define HB_LANGUAGE_INVALID ((hb_language_t) 0)
HB_EXTERN hb_language_t
@@ -279,160 +319,164 @@ hb_language_get_default (void);
/**
* hb_script_t:
- * @HB_SCRIPT_COMMON: HB_TAG ('Z','y','y','y')
- * @HB_SCRIPT_INHERITED: HB_TAG ('Z','i','n','h')
- * @HB_SCRIPT_UNKNOWN: HB_TAG ('Z','z','z','z')
- * @HB_SCRIPT_ARABIC
- * @HB_SCRIPT_ARMENIAN
- * @HB_SCRIPT_BENGALI
- * @HB_SCRIPT_CYRILLIC
- * @HB_SCRIPT_DEVANAGARI
- * @HB_SCRIPT_GEORGIAN
- * @HB_SCRIPT_GREEK
- * @HB_SCRIPT_GUJARATI
- * @HB_SCRIPT_GURMUKHI
- * @HB_SCRIPT_HANGUL
- * @HB_SCRIPT_HAN
- * @HB_SCRIPT_HEBREW
- * @HB_SCRIPT_HIRAGANA
- * @HB_SCRIPT_KANNADA
- * @HB_SCRIPT_KATAKANA
- * @HB_SCRIPT_LAO
- * @HB_SCRIPT_LATIN
- * @HB_SCRIPT_MALAYALAM
- * @HB_SCRIPT_ORIYA
- * @HB_SCRIPT_TAMIL
- * @HB_SCRIPT_TELUGU
- * @HB_SCRIPT_THAI
- * @HB_SCRIPT_TIBETAN
- * @HB_SCRIPT_BOPOMOFO
- * @HB_SCRIPT_BRAILLE
- * @HB_SCRIPT_CANADIAN_SYLLABICS
- * @HB_SCRIPT_CHEROKEE
- * @HB_SCRIPT_ETHIOPIC
- * @HB_SCRIPT_KHMER
- * @HB_SCRIPT_MONGOLIAN
- * @HB_SCRIPT_MYANMAR
- * @HB_SCRIPT_OGHAM
- * @HB_SCRIPT_RUNIC
- * @HB_SCRIPT_SINHALA
- * @HB_SCRIPT_SYRIAC
- * @HB_SCRIPT_THAANA
- * @HB_SCRIPT_YI
- * @HB_SCRIPT_DESERET
- * @HB_SCRIPT_GOTHIC
- * @HB_SCRIPT_OLD_ITALIC
- * @HB_SCRIPT_BUHID
- * @HB_SCRIPT_HANUNOO
- * @HB_SCRIPT_TAGALOG
- * @HB_SCRIPT_TAGBANWA
- * @HB_SCRIPT_CYPRIOT
- * @HB_SCRIPT_LIMBU
- * @HB_SCRIPT_LINEAR_B
- * @HB_SCRIPT_OSMANYA
- * @HB_SCRIPT_SHAVIAN
- * @HB_SCRIPT_TAI_LE
- * @HB_SCRIPT_UGARITIC
- * @HB_SCRIPT_BUGINESE
- * @HB_SCRIPT_COPTIC
- * @HB_SCRIPT_GLAGOLITIC
- * @HB_SCRIPT_KHAROSHTHI
- * @HB_SCRIPT_NEW_TAI_LUE
- * @HB_SCRIPT_OLD_PERSIAN
- * @HB_SCRIPT_SYLOTI_NAGRI
- * @HB_SCRIPT_TIFINAGH
- * @HB_SCRIPT_BALINESE
- * @HB_SCRIPT_CUNEIFORM
- * @HB_SCRIPT_NKO
- * @HB_SCRIPT_PHAGS_PA
- * @HB_SCRIPT_PHOENICIAN
- * @HB_SCRIPT_CARIAN
- * @HB_SCRIPT_CHAM
- * @HB_SCRIPT_KAYAH_LI
- * @HB_SCRIPT_LEPCHA
- * @HB_SCRIPT_LYCIAN
- * @HB_SCRIPT_LYDIAN
- * @HB_SCRIPT_OL_CHIKI
- * @HB_SCRIPT_REJANG
- * @HB_SCRIPT_SAURASHTRA
- * @HB_SCRIPT_SUNDANESE
- * @HB_SCRIPT_VAI
- * @HB_SCRIPT_AVESTAN
- * @HB_SCRIPT_BAMUM
- * @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS
- * @HB_SCRIPT_IMPERIAL_ARAMAIC
- * @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI
- * @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN
- * @HB_SCRIPT_JAVANESE
- * @HB_SCRIPT_KAITHI
- * @HB_SCRIPT_LISU
- * @HB_SCRIPT_MEETEI_MAYEK
- * @HB_SCRIPT_OLD_SOUTH_ARABIAN
- * @HB_SCRIPT_OLD_TURKIC
- * @HB_SCRIPT_SAMARITAN
- * @HB_SCRIPT_TAI_THAM
- * @HB_SCRIPT_TAI_VIET
- * @HB_SCRIPT_BATAK
- * @HB_SCRIPT_BRAHMI
- * @HB_SCRIPT_MANDAIC
- * @HB_SCRIPT_CHAKMA
- * @HB_SCRIPT_MEROITIC_CURSIVE
- * @HB_SCRIPT_MEROITIC_HIEROGLYPHS
- * @HB_SCRIPT_MIAO
- * @HB_SCRIPT_SHARADA
- * @HB_SCRIPT_SORA_SOMPENG
- * @HB_SCRIPT_TAKRI
- * @HB_SCRIPT_BASSA_VAH
- * @HB_SCRIPT_CAUCASIAN_ALBANIAN
- * @HB_SCRIPT_DUPLOYAN
- * @HB_SCRIPT_ELBASAN
- * @HB_SCRIPT_GRANTHA
- * @HB_SCRIPT_KHOJKI
- * @HB_SCRIPT_KHUDAWADI
- * @HB_SCRIPT_LINEAR_A
- * @HB_SCRIPT_MAHAJANI
- * @HB_SCRIPT_MANICHAEAN
- * @HB_SCRIPT_MENDE_KIKAKUI
- * @HB_SCRIPT_MODI
- * @HB_SCRIPT_MRO
- * @HB_SCRIPT_NABATAEAN
- * @HB_SCRIPT_OLD_NORTH_ARABIAN
- * @HB_SCRIPT_OLD_PERMIC
- * @HB_SCRIPT_PAHAWH_HMONG
- * @HB_SCRIPT_PALMYRENE
- * @HB_SCRIPT_PAU_CIN_HAU
- * @HB_SCRIPT_PSALTER_PAHLAVI
- * @HB_SCRIPT_SIDDHAM
- * @HB_SCRIPT_TIRHUTA
- * @HB_SCRIPT_WARANG_CITI
- * @HB_SCRIPT_AHOM
- * @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS
- * @HB_SCRIPT_HATRAN
- * @HB_SCRIPT_MULTANI
- * @HB_SCRIPT_OLD_HUNGARIAN
- * @HB_SCRIPT_SIGNWRITING
- * @HB_SCRIPT_ADLAM
- * @HB_SCRIPT_BHAIKSUKI
- * @HB_SCRIPT_MARCHEN
- * @HB_SCRIPT_OSAGE
- * @HB_SCRIPT_TANGUT
- * @HB_SCRIPT_NEWA
- * @HB_SCRIPT_MASARAM_GONDI
- * @HB_SCRIPT_NUSHU
- * @HB_SCRIPT_SOYOMBO
- * @HB_SCRIPT_ZANABAZAR_SQUARE
- * @HB_SCRIPT_DOGRA
- * @HB_SCRIPT_GUNJALA_GONDI
- * @HB_SCRIPT_HANIFI_ROHINGYA
- * @HB_SCRIPT_MAKASAR
- * @HB_SCRIPT_MEDEFAIDRIN
- * @HB_SCRIPT_OLD_SOGDIAN
- * @HB_SCRIPT_SOGDIAN
- * @HB_SCRIPT_ELYMAIC
- * @HB_SCRIPT_NANDINAGARI
- * @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG
- * @HB_SCRIPT_WANCHO
- * @HB_SCRIPT_INVALID: #HB_TAG_NONE
+ * @HB_SCRIPT_COMMON: `Zyyy`
+ * @HB_SCRIPT_INHERITED: `Zinh`
+ * @HB_SCRIPT_UNKNOWN: `Zzzz`
+ * @HB_SCRIPT_ARABIC: `Arab`
+ * @HB_SCRIPT_ARMENIAN: `Armn`
+ * @HB_SCRIPT_BENGALI: `Beng`
+ * @HB_SCRIPT_CYRILLIC: `Cyrl`
+ * @HB_SCRIPT_DEVANAGARI: `Deva`
+ * @HB_SCRIPT_GEORGIAN: `Geor`
+ * @HB_SCRIPT_GREEK: `Grek`
+ * @HB_SCRIPT_GUJARATI: `Gujr`
+ * @HB_SCRIPT_GURMUKHI: `Guru`
+ * @HB_SCRIPT_HANGUL: `Hang`
+ * @HB_SCRIPT_HAN: `Hani`
+ * @HB_SCRIPT_HEBREW: `Hebr`
+ * @HB_SCRIPT_HIRAGANA: `Hira`
+ * @HB_SCRIPT_KANNADA: `Knda`
+ * @HB_SCRIPT_KATAKANA: `Kana`
+ * @HB_SCRIPT_LAO: `Laoo`
+ * @HB_SCRIPT_LATIN: `Latn`
+ * @HB_SCRIPT_MALAYALAM: `Mlym`
+ * @HB_SCRIPT_ORIYA: `Orya`
+ * @HB_SCRIPT_TAMIL: `Taml`
+ * @HB_SCRIPT_TELUGU: `Telu`
+ * @HB_SCRIPT_THAI: `Thai`
+ * @HB_SCRIPT_TIBETAN: `Tibt`
+ * @HB_SCRIPT_BOPOMOFO: `Bopo`
+ * @HB_SCRIPT_BRAILLE: `Brai`
+ * @HB_SCRIPT_CANADIAN_SYLLABICS: `Cans`
+ * @HB_SCRIPT_CHEROKEE: `Cher`
+ * @HB_SCRIPT_ETHIOPIC: `Ethi`
+ * @HB_SCRIPT_KHMER: `Khmr`
+ * @HB_SCRIPT_MONGOLIAN: `Mong`
+ * @HB_SCRIPT_MYANMAR: `Mymr`
+ * @HB_SCRIPT_OGHAM: `Ogam`
+ * @HB_SCRIPT_RUNIC: `Runr`
+ * @HB_SCRIPT_SINHALA: `Sinh`
+ * @HB_SCRIPT_SYRIAC: `Syrc`
+ * @HB_SCRIPT_THAANA: `Thaa`
+ * @HB_SCRIPT_YI: `Yiii`
+ * @HB_SCRIPT_DESERET: `Dsrt`
+ * @HB_SCRIPT_GOTHIC: `Goth`
+ * @HB_SCRIPT_OLD_ITALIC: `Ital`
+ * @HB_SCRIPT_BUHID: `Buhd`
+ * @HB_SCRIPT_HANUNOO: `Hano`
+ * @HB_SCRIPT_TAGALOG: `Tglg`
+ * @HB_SCRIPT_TAGBANWA: `Tagb`
+ * @HB_SCRIPT_CYPRIOT: `Cprt`
+ * @HB_SCRIPT_LIMBU: `Limb`
+ * @HB_SCRIPT_LINEAR_B: `Linb`
+ * @HB_SCRIPT_OSMANYA: `Osma`
+ * @HB_SCRIPT_SHAVIAN: `Shaw`
+ * @HB_SCRIPT_TAI_LE: `Tale`
+ * @HB_SCRIPT_UGARITIC: `Ugar`
+ * @HB_SCRIPT_BUGINESE: `Bugi`
+ * @HB_SCRIPT_COPTIC: `Copt`
+ * @HB_SCRIPT_GLAGOLITIC: `Glag`
+ * @HB_SCRIPT_KHAROSHTHI: `Khar`
+ * @HB_SCRIPT_NEW_TAI_LUE: `Talu`
+ * @HB_SCRIPT_OLD_PERSIAN: `Xpeo`
+ * @HB_SCRIPT_SYLOTI_NAGRI: `Sylo`
+ * @HB_SCRIPT_TIFINAGH: `Tfng`
+ * @HB_SCRIPT_BALINESE: `Bali`
+ * @HB_SCRIPT_CUNEIFORM: `Xsux`
+ * @HB_SCRIPT_NKO: `Nkoo`
+ * @HB_SCRIPT_PHAGS_PA: `Phag`
+ * @HB_SCRIPT_PHOENICIAN: `Phnx`
+ * @HB_SCRIPT_CARIAN: `Cari`
+ * @HB_SCRIPT_CHAM: `Cham`
+ * @HB_SCRIPT_KAYAH_LI: `Kali`
+ * @HB_SCRIPT_LEPCHA: `Lepc`
+ * @HB_SCRIPT_LYCIAN: `Lyci`
+ * @HB_SCRIPT_LYDIAN: `Lydi`
+ * @HB_SCRIPT_OL_CHIKI: `Olck`
+ * @HB_SCRIPT_REJANG: `Rjng`
+ * @HB_SCRIPT_SAURASHTRA: `Saur`
+ * @HB_SCRIPT_SUNDANESE: `Sund`
+ * @HB_SCRIPT_VAI: `Vaii`
+ * @HB_SCRIPT_AVESTAN: `Avst`
+ * @HB_SCRIPT_BAMUM: `Bamu`
+ * @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: `Egyp`
+ * @HB_SCRIPT_IMPERIAL_ARAMAIC: `Armi`
+ * @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: `Phli`
+ * @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: `Prti`
+ * @HB_SCRIPT_JAVANESE: `Java`
+ * @HB_SCRIPT_KAITHI: `Kthi`
+ * @HB_SCRIPT_LISU: `Lisu`
+ * @HB_SCRIPT_MEETEI_MAYEK: `Mtei`
+ * @HB_SCRIPT_OLD_SOUTH_ARABIAN: `Sarb`
+ * @HB_SCRIPT_OLD_TURKIC: `Orkh`
+ * @HB_SCRIPT_SAMARITAN: `Samr`
+ * @HB_SCRIPT_TAI_THAM: `Lana`
+ * @HB_SCRIPT_TAI_VIET: `Tavt`
+ * @HB_SCRIPT_BATAK: `Batk`
+ * @HB_SCRIPT_BRAHMI: `Brah`
+ * @HB_SCRIPT_MANDAIC: `Mand`
+ * @HB_SCRIPT_CHAKMA: `Cakm`
+ * @HB_SCRIPT_MEROITIC_CURSIVE: `Merc`
+ * @HB_SCRIPT_MEROITIC_HIEROGLYPHS: `Mero`
+ * @HB_SCRIPT_MIAO: `Plrd`
+ * @HB_SCRIPT_SHARADA: `Shrd`
+ * @HB_SCRIPT_SORA_SOMPENG: `Sora`
+ * @HB_SCRIPT_TAKRI: `Takr`
+ * @HB_SCRIPT_BASSA_VAH: `Bass`, Since: 0.9.30
+ * @HB_SCRIPT_CAUCASIAN_ALBANIAN: `Aghb`, Since: 0.9.30
+ * @HB_SCRIPT_DUPLOYAN: `Dupl`, Since: 0.9.30
+ * @HB_SCRIPT_ELBASAN: `Elba`, Since: 0.9.30
+ * @HB_SCRIPT_GRANTHA: `Gran`, Since: 0.9.30
+ * @HB_SCRIPT_KHOJKI: `Khoj`, Since: 0.9.30
+ * @HB_SCRIPT_KHUDAWADI: `Sind`, Since: 0.9.30
+ * @HB_SCRIPT_LINEAR_A: `Lina`, Since: 0.9.30
+ * @HB_SCRIPT_MAHAJANI: `Mahj`, Since: 0.9.30
+ * @HB_SCRIPT_MANICHAEAN: `Mani`, Since: 0.9.30
+ * @HB_SCRIPT_MENDE_KIKAKUI: `Mend`, Since: 0.9.30
+ * @HB_SCRIPT_MODI: `Modi`, Since: 0.9.30
+ * @HB_SCRIPT_MRO: `Mroo`, Since: 0.9.30
+ * @HB_SCRIPT_NABATAEAN: `Nbat`, Since: 0.9.30
+ * @HB_SCRIPT_OLD_NORTH_ARABIAN: `Narb`, Since: 0.9.30
+ * @HB_SCRIPT_OLD_PERMIC: `Perm`, Since: 0.9.30
+ * @HB_SCRIPT_PAHAWH_HMONG: `Hmng`, Since: 0.9.30
+ * @HB_SCRIPT_PALMYRENE: `Palm`, Since: 0.9.30
+ * @HB_SCRIPT_PAU_CIN_HAU: `Pauc`, Since: 0.9.30
+ * @HB_SCRIPT_PSALTER_PAHLAVI: `Phlp`, Since: 0.9.30
+ * @HB_SCRIPT_SIDDHAM: `Sidd`, Since: 0.9.30
+ * @HB_SCRIPT_TIRHUTA: `Tirh`, Since: 0.9.30
+ * @HB_SCRIPT_WARANG_CITI: `Wara`, Since: 0.9.30
+ * @HB_SCRIPT_AHOM: `Ahom`, Since: 0.9.30
+ * @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS: `Hluw`, Since: 0.9.30
+ * @HB_SCRIPT_HATRAN: `Hatr`, Since: 0.9.30
+ * @HB_SCRIPT_MULTANI: `Mult`, Since: 0.9.30
+ * @HB_SCRIPT_OLD_HUNGARIAN: `Hung`, Since: 0.9.30
+ * @HB_SCRIPT_SIGNWRITING: `Sgnw`, Since: 0.9.30
+ * @HB_SCRIPT_ADLAM: `Adlm`, Since: 1.3.0
+ * @HB_SCRIPT_BHAIKSUKI: `Bhks`, Since: 1.3.0
+ * @HB_SCRIPT_MARCHEN: `Marc`, Since: 1.3.0
+ * @HB_SCRIPT_OSAGE: `Osge`, Since: 1.3.0
+ * @HB_SCRIPT_TANGUT: `Tang`, Since: 1.3.0
+ * @HB_SCRIPT_NEWA: `Newa`, Since: 1.3.0
+ * @HB_SCRIPT_MASARAM_GONDI: `Gonm`, Since: 1.6.0
+ * @HB_SCRIPT_NUSHU: `Nshu`, Since: 1.6.0
+ * @HB_SCRIPT_SOYOMBO: `Soyo`, Since: 1.6.0
+ * @HB_SCRIPT_ZANABAZAR_SQUARE: `Zanb`, Since: 1.6.0
+ * @HB_SCRIPT_DOGRA: `Dogr`, Since: 1.8.0
+ * @HB_SCRIPT_GUNJALA_GONDI: `Gong`, Since: 1.8.0
+ * @HB_SCRIPT_HANIFI_ROHINGYA: `Rohg`, Since: 1.8.0
+ * @HB_SCRIPT_MAKASAR: `Maka`, Since: 1.8.0
+ * @HB_SCRIPT_MEDEFAIDRIN: `Medf`, Since: 1.8.0
+ * @HB_SCRIPT_OLD_SOGDIAN: `Sogo`, Since: 1.8.0
+ * @HB_SCRIPT_SOGDIAN: `Sogd`, Since: 1.8.0
+ * @HB_SCRIPT_ELYMAIC: `Elym`, Since: 2.4.0
+ * @HB_SCRIPT_NANDINAGARI: `Nand`, Since: 2.4.0
+ * @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG: `Hmnp`, Since: 2.4.0
+ * @HB_SCRIPT_WANCHO: `Wcho`, Since: 2.4.0
+ * @HB_SCRIPT_CHORASMIAN: `Chrs`, Since: 2.6.7
+ * @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7
+ * @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7
+ * @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7
+ * @HB_SCRIPT_INVALID: No script set
*
* Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
* to the four-letter values defined by [ISO 15924](https://unicode.org/iso15924/).
@@ -441,208 +485,208 @@ hb_language_get_default (void);
*
**/
-/* https://unicode.org/iso15924/ */
/* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */
-/* Unicode Character Database property: Script (sc) */
typedef enum
{
- /*1.1*/ HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'),
- /*1.1*/ HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'),
- /*5.0*/ HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'),
-
- /*1.1*/ HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'),
- /*1.1*/ HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'),
- /*1.1*/ HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'),
- /*1.1*/ HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'),
- /*1.1*/ HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'),
- /*1.1*/ HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'),
- /*1.1*/ HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'),
- /*1.1*/ HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'),
- /*1.1*/ HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'),
- /*1.1*/ HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'),
- /*1.1*/ HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'),
- /*1.1*/ HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'),
- /*1.1*/ HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'),
- /*1.1*/ HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'),
- /*1.1*/ HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'),
- /*1.1*/ HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'),
- /*1.1*/ HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'),
- /*1.1*/ HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'),
- /*1.1*/ HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'),
- /*1.1*/ HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'),
- /*1.1*/ HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'),
- /*1.1*/ HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'),
-
- /*2.0*/ HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'),
-
- /*3.0*/ HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'),
- /*3.0*/ HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'),
- /*3.0*/ HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'),
- /*3.0*/ HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'),
- /*3.0*/ HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'),
- /*3.0*/ HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'),
- /*3.0*/ HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'),
- /*3.0*/ HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'),
- /*3.0*/ HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'),
- /*3.0*/ HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'),
- /*3.0*/ HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'),
- /*3.0*/ HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'),
- /*3.0*/ HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'),
- /*3.0*/ HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'),
-
- /*3.1*/ HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'),
- /*3.1*/ HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'),
- /*3.1*/ HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'),
-
- /*3.2*/ HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'),
- /*3.2*/ HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'),
- /*3.2*/ HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'),
- /*3.2*/ HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'),
-
- /*4.0*/ HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'),
- /*4.0*/ HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'),
- /*4.0*/ HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'),
- /*4.0*/ HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'),
- /*4.0*/ HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'),
- /*4.0*/ HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'),
- /*4.0*/ HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'),
-
- /*4.1*/ HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'),
- /*4.1*/ HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'),
- /*4.1*/ HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'),
- /*4.1*/ HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'),
- /*4.1*/ HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'),
- /*4.1*/ HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'),
- /*4.1*/ HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'),
- /*4.1*/ HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'),
-
- /*5.0*/ HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'),
- /*5.0*/ HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'),
- /*5.0*/ HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'),
- /*5.0*/ HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'),
- /*5.0*/ HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'),
-
- /*5.1*/ HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'),
- /*5.1*/ HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'),
- /*5.1*/ HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'),
- /*5.1*/ HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'),
- /*5.1*/ HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'),
- /*5.1*/ HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'),
- /*5.1*/ HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'),
- /*5.1*/ HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'),
- /*5.1*/ HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'),
- /*5.1*/ HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'),
- /*5.1*/ HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'),
-
- /*5.2*/ HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'),
- /*5.2*/ HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'),
- /*5.2*/ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'),
- /*5.2*/ HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'),
- /*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'),
- /*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'),
- /*5.2*/ HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'),
- /*5.2*/ HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'),
- /*5.2*/ HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'),
- /*5.2*/ HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'),
- /*5.2*/ HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'),
- /*5.2*/ HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'),
- /*5.2*/ HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'),
- /*5.2*/ HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'),
- /*5.2*/ HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'),
-
- /*6.0*/ HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'),
- /*6.0*/ HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'),
- /*6.0*/ HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'),
-
- /*6.1*/ HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'),
- /*6.1*/ HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'),
- /*6.1*/ HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'),
- /*6.1*/ HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'),
- /*6.1*/ HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'),
- /*6.1*/ HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'),
- /*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'),
+ HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), /*1.1*/
+ HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), /*1.1*/
+ HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), /*5.0*/
+
+ HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), /*1.1*/
+ HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), /*1.1*/
+ HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), /*1.1*/
+ HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), /*1.1*/
+ HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), /*1.1*/
+ HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), /*1.1*/
+ HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), /*1.1*/
+ HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), /*1.1*/
+ HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), /*1.1*/
+ HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), /*1.1*/
+ HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), /*1.1*/
+ HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), /*1.1*/
+ HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), /*1.1*/
+ HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), /*1.1*/
+ HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), /*1.1*/
+ HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), /*1.1*/
+ HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), /*1.1*/
+ HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), /*1.1*/
+ HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), /*1.1*/
+ HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), /*1.1*/
+ HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), /*1.1*/
+ HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), /*1.1*/
+
+ HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), /*2.0*/
+
+ HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), /*3.0*/
+ HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), /*3.0*/
+ HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), /*3.0*/
+ HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), /*3.0*/
+ HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), /*3.0*/
+ HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), /*3.0*/
+ HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), /*3.0*/
+ HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), /*3.0*/
+ HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), /*3.0*/
+ HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), /*3.0*/
+ HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), /*3.0*/
+ HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), /*3.0*/
+ HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), /*3.0*/
+ HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), /*3.0*/
+
+ HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), /*3.1*/
+ HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), /*3.1*/
+ HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), /*3.1*/
+
+ HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), /*3.2*/
+ HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), /*3.2*/
+ HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), /*3.2*/
+ HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), /*3.2*/
+
+ HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), /*4.0*/
+ HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), /*4.0*/
+ HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), /*4.0*/
+ HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), /*4.0*/
+ HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), /*4.0*/
+ HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), /*4.0*/
+ HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), /*4.0*/
+
+ HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), /*4.1*/
+ HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), /*4.1*/
+ HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), /*4.1*/
+ HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), /*4.1*/
+ HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), /*4.1*/
+ HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), /*4.1*/
+ HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), /*4.1*/
+ HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), /*4.1*/
+
+ HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), /*5.0*/
+ HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), /*5.0*/
+ HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), /*5.0*/
+ HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), /*5.0*/
+ HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), /*5.0*/
+
+ HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), /*5.1*/
+ HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), /*5.1*/
+ HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), /*5.1*/
+ HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), /*5.1*/
+ HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), /*5.1*/
+ HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), /*5.1*/
+ HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), /*5.1*/
+ HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), /*5.1*/
+ HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), /*5.1*/
+ HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), /*5.1*/
+ HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), /*5.1*/
+
+ HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), /*5.2*/
+ HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), /*5.2*/
+ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), /*5.2*/
+ HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), /*5.2*/
+ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), /*5.2*/
+ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), /*5.2*/
+ HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), /*5.2*/
+ HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), /*5.2*/
+ HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), /*5.2*/
+ HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), /*5.2*/
+ HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), /*5.2*/
+ HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), /*5.2*/
+ HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), /*5.2*/
+ HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), /*5.2*/
+ HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), /*5.2*/
+
+ HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), /*6.0*/
+ HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), /*6.0*/
+ HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), /*6.0*/
+
+ HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), /*6.1*/
+ HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), /*6.1*/
+ HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), /*6.1*/
+ HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), /*6.1*/
+ HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), /*6.1*/
+ HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), /*6.1*/
+ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /*6.1*/
/*
* Since: 0.9.30
*/
- /*7.0*/ HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'),
- /*7.0*/ HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'),
- /*7.0*/ HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'),
- /*7.0*/ HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'),
- /*7.0*/ HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'),
- /*7.0*/ HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'),
- /*7.0*/ HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'),
- /*7.0*/ HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'),
- /*7.0*/ HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'),
- /*7.0*/ HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'),
- /*7.0*/ HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'),
- /*7.0*/ HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'),
- /*7.0*/ HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'),
- /*7.0*/ HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'),
- /*7.0*/ HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'),
- /*7.0*/ HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'),
- /*7.0*/ HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'),
- /*7.0*/ HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'),
- /*7.0*/ HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'),
- /*7.0*/ HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'),
- /*7.0*/ HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'),
- /*7.0*/ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'),
- /*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'),
-
- /*8.0*/ HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'),
- /*8.0*/ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'),
- /*8.0*/ HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'),
- /*8.0*/ HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'),
- /*8.0*/ HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'),
- /*8.0*/ HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'),
+ HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), /*7.0*/
+ HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), /*7.0*/
+ HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), /*7.0*/
+ HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), /*7.0*/
+ HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), /*7.0*/
+ HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), /*7.0*/
+ HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), /*7.0*/
+ HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), /*7.0*/
+ HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), /*7.0*/
+ HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), /*7.0*/
+ HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), /*7.0*/
+ HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), /*7.0*/
+ HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), /*7.0*/
+ HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), /*7.0*/
+ HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), /*7.0*/
+ HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), /*7.0*/
+ HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), /*7.0*/
+ HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), /*7.0*/
+ HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), /*7.0*/
+ HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), /*7.0*/
+ HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), /*7.0*/
+ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/
+ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), /*7.0*/
+
+ HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), /*8.0*/
+ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), /*8.0*/
+ HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), /*8.0*/
+ HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), /*8.0*/
+ HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), /*8.0*/
+ HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), /*8.0*/
/*
* Since 1.3.0
*/
- /*9.0*/ HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'),
- /*9.0*/ HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'),
- /*9.0*/ HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'),
- /*9.0*/ HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'),
- /*9.0*/ HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'),
- /*9.0*/ HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'),
+ HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), /*9.0*/
+ HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), /*9.0*/
+ HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), /*9.0*/
+ HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), /*9.0*/
+ HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/
+ HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), /*9.0*/
/*
* Since 1.6.0
*/
- /*10.0*/HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'),
- /*10.0*/HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'),
- /*10.0*/HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'),
- /*10.0*/HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'),
+ HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), /*10.0*/
+ HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), /*10.0*/
+ HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), /*10.0*/
+ HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), /*10.0*/
/*
* Since 1.8.0
*/
- /*11.0*/HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'),
- /*11.0*/HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'),
- /*11.0*/HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'),
- /*11.0*/HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'),
- /*11.0*/HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'),
- /*11.0*/HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'),
- /*11.0*/HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'),
+ HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), /*11.0*/
+ HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), /*11.0*/
+ HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), /*11.0*/
+ HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), /*11.0*/
+ HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), /*11.0*/
+ HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), /*11.0*/
+ HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), /*11.0*/
/*
* Since 2.4.0
*/
- /*12.0*/HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'),
- /*12.0*/HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'),
- /*12.0*/HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'),
- /*12.0*/HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'),
+ HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), /*12.0*/
+ HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), /*12.0*/
+ HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), /*12.0*/
+ HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), /*12.0*/
/*
* Since 2.6.7
*/
- /*13.0*/HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'),
- /*13.0*/HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'),
- /*13.0*/HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'),
- /*13.0*/HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'),
+ HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), /*13.0*/
+ HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), /*13.0*/
+ HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/
+ HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/
/* No script set. */
- HB_SCRIPT_INVALID = HB_TAG_NONE,
+ HB_SCRIPT_INVALID = HB_TAG_NONE,
+
+ /*< private >*/
/* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
* without risking undefined behavior. We have two, for historical reasons.
@@ -687,19 +731,33 @@ typedef struct hb_user_data_key_t {
char unused;
} hb_user_data_key_t;
+/**
+ * hb_destroy_func_t:
+ * @user_data: the data to be destroyed
+ *
+ * A virtual method for destroy user-data callbacks.
+ *
+ */
typedef void (*hb_destroy_func_t) (void *user_data);
/* Font features and variations. */
/**
- * HB_FEATURE_GLOBAL_START
+ * HB_FEATURE_GLOBAL_START:
+ *
+ * Special setting for #hb_feature_t.start to apply the feature from the start
+ * of the buffer.
*
* Since: 2.0.0
*/
#define HB_FEATURE_GLOBAL_START 0
+
/**
- * HB_FEATURE_GLOBAL_END
+ * HB_FEATURE_GLOBAL_END:
+ *
+ * Special setting for #hb_feature_t.end to apply the feature from to the end
+ * of the buffer.
*
* Since: 2.0.0
*/
@@ -717,7 +775,7 @@ typedef void (*hb_destroy_func_t) (void *user_data);
* The #hb_feature_t is the structure that holds information about requested
* feature application. The feature will be applied with the given value to all
* glyphs which are in clusters between @start (inclusive) and @end (exclusive).
- * Setting start to @HB_FEATURE_GLOBAL_START and end to @HB_FEATURE_GLOBAL_END
+ * Setting start to #HB_FEATURE_GLOBAL_START and end to #HB_FEATURE_GLOBAL_END
* specifies that the feature always applies to the entire buffer.
*/
typedef struct hb_feature_t {
@@ -741,8 +799,8 @@ hb_feature_to_string (hb_feature_t *feature,
* @value: The value of the variation axis
*
* Data type for holding variation data. Registered OpenType
- * variation-axis tags are listed at
- * https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg
+ * variation-axis tags are listed in
+ * [OpenType Axis Tag Registry](https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg).
*
* Since: 1.4.2
*/
@@ -769,6 +827,17 @@ hb_variation_to_string (hb_variation_t *variation,
*/
typedef uint32_t hb_color_t;
+/**
+ * HB_COLOR:
+ * @b: blue channel value
+ * @g: green channel value
+ * @r: red channel value
+ * @a: alpha channel value
+ *
+ * Constructs an #hb_color_t from four integers.
+ *
+ * Since: 2.1.0
+ */
#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a)))
HB_EXTERN uint8_t
diff --git a/thirdparty/harfbuzz/src/hb-coretext.cc b/thirdparty/harfbuzz/src/hb-coretext.cc
index 7b6b2bd5ef..461bd20e65 100644
--- a/thirdparty/harfbuzz/src/hb-coretext.cc
+++ b/thirdparty/harfbuzz/src/hb-coretext.cc
@@ -34,7 +34,6 @@
#include "hb-coretext.h"
#include "hb-aat-layout.hh"
-#include <math.h>
/**
@@ -190,7 +189,10 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
* reconfiguring the cascade list causes CoreText crashes. For details, see
* crbug.com/549610 */
// 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
if (&CTGetCoreTextVersion != nullptr && CTGetCoreTextVersion() < 0x00070000) {
+#pragma GCC diagnostic pop
CFStringRef fontName = CTFontCopyPostScriptName (ct_font);
bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo;
CFRelease (fontName);
@@ -346,7 +348,7 @@ retry:
const hb_coretext_font_data_t *data = font->data.coretext;
if (unlikely (!data)) return nullptr;
- if (fabs (CTFontGetSize ((CTFontRef) data) - (CGFloat) font->ptem) > .5)
+ if (fabs (CTFontGetSize ((CTFontRef) data) - (CGFloat) font->ptem) > (CGFloat) .5)
{
/* XXX-MT-bug
* Note that evaluating condition above can be dangerous if another thread
@@ -402,7 +404,7 @@ hb_coretext_font_create (CTFontRef ct_font)
}
/**
- * hb_coretext_face_get_ct_font:
+ * hb_coretext_font_get_ct_font:
* @font: #hb_font_t to work upon
*
* Fetches the CTFontRef associated with the specified
@@ -858,7 +860,7 @@ resize_and_retry:
buffer->len = 0;
uint32_t status_and = ~0, status_or = 0;
- double advances_so_far = 0;
+ CGFloat advances_so_far = 0;
/* For right-to-left runs, CoreText returns the glyphs positioned such that
* any trailing whitespace is to the left of (0,0). Adjust coordinate system
* to fix for that. Test with any RTL string with trailing spaces.
@@ -880,10 +882,10 @@ resize_and_retry:
status_or |= run_status;
status_and &= run_status;
DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
- double run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr);
+ CGFloat run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr);
if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
run_advance = -run_advance;
- DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance);
+ DEBUG_MSG (CORETEXT, run, "Run advance: %g", (double) run_advance);
/* CoreText does automatic font fallback (AKA "cascading") for characters
* not supported by the requested font, and provides no way to turn it off,
@@ -1062,7 +1064,7 @@ resize_and_retry:
hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult;
for (unsigned int j = 0; j < num_glyphs; j++)
{
- double advance;
+ CGFloat advance;
if (likely (j + 1 < num_glyphs))
advance = positions[j + 1].x - positions[j].x;
else /* last glyph */
@@ -1078,7 +1080,7 @@ resize_and_retry:
hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult;
for (unsigned int j = 0; j < num_glyphs; j++)
{
- double advance;
+ CGFloat advance;
if (likely (j + 1 < num_glyphs))
advance = positions[j + 1].y - positions[j].y;
else /* last glyph */
diff --git a/thirdparty/harfbuzz/src/hb-deprecated.h b/thirdparty/harfbuzz/src/hb-deprecated.h
index 43f89a4c4e..5f19125789 100644
--- a/thirdparty/harfbuzz/src/hb-deprecated.h
+++ b/thirdparty/harfbuzz/src/hb-deprecated.h
@@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
@@ -53,11 +53,50 @@ HB_BEGIN_DECLS
#ifndef HB_DISABLE_DEPRECATED
+/**
+ * HB_SCRIPT_CANADIAN_ABORIGINAL:
+ *
+ * Use #HB_SCRIPT_CANADIAN_SYLLABICS instead:
+ *
+ * Deprecated: 0.9.20
+ */
#define HB_SCRIPT_CANADIAN_ABORIGINAL HB_SCRIPT_CANADIAN_SYLLABICS
+/**
+ * HB_BUFFER_FLAGS_DEFAULT:
+ *
+ * Use #HB_BUFFER_FLAG_DEFAULT instead.
+ *
+ * Deprecated: 0.9.20
+ */
#define HB_BUFFER_FLAGS_DEFAULT HB_BUFFER_FLAG_DEFAULT
+/**
+ * HB_BUFFER_SERIALIZE_FLAGS_DEFAULT:
+ *
+ * Use #HB_BUFFER_SERIALIZE_FLAG_DEFAULT instead.
+ *
+ * Deprecated: 0.9.20
+ */
#define HB_BUFFER_SERIALIZE_FLAGS_DEFAULT HB_BUFFER_SERIALIZE_FLAG_DEFAULT
+/**
+ * hb_font_get_glyph_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @unicode: The Unicode code point to query
+ * @variation_selector: The variation-selector code point to query
+ * @glyph: (out): The glyph ID retrieved
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
+ *
+ * This method should retrieve the glyph ID for a specified Unicode code point
+ * font, with an optional variation selector.
+ *
+ * Return value: %true if data found, %false otherwise
+ * Deprecated: 1.2.3
+ *
+ **/
typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
@@ -73,6 +112,11 @@ hb_set_invert (hb_set_t *set);
/**
* hb_unicode_eastasian_width_func_t:
+ * @ufuncs: A Unicode-functions structure
+ * @unicode: The code point to query
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_unicode_funcs_t structure.
*
* Deprecated: 2.0.0
*/
@@ -82,12 +126,12 @@ typedef unsigned int (*hb_unicode_eastasian_width_func_t) (hb_unicode_funcs_t
/**
* hb_unicode_funcs_set_eastasian_width_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
+ * @ufuncs: a Unicode-function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
- *
+ * Sets the implementation function for #hb_unicode_eastasian_width_func_t.
*
* Since: 0.9.2
* Deprecated: 2.0.0
@@ -99,6 +143,10 @@ hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
/**
* hb_unicode_eastasian_width:
+ * @ufuncs: a Unicode-function structure
+ * @unicode: The code point to query
+ *
+ * Don't use. Not used by HarfBuzz.
*
* Since: 0.9.2
* Deprecated: 2.0.0
@@ -112,7 +160,7 @@ hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
* hb_unicode_decompose_compatibility_func_t:
* @ufuncs: a Unicode function structure
* @u: codepoint to decompose
- * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into
+ * @decomposed: address of codepoint array (of length #HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into
* @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func()
*
* Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed.
@@ -120,7 +168,7 @@ hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
*
* If @u has no compatibility decomposition, zero should be returned.
*
- * The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any
+ * The Unicode standard guarantees that a buffer of length #HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any
* compatibility decomposition plus an terminating value of 0. Consequently, @decompose must be allocated by the caller to be at least this length. Implementations
* of this function type must ensure that they do not write past the provided array.
*
@@ -144,10 +192,12 @@ typedef unsigned int (*hb_unicode_decompose_compatibility_func_t) (hb_unicode_
/**
* hb_unicode_funcs_set_decompose_compatibility_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
+ * @ufuncs: A Unicode-functions structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets the implementation function for #hb_unicode_decompose_compatibility_func_t.
*
*
*
@@ -165,16 +215,25 @@ hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t *decomposed);
+/**
+ * hb_font_get_glyph_v_kerning_func_t:
+ *
+ * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
+ *
+ * This method should retrieve the kerning-adjustment value for a glyph-pair in
+ * the specified font, for vertical text segments.
+ *
+ **/
typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
/**
* hb_font_funcs_set_glyph_v_kerning_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
+ * @ffuncs: A font-function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
- *
+ * Sets the implementation function for #hb_font_get_glyph_v_kerning_func_t.
*
* Since: 0.9.2
* Deprecated: 2.0.0
diff --git a/thirdparty/harfbuzz/src/hb-directwrite.cc b/thirdparty/harfbuzz/src/hb-directwrite.cc
index 92c956c032..a07302159c 100644
--- a/thirdparty/harfbuzz/src/hb-directwrite.cc
+++ b/thirdparty/harfbuzz/src/hb-directwrite.cc
@@ -957,6 +957,8 @@ _hb_directwrite_font_release (void *data)
* hb_directwrite_face_create:
* @font_face: a DirectWrite IDWriteFontFace object.
*
+ * Constructs a new face object from the specified DirectWrite IDWriteFontFace.
+ *
* Return value: #hb_face_t object corresponding to the given input
*
* Since: 2.4.0
@@ -974,6 +976,8 @@ hb_directwrite_face_create (IDWriteFontFace *font_face)
* hb_directwrite_face_get_font_face:
* @face: a #hb_face_t object
*
+* Gets the DirectWrite IDWriteFontFace associated with @face.
+*
* Return value: DirectWrite IDWriteFontFace object corresponding to the given input
*
* Since: 2.5.0
diff --git a/thirdparty/harfbuzz/src/hb-dispatch.hh b/thirdparty/harfbuzz/src/hb-dispatch.hh
index 7eace86e54..4b2b65a8de 100644
--- a/thirdparty/harfbuzz/src/hb-dispatch.hh
+++ b/thirdparty/harfbuzz/src/hb-dispatch.hh
@@ -38,7 +38,6 @@
template <typename Context, typename Return=hb_empty_t, unsigned int MaxDebugDepth=0>
struct hb_dispatch_context_t
{
- hb_dispatch_context_t () : debug_depth (0) {}
private:
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
const Context* thiz () const { return static_cast<const Context *> (this); }
@@ -54,7 +53,7 @@ struct hb_dispatch_context_t
{ return obj.dispatch (thiz (), hb_forward<Ts> (ds)...); }
static return_t no_dispatch_return_value () { return Context::default_return_value (); }
static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; }
- unsigned debug_depth;
+ unsigned debug_depth = 0;
};
diff --git a/thirdparty/harfbuzz/src/hb-draw.h b/thirdparty/harfbuzz/src/hb-draw.h
index 98eccf4c0c..bddc876399 100644
--- a/thirdparty/harfbuzz/src/hb-draw.h
+++ b/thirdparty/harfbuzz/src/hb-draw.h
@@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
diff --git a/thirdparty/harfbuzz/src/hb-face.cc b/thirdparty/harfbuzz/src/hb-face.cc
index 33a788e7c5..61bd4af7b1 100644
--- a/thirdparty/harfbuzz/src/hb-face.cc
+++ b/thirdparty/harfbuzz/src/hb-face.cc
@@ -89,8 +89,8 @@ DEFINE_NULL_INSTANCE (hb_face_t) =
nullptr, /* destroy */
0, /* index */
- HB_ATOMIC_INT_INIT (1000), /* upem */
- HB_ATOMIC_INT_INIT (0), /* num_glyphs */
+ 1000, /* upem */
+ 0, /* num_glyphs */
/* Zero for the rest is fine. */
};
@@ -100,7 +100,7 @@ DEFINE_NULL_INSTANCE (hb_face_t) =
* hb_face_create_for_tables:
* @reference_table_func: (closure user_data) (destroy destroy) (scope notified): Table-referencing function
* @user_data: A pointer to the user data
- * @destroy: (optional): A callback to call when @data is not needed anymore
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
*
* Variant of hb_face_create(), built for those cases where it is more
* convenient to provide data for individual tables instead of the whole font
@@ -235,7 +235,7 @@ hb_face_create (hb_blob_t *blob,
*
* Fetches the singleton empty face object.
*
- * Return value: (transfer full) The empty face object
+ * Return value: (transfer full): The empty face object
*
* Since: 0.9.2
**/
@@ -299,7 +299,7 @@ hb_face_destroy (hb_face_t *face)
* @face: A face object
* @key: The user-data key to set
* @data: A pointer to the user data
- * @destroy: (optional): A callback to call when @data is not needed anymore
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the given face object.
@@ -360,7 +360,7 @@ hb_face_make_immutable (hb_face_t *face)
*
* Tests whether the given face object is immutable.
*
- * Return value: True is @face is immutable, false otherwise
+ * Return value: %true is @face is immutable, %false otherwise
*
* Since: 0.9.2
**/
@@ -756,7 +756,7 @@ hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
- if (data->tables.in_error())
+ if (unlikely (data->tables.in_error()))
return false;
entry->tag = tag;
diff --git a/thirdparty/harfbuzz/src/hb-face.h b/thirdparty/harfbuzz/src/hb-face.h
index 3b18f7eef9..6ef2f8b886 100644
--- a/thirdparty/harfbuzz/src/hb-face.h
+++ b/thirdparty/harfbuzz/src/hb-face.h
@@ -24,7 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
@@ -58,6 +58,19 @@ HB_EXTERN hb_face_t *
hb_face_create (hb_blob_t *blob,
unsigned int index);
+/**
+ * hb_reference_table_func_t:
+ * @face: an #hb_face_t to reference table for
+ * @tag: the tag of the table to reference
+ * @user_data: User data pointer passed by the caller
+ *
+ * Callback function for hb_face_create_for_tables().
+ *
+ * Return value: (transfer full): A pointer to the @tag table within @face
+ *
+ * Since: 0.9.2
+ */
+
typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag, void *user_data);
/* calls destroy() when not needing user_data anymore */
diff --git a/thirdparty/harfbuzz/src/hb-face.hh b/thirdparty/harfbuzz/src/hb-face.hh
index f1b472ccf3..765f272858 100644
--- a/thirdparty/harfbuzz/src/hb-face.hh
+++ b/thirdparty/harfbuzz/src/hb-face.hh
@@ -81,7 +81,7 @@ struct hb_face_t
return blob;
}
- HB_PURE_FUNC unsigned int get_upem () const
+ unsigned int get_upem () const
{
unsigned int ret = upem.get_relaxed ();
if (unlikely (!ret))
diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc
index 5c8357ff28..37a0e7fe85 100644
--- a/thirdparty/harfbuzz/src/hb-font.cc
+++ b/thirdparty/harfbuzz/src/hb-font.cc
@@ -628,7 +628,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
* @ffuncs: The font-functions structure
* @key: The user-data key to set
* @data: A pointer to the user data set
- * @destroy: (optional): A callback to call when @data is not needed anymore
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the specified font-functions structure.
@@ -690,7 +690,7 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
*
* Tests whether a font-functions structure is immutable.
*
- * Return value: %true if @ffuncs is immutable, false otherwise
+ * Return value: %true if @ffuncs is immutable, %false otherwise
*
* Since: 0.9.2
**/
@@ -753,10 +753,10 @@ hb_font_t::has_func (unsigned int i)
* @font: #hb_font_t to work upon
* @extents: (out): The font extents retrieved
*
- * Fetches the extents for a specified font, in horizontal
+ * Fetches the extents for a specified font, for horizontal
* text segments.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 1.1.3
**/
@@ -772,10 +772,10 @@ hb_font_get_h_extents (hb_font_t *font,
* @font: #hb_font_t to work upon
* @extents: (out): The font extents retrieved
*
- * Fetches the extents for a specified font, in vertical
+ * Fetches the extents for a specified font, for vertical
* text segments.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 1.1.3
**/
@@ -790,7 +790,7 @@ hb_font_get_v_extents (hb_font_t *font,
* hb_font_get_glyph:
* @font: #hb_font_t to work upon
* @unicode: The Unicode code point to query
- * @variation_selector: (optional): A variation-selector code point
+ * @variation_selector: A variation-selector code point
* @glyph: (out): The glyph ID retrieved
*
* Fetches the glyph ID for a Unicode code point in the specified
@@ -799,7 +799,7 @@ hb_font_get_v_extents (hb_font_t *font,
* If @variation_selector is 0, calls hb_font_get_nominal_glyph();
* otherwise calls hb_font_get_variation_glyph().
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 0.9.2
**/
@@ -827,7 +827,7 @@ hb_font_get_glyph (hb_font_t *font,
* for code points modified by variation selectors. For variation-selector
* support, user hb_font_get_variation_glyph() or use hb_font_get_glyph().
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 1.2.3
**/
@@ -841,11 +841,17 @@ hb_font_get_nominal_glyph (hb_font_t *font,
/**
* hb_font_get_nominal_glyphs:
- * @font: a font.
- *
+ * @font: #hb_font_t to work upon
+ * @count: number of code points to query
+ * @first_unicode: The first Unicode code point to query
+ * @unicode_stride: The stride between successive code points
+ * @first_glyph: (out): The first glyph ID retrieved
+ * @glyph_stride: The stride between successive glyph IDs
*
+ * Fetches the nominal glyph IDs for a sequence of Unicode code points. Glyph
+ * IDs must be returned in a #hb_codepoint_t output parameter.
*
- * Return value:
+ * Return value: the number of code points processed
*
* Since: 2.6.3
**/
@@ -873,7 +879,7 @@ hb_font_get_nominal_glyphs (hb_font_t *font,
* by the specified variation-selector code point, in the specified
* font.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 1.2.3
**/
@@ -931,7 +937,7 @@ hb_font_get_glyph_v_advance (hb_font_t *font,
* @first_glyph: The first glyph ID to query
* @glyph_stride: The stride between successive glyph IDs
* @first_advance: (out): The first advance retrieved
- * @advance_stride: (out): The stride between successive advances
+ * @advance_stride: The stride between successive advances
*
* Fetches the advances for a sequence of glyph IDs in the specified
* font, for horizontal text segments.
@@ -983,7 +989,7 @@ hb_font_get_glyph_v_advances (hb_font_t* font,
* Fetches the (X,Y) coordinates of the origin for a glyph ID
* in the specified font, for horizontal text segments.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 0.9.2
**/
@@ -1006,7 +1012,7 @@ hb_font_get_glyph_h_origin (hb_font_t *font,
* Fetches the (X,Y) coordinates of the origin for a glyph ID
* in the specified font, for vertical text segments.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 0.9.2
**/
@@ -1026,7 +1032,7 @@ hb_font_get_glyph_v_origin (hb_font_t *font,
* @right_glyph: The glyph ID of the right glyph in the glyph pair
*
* Fetches the kerning-adjustment value for a glyph-pair in
- * the specified font, in horizontal text segments.
+ * the specified font, for horizontal text segments.
*
* <note>It handles legacy kerning only (as returned by the corresponding
* #hb_font_funcs_t function).</note>
@@ -1051,7 +1057,7 @@ hb_font_get_glyph_h_kerning (hb_font_t *font,
* @bottom_glyph: The glyph ID of the bottom glyph in the glyph pair
*
* Fetches the kerning-adjustment value for a glyph-pair in
- * the specified font, in vertical text segments.
+ * the specified font, for vertical text segments.
*
* <note>It handles legacy kerning only (as returned by the corresponding
* #hb_font_funcs_t function).</note>
@@ -1079,7 +1085,7 @@ hb_font_get_glyph_v_kerning (hb_font_t *font,
* Fetches the #hb_glyph_extents_t data for a glyph ID
* in the specified font.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 0.9.2
**/
@@ -1102,7 +1108,7 @@ hb_font_get_glyph_extents (hb_font_t *font,
* Fetches the (x,y) coordinates of a specified contour-point index
* in the specified glyph, within the specified font.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 0.9.2
**/
@@ -1125,7 +1131,7 @@ hb_font_get_glyph_contour_point (hb_font_t *font,
*
* Fetches the glyph-name string for a glyph ID in the specified @font.
*
- * Return value: %true if data found, zero otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 0.9.2
**/
@@ -1149,7 +1155,7 @@ hb_font_get_glyph_name (hb_font_t *font,
*
* <note>Note: @len == -1 means the name string is null-terminated.</note>
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 0.9.2
**/
@@ -1169,7 +1175,7 @@ hb_font_get_glyph_from_name (hb_font_t *font,
* hb_font_get_extents_for_direction:
* @font: #hb_font_t to work upon
* @direction: The direction of the text segment
- * @extents: (out): The #hb_glyph_extents_t retrieved
+ * @extents: (out): The #hb_font_extents_t retrieved
*
* Fetches the extents for a font in a text segment of the
* specified direction.
@@ -1364,7 +1370,7 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
* Calls the appropriate direction-specific variant (horizontal
* or vertical) depending on the value of @direction.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 0.9.2
**/
@@ -1393,7 +1399,7 @@ hb_font_get_glyph_extents_for_origin (hb_font_t *font,
* Calls the appropriate direction-specific variant (horizontal
* or vertical) depending on the value of @direction.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 0.9.2
**/
@@ -1444,7 +1450,7 @@ hb_font_glyph_to_string (hb_font_t *font,
*
* <note>Note: @len == -1 means the string is null-terminated.</note>
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 0.9.2
**/
@@ -1664,12 +1670,12 @@ hb_font_destroy (hb_font_t *font)
* @font: #hb_font_t to work upon
* @key: The user-data key
* @data: A pointer to the user data
- * @destroy: (optional): A callback to call when @data is not needed anymore
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the specified font object.
*
- * Return value:
+ * Return value: %true if success, %false otherwise
*
* Since: 0.9.2
**/
@@ -1728,7 +1734,7 @@ hb_font_make_immutable (hb_font_t *font)
*
* Tests whether a font object is immutable.
*
- * Return value: %true if @font is immutable, false otherwise
+ * Return value: %true if @font is immutable, %false otherwise
*
* Since: 0.9.2
**/
@@ -1828,9 +1834,9 @@ hb_font_get_face (hb_font_t *font)
/**
* hb_font_set_funcs:
* @font: #hb_font_t to work upon
- * @klass: (closure font_data) (destroy destroy) (scope notified):
+ * @klass: (closure font_data) (destroy destroy) (scope notified): The font-functions structure.
* @font_data: Data to attach to @font
- * @destroy: (optional): The function to call when @font_data is not needed anymore
+ * @destroy: (nullable): The function to call when @font_data is not needed anymore
*
* Replaces the font-functions structure attached to a font, updating
* the font's user-data with @font-data and the @destroy callback.
@@ -1867,7 +1873,7 @@ hb_font_set_funcs (hb_font_t *font,
* hb_font_set_funcs_data:
* @font: #hb_font_t to work upon
* @font_data: (destroy destroy) (scope notified): Data to attach to @font
- * @destroy: (optional): The function to call when @font_data is not needed anymore
+ * @destroy: (nullable): The function to call when @font_data is not needed anymore
*
* Replaces the user data attached to a font, updating the font's
* @destroy callback.
@@ -2212,10 +2218,14 @@ hb_font_get_var_coords_normalized (hb_font_t *font,
#ifdef HB_EXPERIMENTAL_API
/**
* hb_font_get_var_coords_design:
+ * @font: #hb_font_t to work upon
+ * @length: (out): number of coordinates
*
* Return value is valid as long as variation coordinates of the font
* are not modified.
*
+ * Return value: coordinates array
+ *
* Since: EXPERIMENTAL
*/
const float *
@@ -2319,7 +2329,7 @@ hb_font_get_variation_glyph_trampoline (hb_font_t *font,
* @ffuncs: The font-functions structure
* @func: (closure user_data) (destroy destroy) (scope notified): callback function
* @user_data: data to pass to @func
- * @destroy: (optional): function to call when @user_data is not needed anymore
+ * @destroy: (nullable): function to call when @user_data is not needed anymore
*
* Deprecated. Use hb_font_funcs_set_nominal_glyph_func() and
* hb_font_funcs_set_variation_glyph_func() instead.
diff --git a/thirdparty/harfbuzz/src/hb-font.h b/thirdparty/harfbuzz/src/hb-font.h
index 05f6c03f47..15dc126523 100644
--- a/thirdparty/harfbuzz/src/hb-font.h
+++ b/thirdparty/harfbuzz/src/hb-font.h
@@ -24,7 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
@@ -37,7 +37,12 @@
HB_BEGIN_DECLS
-
+/**
+ * hb_font_t:
+ *
+ * Data type for holding fonts.
+ *
+ */
typedef struct hb_font_t hb_font_t;
@@ -141,6 +146,16 @@ typedef struct hb_glyph_extents_t {
/* func types */
+/**
+ * hb_font_get_font_extents_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @extents: (out): The font extents retrieved
+ * @user_data: User data pointer passed by the caller
+ *
+ * This method should retrieve the extents for a font.
+ *
+ **/
typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data,
hb_font_extents_t *extents,
void *user_data);
@@ -150,7 +165,7 @@ typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *fon
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
- * This method should retrieve the extents for a font, in horizontal-direction
+ * This method should retrieve the extents for a font, for horizontal-direction
* text segments. Extents must be returned in an #hb_glyph_extents output
* parameter.
*
@@ -162,7 +177,7 @@ typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t;
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
- * This method should retrieve the extents for a font, in vertical-direction
+ * This method should retrieve the extents for a font, for vertical-direction
* text segments. Extents must be returned in an #hb_glyph_extents output
* parameter.
*
@@ -172,12 +187,19 @@ typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
/**
* hb_font_get_nominal_glyph_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @unicode: The Unicode code point to query
+ * @glyph: (out): The glyph ID retrieved
+ * @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the nominal glyph ID for a specified Unicode code
* point. Glyph IDs must be returned in a #hb_codepoint_t output parameter.
*
+ * Return value: %true if data found, %false otherwise
+ *
**/
typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t unicode,
@@ -186,6 +208,12 @@ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *fo
/**
* hb_font_get_variation_glyph_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @unicode: The Unicode code point to query
+ * @variation_selector: The variation-selector code point to query
+ * @glyph: (out): The glyph ID retrieved
+ * @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
@@ -193,6 +221,8 @@ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *fo
* followed by a specified Variation Selector code point. Glyph IDs must be
* returned in a #hb_codepoint_t output parameter.
*
+ * Return value: %true if data found, %false otherwise
+ *
**/
typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
@@ -202,12 +232,22 @@ typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *
/**
* hb_font_get_nominal_glyphs_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @count: number of code points to query
+ * @first_unicode: The first Unicode code point to query
+ * @unicode_stride: The stride between successive code points
+ * @first_glyph: (out): The first glyph ID retrieved
+ * @glyph_stride: The stride between successive glyph IDs
+ * @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the nominal glyph IDs for a sequence of
* Unicode code points. Glyph IDs must be returned in a #hb_codepoint_t
* output parameter.
+ *
+ * Return value: the number of code points processed
*
**/
typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void *font_data,
@@ -220,12 +260,18 @@ typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void
/**
* hb_font_get_glyph_advance_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the advance for a specified glyph. The
* method must return an #hb_position_t.
*
+ * Return value: The advance of @glyph within @font
+ *
**/
typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph,
@@ -257,6 +303,14 @@ typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
/**
* hb_font_get_glyph_advances_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @count: The number of glyph IDs in the sequence queried
+ * @first_glyph: The first glyph ID to query
+ * @glyph_stride: The stride between successive glyph IDs
+ * @first_advance: (out): The first advance retrieved
+ * @advance_stride: The stride between successive advances
+ * @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
@@ -295,12 +349,20 @@ typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
/**
* hb_font_get_glyph_origin_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @x: (out): The X coordinate of the origin
+ * @y: (out): The Y coordinate of the origin
+ * @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the (X,Y) coordinates (in font units) of the
* origin for a glyph. Each coordinate must be returned in an #hb_position_t
* output parameter.
+ *
+ * Return value: %true if data found, %false otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
@@ -314,7 +376,7 @@ typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *fon
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the (X,Y) coordinates (in font units) of the
- * origin for a glyph, in horizontal-direction text segments. Each
+ * origin for a glyph, for horizontal-direction text segments. Each
* coordinate must be returned in an #hb_position_t output parameter.
*
**/
@@ -326,25 +388,53 @@ typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t;
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the (X,Y) coordinates (in font units) of the
- * origin for a glyph, in vertical-direction text segments. Each coordinate
+ * origin for a glyph, for vertical-direction text segments. Each coordinate
* must be returned in an #hb_position_t output parameter.
*
**/
typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t;
+/**
+ * hb_font_get_glyph_kerning_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @first_glyph: The glyph ID of the first glyph in the glyph pair
+ * @second_glyph: The glyph ID of the second glyph in the glyph pair
+ * @user_data: User data pointer passed by the caller
+ *
+ * This method should retrieve the kerning-adjustment value for a glyph-pair in
+ * the specified font, for horizontal text segments.
+ *
+ **/
typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
void *user_data);
+/**
+ * hb_font_get_glyph_h_kerning_func_t:
+ *
+ * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
+ *
+ * This method should retrieve the kerning-adjustment value for a glyph-pair in
+ * the specified font, for horizontal text segments.
+ *
+ **/
typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
/**
* hb_font_get_glyph_extents_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @extents: (out): The #hb_glyph_extents_t retrieved
+ * @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the extents for a specified glyph. Extents must be
* returned in an #hb_glyph_extents output parameter.
+ *
+ * Return value: %true if data found, %false otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
@@ -354,6 +444,13 @@ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *fo
/**
* hb_font_get_glyph_contour_point_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @point_index: The contour-point index to query
+ * @x: (out): The X value retrieved for the contour point
+ * @y: (out): The Y value retrieved for the contour point
+ * @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
@@ -361,6 +458,8 @@ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *fo
* specified contour point in a glyph. Each coordinate must be returned as
* an #hb_position_t output parameter.
*
+ * Return value: %true if data found, %false otherwise
+ *
**/
typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph, unsigned int point_index,
@@ -370,12 +469,20 @@ typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, vo
/**
* hb_font_get_glyph_name_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @name: (out) (array length=size): Name string retrieved for the glyph ID
+ * @size: Length of the glyph-name string retrieved
+ * @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the glyph name that corresponds to a
* glyph ID. The name should be returned in a string output parameter.
*
+ * Return value: %true if data found, %false otherwise
+ *
**/
typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph,
@@ -384,12 +491,20 @@ typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_
/**
* hb_font_get_glyph_from_name_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @name: (array length=len): The name string to query
+ * @len: The length of the name queried
+ * @glyph: (out): The glyph ID retrieved
+ * @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the glyph ID that corresponds to a glyph-name
* string.
*
+ * Return value: %true if data found, %false otherwise
+ *
**/
typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data,
const char *name, int len, /* -1 means nul-terminated */
@@ -404,7 +519,7 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_font_h_extents_func_t.
*
@@ -420,7 +535,7 @@ hb_font_funcs_set_font_h_extents_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_font_v_extents_func_t.
*
@@ -436,7 +551,7 @@ hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_nominal_glyph_func_t.
*
@@ -452,7 +567,7 @@ hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_nominal_glyphs_func_t.
*
@@ -468,7 +583,7 @@ hb_font_funcs_set_nominal_glyphs_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_variation_glyph_func_t.
*
@@ -484,7 +599,7 @@ hb_font_funcs_set_variation_glyph_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_glyph_h_advance_func_t.
*
@@ -500,7 +615,7 @@ hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_glyph_v_advance_func_t.
*
@@ -516,7 +631,7 @@ hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_glyph_h_advances_func_t.
*
@@ -532,7 +647,7 @@ hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_glyph_v_advances_func_t.
*
@@ -548,7 +663,7 @@ hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_glyph_h_origin_func_t.
*
@@ -564,7 +679,7 @@ hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_glyph_v_origin_func_t.
*
@@ -577,12 +692,12 @@ hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
/**
* hb_font_funcs_set_glyph_h_kerning_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
+ * @ffuncs: A font-function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
+ * Sets the implementation function for #hb_font_get_glyph_h_kerning_func_t.
*
* Since: 0.9.2
**/
@@ -596,7 +711,7 @@ hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_glyph_extents_func_t.
*
@@ -612,7 +727,7 @@ hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_glyph_contour_point_func_t.
*
@@ -628,7 +743,7 @@ hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_glyph_name_func_t.
*
@@ -644,7 +759,7 @@ hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_glyph_from_name_func_t.
*
diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc
index ab7d6146ce..b82c1a67bd 100644
--- a/thirdparty/harfbuzz/src/hb-ft.cc
+++ b/thirdparty/harfbuzz/src/hb-ft.cc
@@ -84,7 +84,7 @@ struct hb_ft_font_t
bool symbol; /* Whether selected cmap is symbol cmap. */
bool unref; /* Whether to destroy ft_face when done. */
- mutable hb_atomic_int_t cached_x_scale;
+ mutable int cached_x_scale;
mutable hb_advance_cache_t advance_cache;
};
@@ -101,7 +101,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
- ft_font->cached_x_scale.set_relaxed (0);
+ ft_font->cached_x_scale = 0;
ft_font->advance_cache.init ();
return ft_font;
@@ -179,13 +179,13 @@ hb_ft_font_get_load_flags (hb_font_t *font)
}
/**
- * hb_ft_get_face:
+ * hb_ft_font_get_face:
* @font: #hb_font_t to work upon
*
* Fetches the FT_Face associated with the specified #hb_font_t
* font object.
*
- * Return value: the FT_Face found
+ * Return value: (nullable): the FT_Face found or %NULL
*
* Since: 0.9.2
**/
@@ -202,11 +202,12 @@ hb_ft_font_get_face (hb_font_t *font)
/**
* hb_ft_font_lock_face:
- * @font:
- *
+ * @font: #hb_font_t to work upon
*
+ * Gets the FT_Face associated with @font, This face will be kept around until
+ * you call hb_ft_font_unlock_face().
*
- * Return value:
+ * Return value: (nullable): the FT_Face associated with @font or %NULL
* Since: 2.6.5
**/
FT_Face
@@ -224,11 +225,10 @@ hb_ft_font_lock_face (hb_font_t *font)
/**
* hb_ft_font_unlock_face:
- * @font:
- *
+ * @font: #hb_font_t to work upon
*
+ * Releases an FT_Face previously obtained with hb_ft_font_lock_face().
*
- * Return value:
* Since: 2.6.5
**/
void
@@ -335,10 +335,10 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
int load_flags = ft_font->load_flags;
int mult = font->x_scale < 0 ? -1 : +1;
- if (font->x_scale != ft_font->cached_x_scale.get ())
+ if (font->x_scale != ft_font->cached_x_scale)
{
ft_font->advance_cache.clear ();
- ft_font->cached_x_scale.set (font->x_scale);
+ ft_font->cached_x_scale = font->x_scale;
}
for (unsigned int i = 0; i < count; i++)
@@ -661,7 +661,7 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data
/**
* hb_ft_face_create:
* @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
- * @destroy: (optional): A callback to call when the face object is not needed anymore
+ * @destroy: (nullable): A callback to call when the face object is not needed anymore
*
* Creates an #hb_face_t face object from the specified FT_Face.
*
@@ -771,13 +771,13 @@ hb_ft_face_create_cached (FT_Face ft_face)
/**
* hb_ft_font_create:
* @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
- * @destroy: (optional): A callback to call when the font object is not needed anymore
+ * @destroy: (nullable): A callback to call when the font object is not needed anymore
*
* Creates an #hb_font_t font object from the specified FT_Face.
*
* <note>Note: You must set the face size on @ft_face before calling
- * hb_ft_font_create() on it. Otherwise, HarfBuzz will not pick up
- * the face size.</note>
+ * hb_ft_font_create() on it. HarfBuzz assumes size is always set and will
+ * access `size` member of FT_Face unconditionally.</note>
*
* This variant of the function does not provide any life-cycle management.
*
@@ -814,7 +814,7 @@ hb_ft_font_create (FT_Face ft_face,
}
/**
- * hb_ft_font_has_changed:
+ * hb_ft_font_changed:
* @font: #hb_font_t to work upon
*
* Refreshes the state of @font when the underlying FT_Face has changed.
@@ -884,8 +884,8 @@ hb_ft_font_changed (hb_font_t *font)
* Creates an #hb_font_t font object from the specified FT_Face.
*
* <note>Note: You must set the face size on @ft_face before calling
- * hb_ft_font_create_references() on it. Otherwise, HarfBuzz will not pick up
- * the face size.</note>
+ * hb_ft_font_create_referenced() on it. HarfBuzz assumes size is always set
+ * and will access `size` member of FT_Face unconditionally.</note>
*
* This is the preferred variant of the hb_ft_font_create*
* function family, because it calls FT_Reference_Face() on @ft_face,
diff --git a/thirdparty/harfbuzz/src/hb-gdi.cc b/thirdparty/harfbuzz/src/hb-gdi.cc
index 3a67cef160..dc4659c7f6 100644
--- a/thirdparty/harfbuzz/src/hb-gdi.cc
+++ b/thirdparty/harfbuzz/src/hb-gdi.cc
@@ -70,6 +70,8 @@ fail:
* hb_gdi_face_create:
* @hfont: a HFONT object.
*
+ * Constructs a new face object from the specified GDI HFONT.
+ *
* Return value: #hb_face_t object corresponding to the given input
*
* Since: 2.6.0
diff --git a/thirdparty/harfbuzz/src/hb-gobject-structs.h b/thirdparty/harfbuzz/src/hb-gobject-structs.h
index 6fad8d7019..63467f80df 100644
--- a/thirdparty/harfbuzz/src/hb-gobject-structs.h
+++ b/thirdparty/harfbuzz/src/hb-gobject-structs.h
@@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_GOBJECT_H_IN
+#if !defined(HB_GOBJECT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-gobject.h> instead."
#endif
@@ -40,47 +40,22 @@ HB_BEGIN_DECLS
/* Object types */
-/**
- * hb_gobject_blob_get_type:
- *
- * Since: 0.9.2
- **/
HB_EXTERN GType
hb_gobject_blob_get_type (void);
#define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ())
-/**
- * hb_gobject_buffer_get_type:
- *
- * Since: 0.9.2
- **/
HB_EXTERN GType
hb_gobject_buffer_get_type (void);
#define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
-/**
- * hb_gobject_face_get_type:
- *
- * Since: 0.9.2
- **/
HB_EXTERN GType
hb_gobject_face_get_type (void);
#define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
-/**
- * hb_gobject_font_get_type:
- *
- * Since: 0.9.2
- **/
HB_EXTERN GType
hb_gobject_font_get_type (void);
#define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ())
-/**
- * hb_gobject_font_funcs_get_type:
- *
- * Since: 0.9.2
- **/
HB_EXTERN GType
hb_gobject_font_funcs_get_type (void);
#define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ())
@@ -97,11 +72,6 @@ HB_EXTERN GType
hb_gobject_shape_plan_get_type (void);
#define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ())
-/**
- * hb_gobject_unicode_funcs_get_type:
- *
- * Since: 0.9.2
- **/
HB_EXTERN GType
hb_gobject_unicode_funcs_get_type (void);
#define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ())
diff --git a/thirdparty/harfbuzz/src/hb-graphite2.cc b/thirdparty/harfbuzz/src/hb-graphite2.cc
index d8a72dc2f1..9dafe654c8 100644
--- a/thirdparty/harfbuzz/src/hb-graphite2.cc
+++ b/thirdparty/harfbuzz/src/hb-graphite2.cc
@@ -195,6 +195,11 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED
#ifndef HB_DISABLE_DEPRECATED
/**
* hb_graphite2_font_get_gr_font:
+ * @font: An #hb_font_t
+ *
+ * Always returns %NULL. Use hb_graphite2_face_get_gr_face() instead.
+ *
+ * Return value: (nullable): Graphite2 font associated with @font.
*
* Since: 0.9.10
* Deprecated: 1.4.2
@@ -284,7 +289,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
return true;
}
- buffer->ensure (glyph_count);
+ (void) buffer->ensure (glyph_count);
scratch = buffer->get_scratch_buffer (&scratch_size);
while ((DIV_CEIL (sizeof (hb_graphite2_cluster_t) * buffer->len, sizeof (*scratch)) +
DIV_CEIL (sizeof (hb_codepoint_t) * glyph_count, sizeof (*scratch))) > scratch_size)
diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh
index 981c5c218c..f7018150e4 100644
--- a/thirdparty/harfbuzz/src/hb-iter.hh
+++ b/thirdparty/harfbuzz/src/hb-iter.hh
@@ -922,7 +922,7 @@ HB_FUNCOBJ (hb_none);
template <typename C, typename V,
hb_requires (hb_is_iterable (C))>
inline void
-hb_fill (C& c, const V &v)
+hb_fill (C&& c, const V &v)
{
for (auto i = hb_iter (c); i; i++)
*i = v;
diff --git a/thirdparty/harfbuzz/src/hb-machinery.hh b/thirdparty/harfbuzz/src/hb-machinery.hh
index 54bc60d4c8..3bd5a979b0 100644
--- a/thirdparty/harfbuzz/src/hb-machinery.hh
+++ b/thirdparty/harfbuzz/src/hb-machinery.hh
@@ -80,6 +80,11 @@ static inline Type& StructAfter(TObject &X)
* Size checking
*/
+/* Size signifying variable-sized array */
+#ifndef HB_VAR_ARRAY
+#define HB_VAR_ARRAY 1
+#endif
+
/* Check _assertion in a method environment */
#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
void _instance_assertion_on_line_##_line () const \
diff --git a/thirdparty/harfbuzz/src/hb-map.cc b/thirdparty/harfbuzz/src/hb-map.cc
index f898bd8f92..f115da2bb8 100644
--- a/thirdparty/harfbuzz/src/hb-map.cc
+++ b/thirdparty/harfbuzz/src/hb-map.cc
@@ -117,7 +117,7 @@ hb_map_destroy (hb_map_t *map)
* @map: A map
* @key: The user-data key to set
* @data: A pointer to the user data to set
- * @destroy: (optional): A callback to call when @data is not needed anymore
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the specified map.
@@ -162,7 +162,7 @@ hb_map_get_user_data (hb_map_t *map,
*
* Tests whether memory allocation for a set was successful.
*
- * Return value: %true if allocation succeeded, false otherwise
+ * Return value: %true if allocation succeeded, %false otherwise
*
* Since: 1.7.7
**/
@@ -230,7 +230,7 @@ hb_map_del (hb_map_t *map,
*
* Tests whether @key is an element of @map.
*
- * Return value: %true if @key is found in @map, false otherwise
+ * Return value: %true if @key is found in @map, %false otherwise
*
* Since: 1.7.7
**/
@@ -253,6 +253,9 @@ hb_map_has (const hb_map_t *map,
void
hb_map_clear (hb_map_t *map)
{
+ if (unlikely (hb_object_is_immutable (map)))
+ return;
+
return map->clear ();
}
diff --git a/thirdparty/harfbuzz/src/hb-map.h b/thirdparty/harfbuzz/src/hb-map.h
index 0c19ac8fb5..6a45a7bdd5 100644
--- a/thirdparty/harfbuzz/src/hb-map.h
+++ b/thirdparty/harfbuzz/src/hb-map.h
@@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
@@ -36,7 +36,11 @@
HB_BEGIN_DECLS
-/*
+/**
+ * HB_MAP_VALUE_INVALID:
+ *
+ * Unset #hb_map_t value.
+ *
* Since: 1.7.7
*/
#define HB_MAP_VALUE_INVALID ((hb_codepoint_t) -1)
diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh
index 92c1bd67e5..84fe1d549b 100644
--- a/thirdparty/harfbuzz/src/hb-map.hh
+++ b/thirdparty/harfbuzz/src/hb-map.hh
@@ -97,8 +97,6 @@ struct hb_hashmap_t
void reset ()
{
- if (unlikely (hb_object_is_immutable (this)))
- return;
successful = true;
clear ();
}
@@ -171,8 +169,6 @@ struct hb_hashmap_t
void clear ()
{
- if (unlikely (hb_object_is_immutable (this)))
- return;
if (items)
for (auto &_ : hb_iter (items, mask + 1))
_.clear ();
@@ -181,6 +177,7 @@ struct hb_hashmap_t
}
bool is_empty () const { return population == 0; }
+ explicit operator bool () const { return !is_empty (); }
unsigned int get_population () const { return population; }
diff --git a/thirdparty/harfbuzz/src/hb-meta.hh b/thirdparty/harfbuzz/src/hb-meta.hh
index 4c0898b1b7..e40d9fd178 100644
--- a/thirdparty/harfbuzz/src/hb-meta.hh
+++ b/thirdparty/harfbuzz/src/hb-meta.hh
@@ -49,6 +49,10 @@ template <bool b> using hb_bool_constant = hb_integral_constant<bool, b>;
using hb_true_type = hb_bool_constant<true>;
using hb_false_type = hb_bool_constant<false>;
+/* Static-assert as expression. */
+template <bool cond> struct static_assert_expr;
+template <> struct static_assert_expr<true> : hb_false_type {};
+#define static_assert_expr(C) static_assert_expr<C>::value
/* Basic type SFINAE. */
@@ -220,6 +224,8 @@ struct hb_reference_wrapper<T&>
};
+/* Type traits */
+
template <typename T>
using hb_is_integral = hb_bool_constant<
hb_is_same (hb_decay<T>, char) ||
@@ -292,6 +298,15 @@ template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigne
#define hb_int_max(T) hb_int_max<T>::value
+/* Class traits. */
+
+#define HB_DELETE_COPY_ASSIGN(TypeName) \
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete
+#define HB_DELETE_CREATE_COPY_ASSIGN(TypeName) \
+ TypeName() = delete; \
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete
template <typename T, typename>
struct _hb_is_destructible : hb_false_type {};
diff --git a/thirdparty/harfbuzz/src/hb-mutex.hh b/thirdparty/harfbuzz/src/hb-mutex.hh
index 56392d049b..2fc8d7ee58 100644
--- a/thirdparty/harfbuzz/src/hb-mutex.hh
+++ b/thirdparty/harfbuzz/src/hb-mutex.hh
@@ -73,24 +73,6 @@ typedef CRITICAL_SECTION hb_mutex_impl_t;
#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
-#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
-
-#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
-# include <sched.h>
-# define HB_SCHED_YIELD() sched_yield ()
-#else
-# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
-#endif
-
-/* This actually is not a totally awful implementation. */
-typedef volatile int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT 0
-#define hb_mutex_impl_init(M) *(M) = 0
-#define hb_mutex_impl_lock(M) HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
-#define hb_mutex_impl_unlock(M) __sync_lock_release (M)
-#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
-
-
#elif defined(HB_NO_MT)
typedef int hb_mutex_impl_t;
diff --git a/thirdparty/harfbuzz/src/hb-object.hh b/thirdparty/harfbuzz/src/hb-object.hh
index 39845a70e7..f3048b1c3e 100644
--- a/thirdparty/harfbuzz/src/hb-object.hh
+++ b/thirdparty/harfbuzz/src/hb-object.hh
@@ -140,9 +140,7 @@ struct hb_lockable_set_t
* Reference-count.
*/
-#define HB_REFERENCE_COUNT_INERT_VALUE 0
-#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
-#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)}
+#define HB_REFERENCE_COUNT_INIT {0}
struct hb_reference_count_t
{
@@ -152,9 +150,9 @@ struct hb_reference_count_t
int get_relaxed () const { return ref_count.get_relaxed (); }
int inc () const { return ref_count.inc (); }
int dec () const { return ref_count.dec (); }
- void fini () { ref_count.set_relaxed (HB_REFERENCE_COUNT_POISON_VALUE); }
+ void fini () { ref_count.set_relaxed (-0x0000DEAD); }
- bool is_inert () const { return ref_count.get_relaxed () == HB_REFERENCE_COUNT_INERT_VALUE; }
+ bool is_inert () const { return !ref_count.get_relaxed (); }
bool is_valid () const { return ref_count.get_relaxed () > 0; }
};
@@ -197,15 +195,10 @@ struct hb_user_data_array_t
struct hb_object_header_t
{
hb_reference_count_t ref_count;
- mutable hb_atomic_int_t writable;
+ mutable hb_atomic_int_t writable = 0;
hb_atomic_ptr_t<hb_user_data_array_t> user_data;
};
-#define HB_OBJECT_HEADER_STATIC \
- { \
- HB_REFERENCE_COUNT_INIT, \
- HB_ATOMIC_INT_INIT (false), \
- HB_ATOMIC_PTR_INIT (nullptr) \
- }
+#define HB_OBJECT_HEADER_STATIC {}
/*
diff --git a/thirdparty/harfbuzz/src/hb-open-file.hh b/thirdparty/harfbuzz/src/hb-open-file.hh
index ac13dd23c3..54c07ff13c 100644
--- a/thirdparty/harfbuzz/src/hb-open-file.hh
+++ b/thirdparty/harfbuzz/src/hb-open-file.hh
@@ -48,7 +48,7 @@ namespace OT {
*/
struct OpenTypeFontFile;
-struct OffsetTable;
+struct OpenTypeOffsetTable;
struct TTCHeader;
@@ -78,7 +78,7 @@ typedef struct TableRecord
DEFINE_SIZE_STATIC (16);
} OpenTypeTable;
-typedef struct OffsetTable
+typedef struct OpenTypeOffsetTable
{
friend struct OpenTypeFontFile;
@@ -218,7 +218,7 @@ struct TTCHeaderVersion1
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
FixedVersion<>version; /* Version of the TTC Header (1.0),
* 0x00010000u */
- LArrayOf<LOffsetTo<OffsetTable>>
+ LArrayOf<LOffsetTo<OpenTypeOffsetTable>>
table; /* Array of offsets to the OffsetTable for each font
* from the beginning of the file */
public:
diff --git a/thirdparty/harfbuzz/src/hb-open-type.hh b/thirdparty/harfbuzz/src/hb-open-type.hh
index 99634b76f0..dc0ae1d989 100644
--- a/thirdparty/harfbuzz/src/hb-open-type.hh
+++ b/thirdparty/harfbuzz/src/hb-open-type.hh
@@ -53,14 +53,19 @@ namespace OT {
*/
/* Integer types in big-endian order and no alignment requirement */
-template <typename Type, unsigned int Size>
+template <typename Type,
+ unsigned int Size = sizeof (Type)>
struct IntType
{
typedef Type type;
- typedef hb_conditional<hb_is_signed (Type), signed, unsigned> wide_type;
- IntType& operator = (wide_type i) { v = i; return *this; }
- operator wide_type () const { return v; }
+ IntType () = default;
+ explicit constexpr IntType (Type V) : v {V} {}
+ IntType& operator = (Type i) { v = i; return *this; }
+ /* For reason we define cast out operator for signed/unsigned, instead of Type, see:
+ * https://github.com/harfbuzz/harfbuzz/pull/2875/commits/09836013995cab2b9f07577a179ad7b024130467 */
+ operator hb_conditional<hb_is_signed (Type), signed, unsigned> () const { return v; }
+
bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; }
bool operator != (const IntType &o) const { return !(*this == o); }
@@ -80,14 +85,21 @@ struct IntType
return pb->cmp (*pa);
}
- template <typename Type2>
+ template <typename Type2,
+ hb_enable_if (hb_is_integral (Type2) &&
+ sizeof (Type2) < sizeof (int) &&
+ sizeof (Type) < sizeof (int))>
int cmp (Type2 a) const
{
Type b = v;
- if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
- return (int) a - (int) b;
- else
- return a < b ? -1 : a == b ? 0 : +1;
+ return (int) a - (int) b;
+ }
+ template <typename Type2,
+ hb_enable_if (hb_is_convertible (Type2, Type))>
+ int cmp (Type2 a) const
+ {
+ Type b = v;
+ return a < b ? -1 : a == b ? 0 : +1;
}
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -100,12 +112,12 @@ struct IntType
DEFINE_SIZE_STATIC (Size);
};
-typedef IntType<uint8_t, 1> HBUINT8; /* 8-bit unsigned integer. */
-typedef IntType<int8_t, 1> HBINT8; /* 8-bit signed integer. */
-typedef IntType<uint16_t, 2> HBUINT16; /* 16-bit unsigned integer. */
-typedef IntType<int16_t, 2> HBINT16; /* 16-bit signed integer. */
-typedef IntType<uint32_t, 4> HBUINT32; /* 32-bit unsigned integer. */
-typedef IntType<int32_t, 4> HBINT32; /* 32-bit signed integer. */
+typedef IntType<uint8_t> HBUINT8; /* 8-bit unsigned integer. */
+typedef IntType<int8_t> HBINT8; /* 8-bit signed integer. */
+typedef IntType<uint16_t> HBUINT16; /* 16-bit unsigned integer. */
+typedef IntType<int16_t> HBINT16; /* 16-bit signed integer. */
+typedef IntType<uint32_t> HBUINT32; /* 32-bit unsigned integer. */
+typedef IntType<int32_t> HBINT32; /* 32-bit signed integer. */
/* Note: we cannot defined a signed HBINT24 because there's no corresponding C type.
* Works for unsigned, but not signed, since we rely on compiler for sign-extension. */
typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */
@@ -163,8 +175,8 @@ struct Tag : HBUINT32
{
Tag& operator = (hb_tag_t i) { HBUINT32::operator= (i); return *this; }
/* What the char* converters return is NOT nul-terminated. Print using "%.4s" */
- operator const char* () const { return reinterpret_cast<const char *> (&this->v); }
- operator char* () { return reinterpret_cast<char *> (&this->v); }
+ operator const char* () const { return reinterpret_cast<const char *> (this); }
+ operator char* () { return reinterpret_cast<char *> (this); }
public:
DEFINE_SIZE_STATIC (4);
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh
index e5286cd792..864a27f458 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh
@@ -183,7 +183,7 @@ struct CFFIndex
else
{
serialize_header(c, + it | hb_map ([] (const byte_str_t &_) { return _.length; }));
- for (const byte_str_t &_ : +it)
+ for (const auto &_ : +it)
_.copy (c);
}
return_trace (true);
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc b/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc
index 66b9c8c907..3298fa35ae 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc
@@ -426,7 +426,7 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
else
{
extents->x_bearing = font->em_scalef_x (bounds.min.x.to_real ());
- extents->width = font->em_scalef_x (bounds.max.x.to_real () - bounds.min.x.to_real ());
+ extents->width = font->em_scalef_x (bounds.max.x.to_real ()) - extents->x_bearing;
}
if (bounds.min.y >= bounds.max.y)
{
@@ -436,7 +436,7 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
else
{
extents->y_bearing = font->em_scalef_y (bounds.max.y.to_real ());
- extents->height = font->em_scalef_y (bounds.min.y.to_real () - bounds.max.y.to_real ());
+ extents->height = font->em_scalef_y (bounds.min.y.to_real ()) - extents->y_bearing;
}
return true;
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc
index ac0feeee21..879b7cdb23 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc
@@ -127,7 +127,7 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
else
{
extents->x_bearing = font->em_scalef_x (param.min_x.to_real ());
- extents->width = font->em_scalef_x (param.max_x.to_real () - param.min_x.to_real ());
+ extents->width = font->em_scalef_x (param.max_x.to_real ()) - extents->x_bearing;
}
if (param.min_y >= param.max_y)
{
@@ -137,7 +137,7 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
else
{
extents->y_bearing = font->em_scalef_y (param.max_y.to_real ());
- extents->height = font->em_scalef_y (param.min_y.to_real () - param.max_y.to_real ());
+ extents->height = font->em_scalef_y (param.min_y.to_real ()) - extents->y_bearing;
}
return true;
diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
index cc48379bb8..878e02ff17 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
@@ -95,7 +95,7 @@ struct CmapSubtableFormat4
HBUINT16 *endCode = c->start_embed<HBUINT16> ();
hb_codepoint_t prev_endcp = 0xFFFF;
- for (const hb_item_type<Iterator> _ : +it)
+ for (const auto& _ : +it)
{
if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first)
{
@@ -131,7 +131,7 @@ struct CmapSubtableFormat4
HBUINT16 *startCode = c->start_embed<HBUINT16> ();
hb_codepoint_t prev_cp = 0xFFFF;
- for (const hb_item_type<Iterator> _ : +it)
+ for (const auto& _ : +it)
{
if (prev_cp == 0xFFFF || prev_cp + 1u != _.first)
{
@@ -170,7 +170,7 @@ struct CmapSubtableFormat4
if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size)
return nullptr;
- for (const hb_item_type<Iterator> _ : +it)
+ for (const auto& _ : +it)
{
if (_.first == startCode[i])
{
@@ -696,7 +696,7 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
hb_codepoint_t glyphID = 0;
- for (const hb_item_type<Iterator> _ : +it)
+ for (const auto& _ : +it)
{
if (startCharCode == 0xFFFF)
{
diff --git a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh
index aaa1c37c64..e285acec3d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh
@@ -455,8 +455,8 @@ struct IndexSubtableRecord
unsigned int old_cbdt_prime_length = bitmap_size_context->cbdt_prime->length;
// Set to invalid state to indicate filling glyphs is not yet started.
- if (unlikely (!records->resize (records->length + 1)))
- return_trace (c->serializer->check_success (false));
+ 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;
@@ -567,8 +567,8 @@ struct IndexSubtableArray
hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> lookup;
build_lookup (c, bitmap_size_context, &lookup);
- if (unlikely (lookup.in_error ()))
- return c->serializer->check_success (false);
+ if (unlikely (!c->serializer->propagate_error (lookup)))
+ return false;
bitmap_size_context->size = 0;
bitmap_size_context->num_tables = 0;
diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
index 92a49bb4f4..e2a1ff4662 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
@@ -214,7 +214,7 @@ struct COLR
if (unlikely (!old_record))
return hb_pair_t<bool, BaseGlyphRecord> (false, Null (BaseGlyphRecord));
- BaseGlyphRecord new_record;
+ BaseGlyphRecord new_record = {};
new_record.glyphId = new_gid;
new_record.numLayers = old_record->numLayers;
return hb_pair_t<bool, BaseGlyphRecord> (true, new_record);
diff --git a/thirdparty/harfbuzz/src/hb-ot-color.cc b/thirdparty/harfbuzz/src/hb-ot-color.cc
index 0e7203a88b..4170b71317 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-color.cc
@@ -37,9 +37,6 @@
#include "hb-ot-color-sbix-table.hh"
#include "hb-ot-color-svg-table.hh"
-#include <stdlib.h>
-#include <string.h>
-
/**
* SECTION:hb-ot-color
@@ -64,7 +61,7 @@
*
* Tests whether a face includes a `CPAL` color-palette table.
*
- * Return value: true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 2.1.0
*/
@@ -195,7 +192,7 @@ hb_ot_color_palette_get_colors (hb_face_t *face,
*
* Tests whether a face includes any `COLR` color layers.
*
- * Return value: true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 2.1.0
*/
@@ -242,7 +239,7 @@ hb_ot_color_glyph_get_layers (hb_face_t *face,
*
* Tests whether a face includes any `SVG` glyph images.
*
- * Return value: true if data found, false otherwise.
+ * Return value: %true if data found, %false otherwise.
*
* Since: 2.1.0
*/
@@ -280,7 +277,7 @@ hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
*
* Tests whether a face has PNG glyph images (either in `CBDT` or `sbix` tables).
*
- * Return value: true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 2.1.0
*/
diff --git a/thirdparty/harfbuzz/src/hb-ot-color.h b/thirdparty/harfbuzz/src/hb-ot-color.h
index 4f37a4386f..c23ce4de44 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color.h
+++ b/thirdparty/harfbuzz/src/hb-ot-color.h
@@ -26,7 +26,7 @@
* Google Author(s): Sascha Brawer, Behdad Esfahbod
*/
-#ifndef HB_OT_H_IN
+#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead."
#endif
@@ -66,6 +66,8 @@ hb_ot_color_palette_color_get_name_id (hb_face_t *face,
* @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: Flag indicating that the color
* palette is appropriate to use when displaying the font on a dark background such as black.
*
+ * Flags that describe the properties of color palette.
+ *
* Since: 2.1.0
*/
typedef enum { /*< flags >*/
@@ -95,6 +97,8 @@ hb_ot_color_has_layers (hb_face_t *face);
/**
* hb_ot_color_layer_t:
+ * @glyph: the glyph ID of the layer
+ * @color_index: the palette color index of the layer
*
* Pairs of glyph and color index.
*
diff --git a/thirdparty/harfbuzz/src/hb-ot-deprecated.h b/thirdparty/harfbuzz/src/hb-ot-deprecated.h
index 2e75deef2d..ce6b6fef11 100644
--- a/thirdparty/harfbuzz/src/hb-ot-deprecated.h
+++ b/thirdparty/harfbuzz/src/hb-ot-deprecated.h
@@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_H_IN
+#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead."
#endif
@@ -41,6 +41,13 @@ HB_BEGIN_DECLS
/* https://github.com/harfbuzz/harfbuzz/issues/1734 */
+/**
+ * HB_MATH_GLYPH_PART_FLAG_EXTENDER:
+ *
+ * Use #HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER instead.
+ *
+ * Deprecated: 2.5.1
+ */
#define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER
@@ -71,6 +78,8 @@ hb_ot_tag_from_language (hb_language_t language);
/**
* HB_OT_VAR_NO_AXIS_INDEX:
*
+ * Do not use.
+ *
* Since: 1.4.2
* Deprecated: 2.2.0
*/
@@ -78,6 +87,13 @@ hb_ot_tag_from_language (hb_language_t language);
/**
* hb_ot_var_axis_t:
+ * @tag: axis tag
+ * @name_id: axis name identifier
+ * @min_value: minimum value of the axis
+ * @default_value: default value of the axis
+ * @max_value: maximum value of the axis
+ *
+ * Use #hb_ot_var_axis_info_t instead.
*
* Since: 1.4.2
* Deprecated: 2.2.0
diff --git a/thirdparty/harfbuzz/src/hb-ot-font.h b/thirdparty/harfbuzz/src/hb-ot-font.h
index 80eaa54b1a..e7959d1ae2 100644
--- a/thirdparty/harfbuzz/src/hb-ot-font.h
+++ b/thirdparty/harfbuzz/src/hb-ot-font.h
@@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod, Roozbeh Pournader
*/
-#ifndef HB_OT_H_IN
+#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead."
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
index 5470bd96da..5352156f02 100644
--- a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
@@ -186,7 +186,7 @@ struct glyf
| hb_map (&SubsetGlyph::padded_size)
;
- if (c->serializer->in_error ()) return_trace (false);
+ if (unlikely (c->serializer->in_error ())) return_trace (false);
return_trace (c->serializer->check_success (_add_loca_and_head (c->plan,
padded_offsets)));
}
@@ -944,9 +944,9 @@ struct glyf
return;
}
extents->x_bearing = font->em_scalef_x (min_x);
- extents->width = font->em_scalef_x (max_x - min_x);
+ extents->width = font->em_scalef_x (max_x) - extents->x_bearing;
extents->y_bearing = font->em_scalef_y (max_y);
- extents->height = font->em_scalef_y (min_y - max_y);
+ extents->height = font->em_scalef_y (min_y) - extents->y_bearing;
}
protected:
diff --git a/thirdparty/harfbuzz/src/hb-ot-head-table.hh b/thirdparty/harfbuzz/src/hb-ot-head-table.hh
index 5613a96dbf..ac588e3af6 100644
--- a/thirdparty/harfbuzz/src/hb-ot-head-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-head-table.hh
@@ -43,7 +43,7 @@ namespace OT {
struct head
{
- friend struct OffsetTable;
+ friend struct OpenTypeOffsetTable;
static constexpr hb_tag_t tableTag = HB_OT_TAG_head;
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
index 6ab950a322..0ba7e3c061 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
@@ -1128,7 +1128,7 @@ struct Lookup
out->lookupType = lookupType;
out->lookupFlag = lookupFlag;
- const hb_set_t *glyphset = c->plan->glyphset ();
+ const hb_set_t *glyphset = c->plan->glyphset_gsub ();
unsigned int lookup_type = get_type ();
+ hb_iter (get_subtables <TSubTable> ())
| hb_filter ([this, glyphset, lookup_type] (const OffsetTo<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); })
@@ -1251,8 +1251,9 @@ struct CoverageFormat1
{
/* TODO Speed up, using hb_set_next() and bsearch()? */
unsigned int count = glyphArray.len;
+ const HBGlyphID *arr = glyphArray.arrayZ;
for (unsigned int i = 0; i < count; i++)
- if (glyphs->has (glyphArray[i]))
+ if (glyphs->has (arr[i]))
return true;
return false;
}
@@ -1356,18 +1357,21 @@ struct CoverageFormat2
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[i].intersects (glyphs))
+ /* TODO(iter) Rewrite as dagger. */
+ unsigned count = rangeRecord.len;
+ const RangeRecord *arr = rangeRecord.arrayZ;
+ for (unsigned i = 0; i < count; i++)
+ if (arr[i].intersects (glyphs))
return true;
return false;
}
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
{
- unsigned int i;
- unsigned int count = rangeRecord.len;
- for (i = 0; i < count; i++) {
- const RangeRecord &range = rangeRecord[i];
+ /* TODO(iter) Rewrite as dagger. */
+ unsigned count = rangeRecord.len;
+ const RangeRecord *arr = rangeRecord.arrayZ;
+ for (unsigned i = 0; i < count; i++) {
+ const RangeRecord &range = arr[i];
if (range.value <= index &&
index < (unsigned int) range.value + (range.last - range.first) &&
range.intersects (glyphs))
@@ -1502,7 +1506,7 @@ struct Coverage
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it =
@@ -1729,7 +1733,7 @@ struct ClassDefFormat1
hb_map_t *klass_map = nullptr /*OUT*/) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
hb_sorted_vector_t<HBGlyphID> glyphs;
@@ -1784,7 +1788,7 @@ struct ClassDefFormat1
}
template <typename set_t>
- bool collect_class (set_t *glyphs, unsigned int klass) const
+ bool collect_class (set_t *glyphs, unsigned klass) const
{
unsigned int count = classValue.len;
for (unsigned int i = 0; i < count; i++)
@@ -1802,7 +1806,7 @@ struct ClassDefFormat1
if (classValue[iter - start]) return true;
return false;
}
- bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+ bool intersects_class (const hb_set_t *glyphs, uint16_t klass) const
{
unsigned int count = classValue.len;
if (klass == 0)
@@ -1815,8 +1819,12 @@ struct ClassDefFormat1
if (hb_set_next (glyphs, &g)) return true;
/* Fall through. */
}
+ /* TODO Speed up, using set overlap first? */
+ /* TODO(iter) Rewrite as dagger. */
+ HBUINT16 k {klass};
+ const HBUINT16 *arr = classValue.arrayZ;
for (unsigned int i = 0; i < count; i++)
- if (classValue[i] == klass && glyphs->has (startGlyph + i))
+ if (arr[i] == k && glyphs->has (startGlyph + i))
return true;
return false;
}
@@ -1898,7 +1906,7 @@ struct ClassDefFormat2
hb_map_t *klass_map = nullptr /*OUT*/) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
hb_sorted_vector_t<HBGlyphID> glyphs;
@@ -1961,11 +1969,14 @@ struct ClassDefFormat2
/* TODO Speed up, using hb_set_next() and bsearch()? */
unsigned int count = rangeRecord.len;
for (unsigned int i = 0; i < count; i++)
- if (rangeRecord[i].intersects (glyphs))
+ {
+ const auto& range = rangeRecord[i];
+ if (range.intersects (glyphs) && range.value)
return true;
+ }
return false;
}
- bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+ bool intersects_class (const hb_set_t *glyphs, uint16_t klass) const
{
unsigned int count = rangeRecord.len;
if (klass == 0)
@@ -1984,8 +1995,12 @@ struct ClassDefFormat2
return true;
/* Fall through. */
}
+ /* TODO Speed up, using set overlap first? */
+ /* TODO(iter) Rewrite as dagger. */
+ HBUINT16 k {klass};
+ const RangeRecord *arr = rangeRecord.arrayZ;
for (unsigned int i = 0; i < count; i++)
- if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
+ if (arr[i].value == k && arr[i].intersects (glyphs))
return true;
return false;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
index 2217d298fb..f523e35c00 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
@@ -566,6 +566,26 @@ struct AnchorMatrix
return_trace (true);
}
+ bool subset (hb_subset_context_t *c,
+ unsigned cols,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+
+ auto indexes =
+ + hb_range (rows * cols)
+ | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % cols); })
+ ;
+
+ out->serialize (c->serializer,
+ (unsigned) rows,
+ this,
+ c->plan->layout_variation_idx_map,
+ indexes);
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
{
TRACE_SANITIZE (this);
@@ -755,7 +775,7 @@ struct SinglePosFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it =
@@ -870,7 +890,7 @@ struct SinglePosFormat2
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
unsigned sub_length = valueFormat.get_len ();
@@ -1129,7 +1149,7 @@ struct PairSet
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->len = 0;
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
unsigned len1 = valueFormats[0].get_len ();
@@ -1250,7 +1270,7 @@ struct PairPosFormat1
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
@@ -1441,7 +1461,7 @@ struct PairPosFormat2
})
;
- const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it =
@@ -1728,7 +1748,7 @@ struct CursivePosFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
@@ -1904,7 +1924,7 @@ struct MarkBasePosFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
@@ -2025,10 +2045,37 @@ typedef AnchorMatrix LigatureAttach; /* component-major--
* mark-minor--
* ordered by class--zero-based. */
-typedef OffsetListOf<LigatureAttach> LigatureArray;
- /* Array of LigatureAttach
- * tables ordered by
- * LigatureCoverage Index */
+/* Array of LigatureAttach tables ordered by LigatureCoverage Index */
+struct LigatureArray : OffsetListOf<LigatureAttach>
+{
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ Iterator coverage,
+ unsigned class_count,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ for (const auto _ : + hb_zip (coverage, *this)
+ | hb_filter (glyphset, hb_first))
+ {
+ auto *matrix = out->serialize_append (c->serializer);
+ if (unlikely (!matrix)) return_trace (false);
+
+ matrix->serialize_subset (c,
+ _.second,
+ this,
+ class_count,
+ klass_mapping);
+ }
+ return_trace (this->len);
+ }
+};
struct MarkLigPosFormat1
{
@@ -2130,8 +2177,56 @@ struct MarkLigPosFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- // TODO(subset)
- return_trace (false);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark_iter =
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ auto new_mark_coverage =
+ + mark_iter
+ | hb_map_retains_sorting (hb_first)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ if (!out->markCoverage.serialize (c->serializer, out)
+ .serialize (c->serializer, new_mark_coverage))
+ return_trace (false);
+
+ out->markArray.serialize (c->serializer, out)
+ .serialize (c->serializer,
+ &klass_mapping,
+ c->plan->layout_variation_idx_map,
+ &(this+markArray),
+ + mark_iter
+ | hb_map (hb_second));
+
+ auto new_ligature_coverage =
+ + hb_iter (this + ligatureCoverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ if (!out->ligatureCoverage.serialize (c->serializer, out)
+ .serialize (c->serializer, new_ligature_coverage))
+ return_trace (false);
+
+ out->ligatureArray.serialize_subset (c, ligatureArray, this,
+ hb_iter (this+ligatureCoverage), classCount, &klass_mapping);
+
+ return_trace (true);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2164,6 +2259,7 @@ struct MarkLigPosFormat1
DEFINE_SIZE_STATIC (12);
};
+
struct MarkLigPos
{
template <typename context_t, typename ...Ts>
@@ -2288,7 +2384,7 @@ struct MarkMarkPosFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
index 2f41d67819..5f10ecb7ee 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
@@ -356,7 +356,7 @@ struct Sequence
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
if (!intersects (&glyphset)) return_trace (false);
@@ -447,7 +447,7 @@ struct MultipleSubstFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
@@ -582,7 +582,7 @@ struct AlternateSet
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it =
@@ -682,7 +682,7 @@ struct AlternateSubstFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
@@ -840,7 +840,7 @@ struct Ligature
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
@@ -1058,7 +1058,7 @@ struct LigatureSubstFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
index cb95e6dcd5..36a95ead15 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
@@ -89,7 +89,7 @@ struct hb_closure_context_t :
bool is_lookup_done (unsigned int lookup_index)
{
- if (done_lookups->in_error ())
+ if (unlikely (done_lookups->in_error ()))
return true;
/* Have we visited this lookup with the current set of glyphs? */
@@ -146,7 +146,6 @@ struct hb_closure_lookups_context_t :
if (is_lookup_visited (lookup_index))
return;
- set_lookup_visited (lookup_index);
nesting_level_left--;
recurse_func (this, lookup_index);
nesting_level_left++;
@@ -163,10 +162,10 @@ struct hb_closure_lookups_context_t :
bool is_lookup_visited (unsigned lookup_index)
{
- if (lookup_count++ > HB_MAX_LOOKUP_INDICES)
+ if (unlikely (lookup_count++ > HB_MAX_LOOKUP_INDICES))
return true;
- if (visited_lookups->in_error ())
+ if (unlikely (visited_lookups->in_error ()))
return true;
return visited_lookups->has (lookup_index);
@@ -660,7 +659,7 @@ struct hb_ot_apply_context_t :
void replace_glyph (hb_codepoint_t glyph_index) const
{
_set_glyph_props (glyph_index);
- buffer->replace_glyph (glyph_index);
+ (void) buffer->replace_glyph (glyph_index);
}
void replace_glyph_inplace (hb_codepoint_t glyph_index) const
{
@@ -671,13 +670,13 @@ struct hb_ot_apply_context_t :
unsigned int class_guess) const
{
_set_glyph_props (glyph_index, class_guess, true);
- buffer->replace_glyph (glyph_index);
+ (void) buffer->replace_glyph (glyph_index);
}
void output_glyph_for_component (hb_codepoint_t glyph_index,
unsigned int class_guess) const
{
_set_glyph_props (glyph_index, class_guess, false, true);
- buffer->output_glyph (glyph_index);
+ (void) buffer->output_glyph (glyph_index);
}
};
@@ -1044,7 +1043,7 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
hb_min (this_comp, last_num_components);
_hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
}
last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
@@ -1188,7 +1187,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
/* Don't recurse to ourself at same position.
* Note that this test is too naive, it doesn't catch longer loops. */
- if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
+ if (unlikely (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index))
continue;
if (unlikely (!buffer->move_to (match_positions[idx])))
@@ -1226,7 +1225,8 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
* mean that n match positions where removed, as there might
* have been marks and default-ignorables in the sequence. We
* should instead drop match positions between current-position
- * and current-position + n instead.
+ * and current-position + n instead. Though, am not sure which
+ * one is better. Both cases have valid uses. Sigh.
*
* It should be possible to construct tests for both of these cases.
*/
@@ -1272,7 +1272,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
match_positions[next] += delta;
}
- buffer->move_to (end);
+ (void) buffer->move_to (end);
return_trace (true);
}
@@ -1389,9 +1389,11 @@ struct Rule
lookup_context);
}
- void closure_lookups (hb_closure_lookups_context_t *c) const
+ void closure_lookups (hb_closure_lookups_context_t *c,
+ ContextClosureLookupContext &lookup_context) const
{
if (unlikely (c->lookup_limit_exceeded ())) return;
+ if (!intersects (c->glyphs, lookup_context)) return;
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
(inputZ.as_array (inputCount ? inputCount - 1 : 0));
@@ -1521,14 +1523,13 @@ struct RuleSet
;
}
- void closure_lookups (hb_closure_lookups_context_t *c) const
+ void closure_lookups (hb_closure_lookups_context_t *c,
+ ContextClosureLookupContext &lookup_context) const
{
if (unlikely (c->lookup_limit_exceeded ())) return;
-
- return
+ hb_iter (rule)
| hb_map (hb_add (this))
- | hb_apply ([&] (const Rule &_) { _.closure_lookups (c); })
+ | hb_apply ([&] (const Rule &_) { _.closure_lookups (c, lookup_context); })
;
}
@@ -1647,9 +1648,16 @@ struct ContextFormat1
void closure_lookups (hb_closure_lookups_context_t *c) const
{
- + hb_iter (ruleSet)
+ struct ContextClosureLookupContext lookup_context = {
+ {intersects_glyph},
+ nullptr
+ };
+
+ + hb_zip (this+coverage, ruleSet)
+ | hb_filter (*c->glyphs, hb_first)
+ | hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); })
+ | hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c, lookup_context); })
;
}
@@ -1700,7 +1708,7 @@ struct ContextFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
@@ -1791,10 +1799,24 @@ struct ContextFormat2
void closure_lookups (hb_closure_lookups_context_t *c) const
{
+ if (!(this+coverage).intersects (c->glyphs))
+ return;
+
+ const ClassDef &class_def = this+classDef;
+
+ struct ContextClosureLookupContext lookup_context = {
+ {intersects_class},
+ &class_def
+ };
+
+ hb_iter (ruleSet)
| hb_map (hb_add (this))
- | hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); })
- ;
+ | hb_enumerate
+ | hb_filter ([&] (const hb_pair_t<unsigned, const RuleSet &> p)
+ { return class_def.intersects_class (c->glyphs, p.first); })
+ | hb_map (hb_second)
+ | hb_apply ([&] (const RuleSet & _)
+ { _.closure_lookups (c, lookup_context); });
}
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
@@ -1860,8 +1882,8 @@ struct ContextFormat2
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 = 0, index = 0;
- for (const hb_pair_t<unsigned, const OffsetTo<RuleSet>&> _ : + hb_enumerate (ruleSet)
- | hb_filter (klass_map, hb_first))
+ for (const auto& _ : + hb_enumerate (ruleSet)
+ | hb_filter (klass_map, hb_first))
{
auto *o = out->ruleSet.serialize_append (c->serializer);
if (unlikely (!o))
@@ -1945,6 +1967,8 @@ struct ContextFormat3
void closure_lookups (hb_closure_lookups_context_t *c) const
{
+ if (!intersects (c->glyphs))
+ return;
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
recurse_lookups (c, lookupCount, lookupRecord);
}
@@ -2010,6 +2034,7 @@ struct ContextFormat3
for (const OffsetTo<Coverage>& offset : coverages)
{
+ /* TODO(subset) This looks like should not be necessary to write this way. */
auto *o = c->serializer->allocate_size<OffsetTo<Coverage>> (OffsetTo<Coverage>::static_size);
if (unlikely (!o)) return_trace (false);
if (!o->serialize_subset (c, offset, this)) return_trace (false);
@@ -2238,9 +2263,11 @@ struct ChainRule
lookup_context);
}
- void closure_lookups (hb_closure_lookups_context_t *c) const
+ void closure_lookups (hb_closure_lookups_context_t *c,
+ ChainContextClosureLookupContext &lookup_context) const
{
if (unlikely (c->lookup_limit_exceeded ())) return;
+ if (!intersects (c->glyphs, lookup_context)) return;
const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
@@ -2296,11 +2323,7 @@ struct ChainRule
{
c->copy (len);
for (const auto g : it)
- {
- HBUINT16 gid;
- gid = g;
- c->copy (gid);
- }
+ c->copy ((HBUINT16) g);
}
ChainRule* copy (hb_serialize_context_t *c,
@@ -2328,12 +2351,19 @@ struct ChainRule
| hb_map (mapping));
const ArrayOf<LookupRecord> &lookupRecord = StructAfter<ArrayOf<LookupRecord>> (lookahead);
- HBUINT16 lookupCount;
- lookupCount = lookupRecord.len;
- if (!c->copy (lookupCount)) return_trace (nullptr);
- for (unsigned i = 0; i < (unsigned) lookupCount; i++)
+ HBUINT16* lookupCount = c->embed (&(lookupRecord.len));
+ if (!lookupCount) return_trace (nullptr);
+
+ for (unsigned i = 0; i < lookupRecord.len; i++)
+ {
+ if (!lookup_map->has (lookupRecord[i].lookupListIndex))
+ {
+ (*lookupCount)--;
+ continue;
+ }
if (!c->copy (lookupRecord[i], lookup_map)) return_trace (nullptr);
+ }
return_trace (out);
}
@@ -2351,7 +2381,7 @@ struct ChainRule
if (!backtrack_map)
{
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
if (!hb_all (backtrack, glyphset) ||
!hb_all (input, glyphset) ||
!hb_all (lookahead, glyphset))
@@ -2424,14 +2454,14 @@ struct ChainRuleSet
;
}
- void closure_lookups (hb_closure_lookups_context_t *c) const
+ void closure_lookups (hb_closure_lookups_context_t *c,
+ ChainContextClosureLookupContext &lookup_context) const
{
if (unlikely (c->lookup_limit_exceeded ())) return;
- return
+ hb_iter (rule)
| hb_map (hb_add (this))
- | hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c); })
+ | hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c, lookup_context); })
;
}
@@ -2552,9 +2582,16 @@ struct ChainContextFormat1
void closure_lookups (hb_closure_lookups_context_t *c) const
{
- + hb_iter (ruleSet)
+ struct ChainContextClosureLookupContext lookup_context = {
+ {intersects_glyph},
+ {nullptr, nullptr, nullptr}
+ };
+
+ + hb_zip (this+coverage, ruleSet)
+ | hb_filter (*c->glyphs, hb_first)
+ | hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); })
+ | hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c, lookup_context); })
;
}
@@ -2604,7 +2641,7 @@ struct ChainContextFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
@@ -2701,9 +2738,28 @@ struct ChainContextFormat2
void closure_lookups (hb_closure_lookups_context_t *c) const
{
+ if (!(this+coverage).intersects (c->glyphs))
+ return;
+
+ const ClassDef &backtrack_class_def = this+backtrackClassDef;
+ const ClassDef &input_class_def = this+inputClassDef;
+ const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+ struct ChainContextClosureLookupContext lookup_context = {
+ {intersects_class},
+ {&backtrack_class_def,
+ &input_class_def,
+ &lookahead_class_def}
+ };
+
+ hb_iter (ruleSet)
| hb_map (hb_add (this))
- | hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); })
+ | hb_enumerate
+ | hb_filter([&] (unsigned klass)
+ { return input_class_def.intersects_class (c->glyphs, klass); }, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const ChainRuleSet &_)
+ { _.closure_lookups (c, lookup_context); })
;
}
@@ -2779,24 +2835,23 @@ struct ChainContextFormat2
out->coverage.serialize_subset (c, coverage, this);
hb_map_t backtrack_klass_map;
- out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, &backtrack_klass_map);
- if (unlikely (!c->serializer->check_success (!backtrack_klass_map.in_error ())))
- return_trace (false);
-
- // subset inputClassDef based on glyphs survived in Coverage subsetting
hb_map_t input_klass_map;
- out->inputClassDef.serialize_subset (c, inputClassDef, this, &input_klass_map);
- if (unlikely (!c->serializer->check_success (!input_klass_map.in_error ())))
- return_trace (false);
-
hb_map_t lookahead_klass_map;
+
+ out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, &backtrack_klass_map);
+ // TODO: subset inputClassDef based on glyphs survived in Coverage subsetting
+ out->inputClassDef.serialize_subset (c, inputClassDef, this, &input_klass_map);
out->lookaheadClassDef.serialize_subset (c, lookaheadClassDef, this, &lookahead_klass_map);
- if (unlikely (!c->serializer->check_success (!lookahead_klass_map.in_error ())))
+
+ if (unlikely (!c->serializer->propagate_error (backtrack_klass_map,
+ input_klass_map,
+ lookahead_klass_map)))
return_trace (false);
- unsigned non_zero_index = 0, index = 0;
+ int non_zero_index = -1, index = 0;
bool ret = true;
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
+ auto last_non_zero = c->serializer->snapshot ();
for (const OffsetTo<ChainRuleSet>& _ : + hb_enumerate (ruleSet)
| hb_filter (input_klass_map, hb_first)
| hb_map (hb_second))
@@ -2812,19 +2867,20 @@ struct ChainContextFormat2
&backtrack_klass_map,
&input_klass_map,
&lookahead_klass_map))
+ {
+ last_non_zero = c->serializer->snapshot ();
non_zero_index = index;
+ }
index++;
}
if (!ret) return_trace (ret);
- //prune empty trailing ruleSets
- --index;
- while (index > non_zero_index)
- {
- out->ruleSet.pop ();
- index--;
+ // prune empty trailing ruleSets
+ if (index > non_zero_index) {
+ c->serializer->revert (last_non_zero);
+ out->ruleSet.len = non_zero_index + 1;
}
return_trace (bool (out->ruleSet));
@@ -2908,6 +2964,9 @@ struct ChainContextFormat3
void closure_lookups (hb_closure_lookups_context_t *c) const
{
+ if (!intersects (c->glyphs))
+ return;
+
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
@@ -2986,13 +3045,16 @@ struct ChainContextFormat3
TRACE_SERIALIZE (this);
auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> ();
- if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size))) return_trace (false);
+ if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
+ return_trace (false);
- + it
- | hb_apply (subset_offset_array (c, *out, base))
- ;
+ for (auto& offset : it) {
+ auto *o = out->serialize_append (c->serializer);
+ if (unlikely (!o) || !o->serialize_subset (c, offset, base))
+ return_trace (false);
+ }
- return_trace (out->len);
+ return_trace (true);
}
bool subset (hb_subset_context_t *c) const
@@ -3113,6 +3175,24 @@ struct ExtensionFormat1
extensionLookupType != T::SubTable::Extension);
}
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ out->format = format;
+ out->extensionLookupType = extensionLookupType;
+
+ const auto& src_offset =
+ reinterpret_cast<const LOffsetTo<typename T::SubTable> &> (extensionOffset);
+ auto& dest_offset =
+ reinterpret_cast<LOffsetTo<typename T::SubTable> &> (out->extensionOffset);
+
+ return_trace (dest_offset.serialize_subset (c, src_offset, this, get_type ()));
+ }
+
protected:
HBUINT16 format; /* Format identifier. Set to 1. */
HBUINT16 extensionLookupType; /* Lookup type of subtable referenced
@@ -3143,6 +3223,18 @@ struct Extension
}
}
+ // Specialization of dispatch for subset. dispatch() normally just
+ // dispatches to the sub table this points too, but for subset
+ // we need to run subset on this subtable too.
+ template <typename ...Ts>
+ typename hb_subset_context_t::return_t dispatch (hb_subset_context_t *c, Ts&&... ds) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.subset (c);
+ default: return c->default_return_value ();
+ }
+ }
+
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
@@ -3320,20 +3412,34 @@ struct GSUBGPOS
return_trace (true);
}
- void closure_features (const hb_map_t *lookup_indexes, /* IN */
- hb_set_t *feature_indexes /* OUT */) const
+ void prune_features (const hb_map_t *lookup_indices, /* IN */
+ hb_set_t *feature_indices /* IN/OUT */) const
{
- unsigned int feature_count = hb_min (get_feature_count (), (unsigned) HB_MAX_FEATURES);
- for (unsigned i = 0; i < feature_count; i++)
+#ifndef HB_NO_VAR
+ // This is the set of feature indices which have alternate versions defined
+ // if the FeatureVariation's table and the alternate version(s) intersect the
+ // set of lookup indices.
+ hb_set_t alternate_feature_indices;
+ if (version.to_int () >= 0x00010001u)
+ (this+featureVars).closure_features (lookup_indices, &alternate_feature_indices);
+ if (unlikely (alternate_feature_indices.in_error())) {
+ feature_indices->successful = false;
+ return;
+ }
+#endif
+
+ for (unsigned i : feature_indices->iter())
{
const Feature& f = get_feature (i);
- if ((!f.featureParams.is_null ()) || f.intersects_lookup_indexes (lookup_indexes))
- feature_indexes->add (i);
- }
+
+ if (f.featureParams.is_null ()
+ && !f.intersects_lookup_indexes (lookup_indices)
#ifndef HB_NO_VAR
- if (version.to_int () >= 0x00010001u)
- (this+featureVars).closure_features (lookup_indexes, feature_indexes);
+ && !alternate_feature_indices.has (i)
#endif
+ )
+ feature_indices->del (i);
+ }
}
unsigned int get_size () const
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc
index f25f0f9e23..89df949b26 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc
@@ -76,7 +76,7 @@
* Tests whether a face includes any kerning data in the 'kern' table.
* Does NOT test for kerning lookups in the GPOS table.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
**/
bool
@@ -92,7 +92,7 @@ hb_ot_layout_has_kerning (hb_face_t *face)
* Tests whether a face includes any state-machine kerning in the 'kern' table.
* Does NOT examine the GPOS table.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
**/
bool
@@ -112,7 +112,7 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face)
*
* Does NOT examine the GPOS table.
*
- * Return value: %true is data found, false otherwise
+ * Return value: %true is data found, %false otherwise
*
**/
bool
@@ -268,7 +268,7 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font,
*
* Tests whether a face has any glyph classes defined in its GDEF table.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
**/
hb_bool_t
@@ -322,7 +322,7 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face,
* @face: The #hb_face_t to work on
* @glyph: The #hb_codepoint_t code point to query
* @start_offset: offset of the first attachment point to retrieve
- * @point_count: (inout) (allow-none): Input = the maximum number of attachment points to return;
+ * @point_count: (inout) (optional): Input = the maximum number of attachment points to return;
* Output = the actual number of attachment points returned (may be zero)
* @point_array: (out) (array length=point_count): The array of attachment points found for the query
*
@@ -350,7 +350,7 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
* @direction: The #hb_direction_t text direction to use
* @glyph: The #hb_codepoint_t code point to query
* @start_offset: offset of the first caret position to retrieve
- * @caret_count: (inout) (allow-none): Input = the maximum number of caret positions to return;
+ * @caret_count: (inout) (optional): Input = the maximum number of caret positions to return;
* Output = the actual number of caret positions returned (may be zero)
* @caret_array: (out) (array length=caret_count): The array of caret positions found for the query
*
@@ -410,9 +410,9 @@ get_gsubgpos_table (hb_face_t *face,
/**
* hb_ot_layout_table_get_script_tags:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @start_offset: offset of the first script tag to retrieve
- * @script_count: (inout) (allow-none): Input = the maximum number of script tags to return;
+ * @script_count: (inout) (optional): Input = the maximum number of script tags to return;
* Output = the actual number of script tags returned (may be zero)
* @script_tags: (out) (array length=script_count): The array of #hb_tag_t script tags found for the query
*
@@ -437,14 +437,14 @@ hb_ot_layout_table_get_script_tags (hb_face_t *face,
/**
* hb_ot_layout_table_find_script:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_tag: #hb_tag_t of the script tag requested
* @script_index: (out): The index of the requested script tag
*
* Fetches the index if a given script tag in the specified face's GSUB table
* or GPOS table.
*
- * Return value: %true if the script is found, false otherwise
+ * Return value: %true if the script is found, %false otherwise
*
**/
hb_bool_t
@@ -481,7 +481,7 @@ hb_ot_layout_table_find_script (hb_face_t *face,
/**
* hb_ot_layout_table_choose_script:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_tags: Array of #hb_tag_t script tags
* @script_index: (out): The index of the requested script tag
* @chosen_script: (out): #hb_tag_t of the script tag requested
@@ -504,11 +504,22 @@ hb_ot_layout_table_choose_script (hb_face_t *face,
/**
* hb_ot_layout_table_select_script:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_count: Number of script tags in the array
* @script_tags: Array of #hb_tag_t script tags
- * @script_index: (out): The index of the requested script
- * @chosen_script: (out): #hb_tag_t of the requested script
+ * @script_index: (out) (optional): The index of the requested script
+ * @chosen_script: (out) (optional): #hb_tag_t of the requested script
+ *
+ * Selects an OpenType script for @table_tag from the @script_tags array.
+ *
+ * If the table does not have any of the requested scripts, then `DFLT`,
+ * `dflt`, and `latn` tags are tried in that order. If the table still does not
+ * have any of these scripts, @script_index and @chosen_script are set to
+ * #HB_OT_LAYOUT_NO_SCRIPT_INDEX.
+ *
+ * Return value:
+ * %true if one of the requested scripts is selected, %false if a fallback
+ * script is selected or if no scripts are selected.
*
* Since: 2.0.0
**/
@@ -566,9 +577,9 @@ hb_ot_layout_table_select_script (hb_face_t *face,
/**
* hb_ot_layout_table_get_feature_tags:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @start_offset: offset of the first feature tag to retrieve
- * @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return;
+ * @feature_count: (inout) (optional): Input = the maximum number of feature tags to return;
* Output = the actual number of feature tags returned (may be zero)
* @feature_tags: (out) (array length=feature_count): Array of feature tags found in the table
*
@@ -591,14 +602,14 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face,
/**
* hb_ot_layout_table_find_feature:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @feature_tag: The #hb_tag_t og the requested feature tag
* @feature_index: (out): The index of the requested feature
*
* Fetches the index for a given feature tag in the specified face's GSUB table
* or GPOS table.
*
- * Return value: %true if the feature is found, false otherwise
+ * Return value: %true if the feature is found, %false otherwise
**/
bool
hb_ot_layout_table_find_feature (hb_face_t *face,
@@ -626,10 +637,10 @@ hb_ot_layout_table_find_feature (hb_face_t *face,
/**
* hb_ot_layout_script_get_language_tags:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag
* @start_offset: offset of the first language tag to retrieve
- * @language_count: (inout) (allow-none): Input = the maximum number of language tags to return;
+ * @language_count: (inout) (optional): Input = the maximum number of language tags to return;
* Output = the actual number of language tags returned (may be zero)
* @language_tags: (out) (array length=language_count): Array of language tags found in the table
*
@@ -655,7 +666,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face,
/**
* hb_ot_layout_script_find_language:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag
* @language_tag: The #hb_tag_t of the requested language
* @language_index: The index of the requested language
@@ -663,7 +674,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face,
* Fetches the index of a given language tag in the specified face's GSUB table
* or GPOS table, underneath the specified script tag.
*
- * Return value: %true if the language tag is found, false otherwise
+ * Return value: %true if the language tag is found, %false otherwise
*
* Since: ??
* Deprecated: ??
@@ -688,7 +699,7 @@ hb_ot_layout_script_find_language (hb_face_t *face,
/**
* hb_ot_layout_script_select_language:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag
* @language_count: The number of languages in the specified script
* @language_tags: The array of language tags
@@ -697,7 +708,7 @@ hb_ot_layout_script_find_language (hb_face_t *face,
* Fetches the index of a given language tag in the specified face's GSUB table
* or GPOS table, underneath the specified script index.
*
- * Return value: %true if the language tag is found, false otherwise
+ * Return value: %true if the language tag is found, %false otherwise
*
* Since: 2.0.0
**/
@@ -731,7 +742,7 @@ hb_ot_layout_script_select_language (hb_face_t *face,
/**
* hb_ot_layout_language_get_required_feature_index:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag
* @language_index: The index of the requested language tag
* @feature_index: (out): The index of the requested feature
@@ -739,7 +750,7 @@ hb_ot_layout_script_select_language (hb_face_t *face,
* Fetches the index of a requested feature in the given face's GSUB or GPOS table,
* underneath the specified script and language.
*
- * Return value: %true if the feature is found, false otherwise
+ * Return value: %true if the feature is found, %false otherwise
*
**/
hb_bool_t
@@ -761,7 +772,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
/**
* hb_ot_layout_language_get_required_feature:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag
* @language_index: The index of the requested language tag
* @feature_index: (out): The index of the requested feature
@@ -770,7 +781,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
* Fetches the tag of a requested feature index in the given face's GSUB or GPOS table,
* underneath the specified script and language.
*
- * Return value: %true if the feature is found, false otherwise
+ * Return value: %true if the feature is found, %false otherwise
*
* Since: 0.9.30
**/
@@ -796,11 +807,11 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face,
/**
* hb_ot_layout_language_get_feature_indexes:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag
* @language_index: The index of the requested language tag
* @start_offset: offset of the first feature tag to retrieve
- * @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return;
+ * @feature_count: (inout) (optional): Input = the maximum number of feature tags to return;
* Output: the actual number of feature tags returned (may be zero)
* @feature_indexes: (out) (array length=feature_count): The array of feature indexes found for the query
*
@@ -827,11 +838,11 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
/**
* hb_ot_layout_language_get_feature_tags:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag
* @language_index: The index of the requested language tag
* @start_offset: offset of the first feature tag to retrieve
- * @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return;
+ * @feature_count: (inout) (optional): Input = the maximum number of feature tags to return;
* Output = the actual number of feature tags returned (may be zero)
* @feature_tags: (out) (array length=feature_count): The array of #hb_tag_t feature tags found for the query
*
@@ -868,7 +879,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face,
/**
* hb_ot_layout_language_find_feature:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag
* @language_index: The index of the requested language tag
* @feature_tag: #hb_tag_t of the feature tag requested
@@ -877,7 +888,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face,
* Fetches the index of a given feature tag in the specified face's GSUB table
* or GPOS table, underneath the specified script and language.
*
- * Return value: %true if the feature is found, false otherwise
+ * Return value: %true if the feature is found, %false otherwise
*
**/
hb_bool_t
@@ -910,10 +921,10 @@ hb_ot_layout_language_find_feature (hb_face_t *face,
/**
* hb_ot_layout_feature_get_lookups:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @feature_index: The index of the requested feature
* @start_offset: offset of the first lookup to retrieve
- * @lookup_count: (inout) (allow-none): Input = the maximum number of lookups to return;
+ * @lookup_count: (inout) (optional): Input = the maximum number of lookups to return;
* Output = the actual number of lookups returned (may be zero)
* @lookup_indexes: (out) (array length=lookup_count): The array of lookup indexes found for the query
*
@@ -944,7 +955,7 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face,
/**
* hb_ot_layout_table_get_lookup_count:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
*
* Fetches the total number of lookups enumerated in the specified
* face's GSUB table or GPOS table.
@@ -1101,7 +1112,7 @@ script_collect_features (hb_collect_features_context_t *c,
/**
* hb_ot_layout_collect_features:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @scripts: The array of scripts to collect features for
* @languages: The array of languages to collect features for
* @features: The array of features to collect
@@ -1152,7 +1163,7 @@ hb_ot_layout_collect_features (hb_face_t *face,
/**
* hb_ot_layout_collect_lookups:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @scripts: The array of scripts to collect lookups for
* @languages: The array of languages to collect lookups for
* @features: The array of features to collect lookups for
@@ -1191,7 +1202,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
/**
* hb_ot_layout_lookup_collect_glyphs:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @lookup_index: The index of the feature lookup to query
* @glyphs_before: (out): Array of glyphs preceding the substitution range
* @glyphs_input: (out): Array of input glyphs that would be substituted by the lookup
@@ -1243,7 +1254,7 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
/**
* hb_ot_layout_table_find_feature_variations:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @coords: The variation coordinates to query
* @num_coords: The number of variation coordinates
* @variations_index: (out): The array of feature variations found for the query
@@ -1268,11 +1279,11 @@ hb_ot_layout_table_find_feature_variations (hb_face_t *face,
/**
* hb_ot_layout_feature_with_variations_get_lookups:
* @face: #hb_face_t to work upon
- * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @feature_index: The index of the feature to query
* @variations_index: The index of the feature variation to query
* @start_offset: offset of the first lookup to retrieve
- * @lookup_count: (inout) (allow-none): Input = the maximum number of lookups to return;
+ * @lookup_count: (inout) (optional): Input = the maximum number of lookups to return;
* Output = the actual number of lookups returned (may be zero)
* @lookup_indexes: (out) (array length=lookup_count): The array of lookups found for the query
*
@@ -1310,7 +1321,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
*
* Tests whether the specified face includes any GSUB substitutions.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
**/
hb_bool_t
@@ -1331,7 +1342,7 @@ hb_ot_layout_has_substitution (hb_face_t *face)
* Tests whether a specified lookup in the specified face would
* trigger a substitution on the given glyph sequence.
*
- * Return value: %true if a substitution would be triggered, false otherwise
+ * Return value: %true if a substitution would be triggered, %false otherwise
*
* Since: 0.9.7
**/
@@ -1488,7 +1499,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
* hb_ot_layout_has_positioning:
* @face: #hb_face_t to work upon
*
- * Return value: %true if the face has GPOS data, false otherwise
+ * Tests whether the specified face includes any GPOS positioning.
+ *
+ * Return value: %true if the face has GPOS data, %false otherwise
*
**/
hb_bool_t
@@ -1561,7 +1574,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
* For more information on this distinction, see the [`size` feature documentation](
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size).
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 0.9.10
**/
@@ -1610,22 +1623,22 @@ hb_ot_layout_get_size_params (hb_face_t *face,
* @face: #hb_face_t to work upon
* @table_tag: table tag to query, "GSUB" or "GPOS".
* @feature_index: index of feature to query.
- * @label_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
+ * @label_id: (out) (optional): The ‘name’ table name ID that specifies a string
* for a user-interface label for this feature. (May be NULL.)
- * @tooltip_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
+ * @tooltip_id: (out) (optional): The ‘name’ table name ID that specifies a string
* that an application can use for tooltip text for this
* feature. (May be NULL.)
- * @sample_id: (out) (allow-none): The ‘name’ table name ID that specifies sample text
+ * @sample_id: (out) (optional): The ‘name’ table name ID that specifies sample text
* that illustrates the effect of this feature. (May be NULL.)
- * @num_named_parameters: (out) (allow-none): Number of named parameters. (May be zero.)
- * @first_param_id: (out) (allow-none): The first ‘name’ table name ID used to specify
+ * @num_named_parameters: (out) (optional): Number of named parameters. (May be zero.)
+ * @first_param_id: (out) (optional): The first ‘name’ table name ID used to specify
* strings for user-interface labels for the feature
* parameters. (Must be zero if numParameters is zero.)
*
* Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or
* "Character Variant" ('cvXX') features.
*
- * Return value: %true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 2.0.0
**/
@@ -1685,7 +1698,7 @@ hb_ot_layout_feature_get_name_ids (hb_face_t *face,
* @table_tag: table tag to query, "GSUB" or "GPOS".
* @feature_index: index of feature to query.
* @start_offset: offset of the first character to retrieve
- * @char_count: (inout) (allow-none): Input = the maximum number of characters to return;
+ * @char_count: (inout) (optional): Input = the maximum number of characters to return;
* Output = the actual number of characters returned (may be zero)
* @characters: (out caller-allocates) (array length=char_count): A buffer pointer.
* The Unicode codepoints of the characters for which this feature provides
@@ -1769,7 +1782,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
if (applied)
ret = true;
else
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
}
return ret;
}
@@ -1907,7 +1920,7 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
* @baseline_tag: a baseline tag
* @direction: text direction.
* @script_tag: script tag.
- * @language_tag: language tag.
+ * @language_tag: language tag, currently unused.
* @coord: (out): baseline value if found.
*
* Fetches a baseline value from the face.
@@ -1964,7 +1977,7 @@ struct hb_get_glyph_alternates_dispatch_t :
* @lookup_index: index of the feature lookup to query.
* @glyph: a glyph id.
* @start_offset: starting offset.
- * @alternate_count: (inout) (allow-none): Input = the maximum number of alternate glyphs to return;
+ * @alternate_count: (inout) (optional): Input = the maximum number of alternate glyphs to return;
* Output = the actual number of alternate glyphs returned (may be zero).
* @alternate_glyphs: (out caller-allocates) (array length=alternate_count): A glyphs buffer.
* Alternate glyphs associated with the glyph id.
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.h b/thirdparty/harfbuzz/src/hb-ot-layout.h
index 545d5f7fc4..d47ba0fc92 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.h
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.h
@@ -24,7 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_H_IN
+#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead."
#endif
@@ -38,10 +38,35 @@
HB_BEGIN_DECLS
+/**
+ * HB_OT_TAG_BASE:
+ *
+ * OpenType [Baseline Table](https://docs.microsoft.com/en-us/typography/opentype/spec/base).
+ */
#define HB_OT_TAG_BASE HB_TAG('B','A','S','E')
+/**
+ * HB_OT_TAG_GDEF:
+ *
+ * OpenType [Glyph Definition Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef).
+ */
#define HB_OT_TAG_GDEF HB_TAG('G','D','E','F')
+/**
+ * HB_OT_TAG_GSUB:
+ *
+ * OpenType [Glyph Substitution Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gsub).
+ */
#define HB_OT_TAG_GSUB HB_TAG('G','S','U','B')
+/**
+ * HB_OT_TAG_GPOS:
+ *
+ * OpenType [Glyph Positioning Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos).
+ */
#define HB_OT_TAG_GPOS HB_TAG('G','P','O','S')
+/**
+ * HB_OT_TAG_JSTF:
+ *
+ * OpenType [Justification Table](https://docs.microsoft.com/en-us/typography/opentype/spec/jstf).
+ */
#define HB_OT_TAG_JSTF HB_TAG('J','S','T','F')
@@ -49,18 +74,34 @@ HB_BEGIN_DECLS
* Script & Language tags.
*/
+/**
+ * HB_OT_TAG_DEFAULT_SCRIPT:
+ *
+ * OpenType script tag, `DFLT`, for features that are not script-specific.
+ *
+ */
#define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T')
+/**
+ * HB_OT_TAG_DEFAULT_LANGUAGE:
+ *
+ * OpenType language tag, `dflt`. Not a valid language tag, but some fonts
+ * mistakenly use it.
+ */
#define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't')
/**
* HB_OT_MAX_TAGS_PER_SCRIPT:
*
+ * Maximum number of OpenType tags that can correspond to a give #hb_script_t.
+ *
* Since: 2.0.0
**/
#define HB_OT_MAX_TAGS_PER_SCRIPT 3u
/**
* HB_OT_MAX_TAGS_PER_LANGUAGE:
*
+ * Maximum number of OpenType tags that can correspond to a give #hb_language_t.
+ *
* Since: 2.0.0
**/
#define HB_OT_MAX_TAGS_PER_LANGUAGE 3u
@@ -144,9 +185,29 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
* GSUB/GPOS feature query and enumeration interface
*/
+/**
+ * HB_OT_LAYOUT_NO_SCRIPT_INDEX:
+ *
+ * Special value for script index indicating unsupported script.
+ */
#define HB_OT_LAYOUT_NO_SCRIPT_INDEX 0xFFFFu
+/**
+ * HB_OT_LAYOUT_NO_FEATURE_INDEX:
+ *
+ * Special value for feature index indicating unsupported feature.
+ */
#define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu
+/**
+ * HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX:
+ *
+ * Special value for language index indicating default or unsupported language.
+ */
#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu
+/**
+ * HB_OT_LAYOUT_NO_VARIATIONS_INDEX:
+ *
+ * Special value for variations index indicating unsupported variation.
+ */
#define HB_OT_LAYOUT_NO_VARIATIONS_INDEX 0xFFFFFFFFu
HB_EXTERN unsigned int
@@ -433,7 +494,7 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
* @HB_OT_LAYOUT_BASELINE_TAG_MATH: The baseline about which mathematical characters are centered.
* In vertical writing mode when mathematical characters rotated 90 degrees clockwise, are centered.
*
- * Baseline tags from https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags
+ * Baseline tags from [Baseline Tags](https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags) registry.
*
* Since: 2.6.0
*/
@@ -446,6 +507,7 @@ typedef enum {
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT = HB_TAG ('i','d','t','p'),
HB_OT_LAYOUT_BASELINE_TAG_MATH = HB_TAG ('m','a','t','h'),
+ /*< private >*/
_HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_layout_baseline_tag_t;
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh
index f3bb15581a..ac61bc70de 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh
@@ -315,12 +315,13 @@ _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
}
static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
+static inline bool _hb_glyph_info_substituted (const hb_glyph_info_t *info);
static inline bool
_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
{
return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
- !_hb_glyph_info_ligated (info);
+ !_hb_glyph_info_substituted (info);
}
static inline bool
_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
diff --git a/thirdparty/harfbuzz/src/hb-ot-math.cc b/thirdparty/harfbuzz/src/hb-ot-math.cc
index 9d8c6e735a..5781d25f2a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-math.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-math.cc
@@ -56,7 +56,7 @@
*
* Tests whether a face has a `MATH` table.
*
- * Return value: true if the table is found, false otherwise
+ * Return value: %true if the table is found, %false otherwise
*
* Since: 1.3.3
**/
@@ -142,7 +142,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
*
* Tests whether the given glyph index is an extended shape in the face.
*
- * Return value: true if the glyph is an extended shape, false otherwise
+ * Return value: %true if the glyph is an extended shape, %false otherwise
*
* Since: 1.3.3
**/
diff --git a/thirdparty/harfbuzz/src/hb-ot-math.h b/thirdparty/harfbuzz/src/hb-ot-math.h
index ad864a762d..d3ffa19d85 100644
--- a/thirdparty/harfbuzz/src/hb-ot-math.h
+++ b/thirdparty/harfbuzz/src/hb-ot-math.h
@@ -24,7 +24,7 @@
* Igalia Author(s): Frédéric Wang
*/
-#ifndef HB_OT_H_IN
+#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead."
#endif
@@ -40,18 +40,89 @@ HB_BEGIN_DECLS
* MATH
*/
+/**
+ * HB_OT_TAG_MATH:
+ *
+ * OpenType [Mathematical Typesetting Table](https://docs.microsoft.com/en-us/typography/opentype/spec/math).
+ *
+ * Since: 1.3.3
+ */
#define HB_OT_TAG_MATH HB_TAG('M','A','T','H')
-/* Use with hb_buffer_set_script() for math shaping. */
+/**
+ * HB_OT_MATH_SCRIPT:
+ *
+ * OpenType script tag for math shaping, for use with
+ * Use with hb_buffer_set_script().
+ *
+ * Since: 1.3.3
+ */
#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h')
/* Types */
/**
* hb_ot_math_constant_t:
+ * @HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: scriptPercentScaleDown
+ * @HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: scriptScriptPercentScaleDown
+ * @HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: delimitedSubFormulaMinHeight
+ * @HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: displayOperatorMinHeight
+ * @HB_OT_MATH_CONSTANT_MATH_LEADING: mathLeading
+ * @HB_OT_MATH_CONSTANT_AXIS_HEIGHT: axisHeight
+ * @HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: accentBaseHeight
+ * @HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT: flattenedAccentBaseHeight
+ * @HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN: subscriptShiftDown
+ * @HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX: subscriptTopMax
+ * @HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN: subscriptBaselineDropMin
+ * @HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP: superscriptShiftUp
+ * @HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED: superscriptShiftUpCramped
+ * @HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN: superscriptBottomMin
+ * @HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX: superscriptBaselineDropMax
+ * @HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN: subSuperscriptGapMin
+ * @HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT: superscriptBottomMaxWithSubscript
+ * @HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: spaceAfterScript
+ * @HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: upperLimitGapMin
+ * @HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: upperLimitBaselineRiseMin
+ * @HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN: lowerLimitGapMin
+ * @HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN: lowerLimitBaselineDropMin
+ * @HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP: stackTopShiftUp
+ * @HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP: stackTopDisplayStyleShiftUp
+ * @HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN: stackBottomShiftDown
+ * @HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN: stackBottomDisplayStyleShiftDown
+ * @HB_OT_MATH_CONSTANT_STACK_GAP_MIN: stackGapMin
+ * @HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN: stackDisplayStyleGapMin
+ * @HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP: stretchStackTopShiftUp
+ * @HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN: stretchStackBottomShiftDown
+ * @HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN: stretchStackGapAboveMin
+ * @HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN: stretchStackGapBelowMin
+ * @HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP: fractionNumeratorShiftUp
+ * @HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP: fractionNumeratorDisplayStyleShiftUp
+ * @HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN: fractionDenominatorShiftDown
+ * @HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN: fractionDenominatorDisplayStyleShiftDown
+ * @HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN: fractionNumeratorGapMin
+ * @HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN: fractionNumDisplayStyleGapMin
+ * @HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS: fractionRuleThickness
+ * @HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN: fractionDenominatorGapMin
+ * @HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN: fractionDenomDisplayStyleGapMin
+ * @HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: skewedFractionHorizontalGap
+ * @HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP: skewedFractionVerticalGap
+ * @HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP: overbarVerticalGap
+ * @HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS: overbarRuleThickness
+ * @HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER: overbarExtraAscender
+ * @HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: underbarVerticalGap
+ * @HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS: underbarRuleThickness
+ * @HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER: underbarExtraDescender
+ * @HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP: radicalVerticalGap
+ * @HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP: radicalDisplayStyleVerticalGap
+ * @HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS: radicalRuleThickness
+ * @HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER: radicalExtraAscender
+ * @HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: radicalKernBeforeDegree
+ * @HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE: radicalKernAfterDegree
+ * @HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: radicalDegreeBottomRaisePercent
*
- * The 'MATH' table constants specified at
- * https://docs.microsoft.com/en-us/typography/opentype/spec/math
+ * The 'MATH' table constants, refer to
+ * [OpenType documentation](https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathconstants-table)
+ * For more explanations.
*
* Since: 1.3.3
*/
@@ -116,6 +187,10 @@ typedef enum {
/**
* hb_ot_math_kern_t:
+ * @HB_OT_MATH_KERN_TOP_RIGHT: The top right corner of the glyph.
+ * @HB_OT_MATH_KERN_TOP_LEFT: The top left corner of the glyph.
+ * @HB_OT_MATH_KERN_BOTTOM_RIGHT: The bottom right corner of the glyph.
+ * @HB_OT_MATH_KERN_BOTTOM_LEFT: The bottom left corner of the glyph.
*
* The math kerning-table types defined for the four corners
* of a glyph.
@@ -145,6 +220,8 @@ typedef struct hb_ot_math_glyph_variant_t {
/**
* hb_ot_math_glyph_part_flags_t:
+ * @HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER: This is an extender glyph part that
+ * can be repeated to reach the desired length.
*
* Flags for math glyph parts.
*
diff --git a/thirdparty/harfbuzz/src/hb-ot-meta.cc b/thirdparty/harfbuzz/src/hb-ot-meta.cc
index 54a0e10f9b..35c8eb523f 100644
--- a/thirdparty/harfbuzz/src/hb-ot-meta.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-meta.cc
@@ -41,9 +41,11 @@
* hb_ot_meta_get_entry_tags:
* @face: a face object
* @start_offset: iteration's start offset
- * @entries_count:(inout) (allow-none): buffer size as input, filled size as output
+ * @entries_count:(inout) (optional): buffer size as input, filled size as output
* @entries: (out caller-allocates) (array length=entries_count): entries tags buffer
*
+ * Fetches all available feature types.
+ *
* Return value: Number of all available feature types.
*
* Since: 2.6.0
diff --git a/thirdparty/harfbuzz/src/hb-ot-meta.h b/thirdparty/harfbuzz/src/hb-ot-meta.h
index 0278d84148..7748eb4958 100644
--- a/thirdparty/harfbuzz/src/hb-ot-meta.h
+++ b/thirdparty/harfbuzz/src/hb-ot-meta.h
@@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-#ifndef HB_OT_H_IN
+#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead."
#endif
@@ -54,6 +54,7 @@ typedef enum {
HB_OT_META_TAG_DESIGN_LANGUAGES = HB_TAG ('d','l','n','g'),
HB_OT_META_TAG_SUPPORTED_LANGUAGES = HB_TAG ('s','l','n','g'),
+ /*< private >*/
_HB_OT_META_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_meta_tag_t;
diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.cc b/thirdparty/harfbuzz/src/hb-ot-metrics.cc
index 3065ea2adf..72aeff82d6 100644
--- a/thirdparty/harfbuzz/src/hb-ot-metrics.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-metrics.cc
@@ -119,11 +119,11 @@ _get_gasp (hb_face_t *face, float *result, hb_ot_metrics_tag_t metrics_tag)
/**
* hb_ot_metrics_get_position:
- * @font: a #hb_font_t object.
+ * @font: an #hb_font_t object.
* @metrics_tag: tag of metrics value you like to fetch.
* @position: (out) (optional): result of metrics value from the font.
*
- * It fetches metrics value corresponding to a given tag from a font.
+ * Fetches metrics value corresponding to @metrics_tag from @font.
*
* Returns: Whether found the requested metrics in the font.
* Since: 2.6.0
@@ -193,10 +193,13 @@ hb_ot_metrics_get_position (hb_font_t *font,
#ifndef HB_NO_VAR
/**
* hb_ot_metrics_get_variation:
- * @font:
- * @metrics_tag:
+ * @font: an #hb_font_t object.
+ * @metrics_tag: tag of metrics value you like to fetch.
+ *
+ * Fetches metrics value corresponding to @metrics_tag from @font with the
+ * current font variation settings applied.
*
- * Returns:
+ * Returns: The requested metric value.
*
* Since: 2.6.0
**/
@@ -208,10 +211,13 @@ hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
/**
* hb_ot_metrics_get_x_variation:
- * @font:
- * @metrics_tag:
+ * @font: an #hb_font_t object.
+ * @metrics_tag: tag of metrics value you like to fetch.
*
- * Returns:
+ * Fetches horizontal metrics value corresponding to @metrics_tag from @font
+ * with the current font variation settings applied.
+ *
+ * Returns: The requested metric value.
*
* Since: 2.6.0
**/
@@ -223,10 +229,13 @@ hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
/**
* hb_ot_metrics_get_y_variation:
- * @font:
- * @metrics_tag:
+ * @font: an #hb_font_t object.
+ * @metrics_tag: tag of metrics value you like to fetch.
+ *
+ * Fetches vertical metrics value corresponding to @metrics_tag from @font with
+ * the current font variation settings applied.
*
- * Returns:
+ * Returns: The requested metric value.
*
* Since: 2.6.0
**/
diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.h b/thirdparty/harfbuzz/src/hb-ot-metrics.h
index 42c7363c03..5841fc8b0f 100644
--- a/thirdparty/harfbuzz/src/hb-ot-metrics.h
+++ b/thirdparty/harfbuzz/src/hb-ot-metrics.h
@@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-#ifndef HB_OT_H_IN
+#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead."
#endif
@@ -66,7 +66,8 @@ HB_BEGIN_DECLS
* @HB_OT_METRICS_TAG_UNDERLINE_SIZE: underline size.
* @HB_OT_METRICS_TAG_UNDERLINE_OFFSET: underline offset.
*
- * From https://docs.microsoft.com/en-us/typography/opentype/spec/mvar#value-tags
+ * Metric tags corresponding to [MVAR Value
+ * Tags](https://docs.microsoft.com/en-us/typography/opentype/spec/mvar#value-tags)
*
* Since: 2.6.0
**/
@@ -100,6 +101,7 @@ typedef enum {
HB_OT_METRICS_TAG_UNDERLINE_SIZE = HB_TAG ('u','n','d','s'),
HB_OT_METRICS_TAG_UNDERLINE_OFFSET = HB_TAG ('u','n','d','o'),
+ /*< private >*/
_HB_OT_METRICS_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_metrics_tag_t;
diff --git a/thirdparty/harfbuzz/src/hb-ot-name.cc b/thirdparty/harfbuzz/src/hb-ot-name.cc
index 10122b8c2e..4588226e6e 100644
--- a/thirdparty/harfbuzz/src/hb-ot-name.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-name.cc
@@ -46,7 +46,7 @@
/**
* hb_ot_name_list_names:
* @face: font face.
- * @num_entries: (out) (allow-none): number of returned entries.
+ * @num_entries: (out) (optional): number of returned entries.
*
* Enumerates all available name IDs and language combinations. Returned
* array is owned by the @face and should not be modified. It can be
@@ -150,7 +150,7 @@ hb_ot_name_get_utf (hb_face_t *face,
* @face: font face.
* @name_id: OpenType name identifier to fetch.
* @language: language to fetch the name for.
- * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ * @text_size: (inout) (optional): input size of @text buffer, and output size of
* text written to buffer.
* @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
*
@@ -177,7 +177,7 @@ hb_ot_name_get_utf8 (hb_face_t *face,
* @face: font face.
* @name_id: OpenType name identifier to fetch.
* @language: language to fetch the name for.
- * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ * @text_size: (inout) (optional): input size of @text buffer, and output size of
* text written to buffer.
* @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
*
@@ -203,7 +203,7 @@ hb_ot_name_get_utf16 (hb_face_t *face,
* @face: font face.
* @name_id: OpenType name identifier to fetch.
* @language: language to fetch the name for.
- * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ * @text_size: (inout) (optional): input size of @text buffer, and output size of
* text written to buffer.
* @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
*
diff --git a/thirdparty/harfbuzz/src/hb-ot-name.h b/thirdparty/harfbuzz/src/hb-ot-name.h
index 6f3fcd2427..9359014c8a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-name.h
+++ b/thirdparty/harfbuzz/src/hb-ot-name.h
@@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-#ifndef HB_OT_H_IN
+#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead."
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
index 7d31b712c4..8e98f87f4e 100644
--- a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
@@ -177,15 +177,14 @@ struct OS2
if (!c->plan->glyphs_requested->is_empty ())
{
hb_map_t unicode_glyphid_map;
-
+
OT::cmap::accelerator_t cmap;
cmap.init (c->plan->source);
cmap.collect_mapping (&unicodes, &unicode_glyphid_map);
cmap.fini ();
-
- if (c->plan->unicodes->is_empty ()) unicodes.clear ();
- else hb_set_set (&unicodes, c->plan->unicodes);
-
+
+ hb_set_set (&unicodes, c->plan->unicodes);
+
+ unicode_glyphid_map.iter ()
| hb_filter (c->plan->glyphs_requested, hb_second)
| hb_map (hb_first)
diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table.hh b/thirdparty/harfbuzz/src/hb-ot-post-table.hh
index 8586331cd4..f22d6e244d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-post-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-post-table.hh
@@ -87,7 +87,6 @@ struct post
if (unlikely (!post_prime)) return_trace (false);
serialize (c->serializer);
- if (c->serializer->in_error () || c->serializer->ran_out_of_room) return_trace (false);
return_trace (true);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
index b15e145f2f..41e3dd38ab 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
@@ -142,7 +142,7 @@
OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \
) \
OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \
- /* ASSERT_STATIC_EXPR_ZERO (len(FromGlyphs) == len(ToGlyphs)) */
+ /* static_assert_expr (len(FromGlyphs) == len(ToGlyphs)) */
#define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \
OT_SUBLOOKUP(Name, 1, \
@@ -151,7 +151,7 @@
OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \
) \
OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \
- /* ASSERT_STATIC_EXPR_ZERO (len(FirstGlyphs) == len(LigatureSetOffsets)) */
+ /* static_assert_expr (len(FirstGlyphs) == len(LigatureSetOffsets)) */
#define OT_LIGATURE_SET(Name, LigatureSetOffsets) \
OT_UARRAY(Name, OT_LIST(LigatureSetOffsets))
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc
index 1e93f0efd5..1f244f940c 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc
@@ -33,7 +33,7 @@
/* buffer var allocations */
-#define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */
+#define arabic_shaping_action() complex_var_u8_auxiliary() /* arabic shaping action */
#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc
index f5915f43ae..dbedd6af0c 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc
@@ -119,7 +119,7 @@ data_destroy_hangul (void *data)
#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu))
/* buffer var allocations */
-#define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */
+#define hangul_shaping_feature() complex_var_u8_auxiliary() /* hangul jamo shaping feature */
static bool
is_zero_width_char (hb_font_t *font,
@@ -205,7 +205,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
{
/* Tone mark follows a valid syllable; move it in front, unless it's zero width. */
buffer->unsafe_to_break_from_outbuffer (start, buffer->idx);
- buffer->next_glyph ();
+ if (unlikely (!buffer->next_glyph ())) break;
if (!is_zero_width_char (font, u))
{
buffer->merge_out_clusters (start, end + 1);
@@ -218,23 +218,25 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
else
{
/* No valid syllable as base for tone mark; try to insert dotted circle. */
- if (!(buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE) &&
- font->has_glyph (0x25CCu))
+ if (!(buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE) &&
+ font->has_glyph (0x25CCu))
{
hb_codepoint_t chars[2];
- if (!is_zero_width_char (font, u)) {
+ if (!is_zero_width_char (font, u))
+ {
chars[0] = u;
chars[1] = 0x25CCu;
- } else {
+ } else
+ {
chars[0] = 0x25CCu;
chars[1] = u;
}
- buffer->replace_glyphs (1, 2, chars);
+ (void) buffer->replace_glyphs (1, 2, chars);
}
else
{
/* No dotted circle available in the font; just leave tone mark untouched. */
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
}
}
start = end = buffer->out_len;
@@ -271,9 +273,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_codepoint_t s = SBase + (l - LBase) * NCount + (v - VBase) * TCount + tindex;
if (font->has_glyph (s))
{
- buffer->replace_glyphs (t ? 3 : 2, 1, &s);
- if (unlikely (!buffer->successful))
- return;
+ (void) buffer->replace_glyphs (t ? 3 : 2, 1, &s);
end = start + 1;
continue;
}
@@ -285,17 +285,19 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
* Set jamo features on the individual glyphs, and advance past them.
*/
buffer->cur().hangul_shaping_feature() = LJMO;
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
buffer->cur().hangul_shaping_feature() = VJMO;
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (t)
{
buffer->cur().hangul_shaping_feature() = TJMO;
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
end = start + 3;
}
else
end = start + 2;
+ if (unlikely (!buffer->successful))
+ break;
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
buffer->merge_out_clusters (start, end);
continue;
@@ -321,9 +323,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_codepoint_t new_s = s + new_tindex;
if (font->has_glyph (new_s))
{
- buffer->replace_glyphs (2, 1, &new_s);
- if (unlikely (!buffer->successful))
- return;
+ (void) buffer->replace_glyphs (2, 1, &new_s);
end = start + 1;
continue;
}
@@ -347,19 +347,18 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
(!tindex || font->has_glyph (decomposed[2])))
{
unsigned int s_len = tindex ? 3 : 2;
- buffer->replace_glyphs (1, s_len, decomposed);
+ (void) buffer->replace_glyphs (1, s_len, decomposed);
/* If we decomposed an LV because of a non-combining T following,
* we want to include this T in the syllable.
*/
if (has_glyph && !tindex)
{
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
s_len++;
}
-
if (unlikely (!buffer->successful))
- return;
+ break;
/* We decomposed S: apply jamo features to the individual glyphs
* that are now in buffer->out_info.
@@ -383,17 +382,15 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
if (has_glyph)
{
- /* We didn't decompose the S, so just advance past it. */
+ /* We didn't decompose the S, so just advance past it and fall through. */
end = start + 1;
- buffer->next_glyph ();
- continue;
}
}
/* Didn't find a recognizable syllable, so we leave end <= start;
* this will prevent tone-mark reordering happening.
*/
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
}
buffer->swap_buffers ();
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
index 670b6bf486..74bf3ca0fa 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
@@ -31,8 +31,37 @@
#include "hb.hh"
+enum indic_syllable_type_t {
+ indic_consonant_syllable,
+ indic_vowel_syllable,
+ indic_standalone_cluster,
+ indic_symbol_cluster,
+ indic_broken_cluster,
+ indic_non_indic_cluster,
+};
+
-#line 36 "hb-ot-shape-complex-indic-machine.hh"
+#line 45 "hb-ot-shape-complex-indic-machine.hh"
+#define indic_syllable_machine_ex_A 10u
+#define indic_syllable_machine_ex_C 1u
+#define indic_syllable_machine_ex_CM 17u
+#define indic_syllable_machine_ex_CS 19u
+#define indic_syllable_machine_ex_DOTTEDCIRCLE 12u
+#define indic_syllable_machine_ex_H 4u
+#define indic_syllable_machine_ex_M 7u
+#define indic_syllable_machine_ex_N 3u
+#define indic_syllable_machine_ex_PLACEHOLDER 11u
+#define indic_syllable_machine_ex_RS 13u
+#define indic_syllable_machine_ex_Ra 16u
+#define indic_syllable_machine_ex_Repha 15u
+#define indic_syllable_machine_ex_SM 8u
+#define indic_syllable_machine_ex_Symbol 18u
+#define indic_syllable_machine_ex_V 2u
+#define indic_syllable_machine_ex_ZWJ 6u
+#define indic_syllable_machine_ex_ZWNJ 5u
+
+
+#line 65 "hb-ot-shape-complex-indic-machine.hh"
static const unsigned char _indic_syllable_machine_trans_keys[] = {
8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u,
4u, 13u, 4u, 8u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u,
@@ -384,18 +413,18 @@ static const int indic_syllable_machine_error = -1;
static const int indic_syllable_machine_en_main = 39;
-#line 36 "hb-ot-shape-complex-indic-machine.rl"
+#line 46 "hb-ot-shape-complex-indic-machine.rl"
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
+#line 102 "hb-ot-shape-complex-indic-machine.rl"
#define found_syllable(syllable_type) \
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | indic_##syllable_type; \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
@@ -407,7 +436,7 @@ find_syllables_indic (hb_buffer_t *buffer)
int cs;
hb_glyph_info_t *info = buffer->info;
-#line 411 "hb-ot-shape-complex-indic-machine.hh"
+#line 440 "hb-ot-shape-complex-indic-machine.hh"
{
cs = indic_syllable_machine_start;
ts = 0;
@@ -415,7 +444,7 @@ find_syllables_indic (hb_buffer_t *buffer)
act = 0;
}
-#line 113 "hb-ot-shape-complex-indic-machine.rl"
+#line 122 "hb-ot-shape-complex-indic-machine.rl"
p = 0;
@@ -423,7 +452,7 @@ find_syllables_indic (hb_buffer_t *buffer)
unsigned int syllable_serial = 1;
-#line 427 "hb-ot-shape-complex-indic-machine.hh"
+#line 456 "hb-ot-shape-complex-indic-machine.hh"
{
int _slen;
int _trans;
@@ -437,7 +466,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
-#line 441 "hb-ot-shape-complex-indic-machine.hh"
+#line 470 "hb-ot-shape-complex-indic-machine.hh"
}
_keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -460,64 +489,64 @@ _eof_trans:
{te = p+1;}
break;
case 11:
-#line 89 "hb-ot-shape-complex-indic-machine.rl"
- {te = p+1;{ found_syllable (non_indic_cluster); }}
+#line 98 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p+1;{ found_syllable (indic_non_indic_cluster); }}
break;
case 13:
-#line 84 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (consonant_syllable); }}
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_consonant_syllable); }}
break;
case 14:
-#line 85 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (vowel_syllable); }}
+#line 94 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_vowel_syllable); }}
break;
case 17:
-#line 86 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (standalone_cluster); }}
+#line 95 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_standalone_cluster); }}
break;
case 19:
-#line 87 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (symbol_cluster); }}
+#line 96 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_symbol_cluster); }}
break;
case 15:
-#line 88 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (broken_cluster); }}
+#line 97 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_broken_cluster); }}
break;
case 16:
-#line 89 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (non_indic_cluster); }}
+#line 98 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_non_indic_cluster); }}
break;
case 1:
-#line 84 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }}
break;
case 3:
-#line 85 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (vowel_syllable); }}
+#line 94 "hb-ot-shape-complex-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }}
break;
case 7:
-#line 86 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (standalone_cluster); }}
+#line 95 "hb-ot-shape-complex-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }}
break;
case 8:
-#line 87 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (symbol_cluster); }}
+#line 96 "hb-ot-shape-complex-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }}
break;
case 4:
-#line 88 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
+#line 97 "hb-ot-shape-complex-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); }}
break;
case 6:
#line 1 "NONE"
{ switch( act ) {
case 1:
- {{p = ((te))-1;} found_syllable (consonant_syllable); }
+ {{p = ((te))-1;} found_syllable (indic_consonant_syllable); }
break;
case 5:
- {{p = ((te))-1;} found_syllable (broken_cluster); }
+ {{p = ((te))-1;} found_syllable (indic_broken_cluster); }
break;
case 6:
- {{p = ((te))-1;} found_syllable (non_indic_cluster); }
+ {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
break;
}
}
@@ -525,22 +554,22 @@ _eof_trans:
case 18:
#line 1 "NONE"
{te = p+1;}
-#line 84 "hb-ot-shape-complex-indic-machine.rl"
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
{act = 1;}
break;
case 5:
#line 1 "NONE"
{te = p+1;}
-#line 88 "hb-ot-shape-complex-indic-machine.rl"
+#line 97 "hb-ot-shape-complex-indic-machine.rl"
{act = 5;}
break;
case 12:
#line 1 "NONE"
{te = p+1;}
-#line 89 "hb-ot-shape-complex-indic-machine.rl"
+#line 98 "hb-ot-shape-complex-indic-machine.rl"
{act = 6;}
break;
-#line 544 "hb-ot-shape-complex-indic-machine.hh"
+#line 573 "hb-ot-shape-complex-indic-machine.hh"
}
_again:
@@ -549,7 +578,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
-#line 553 "hb-ot-shape-complex-indic-machine.hh"
+#line 582 "hb-ot-shape-complex-indic-machine.hh"
}
if ( ++p != pe )
@@ -565,7 +594,7 @@ _again:
}
-#line 121 "hb-ot-shape-complex-indic-machine.rl"
+#line 130 "hb-ot-shape-complex-indic-machine.rl"
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
index a150fd2486..dd204b23c1 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
@@ -82,7 +82,7 @@
#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
-static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
+static const uint16_t indic_table[] = {
#define indic_offset_0x0028u 0
@@ -404,7 +404,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
}; /* Table items: 1792; occupancy: 70% */
-INDIC_TABLE_ELEMENT_TYPE
+uint16_t
hb_indic_get_categories (hb_codepoint_t u)
{
switch (u >> 12)
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc
index 652ef47040..a4f2d9a847 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc
@@ -29,6 +29,7 @@
#ifndef HB_NO_OT_SHAPE
#include "hb-ot-shape-complex-indic.hh"
+#include "hb-ot-shape-complex-indic-machine.hh"
#include "hb-ot-shape-complex-vowel-constraints.hh"
#include "hb-ot-layout.hh"
@@ -337,19 +338,6 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan,
return POS_BASE_C;
}
-
-enum indic_syllable_type_t {
- indic_consonant_syllable,
- indic_vowel_syllable,
- indic_standalone_cluster,
- indic_symbol_cluster,
- indic_broken_cluster,
- indic_non_indic_cluster,
-};
-
-#include "hb-ot-shape-complex-indic-machine.hh"
-
-
static void
setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
@@ -764,7 +752,28 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
* We could use buffer->sort() for this, if there was no special
* reordering of pre-base stuff happening later...
* We don't want to merge_clusters all of that, which buffer->sort()
- * would.
+ * would. Here's a concrete example:
+ *
+ * Assume there's a pre-base consonant and explicit Halant before base,
+ * followed by a prebase-reordering (left) Matra:
+ *
+ * C,H,ZWNJ,B,M
+ *
+ * At this point in reordering we would have:
+ *
+ * M,C,H,ZWNJ,B
+ *
+ * whereas in final reordering we will bring the Matra closer to Base:
+ *
+ * C,H,ZWNJ,M,B
+ *
+ * That's why we don't want to merge-clusters anything before the Base
+ * at this point. But if something moved from after Base to before it,
+ * we should merge clusters from base to them. In final-reordering, we
+ * only move things around before base, and merge-clusters up to base.
+ * These two merge-clusters from the two sides of base will interlock
+ * to merge things correctly. See:
+ * https://github.com/harfbuzz/harfbuzz/issues/2272
*/
if (indic_plan->is_old_spec || end - start > 127)
buffer->merge_clusters (base, end);
@@ -774,17 +783,18 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
for (unsigned int i = base; i < end; i++)
if (info[i].syllable() != 255)
{
+ unsigned int min = i;
unsigned int max = i;
unsigned int j = start + info[i].syllable();
while (j != i)
{
+ min = hb_min (min, j);
max = hb_max (max, j);
unsigned int next = start + info[j].syllable();
info[j].syllable() = 255; /* So we don't process j later again. */
j = next;
}
- if (i != max)
- buffer->merge_clusters (i, max + 1);
+ buffer->merge_clusters (hb_max (base, min), max + 1);
}
}
@@ -938,69 +948,6 @@ initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
}
}
-static inline void
-insert_dotted_circles_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
- if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
- return;
-
- /* Note: This loop is extra overhead, but should not be measurable.
- * TODO Use a buffer scratch flag to remove the loop. */
- bool has_broken_syllables = false;
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- if ((info[i].syllable() & 0x0F) == indic_broken_cluster)
- {
- has_broken_syllables = true;
- break;
- }
- if (likely (!has_broken_syllables))
- return;
-
-
- hb_codepoint_t dottedcircle_glyph;
- if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
- return;
-
- hb_glyph_info_t dottedcircle = {0};
- dottedcircle.codepoint = 0x25CCu;
- set_indic_properties (dottedcircle);
- dottedcircle.codepoint = dottedcircle_glyph;
-
- buffer->clear_output ();
-
- buffer->idx = 0;
- unsigned int last_syllable = 0;
- while (buffer->idx < buffer->len && buffer->successful)
- {
- unsigned int syllable = buffer->cur().syllable();
- indic_syllable_type_t syllable_type = (indic_syllable_type_t) (syllable & 0x0F);
- if (unlikely (last_syllable != syllable && syllable_type == indic_broken_cluster))
- {
- last_syllable = syllable;
-
- hb_glyph_info_t ginfo = dottedcircle;
- ginfo.cluster = buffer->cur().cluster;
- ginfo.mask = buffer->cur().mask;
- ginfo.syllable() = buffer->cur().syllable();
-
- /* Insert dottedcircle after possible Repha. */
- while (buffer->idx < buffer->len && buffer->successful &&
- last_syllable == buffer->cur().syllable() &&
- buffer->cur().indic_category() == OT_Repha)
- buffer->next_glyph ();
-
- buffer->output_info (ginfo);
- }
- else
- buffer->next_glyph ();
- }
- buffer->swap_buffers ();
-}
-
static void
initial_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
@@ -1008,11 +955,16 @@ initial_reordering_indic (const hb_ot_shape_plan_t *plan,
{
if (!buffer->message (font, "start reordering indic initial"))
return;
+
update_consonant_positions_indic (plan, font, buffer);
- insert_dotted_circles_indic (plan, font, buffer);
+ hb_syllabic_insert_dotted_circles (font, buffer,
+ indic_broken_cluster,
+ OT_DOTTEDCIRCLE,
+ OT_Repha);
foreach_syllable (buffer, start, end)
initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
+
(void) buffer->message (font, "end reordering indic initial");
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh
index 41bd8bd6cc..dcb28a4e84 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh
@@ -29,16 +29,14 @@
#include "hb.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shape-complex-syllabic.hh"
/* buffer var allocations */
-#define indic_category() complex_var_u8_0() /* indic_category_t */
-#define indic_position() complex_var_u8_1() /* indic_position_t */
+#define indic_category() complex_var_u8_category() /* indic_category_t */
+#define indic_position() complex_var_u8_auxiliary() /* indic_position_t */
-#define INDIC_TABLE_ELEMENT_TYPE uint16_t
-
/* Cateories used in the OpenType spec:
* https://docs.microsoft.com/en-us/typography/script-development/devanagari
*/
@@ -177,7 +175,7 @@ enum indic_matra_category_t {
#define INDIC_COMBINE_CATEGORIES(S,M) \
( \
- ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
+ static_assert_expr (S < 255 && M < 255) + \
( S | \
( \
( \
@@ -194,7 +192,7 @@ enum indic_matra_category_t {
) \
)
-HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
+HB_INTERNAL uint16_t
hb_indic_get_categories (hb_codepoint_t u);
@@ -307,17 +305,12 @@ static const hb_codepoint_t ra_chars[] = {
0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
-
- 0x179Au, /* Khmer */
};
static inline bool
is_ra (hb_codepoint_t u)
{
- for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
- if (u == ra_chars[i])
- return true;
- return false;
+ return hb_array (ra_chars).lfind (u);
}
static inline void
@@ -325,7 +318,7 @@ set_indic_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
- indic_category_t cat = (indic_category_t) (type & 0x7Fu);
+ indic_category_t cat = (indic_category_t) (type & 0xFFu);
indic_position_t pos = (indic_position_t) (type >> 8);
@@ -370,6 +363,7 @@ set_indic_properties (hb_glyph_info_t &info)
else if (unlikely (u == 0x1133Bu || u == 0x1133Cu)) cat = OT_N;
else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
+ else if (unlikely (u == 0x0B55u)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/2849 */
else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
else if (unlikely (u == 0x09FCu)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/1613 */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh
index a040318d34..82ab186a41 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh
@@ -1,211 +1,179 @@
-
#line 1 "hb-ot-shape-complex-khmer-machine.rl"
/*
- * Copyright © 2011,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
+* Copyright © 2011,2012 Google, Inc.
+*
+* This is part of HarfBuzz, a text shaping library.
+*
+* Permission is hereby granted, without written agreement and without
+* license or royalty fees, to use, copy, modify, and distribute this
+* software and its documentation for any purpose, provided that the
+* above copyright notice and the following two paragraphs appear in
+* all copies of this software.
+*
+* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+* DAMAGE.
+*
+* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+*
+* Google Author(s): Behdad Esfahbod
+*/
#ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
#include "hb.hh"
+enum khmer_syllable_type_t {
+ khmer_consonant_syllable,
+ khmer_broken_cluster,
+ khmer_non_khmer_cluster,
+};
+
-#line 36 "hb-ot-shape-complex-khmer-machine.hh"
+#line 41 "hb-ot-shape-complex-khmer-machine.hh"
+#define khmer_syllable_machine_ex_C 1u
+#define khmer_syllable_machine_ex_Coeng 14u
+#define khmer_syllable_machine_ex_DOTTEDCIRCLE 12u
+#define khmer_syllable_machine_ex_PLACEHOLDER 11u
+#define khmer_syllable_machine_ex_Ra 16u
+#define khmer_syllable_machine_ex_Robatic 20u
+#define khmer_syllable_machine_ex_V 2u
+#define khmer_syllable_machine_ex_VAbv 26u
+#define khmer_syllable_machine_ex_VBlw 27u
+#define khmer_syllable_machine_ex_VPre 28u
+#define khmer_syllable_machine_ex_VPst 29u
+#define khmer_syllable_machine_ex_Xgroup 21u
+#define khmer_syllable_machine_ex_Ygroup 22u
+#define khmer_syllable_machine_ex_ZWJ 6u
+#define khmer_syllable_machine_ex_ZWNJ 5u
+
+
+#line 59 "hb-ot-shape-complex-khmer-machine.hh"
static const unsigned char _khmer_syllable_machine_trans_keys[] = {
- 5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u,
- 5u, 26u, 5u, 21u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u,
- 5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 29u, 5u, 29u, 5u, 29u, 5u, 29u,
- 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 26u, 5u, 29u,
- 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u, 5u, 29u,
- 0
+ 2u, 8u, 2u, 6u, 2u, 8u, 2u, 6u,
+ 0u, 0u, 2u, 6u, 2u, 8u, 2u, 6u,
+ 2u, 8u, 2u, 6u, 2u, 6u, 2u, 8u,
+ 2u, 6u, 0u, 0u, 2u, 6u, 2u, 8u,
+ 2u, 6u, 2u, 8u, 2u, 6u, 2u, 8u,
+ 0u, 11u, 2u, 11u, 2u, 11u, 2u, 11u,
+ 7u, 7u, 2u, 7u, 2u, 11u, 2u, 11u,
+ 2u, 11u, 0u, 0u, 2u, 8u, 2u, 11u,
+ 2u, 11u, 7u, 7u, 2u, 7u, 2u, 11u,
+ 2u, 11u, 0u, 0u, 2u, 11u, 2u, 11u,
+ 0u
};
-static const char _khmer_syllable_machine_key_spans[] = {
- 22, 17, 22, 17, 16, 17, 22, 17,
- 22, 17, 17, 22, 17, 16, 17, 22,
- 17, 22, 17, 22, 29, 25, 25, 25,
- 1, 18, 25, 25, 25, 16, 22, 25,
- 25, 1, 18, 25, 25, 16, 25, 25
+static const signed char _khmer_syllable_machine_char_class[] = {
+ 0, 0, 1, 1, 2, 2, 1, 1,
+ 1, 1, 3, 3, 1, 4, 1, 0,
+ 1, 1, 1, 5, 6, 7, 1, 1,
+ 1, 8, 9, 10, 11, 0
};
static const short _khmer_syllable_machine_index_offsets[] = {
- 0, 23, 41, 64, 82, 99, 117, 140,
- 158, 181, 199, 217, 240, 258, 275, 293,
- 316, 334, 357, 375, 398, 428, 454, 480,
- 506, 508, 527, 553, 579, 605, 622, 645,
- 671, 697, 699, 718, 744, 770, 787, 813
+ 0, 7, 12, 19, 24, 25, 30, 37,
+ 42, 49, 54, 59, 66, 71, 72, 77,
+ 84, 89, 96, 101, 108, 120, 130, 140,
+ 150, 151, 157, 167, 177, 187, 188, 195,
+ 205, 215, 216, 222, 232, 242, 243, 253,
+ 0
};
-static const char _khmer_syllable_machine_indicies[] = {
- 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 2,
- 3, 0, 0, 0, 0, 4, 0, 1,
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 3,
- 0, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 3, 0, 0, 0, 0, 4, 0,
- 5, 5, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 4, 0, 6, 6, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 6, 0, 7, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 8, 0, 9, 9, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 10, 0, 0,
- 0, 0, 4, 0, 9, 9, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 10, 0, 11, 11,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 12, 0,
- 0, 0, 0, 4, 0, 11, 11, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 12, 0, 14,
- 14, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 15,
- 13, 14, 14, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 15, 16, 16, 16, 16, 17, 16,
- 18, 18, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 17, 16, 19, 19, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 19, 16, 20, 20, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 21, 16, 22, 22, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 23, 16, 16,
- 16, 16, 17, 16, 22, 22, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 23, 16, 24, 24,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 25, 16,
- 16, 16, 16, 17, 16, 24, 24, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 25, 16, 14,
- 14, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 26, 15,
- 16, 16, 16, 16, 17, 16, 28, 28,
- 27, 27, 29, 29, 27, 27, 27, 27,
- 2, 2, 27, 30, 27, 28, 27, 27,
- 27, 27, 15, 19, 27, 27, 27, 17,
- 23, 25, 21, 27, 32, 32, 31, 31,
- 31, 31, 31, 31, 31, 33, 31, 31,
- 31, 31, 31, 2, 3, 6, 31, 31,
- 31, 4, 10, 12, 8, 31, 34, 34,
- 31, 31, 31, 31, 31, 31, 31, 35,
- 31, 31, 31, 31, 31, 31, 3, 6,
- 31, 31, 31, 4, 10, 12, 8, 31,
- 5, 5, 31, 31, 31, 31, 31, 31,
- 31, 35, 31, 31, 31, 31, 31, 31,
- 4, 6, 31, 31, 31, 31, 31, 31,
- 8, 31, 6, 31, 7, 7, 31, 31,
- 31, 31, 31, 31, 31, 35, 31, 31,
- 31, 31, 31, 31, 8, 6, 31, 36,
- 36, 31, 31, 31, 31, 31, 31, 31,
- 35, 31, 31, 31, 31, 31, 31, 10,
- 6, 31, 31, 31, 4, 31, 31, 8,
- 31, 37, 37, 31, 31, 31, 31, 31,
- 31, 31, 35, 31, 31, 31, 31, 31,
- 31, 12, 6, 31, 31, 31, 4, 10,
- 31, 8, 31, 34, 34, 31, 31, 31,
- 31, 31, 31, 31, 33, 31, 31, 31,
- 31, 31, 31, 3, 6, 31, 31, 31,
- 4, 10, 12, 8, 31, 28, 28, 31,
- 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 28, 31, 14, 14,
- 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 15, 38,
- 38, 38, 38, 17, 38, 40, 40, 39,
- 39, 39, 39, 39, 39, 39, 41, 39,
- 39, 39, 39, 39, 39, 15, 19, 39,
- 39, 39, 17, 23, 25, 21, 39, 18,
- 18, 39, 39, 39, 39, 39, 39, 39,
- 41, 39, 39, 39, 39, 39, 39, 17,
- 19, 39, 39, 39, 39, 39, 39, 21,
- 39, 19, 39, 20, 20, 39, 39, 39,
- 39, 39, 39, 39, 41, 39, 39, 39,
- 39, 39, 39, 21, 19, 39, 42, 42,
- 39, 39, 39, 39, 39, 39, 39, 41,
- 39, 39, 39, 39, 39, 39, 23, 19,
- 39, 39, 39, 17, 39, 39, 21, 39,
- 43, 43, 39, 39, 39, 39, 39, 39,
- 39, 41, 39, 39, 39, 39, 39, 39,
- 25, 19, 39, 39, 39, 17, 23, 39,
- 21, 39, 44, 44, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 44, 39, 45, 45, 39, 39, 39,
- 39, 39, 39, 39, 30, 39, 39, 39,
- 39, 39, 26, 15, 19, 39, 39, 39,
- 17, 23, 25, 21, 39, 40, 40, 39,
- 39, 39, 39, 39, 39, 39, 30, 39,
- 39, 39, 39, 39, 39, 15, 19, 39,
- 39, 39, 17, 23, 25, 21, 39, 0
+static const signed char _khmer_syllable_machine_indicies[] = {
+ 1, 0, 0, 2, 3, 0, 4, 1,
+ 0, 0, 0, 3, 1, 0, 0, 0,
+ 3, 0, 4, 5, 0, 0, 0, 4,
+ 6, 7, 0, 0, 0, 8, 9, 0,
+ 0, 0, 10, 0, 4, 9, 0, 0,
+ 0, 10, 11, 0, 0, 0, 12, 0,
+ 4, 11, 0, 0, 0, 12, 14, 13,
+ 13, 13, 15, 14, 16, 16, 16, 15,
+ 16, 17, 18, 16, 16, 16, 17, 19,
+ 20, 16, 16, 16, 21, 22, 16, 16,
+ 16, 23, 16, 17, 22, 16, 16, 16,
+ 23, 24, 16, 16, 16, 25, 16, 17,
+ 24, 16, 16, 16, 25, 14, 16, 16,
+ 26, 15, 16, 17, 29, 28, 30, 2,
+ 31, 28, 15, 19, 17, 23, 25, 21,
+ 33, 32, 34, 2, 3, 6, 4, 10,
+ 12, 8, 35, 32, 36, 32, 3, 6,
+ 4, 10, 12, 8, 5, 32, 36, 32,
+ 4, 6, 32, 32, 32, 8, 6, 7,
+ 32, 36, 32, 8, 6, 37, 32, 36,
+ 32, 10, 6, 4, 32, 32, 8, 38,
+ 32, 36, 32, 12, 6, 4, 10, 32,
+ 8, 35, 32, 34, 32, 3, 6, 4,
+ 10, 12, 8, 29, 14, 39, 39, 39,
+ 15, 39, 17, 41, 40, 42, 40, 15,
+ 19, 17, 23, 25, 21, 18, 40, 42,
+ 40, 17, 19, 40, 40, 40, 21, 19,
+ 20, 40, 42, 40, 21, 19, 43, 40,
+ 42, 40, 23, 19, 17, 40, 40, 21,
+ 44, 40, 42, 40, 25, 19, 17, 23,
+ 40, 21, 45, 46, 40, 31, 26, 15,
+ 19, 17, 23, 25, 21, 41, 40, 31,
+ 40, 15, 19, 17, 23, 25, 21, 0
};
-static const char _khmer_syllable_machine_trans_targs[] = {
- 20, 1, 28, 22, 23, 3, 24, 5,
- 25, 7, 26, 9, 27, 20, 10, 31,
- 20, 32, 12, 33, 14, 34, 16, 35,
- 18, 36, 39, 20, 21, 30, 37, 20,
- 0, 29, 2, 4, 6, 8, 20, 20,
- 11, 13, 15, 17, 38, 19
+static const signed char _khmer_syllable_machine_index_defaults[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 13, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 28, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 39, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40,
+ 0
};
-static const char _khmer_syllable_machine_trans_actions[] = {
- 1, 0, 2, 2, 2, 0, 0, 0,
- 2, 0, 2, 0, 2, 3, 0, 4,
- 5, 2, 0, 0, 0, 2, 0, 2,
- 0, 2, 4, 8, 2, 9, 0, 10,
- 0, 0, 0, 0, 0, 0, 11, 12,
- 0, 0, 0, 0, 4, 0
+static const signed char _khmer_syllable_machine_cond_targs[] = {
+ 20, 1, 28, 22, 23, 3, 24, 5,
+ 25, 7, 26, 9, 27, 20, 10, 31,
+ 20, 32, 12, 33, 14, 34, 16, 35,
+ 18, 36, 39, 20, 20, 21, 30, 37,
+ 20, 0, 29, 2, 4, 6, 8, 20,
+ 20, 11, 13, 15, 17, 38, 19, 0
};
-static const char _khmer_syllable_machine_to_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 6, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
+static const signed char _khmer_syllable_machine_cond_actions[] = {
+ 1, 0, 2, 2, 2, 0, 0, 0,
+ 2, 0, 2, 0, 2, 3, 0, 4,
+ 5, 2, 0, 0, 0, 2, 0, 2,
+ 0, 2, 4, 0, 8, 2, 9, 0,
+ 10, 0, 0, 0, 0, 0, 0, 11,
+ 12, 0, 0, 0, 0, 4, 0, 0
};
-static const char _khmer_syllable_machine_from_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
+static const signed char _khmer_syllable_machine_to_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 6, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0
};
-static const unsigned char _khmer_syllable_machine_eof_trans[] = {
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 14, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 0, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 39, 40,
- 40, 40, 40, 40, 40, 40, 40, 40
+static const signed char _khmer_syllable_machine_from_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0
+};
+
+static const signed char _khmer_syllable_machine_eof_trans[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 14, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 28, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 40, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 0
};
static const int khmer_syllable_machine_start = 20;
@@ -215,156 +183,271 @@ static const int khmer_syllable_machine_error = -1;
static const int khmer_syllable_machine_en_main = 20;
-#line 36 "hb-ot-shape-complex-khmer-machine.rl"
+#line 43 "hb-ot-shape-complex-khmer-machine.rl"
-#line 80 "hb-ot-shape-complex-khmer-machine.rl"
+#line 86 "hb-ot-shape-complex-khmer-machine.rl"
#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
- for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
+HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+ for (unsigned int i = ts; i < te; i++) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+ } HB_STMT_END
static void
find_syllables_khmer (hb_buffer_t *buffer)
{
- unsigned int p, pe, eof, ts, te, act HB_UNUSED;
- int cs;
- hb_glyph_info_t *info = buffer->info;
-
-#line 242 "hb-ot-shape-complex-khmer-machine.hh"
+ unsigned int p, pe, eof, ts, te, act HB_UNUSED;
+ int cs;
+ hb_glyph_info_t *info = buffer->info;
+
+#line 210 "hb-ot-shape-complex-khmer-machine.hh"
{
- cs = khmer_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
+ cs = (int)khmer_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
}
-
-#line 100 "hb-ot-shape-complex-khmer-machine.rl"
-
-
- p = 0;
- pe = eof = buffer->len;
-
- unsigned int syllable_serial = 1;
-
-#line 258 "hb-ot-shape-complex-khmer-machine.hh"
+
+#line 106 "hb-ot-shape-complex-khmer-machine.rl"
+
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int syllable_serial = 1;
+
+#line 226 "hb-ot-shape-complex-khmer-machine.hh"
{
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
- case 7:
+ unsigned int _trans = 0;
+ const unsigned char * _keys;
+ const signed char * _inds;
+ int _ic;
+ _resume: {}
+ if ( p == pe && p != eof )
+ goto _out;
+ switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
+ case 7: {
+ {
#line 1 "NONE"
- {ts = p;}
- break;
-#line 272 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
- _keys = _khmer_syllable_machine_trans_keys + (cs<<1);
- _inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs];
-
- _slen = _khmer_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) &&
- ( info[p].khmer_category()) <= _keys[1] ?
- ( info[p].khmer_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _khmer_syllable_machine_trans_targs[_trans];
-
- if ( _khmer_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _khmer_syllable_machine_trans_actions[_trans] ) {
- case 2:
+ {ts = p;}}
+
+#line 241 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ }
+
+ if ( p == eof ) {
+ if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = (unsigned int)_khmer_syllable_machine_eof_trans[cs] - 1;
+ }
+ }
+ else {
+ _keys = ( _khmer_syllable_machine_trans_keys + ((cs<<1)));
+ _inds = ( _khmer_syllable_machine_indicies + (_khmer_syllable_machine_index_offsets[cs]));
+
+ if ( (info[p].khmer_category()) <= 29 && (info[p].khmer_category()) >= 1 ) {
+ _ic = (int)_khmer_syllable_machine_char_class[(int)(info[p].khmer_category()) - 1];
+ if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) )
+ _trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) ));
+ else
+ _trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs];
+ }
+ else {
+ _trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs];
+ }
+
+ }
+ cs = (int)_khmer_syllable_machine_cond_targs[_trans];
+
+ if ( _khmer_syllable_machine_cond_actions[_trans] != 0 ) {
+
+ switch ( _khmer_syllable_machine_cond_actions[_trans] ) {
+ case 2: {
+ {
#line 1 "NONE"
- {te = p+1;}
- break;
- case 8:
-#line 76 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p+1;{ found_syllable (non_khmer_cluster); }}
- break;
- case 10:
-#line 74 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (consonant_syllable); }}
- break;
- case 12:
-#line 75 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (broken_cluster); }}
- break;
- case 11:
-#line 76 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (non_khmer_cluster); }}
- break;
- case 1:
-#line 74 "hb-ot-shape-complex-khmer-machine.rl"
- {{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
- break;
- case 5:
-#line 75 "hb-ot-shape-complex-khmer-machine.rl"
- {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
- break;
- case 3:
+ {te = p+1;}}
+
+#line 279 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ case 8: {
+ {
+#line 82 "hb-ot-shape-complex-khmer-machine.rl"
+ {te = p+1;{
+#line 82 "hb-ot-shape-complex-khmer-machine.rl"
+ found_syllable (khmer_non_khmer_cluster); }
+ }}
+
+#line 292 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ case 10: {
+ {
+#line 80 "hb-ot-shape-complex-khmer-machine.rl"
+ {te = p;p = p - 1;{
+#line 80 "hb-ot-shape-complex-khmer-machine.rl"
+ found_syllable (khmer_consonant_syllable); }
+ }}
+
+#line 305 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ case 12: {
+ {
+#line 81 "hb-ot-shape-complex-khmer-machine.rl"
+ {te = p;p = p - 1;{
+#line 81 "hb-ot-shape-complex-khmer-machine.rl"
+ found_syllable (khmer_broken_cluster); }
+ }}
+
+#line 318 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ case 11: {
+ {
+#line 82 "hb-ot-shape-complex-khmer-machine.rl"
+ {te = p;p = p - 1;{
+#line 82 "hb-ot-shape-complex-khmer-machine.rl"
+ found_syllable (khmer_non_khmer_cluster); }
+ }}
+
+#line 331 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ case 1: {
+ {
+#line 80 "hb-ot-shape-complex-khmer-machine.rl"
+ {p = ((te))-1;
+ {
+#line 80 "hb-ot-shape-complex-khmer-machine.rl"
+ found_syllable (khmer_consonant_syllable); }
+ }}
+
+#line 345 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ case 5: {
+ {
+#line 81 "hb-ot-shape-complex-khmer-machine.rl"
+ {p = ((te))-1;
+ {
+#line 81 "hb-ot-shape-complex-khmer-machine.rl"
+ found_syllable (khmer_broken_cluster); }
+ }}
+
+#line 359 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ case 3: {
+ {
#line 1 "NONE"
- { switch( act ) {
- case 2:
- {{p = ((te))-1;} found_syllable (broken_cluster); }
- break;
- case 3:
- {{p = ((te))-1;} found_syllable (non_khmer_cluster); }
- break;
- }
- }
- break;
- case 4:
+ {switch( act ) {
+ case 2: {
+ p = ((te))-1;
+ {
+#line 81 "hb-ot-shape-complex-khmer-machine.rl"
+ found_syllable (khmer_broken_cluster); }
+ break;
+ }
+ case 3: {
+ p = ((te))-1;
+ {
+#line 82 "hb-ot-shape-complex-khmer-machine.rl"
+ found_syllable (khmer_non_khmer_cluster); }
+ break;
+ }
+ }}
+ }
+
+#line 385 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ case 4: {
+ {
#line 1 "NONE"
- {te = p+1;}
-#line 75 "hb-ot-shape-complex-khmer-machine.rl"
- {act = 2;}
- break;
- case 9:
+ {te = p+1;}}
+
+#line 395 "hb-ot-shape-complex-khmer-machine.hh"
+
+ {
+#line 81 "hb-ot-shape-complex-khmer-machine.rl"
+ {act = 2;}}
+
+#line 401 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ case 9: {
+ {
#line 1 "NONE"
- {te = p+1;}
-#line 76 "hb-ot-shape-complex-khmer-machine.rl"
- {act = 3;}
- break;
-#line 342 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
-_again:
- switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
- case 6:
+ {te = p+1;}}
+
+#line 411 "hb-ot-shape-complex-khmer-machine.hh"
+
+ {
+#line 82 "hb-ot-shape-complex-khmer-machine.rl"
+ {act = 3;}}
+
+#line 417 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ }
+
+ }
+
+ if ( p == eof ) {
+ if ( cs >= 20 )
+ goto _out;
+ }
+ else {
+ switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
+ case 6: {
+ {
#line 1 "NONE"
- {ts = 0;}
- break;
-#line 351 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _khmer_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
+ {ts = 0;}}
+
+#line 437 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+ break;
+ }
+ }
+
+ p += 1;
+ goto _resume;
+ }
+ _out: {}
}
-
- }
-
-#line 108 "hb-ot-shape-complex-khmer-machine.rl"
-
+
+#line 114 "hb-ot-shape-complex-khmer-machine.rl"
+
}
#undef found_syllable
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.rl b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.rl
deleted file mode 100644
index e7f14533dd..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.rl
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright © 2011,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
-
-#include "hb.hh"
-
-%%{
- machine khmer_syllable_machine;
- alphtype unsigned char;
- write data;
-}%%
-
-%%{
-
-# Same order as enum khmer_category_t. Not sure how to avoid duplication.
-C = 1;
-V = 2;
-ZWNJ = 5;
-ZWJ = 6;
-PLACEHOLDER = 11;
-DOTTEDCIRCLE = 12;
-Coeng= 14;
-Ra = 16;
-Robatic = 20;
-Xgroup = 21;
-Ygroup = 22;
-VAbv = 26;
-VBlw = 27;
-VPre = 28;
-VPst = 29;
-
-c = (C | Ra | V);
-cn = c.((ZWJ|ZWNJ)?.Robatic)?;
-joiner = (ZWJ | ZWNJ);
-xgroup = (joiner*.Xgroup)*;
-ygroup = Ygroup*;
-
-# This grammar was experimentally extracted from what Uniscribe allows.
-
-matra_group = VPre? xgroup VBlw? xgroup (joiner?.VAbv)? xgroup VPst?;
-syllable_tail = xgroup matra_group xgroup (Coeng.c)? ygroup;
-
-
-broken_cluster = (Coeng.cn)* (Coeng | syllable_tail);
-consonant_syllable = (cn|PLACEHOLDER|DOTTEDCIRCLE) broken_cluster;
-other = any;
-
-main := |*
- consonant_syllable => { found_syllable (consonant_syllable); };
- broken_cluster => { found_syllable (broken_cluster); };
- other => { found_syllable (non_khmer_cluster); };
-*|;
-
-
-}%%
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
- for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-static void
-find_syllables_khmer (hb_buffer_t *buffer)
-{
- unsigned int p, pe, eof, ts, te, act HB_UNUSED;
- int cs;
- hb_glyph_info_t *info = buffer->info;
- %%{
- write init;
- getkey info[p].khmer_category();
- }%%
-
- p = 0;
- pe = eof = buffer->len;
-
- unsigned int syllable_serial = 1;
- %%{
- write exec;
- }%%
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc
index d6fcd7c814..dddba142a3 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc
@@ -29,6 +29,7 @@
#ifndef HB_NO_OT_SHAPE
#include "hb-ot-shape-complex-khmer.hh"
+#include "hb-ot-shape-complex-khmer-machine.hh"
#include "hb-ot-layout.hh"
@@ -140,27 +141,6 @@ override_features_khmer (hb_ot_shape_planner_t *plan)
struct khmer_shape_plan_t
{
- bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
- {
- hb_codepoint_t glyph = virama_glyph;
- if (unlikely (virama_glyph == (hb_codepoint_t) -1))
- {
- if (!font->get_nominal_glyph (0x17D2u, &glyph))
- glyph = 0;
- /* Technically speaking, the spec says we should apply 'locl' to virama too.
- * Maybe one day... */
-
- /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
- * during shape planning... Instead, overwrite it here. It's safe. Don't worry! */
- virama_glyph = glyph;
- }
-
- *pglyph = glyph;
- return glyph != 0;
- }
-
- mutable hb_codepoint_t virama_glyph;
-
hb_mask_t mask_array[KHMER_NUM_FEATURES];
};
@@ -171,8 +151,6 @@ data_create_khmer (const hb_ot_shape_plan_t *plan)
if (unlikely (!khmer_plan))
return nullptr;
- khmer_plan->virama_glyph = (hb_codepoint_t) -1;
-
for (unsigned int i = 0; i < ARRAY_LENGTH (khmer_plan->mask_array); i++)
khmer_plan->mask_array[i] = (khmer_features[i].flags & F_GLOBAL) ?
0 : plan->map.get_1_mask (khmer_features[i].tag);
@@ -186,15 +164,6 @@ data_destroy_khmer (void *data)
free (data);
}
-
-enum khmer_syllable_type_t {
- khmer_consonant_syllable,
- khmer_broken_cluster,
- khmer_non_khmer_cluster,
-};
-
-#include "hb-ot-shape-complex-khmer-machine.hh"
-
static void
setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
@@ -321,76 +290,17 @@ reorder_syllable_khmer (const hb_ot_shape_plan_t *plan,
}
}
-static inline void
-insert_dotted_circles_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
- if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
- return;
-
- /* Note: This loop is extra overhead, but should not be measurable.
- * TODO Use a buffer scratch flag to remove the loop. */
- bool has_broken_syllables = false;
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- if ((info[i].syllable() & 0x0F) == khmer_broken_cluster)
- {
- has_broken_syllables = true;
- break;
- }
- if (likely (!has_broken_syllables))
- return;
-
-
- hb_codepoint_t dottedcircle_glyph;
- if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
- return;
-
- hb_glyph_info_t dottedcircle = {0};
- dottedcircle.codepoint = 0x25CCu;
- set_khmer_properties (dottedcircle);
- dottedcircle.codepoint = dottedcircle_glyph;
-
- buffer->clear_output ();
-
- buffer->idx = 0;
- unsigned int last_syllable = 0;
- while (buffer->idx < buffer->len && buffer->successful)
- {
- unsigned int syllable = buffer->cur().syllable();
- khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (syllable & 0x0F);
- if (unlikely (last_syllable != syllable && syllable_type == khmer_broken_cluster))
- {
- last_syllable = syllable;
-
- hb_glyph_info_t ginfo = dottedcircle;
- ginfo.cluster = buffer->cur().cluster;
- ginfo.mask = buffer->cur().mask;
- ginfo.syllable() = buffer->cur().syllable();
-
- /* Insert dottedcircle after possible Repha. */
- while (buffer->idx < buffer->len && buffer->successful &&
- last_syllable == buffer->cur().syllable() &&
- buffer->cur().khmer_category() == OT_Repha)
- buffer->next_glyph ();
-
- buffer->output_info (ginfo);
- }
- else
- buffer->next_glyph ();
- }
- buffer->swap_buffers ();
-}
-
static void
reorder_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
- if (buffer->message (font, "start reordering khmer")) {
- insert_dotted_circles_khmer (plan, font, buffer);
+ if (buffer->message (font, "start reordering khmer"))
+ {
+ hb_syllabic_insert_dotted_circles (font, buffer,
+ khmer_broken_cluster,
+ OT_DOTTEDCIRCLE,
+ OT_Repha);
foreach_syllable (buffer, start, end)
reorder_syllable_khmer (plan, font->face, buffer, start, end);
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh
index 11a77bfd4b..e24d68a8b5 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh
@@ -54,7 +54,7 @@ set_khmer_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
- khmer_category_t cat = (khmer_category_t) (type & 0x7Fu);
+ khmer_category_t cat = (khmer_category_t) (type & 0xFFu);
indic_position_t pos = (indic_position_t) (type >> 8);
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-machine-index.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-machine-index.hh
deleted file mode 100644
index 9ec1f3eb7c..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-machine-index.hh
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright © 2019,2020 David Corbett
- *
- * 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_OT_SHAPE_COMPLEX_MACHINE_INDEX_HH
-#define HB_OT_SHAPE_COMPLEX_MACHINE_INDEX_HH
-
-#include "hb.hh"
-
-
-template <typename Iter>
-struct machine_index_t :
- hb_iter_with_fallback_t<machine_index_t<Iter>,
- typename Iter::item_t>
-{
- machine_index_t (const Iter& it) : it (it) {}
- machine_index_t (const machine_index_t& o) : it (o.it) {}
-
- static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
- static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
-
- typename Iter::item_t __item__ () const { return *it; }
- typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; }
- unsigned __len__ () const { return it.len (); }
- void __next__ () { ++it; }
- void __forward__ (unsigned n) { it += n; }
- void __prev__ () { --it; }
- void __rewind__ (unsigned n) { it -= n; }
- void operator = (unsigned n)
- { unsigned index = (*it).first; if (index < n) it += n - index; else if (index > n) it -= index - n; }
- void operator = (const machine_index_t& o) { *this = (*o.it).first; }
- bool operator == (const machine_index_t& o) const { return (*it).first == (*o.it).first; }
- bool operator != (const machine_index_t& o) const { return !(*this == o); }
-
- private:
- Iter it;
-};
-struct
-{
- template <typename Iter,
- hb_requires (hb_is_iterable (Iter))>
- machine_index_t<hb_iter_type<Iter>>
- operator () (Iter&& it) const
- { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); }
-}
-HB_FUNCOBJ (machine_index);
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_MACHINE_INDEX_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
index c2f4c0045c..c09497896d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
@@ -31,8 +31,43 @@
#include "hb.hh"
+enum myanmar_syllable_type_t {
+ myanmar_consonant_syllable,
+ myanmar_punctuation_cluster,
+ myanmar_broken_cluster,
+ myanmar_non_myanmar_cluster,
+};
+
-#line 36 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 43 "hb-ot-shape-complex-myanmar-machine.hh"
+#define myanmar_syllable_machine_ex_A 10u
+#define myanmar_syllable_machine_ex_As 18u
+#define myanmar_syllable_machine_ex_C 1u
+#define myanmar_syllable_machine_ex_CS 19u
+#define myanmar_syllable_machine_ex_D 32u
+#define myanmar_syllable_machine_ex_D0 20u
+#define myanmar_syllable_machine_ex_DB 3u
+#define myanmar_syllable_machine_ex_GB 11u
+#define myanmar_syllable_machine_ex_H 4u
+#define myanmar_syllable_machine_ex_IV 2u
+#define myanmar_syllable_machine_ex_MH 21u
+#define myanmar_syllable_machine_ex_MR 22u
+#define myanmar_syllable_machine_ex_MW 23u
+#define myanmar_syllable_machine_ex_MY 24u
+#define myanmar_syllable_machine_ex_P 31u
+#define myanmar_syllable_machine_ex_PT 25u
+#define myanmar_syllable_machine_ex_Ra 16u
+#define myanmar_syllable_machine_ex_V 8u
+#define myanmar_syllable_machine_ex_VAbv 26u
+#define myanmar_syllable_machine_ex_VBlw 27u
+#define myanmar_syllable_machine_ex_VPre 28u
+#define myanmar_syllable_machine_ex_VPst 29u
+#define myanmar_syllable_machine_ex_VS 30u
+#define myanmar_syllable_machine_ex_ZWJ 6u
+#define myanmar_syllable_machine_ex_ZWNJ 5u
+
+
+#line 71 "hb-ot-shape-complex-myanmar-machine.hh"
static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u,
@@ -293,18 +328,18 @@ static const int myanmar_syllable_machine_error = -1;
static const int myanmar_syllable_machine_en_main = 0;
-#line 36 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 44 "hb-ot-shape-complex-myanmar-machine.rl"
-#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 101 "hb-ot-shape-complex-myanmar-machine.rl"
#define found_syllable(syllable_type) \
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | myanmar_##syllable_type; \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
@@ -316,7 +351,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
int cs;
hb_glyph_info_t *info = buffer->info;
-#line 320 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 355 "hb-ot-shape-complex-myanmar-machine.hh"
{
cs = myanmar_syllable_machine_start;
ts = 0;
@@ -324,7 +359,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
act = 0;
}
-#line 114 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 121 "hb-ot-shape-complex-myanmar-machine.rl"
p = 0;
@@ -332,7 +367,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
unsigned int syllable_serial = 1;
-#line 336 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 371 "hb-ot-shape-complex-myanmar-machine.hh"
{
int _slen;
int _trans;
@@ -346,7 +381,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
-#line 350 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 385 "hb-ot-shape-complex-myanmar-machine.hh"
}
_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -365,38 +400,38 @@ _eof_trans:
switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
case 6:
-#line 86 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (consonant_syllable); }}
+#line 93 "hb-ot-shape-complex-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
break;
case 4:
-#line 87 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (non_myanmar_cluster); }}
+#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
break;
case 10:
-#line 88 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (punctuation_cluster); }}
+#line 95 "hb-ot-shape-complex-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_punctuation_cluster); }}
break;
case 8:
-#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (broken_cluster); }}
+#line 96 "hb-ot-shape-complex-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_broken_cluster); }}
break;
case 3:
-#line 90 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (non_myanmar_cluster); }}
+#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
break;
case 5:
-#line 86 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (consonant_syllable); }}
+#line 93 "hb-ot-shape-complex-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
break;
case 7:
-#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (broken_cluster); }}
+#line 96 "hb-ot-shape-complex-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_broken_cluster); }}
break;
case 9:
-#line 90 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (non_myanmar_cluster); }}
+#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
break;
-#line 400 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 435 "hb-ot-shape-complex-myanmar-machine.hh"
}
_again:
@@ -405,7 +440,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
-#line 409 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 444 "hb-ot-shape-complex-myanmar-machine.hh"
}
if ( ++p != pe )
@@ -421,7 +456,7 @@ _again:
}
-#line 122 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 129 "hb-ot-shape-complex-myanmar-machine.rl"
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
index fe096ef28a..bc5dcb904c 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
@@ -29,6 +29,7 @@
#ifndef HB_NO_OT_SHAPE
#include "hb-ot-shape-complex-myanmar.hh"
+#include "hb-ot-shape-complex-myanmar-machine.hh"
/*
@@ -97,17 +98,6 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
}
-
-enum myanmar_syllable_type_t {
- myanmar_consonant_syllable,
- myanmar_punctuation_cluster,
- myanmar_broken_cluster,
- myanmar_non_myanmar_cluster,
-};
-
-#include "hb-ot-shape-complex-myanmar-machine.hh"
-
-
static void
setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
@@ -265,70 +255,16 @@ reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
}
-static inline void
-insert_dotted_circles_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
- if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
- return;
-
- /* Note: This loop is extra overhead, but should not be measurable.
- * TODO Use a buffer scratch flag to remove the loop. */
- bool has_broken_syllables = false;
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- if ((info[i].syllable() & 0x0F) == myanmar_broken_cluster)
- {
- has_broken_syllables = true;
- break;
- }
- if (likely (!has_broken_syllables))
- return;
-
-
- hb_codepoint_t dottedcircle_glyph;
- if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
- return;
-
- hb_glyph_info_t dottedcircle = {0};
- dottedcircle.codepoint = 0x25CCu;
- set_myanmar_properties (dottedcircle);
- dottedcircle.codepoint = dottedcircle_glyph;
-
- buffer->clear_output ();
-
- buffer->idx = 0;
- unsigned int last_syllable = 0;
- while (buffer->idx < buffer->len && buffer->successful)
- {
- unsigned int syllable = buffer->cur().syllable();
- myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (syllable & 0x0F);
- if (unlikely (last_syllable != syllable && syllable_type == myanmar_broken_cluster))
- {
- last_syllable = syllable;
-
- hb_glyph_info_t ginfo = dottedcircle;
- ginfo.cluster = buffer->cur().cluster;
- ginfo.mask = buffer->cur().mask;
- ginfo.syllable() = buffer->cur().syllable();
-
- buffer->output_info (ginfo);
- }
- else
- buffer->next_glyph ();
- }
- buffer->swap_buffers ();
-}
-
static void
reorder_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
- if (buffer->message (font, "start reordering myanmar")) {
- insert_dotted_circles_myanmar (plan, font, buffer);
+ if (buffer->message (font, "start reordering myanmar"))
+ {
+ hb_syllabic_insert_dotted_circles (font, buffer,
+ myanmar_broken_cluster,
+ OT_GB);
foreach_syllable (buffer, start, end)
reorder_syllable_myanmar (plan, font->face, buffer, start, end);
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh
index 7b9821e6ba..a6d68aae57 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh
@@ -64,7 +64,7 @@ set_myanmar_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
- unsigned int cat = type & 0x7Fu;
+ unsigned int cat = type & 0xFFu;
indic_position_t pos = (indic_position_t) (type >> 8);
/* Myanmar
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc
new file mode 100644
index 0000000000..46509abee2
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc
@@ -0,0 +1,100 @@
+/*
+ * Copyright © 2021 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.
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shape-complex-syllabic.hh"
+
+
+void
+hb_syllabic_insert_dotted_circles (hb_font_t *font,
+ hb_buffer_t *buffer,
+ unsigned int broken_syllable_type,
+ unsigned int dottedcircle_category,
+ int repha_category)
+{
+ if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
+ return;
+
+ /* Note: This loop is extra overhead, but should not be measurable.
+ * TODO Use a buffer scratch flag to remove the loop. */
+ bool has_broken_syllables = false;
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 0; i < count; i++)
+ if ((info[i].syllable() & 0x0F) == broken_syllable_type)
+ {
+ has_broken_syllables = true;
+ break;
+ }
+ if (likely (!has_broken_syllables))
+ return;
+
+
+ hb_codepoint_t dottedcircle_glyph;
+ if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
+ return;
+
+ hb_glyph_info_t dottedcircle = {0};
+ dottedcircle.codepoint = 0x25CCu;
+ dottedcircle.complex_var_u8_category() = dottedcircle_category;
+ dottedcircle.codepoint = dottedcircle_glyph;
+
+ buffer->clear_output ();
+
+ buffer->idx = 0;
+ unsigned int last_syllable = 0;
+ while (buffer->idx < buffer->len && buffer->successful)
+ {
+ unsigned int syllable = buffer->cur().syllable();
+ if (unlikely (last_syllable != syllable && (syllable & 0x0F) == broken_syllable_type))
+ {
+ last_syllable = syllable;
+
+ hb_glyph_info_t ginfo = dottedcircle;
+ ginfo.cluster = buffer->cur().cluster;
+ ginfo.mask = buffer->cur().mask;
+ ginfo.syllable() = buffer->cur().syllable();
+
+ /* Insert dottedcircle after possible Repha. */
+ if (repha_category != -1)
+ {
+ while (buffer->idx < buffer->len && buffer->successful &&
+ last_syllable == buffer->cur().syllable() &&
+ buffer->cur().complex_var_u8_category() == (unsigned) repha_category)
+ (void) buffer->next_glyph ();
+ }
+
+ (void) buffer->output_info (ginfo);
+ }
+ else
+ (void) buffer->next_glyph ();
+ }
+ buffer->swap_buffers ();
+}
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh
new file mode 100644
index 0000000000..c80b8fee1d
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2021 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_OT_SHAPE_COMPLEX_SYLLABIC_HH
+#define HB_OT_SHAPE_COMPLEX_SYLLABIC_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex.hh"
+
+
+HB_INTERNAL void
+hb_syllabic_insert_dotted_circles (hb_font_t *font,
+ hb_buffer_t *buffer,
+ unsigned int broken_syllable_type,
+ unsigned int dottedcircle_category,
+ int repha_category = -1);
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_SYLLABIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc
index 347ea2e7ac..4c3068173b 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc
@@ -323,20 +323,19 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
buffer->clear_output ();
unsigned int count = buffer->len;
- for (buffer->idx = 0; buffer->idx < count && buffer->successful;)
+ for (buffer->idx = 0; buffer->idx < count /* No need for: && buffer->successful */;)
{
hb_codepoint_t u = buffer->cur().codepoint;
- if (likely (!IS_SARA_AM (u))) {
- buffer->next_glyph ();
+ if (likely (!IS_SARA_AM (u)))
+ {
+ if (unlikely (!buffer->next_glyph ())) break;
continue;
}
/* Is SARA AM. Decompose and reorder. */
- hb_glyph_info_t &nikhahit = buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u));
- _hb_glyph_info_set_continuation (&nikhahit);
- buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u));
- if (unlikely (!buffer->successful))
- return;
+ (void) buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u));
+ _hb_glyph_info_set_continuation (&buffer->prev());
+ if (unlikely (!buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u)))) break;
/* Make Nikhahit be recognized as a ccc=0 mark when zeroing widths. */
unsigned int end = buffer->out_len;
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
index 144e7d3a40..b4b2b75100 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
@@ -1,300 +1,348 @@
-
#line 1 "hb-ot-shape-complex-use-machine.rl"
/*
- * Copyright © 2015 Mozilla Foundation.
- * Copyright © 2015 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
+* Copyright © 2015 Mozilla Foundation.
+* Copyright © 2015 Google, Inc.
+*
+* This is part of HarfBuzz, a text shaping library.
+*
+* Permission is hereby granted, without written agreement and without
+* license or royalty fees, to use, copy, modify, and distribute this
+* software and its documentation for any purpose, provided that the
+* above copyright notice and the following two paragraphs appear in
+* all copies of this software.
+*
+* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+* DAMAGE.
+*
+* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+*
+* Mozilla Author(s): Jonathan Kew
+* Google Author(s): Behdad Esfahbod
+*/
#ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
#include "hb.hh"
-#include "hb-ot-shape-complex-machine-index.hh"
+#include "hb-ot-shape-complex-syllabic.hh"
+
+/* buffer var allocations */
+#define use_category() complex_var_u8_category()
+
+#define USE(Cat) use_syllable_machine_ex_##Cat
+
+enum use_syllable_type_t {
+ use_independent_cluster,
+ use_virama_terminated_cluster,
+ use_sakot_terminated_cluster,
+ use_standard_cluster,
+ use_number_joiner_terminated_cluster,
+ use_numeral_cluster,
+ use_symbol_cluster,
+ use_hieroglyph_cluster,
+ use_broken_cluster,
+ use_non_cluster,
+};
-#line 39 "hb-ot-shape-complex-use-machine.hh"
+
+#line 57 "hb-ot-shape-complex-use-machine.hh"
+#define use_syllable_machine_ex_B 1u
+#define use_syllable_machine_ex_CMAbv 31u
+#define use_syllable_machine_ex_CMBlw 32u
+#define use_syllable_machine_ex_CS 43u
+#define use_syllable_machine_ex_FAbv 24u
+#define use_syllable_machine_ex_FBlw 25u
+#define use_syllable_machine_ex_FMAbv 45u
+#define use_syllable_machine_ex_FMBlw 46u
+#define use_syllable_machine_ex_FMPst 47u
+#define use_syllable_machine_ex_FPst 26u
+#define use_syllable_machine_ex_G 49u
+#define use_syllable_machine_ex_GB 5u
+#define use_syllable_machine_ex_H 12u
+#define use_syllable_machine_ex_HN 13u
+#define use_syllable_machine_ex_HVM 44u
+#define use_syllable_machine_ex_J 50u
+#define use_syllable_machine_ex_MAbv 27u
+#define use_syllable_machine_ex_MBlw 28u
+#define use_syllable_machine_ex_MPre 30u
+#define use_syllable_machine_ex_MPst 29u
+#define use_syllable_machine_ex_N 4u
+#define use_syllable_machine_ex_O 0u
+#define use_syllable_machine_ex_R 18u
+#define use_syllable_machine_ex_S 19u
+#define use_syllable_machine_ex_SB 51u
+#define use_syllable_machine_ex_SE 52u
+#define use_syllable_machine_ex_SMAbv 41u
+#define use_syllable_machine_ex_SMBlw 42u
+#define use_syllable_machine_ex_SUB 11u
+#define use_syllable_machine_ex_Sk 48u
+#define use_syllable_machine_ex_VAbv 33u
+#define use_syllable_machine_ex_VBlw 34u
+#define use_syllable_machine_ex_VMAbv 37u
+#define use_syllable_machine_ex_VMBlw 38u
+#define use_syllable_machine_ex_VMPre 23u
+#define use_syllable_machine_ex_VMPst 39u
+#define use_syllable_machine_ex_VPre 22u
+#define use_syllable_machine_ex_VPst 35u
+#define use_syllable_machine_ex_ZWNJ 14u
+
+
+#line 99 "hb-ot-shape-complex-use-machine.hh"
static const unsigned char _use_syllable_machine_trans_keys[] = {
- 1u, 1u, 1u, 1u, 0u, 51u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 23u, 48u,
- 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u,
- 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u,
- 11u, 48u, 1u, 48u, 13u, 13u, 4u, 4u, 11u, 48u, 41u, 42u, 42u, 42u, 11u, 48u,
- 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
- 24u, 48u, 24u, 48u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u,
- 22u, 48u, 11u, 48u, 1u, 48u, 1u, 1u, 4u, 4u, 13u, 13u, 1u, 48u, 11u, 48u,
- 41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u, 0
+ 1u, 1u, 1u, 1u, 0u, 37u, 5u, 34u,
+ 5u, 34u, 1u, 1u, 10u, 34u, 11u, 34u,
+ 12u, 33u, 13u, 33u, 14u, 33u, 31u, 32u,
+ 32u, 32u, 12u, 34u, 12u, 34u, 12u, 34u,
+ 1u, 1u, 12u, 34u, 11u, 34u, 11u, 34u,
+ 11u, 34u, 10u, 34u, 10u, 34u, 10u, 34u,
+ 5u, 34u, 1u, 34u, 7u, 7u, 3u, 3u,
+ 5u, 34u, 27u, 28u, 28u, 28u, 5u, 34u,
+ 10u, 34u, 11u, 34u, 12u, 33u, 13u, 33u,
+ 14u, 33u, 31u, 32u, 32u, 32u, 12u, 34u,
+ 12u, 34u, 12u, 34u, 12u, 34u, 11u, 34u,
+ 11u, 34u, 11u, 34u, 10u, 34u, 10u, 34u,
+ 10u, 34u, 5u, 34u, 1u, 34u, 1u, 1u,
+ 3u, 3u, 7u, 7u, 1u, 34u, 5u, 34u,
+ 27u, 28u, 28u, 28u, 1u, 4u, 36u, 38u,
+ 35u, 38u, 35u, 37u, 0u
};
-static const char _use_syllable_machine_key_spans[] = {
- 1, 1, 52, 38, 38, 1, 27, 26,
- 24, 23, 22, 2, 1, 25, 25, 25,
- 1, 25, 26, 26, 26, 27, 27, 27,
- 38, 48, 1, 1, 38, 2, 1, 38,
- 27, 26, 24, 23, 22, 2, 1, 25,
- 25, 25, 25, 26, 26, 26, 27, 27,
- 27, 38, 48, 1, 1, 1, 48, 38,
- 2, 1, 5, 3, 4, 3
+static const signed char _use_syllable_machine_char_class[] = {
+ 0, 1, 2, 2, 3, 4, 2, 2,
+ 2, 2, 2, 5, 6, 7, 2, 2,
+ 2, 2, 8, 9, 2, 2, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 2, 24, 25, 26,
+ 2, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 0
};
static const short _use_syllable_machine_index_offsets[] = {
- 0, 2, 4, 57, 96, 135, 137, 165,
- 192, 217, 241, 264, 267, 269, 295, 321,
- 347, 349, 375, 402, 429, 456, 484, 512,
- 540, 579, 628, 630, 632, 671, 674, 676,
- 715, 743, 770, 795, 819, 842, 845, 847,
- 873, 899, 925, 951, 978, 1005, 1032, 1060,
- 1088, 1116, 1155, 1204, 1206, 1208, 1210, 1259,
- 1298, 1301, 1303, 1309, 1313, 1318
+ 0, 1, 2, 40, 70, 100, 101, 126,
+ 150, 172, 193, 213, 215, 216, 239, 262,
+ 285, 286, 309, 333, 357, 381, 406, 431,
+ 456, 486, 520, 521, 522, 552, 554, 555,
+ 585, 610, 634, 656, 677, 697, 699, 700,
+ 723, 746, 769, 792, 816, 840, 864, 889,
+ 914, 939, 969, 1003, 1004, 1005, 1006, 1040,
+ 1070, 1072, 1073, 1077, 1080, 1084, 0
+};
+
+static const signed char _use_syllable_machine_indicies[] = {
+ 1, 2, 4, 5, 6, 7, 8, 1,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 13, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 9, 36, 6, 37,
+ 39, 40, 38, 38, 38, 41, 42, 43,
+ 44, 45, 46, 47, 41, 48, 5, 49,
+ 50, 51, 52, 53, 54, 55, 38, 38,
+ 38, 56, 57, 58, 59, 40, 39, 40,
+ 38, 38, 38, 41, 42, 43, 44, 45,
+ 46, 47, 41, 48, 49, 49, 50, 51,
+ 52, 53, 54, 55, 38, 38, 38, 56,
+ 57, 58, 59, 40, 39, 41, 42, 43,
+ 44, 45, 38, 38, 38, 38, 38, 38,
+ 50, 51, 52, 53, 54, 55, 38, 38,
+ 38, 42, 57, 58, 59, 61, 42, 43,
+ 44, 45, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 53, 54, 55, 38, 38,
+ 38, 38, 57, 58, 59, 61, 43, 44,
+ 45, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 57, 58, 59, 44, 45, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 57, 58,
+ 59, 45, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 57, 58, 59, 57, 58, 58,
+ 43, 44, 45, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 53, 54, 55, 38,
+ 38, 38, 38, 57, 58, 59, 61, 43,
+ 44, 45, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 54, 55, 38, 38,
+ 38, 38, 57, 58, 59, 61, 43, 44,
+ 45, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 55, 38, 38, 38,
+ 38, 57, 58, 59, 61, 63, 43, 44,
+ 45, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 57, 58, 59, 61, 42, 43, 44,
+ 45, 38, 38, 38, 38, 38, 38, 50,
+ 51, 52, 53, 54, 55, 38, 38, 38,
+ 42, 57, 58, 59, 61, 42, 43, 44,
+ 45, 38, 38, 38, 38, 38, 38, 38,
+ 51, 52, 53, 54, 55, 38, 38, 38,
+ 42, 57, 58, 59, 61, 42, 43, 44,
+ 45, 38, 38, 38, 38, 38, 38, 38,
+ 38, 52, 53, 54, 55, 38, 38, 38,
+ 42, 57, 58, 59, 61, 41, 42, 43,
+ 44, 45, 38, 47, 41, 38, 38, 38,
+ 50, 51, 52, 53, 54, 55, 38, 38,
+ 38, 42, 57, 58, 59, 61, 41, 42,
+ 43, 44, 45, 38, 38, 41, 38, 38,
+ 38, 50, 51, 52, 53, 54, 55, 38,
+ 38, 38, 42, 57, 58, 59, 61, 41,
+ 42, 43, 44, 45, 46, 47, 41, 38,
+ 38, 38, 50, 51, 52, 53, 54, 55,
+ 38, 38, 38, 42, 57, 58, 59, 61,
+ 39, 40, 38, 38, 38, 41, 42, 43,
+ 44, 45, 46, 47, 41, 48, 38, 49,
+ 50, 51, 52, 53, 54, 55, 38, 38,
+ 38, 56, 57, 58, 59, 40, 39, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60,
+ 42, 43, 44, 45, 60, 60, 60, 60,
+ 60, 60, 60, 60, 60, 53, 54, 55,
+ 60, 60, 60, 60, 57, 58, 59, 61,
+ 65, 7, 39, 40, 38, 38, 38, 41,
+ 42, 43, 44, 45, 46, 47, 41, 48,
+ 5, 49, 50, 51, 52, 53, 54, 55,
+ 12, 67, 38, 56, 57, 58, 59, 40,
+ 12, 67, 67, 1, 70, 69, 69, 69,
+ 13, 14, 15, 16, 17, 18, 19, 13,
+ 20, 22, 22, 23, 24, 25, 26, 27,
+ 28, 69, 69, 69, 32, 33, 34, 35,
+ 70, 13, 14, 15, 16, 17, 69, 69,
+ 69, 69, 69, 69, 23, 24, 25, 26,
+ 27, 28, 69, 69, 69, 14, 33, 34,
+ 35, 71, 14, 15, 16, 17, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 26,
+ 27, 28, 69, 69, 69, 69, 33, 34,
+ 35, 71, 15, 16, 17, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 33, 34, 35,
+ 16, 17, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 33, 34, 35, 17, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 33, 34,
+ 35, 33, 34, 34, 15, 16, 17, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 26, 27, 28, 69, 69, 69, 69, 33,
+ 34, 35, 71, 15, 16, 17, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 27, 28, 69, 69, 69, 69, 33, 34,
+ 35, 71, 15, 16, 17, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 28, 69, 69, 69, 69, 33, 34, 35,
+ 71, 15, 16, 17, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 33, 34, 35, 71,
+ 14, 15, 16, 17, 69, 69, 69, 69,
+ 69, 69, 23, 24, 25, 26, 27, 28,
+ 69, 69, 69, 14, 33, 34, 35, 71,
+ 14, 15, 16, 17, 69, 69, 69, 69,
+ 69, 69, 69, 24, 25, 26, 27, 28,
+ 69, 69, 69, 14, 33, 34, 35, 71,
+ 14, 15, 16, 17, 69, 69, 69, 69,
+ 69, 69, 69, 69, 25, 26, 27, 28,
+ 69, 69, 69, 14, 33, 34, 35, 71,
+ 13, 14, 15, 16, 17, 69, 19, 13,
+ 69, 69, 69, 23, 24, 25, 26, 27,
+ 28, 69, 69, 69, 14, 33, 34, 35,
+ 71, 13, 14, 15, 16, 17, 69, 69,
+ 13, 69, 69, 69, 23, 24, 25, 26,
+ 27, 28, 69, 69, 69, 14, 33, 34,
+ 35, 71, 13, 14, 15, 16, 17, 18,
+ 19, 13, 69, 69, 69, 23, 24, 25,
+ 26, 27, 28, 69, 69, 69, 14, 33,
+ 34, 35, 71, 1, 70, 69, 69, 69,
+ 13, 14, 15, 16, 17, 18, 19, 13,
+ 20, 69, 22, 23, 24, 25, 26, 27,
+ 28, 69, 69, 69, 32, 33, 34, 35,
+ 70, 1, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 14, 15, 16, 17, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 26, 27, 28, 69, 69, 69, 69, 33,
+ 34, 35, 71, 1, 73, 10, 5, 69,
+ 69, 5, 1, 70, 10, 69, 69, 13,
+ 14, 15, 16, 17, 18, 19, 13, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 69, 32, 33, 34, 35, 70,
+ 1, 70, 69, 69, 69, 13, 14, 15,
+ 16, 17, 18, 19, 13, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 69, 69,
+ 69, 32, 33, 34, 35, 70, 29, 30,
+ 30, 5, 72, 72, 5, 75, 74, 36,
+ 36, 75, 74, 75, 36, 74, 37, 0
};
-static const char _use_syllable_machine_indicies[] = {
- 1, 0, 2, 0, 3, 4, 5, 5,
- 6, 7, 5, 5, 5, 5, 5, 1,
- 8, 9, 5, 5, 5, 5, 10, 11,
- 5, 5, 12, 13, 14, 15, 16, 17,
- 18, 12, 19, 20, 21, 22, 23, 24,
- 5, 25, 26, 27, 5, 28, 29, 30,
- 31, 32, 33, 34, 8, 35, 5, 36,
- 5, 38, 39, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 40, 41, 42, 43,
- 44, 45, 46, 40, 47, 4, 48, 49,
- 50, 51, 37, 52, 53, 54, 37, 37,
- 37, 37, 55, 56, 57, 58, 39, 37,
- 38, 39, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 40, 41, 42, 43, 44,
- 45, 46, 40, 47, 48, 48, 49, 50,
- 51, 37, 52, 53, 54, 37, 37, 37,
- 37, 55, 56, 57, 58, 39, 37, 38,
- 59, 40, 41, 42, 43, 44, 37, 37,
- 37, 37, 37, 37, 49, 50, 51, 37,
- 52, 53, 54, 37, 37, 37, 37, 41,
- 56, 57, 58, 60, 37, 41, 42, 43,
- 44, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 52, 53, 54, 37, 37,
- 37, 37, 37, 56, 57, 58, 60, 37,
- 42, 43, 44, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 56, 57, 58,
- 37, 43, 44, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 56, 57, 58,
- 37, 44, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 56, 57, 58, 37,
- 56, 57, 37, 57, 37, 42, 43, 44,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 52, 53, 54, 37, 37, 37,
- 37, 37, 56, 57, 58, 60, 37, 42,
- 43, 44, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 53, 54, 37,
- 37, 37, 37, 37, 56, 57, 58, 60,
- 37, 42, 43, 44, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 54, 37, 37, 37, 37, 37, 56, 57,
- 58, 60, 37, 62, 61, 42, 43, 44,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 56, 57, 58, 60, 37, 41,
- 42, 43, 44, 37, 37, 37, 37, 37,
- 37, 49, 50, 51, 37, 52, 53, 54,
- 37, 37, 37, 37, 41, 56, 57, 58,
- 60, 37, 41, 42, 43, 44, 37, 37,
- 37, 37, 37, 37, 37, 50, 51, 37,
- 52, 53, 54, 37, 37, 37, 37, 41,
- 56, 57, 58, 60, 37, 41, 42, 43,
- 44, 37, 37, 37, 37, 37, 37, 37,
- 37, 51, 37, 52, 53, 54, 37, 37,
- 37, 37, 41, 56, 57, 58, 60, 37,
- 40, 41, 42, 43, 44, 37, 46, 40,
- 37, 37, 37, 49, 50, 51, 37, 52,
- 53, 54, 37, 37, 37, 37, 41, 56,
- 57, 58, 60, 37, 40, 41, 42, 43,
- 44, 37, 37, 40, 37, 37, 37, 49,
- 50, 51, 37, 52, 53, 54, 37, 37,
- 37, 37, 41, 56, 57, 58, 60, 37,
- 40, 41, 42, 43, 44, 45, 46, 40,
- 37, 37, 37, 49, 50, 51, 37, 52,
- 53, 54, 37, 37, 37, 37, 41, 56,
- 57, 58, 60, 37, 38, 39, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 40,
- 41, 42, 43, 44, 45, 46, 40, 47,
- 37, 48, 49, 50, 51, 37, 52, 53,
- 54, 37, 37, 37, 37, 55, 56, 57,
- 58, 39, 37, 38, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 41, 42, 43, 44, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 52,
- 53, 54, 59, 59, 59, 59, 59, 56,
- 57, 58, 60, 59, 64, 63, 6, 65,
- 38, 39, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 40, 41, 42, 43, 44,
- 45, 46, 40, 47, 4, 48, 49, 50,
- 51, 37, 52, 53, 54, 37, 11, 66,
- 37, 55, 56, 57, 58, 39, 37, 11,
- 66, 67, 66, 67, 1, 69, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 12,
- 13, 14, 15, 16, 17, 18, 12, 19,
- 21, 21, 22, 23, 24, 68, 25, 26,
- 27, 68, 68, 68, 68, 31, 32, 33,
- 34, 69, 68, 12, 13, 14, 15, 16,
- 68, 68, 68, 68, 68, 68, 22, 23,
- 24, 68, 25, 26, 27, 68, 68, 68,
- 68, 13, 32, 33, 34, 70, 68, 13,
- 14, 15, 16, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 25, 26, 27,
- 68, 68, 68, 68, 68, 32, 33, 34,
- 70, 68, 14, 15, 16, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 32,
- 33, 34, 68, 15, 16, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 32,
- 33, 34, 68, 16, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 32, 33,
- 34, 68, 32, 33, 68, 33, 68, 14,
- 15, 16, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 25, 26, 27, 68,
- 68, 68, 68, 68, 32, 33, 34, 70,
- 68, 14, 15, 16, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 26,
- 27, 68, 68, 68, 68, 68, 32, 33,
- 34, 70, 68, 14, 15, 16, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 27, 68, 68, 68, 68, 68,
- 32, 33, 34, 70, 68, 14, 15, 16,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 32, 33, 34, 70, 68, 13,
- 14, 15, 16, 68, 68, 68, 68, 68,
- 68, 22, 23, 24, 68, 25, 26, 27,
- 68, 68, 68, 68, 13, 32, 33, 34,
- 70, 68, 13, 14, 15, 16, 68, 68,
- 68, 68, 68, 68, 68, 23, 24, 68,
- 25, 26, 27, 68, 68, 68, 68, 13,
- 32, 33, 34, 70, 68, 13, 14, 15,
- 16, 68, 68, 68, 68, 68, 68, 68,
- 68, 24, 68, 25, 26, 27, 68, 68,
- 68, 68, 13, 32, 33, 34, 70, 68,
- 12, 13, 14, 15, 16, 68, 18, 12,
- 68, 68, 68, 22, 23, 24, 68, 25,
- 26, 27, 68, 68, 68, 68, 13, 32,
- 33, 34, 70, 68, 12, 13, 14, 15,
- 16, 68, 68, 12, 68, 68, 68, 22,
- 23, 24, 68, 25, 26, 27, 68, 68,
- 68, 68, 13, 32, 33, 34, 70, 68,
- 12, 13, 14, 15, 16, 17, 18, 12,
- 68, 68, 68, 22, 23, 24, 68, 25,
- 26, 27, 68, 68, 68, 68, 13, 32,
- 33, 34, 70, 68, 1, 69, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 12,
- 13, 14, 15, 16, 17, 18, 12, 19,
- 68, 21, 22, 23, 24, 68, 25, 26,
- 27, 68, 68, 68, 68, 31, 32, 33,
- 34, 69, 68, 1, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 13, 14, 15, 16, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 25,
- 26, 27, 68, 68, 68, 68, 68, 32,
- 33, 34, 70, 68, 1, 71, 72, 68,
- 9, 68, 4, 68, 68, 68, 4, 68,
- 68, 68, 68, 68, 1, 69, 9, 68,
- 68, 68, 68, 68, 68, 68, 68, 12,
- 13, 14, 15, 16, 17, 18, 12, 19,
- 20, 21, 22, 23, 24, 68, 25, 26,
- 27, 68, 28, 29, 68, 31, 32, 33,
- 34, 69, 68, 1, 69, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 12, 13,
- 14, 15, 16, 17, 18, 12, 19, 20,
- 21, 22, 23, 24, 68, 25, 26, 27,
- 68, 68, 68, 68, 31, 32, 33, 34,
- 69, 68, 28, 29, 68, 29, 68, 4,
- 71, 71, 71, 4, 71, 74, 73, 35,
- 73, 35, 74, 73, 74, 73, 35, 73,
- 36, 73, 0
+static const signed char _use_syllable_machine_index_defaults[] = {
+ 0, 0, 6, 38, 38, 60, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 62, 38, 38, 38, 38, 38, 38, 38,
+ 38, 60, 64, 66, 38, 68, 68, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 72, 69, 69, 69, 69,
+ 69, 69, 72, 74, 74, 74, 0
};
-static const char _use_syllable_machine_trans_targs[] = {
- 2, 31, 42, 2, 3, 2, 26, 28,
- 51, 52, 54, 29, 32, 33, 34, 35,
- 36, 46, 47, 48, 55, 49, 43, 44,
- 45, 39, 40, 41, 56, 57, 58, 50,
- 37, 38, 2, 59, 61, 2, 4, 5,
- 6, 7, 8, 9, 10, 21, 22, 23,
- 24, 18, 19, 20, 13, 14, 15, 25,
- 11, 12, 2, 2, 16, 2, 17, 2,
- 27, 2, 30, 2, 2, 0, 1, 2,
- 53, 2, 60
+static const signed char _use_syllable_machine_cond_targs[] = {
+ 2, 31, 42, 2, 2, 3, 2, 26,
+ 28, 51, 52, 54, 29, 32, 33, 34,
+ 35, 36, 46, 47, 48, 55, 49, 43,
+ 44, 45, 39, 40, 41, 56, 57, 58,
+ 50, 37, 38, 2, 59, 61, 2, 4,
+ 5, 6, 7, 8, 9, 10, 21, 22,
+ 23, 24, 18, 19, 20, 13, 14, 15,
+ 25, 11, 12, 2, 2, 16, 2, 17,
+ 2, 27, 2, 30, 2, 2, 0, 1,
+ 2, 53, 2, 60, 0
};
-static const char _use_syllable_machine_trans_actions[] = {
- 1, 2, 2, 5, 0, 6, 0, 0,
- 0, 0, 2, 0, 2, 2, 0, 0,
- 0, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 0, 0, 0, 2,
- 0, 0, 7, 0, 0, 8, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 9, 10, 0, 11, 0, 12,
- 0, 13, 0, 14, 15, 0, 0, 16,
- 0, 17, 0
+static const signed char _use_syllable_machine_cond_actions[] = {
+ 1, 2, 2, 0, 5, 0, 6, 0,
+ 0, 0, 0, 2, 0, 2, 2, 0,
+ 0, 0, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 0, 0,
+ 2, 0, 0, 7, 0, 0, 8, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 9, 10, 0, 11, 0,
+ 12, 0, 13, 0, 14, 15, 0, 0,
+ 16, 0, 17, 0, 0
};
-static const char _use_syllable_machine_to_state_actions[] = {
- 0, 0, 3, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 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 signed char _use_syllable_machine_to_state_actions[] = {
+ 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
};
-static const char _use_syllable_machine_from_state_actions[] = {
- 0, 0, 4, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 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 signed char _use_syllable_machine_from_state_actions[] = {
+ 0, 0, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
};
-static const short _use_syllable_machine_eof_trans[] = {
- 1, 1, 0, 38, 38, 60, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38,
- 62, 38, 38, 38, 38, 38, 38, 38,
- 38, 60, 64, 66, 38, 68, 68, 69,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 72, 69, 69, 69, 69,
- 69, 69, 72, 74, 74, 74
+static const signed char _use_syllable_machine_eof_trans[] = {
+ 1, 1, 4, 39, 39, 61, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39,
+ 63, 39, 39, 39, 39, 39, 39, 39,
+ 39, 61, 65, 67, 39, 69, 69, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 73, 70, 70, 70, 70,
+ 70, 70, 73, 75, 75, 75, 0
};
static const int use_syllable_machine_start = 2;
@@ -304,185 +352,376 @@ static const int use_syllable_machine_error = -1;
static const int use_syllable_machine_en_main = 2;
-#line 39 "hb-ot-shape-complex-use-machine.rl"
+#line 59 "hb-ot-shape-complex-use-machine.rl"
-#line 154 "hb-ot-shape-complex-use-machine.rl"
+#line 176 "hb-ot-shape-complex-use-machine.rl"
#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \
- for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
- info[i].syllable() = (syllable_serial << 4) | use_##syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
+HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %d..%d %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \
+ for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+ } HB_STMT_END
+
+
+template <typename Iter>
+struct machine_index_t :
+hb_iter_with_fallback_t<machine_index_t<Iter>,
+typename Iter::item_t>
+{
+ machine_index_t (const Iter& it) : it (it) {}
+ machine_index_t (const machine_index_t& o) : it (o.it) {}
+
+ static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
+ static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
+
+ typename Iter::item_t __item__ () const { return *it; }
+ typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; }
+ unsigned __len__ () const { return it.len (); }
+ void __next__ () { ++it; }
+ void __forward__ (unsigned n) { it += n; }
+ void __prev__ () { --it; }
+ void __rewind__ (unsigned n) { it -= n; }
+ void operator = (unsigned n)
+ { unsigned index = (*it).first; if (index < n) it += n - index; else if (index > n) it -= index - n; }
+ void operator = (const machine_index_t& o) { *this = (*o.it).first; }
+ bool operator == (const machine_index_t& o) const { return (*it).first == (*o.it).first; }
+ bool operator != (const machine_index_t& o) const { return !(*this == o); }
+
+ private:
+ Iter it;
+};
+struct
+{
+ template <typename Iter,
+ hb_requires (hb_is_iterable (Iter))>
+ machine_index_t<hb_iter_type<Iter>>
+ operator () (Iter&& it) const
+ { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); }
+}
+HB_FUNCOBJ (machine_index);
+
+
static bool
not_standard_default_ignorable (const hb_glyph_info_t &i)
-{ return !(i.use_category() == USE_O && _hb_glyph_info_is_default_ignorable (&i)); }
+{ return !(i.use_category() == USE(O) && _hb_glyph_info_is_default_ignorable (&i)); }
-static void
+static inline void
find_syllables_use (hb_buffer_t *buffer)
{
- hb_glyph_info_t *info = buffer->info;
- auto p =
- + hb_iter (info, buffer->len)
- | hb_enumerate
- | hb_filter ([] (const hb_glyph_info_t &i) { return not_standard_default_ignorable (i); },
- hb_second)
- | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
- {
- if (p.second.use_category() == USE_ZWNJ)
- for (unsigned i = p.first + 1; i < buffer->len; ++i)
- if (not_standard_default_ignorable (info[i]))
- return !_hb_glyph_info_is_unicode_mark (&info[i]);
- return true;
- })
- | hb_enumerate
- | machine_index
- ;
- auto pe = p + p.len ();
- auto eof = +pe;
- auto ts = +p;
- auto te = +p;
- unsigned int act HB_UNUSED;
- int cs;
-
-#line 355 "hb-ot-shape-complex-use-machine.hh"
+ hb_glyph_info_t *info = buffer->info;
+ auto p =
+ + hb_iter (info, buffer->len)
+ | hb_enumerate
+ | hb_filter ([] (const hb_glyph_info_t &i) { return not_standard_default_ignorable (i); },
+ hb_second)
+ | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
+ {
+ if (p.second.use_category() == USE(ZWNJ))
+ for (unsigned i = p.first + 1; i < buffer->len; ++i)
+ if (not_standard_default_ignorable (info[i]))
+ return !_hb_glyph_info_is_unicode_mark (&info[i]);
+ return true;
+ })
+ | hb_enumerate
+ | machine_index
+ ;
+ auto pe = p + p.len ();
+ auto eof = +pe;
+ auto ts = +p;
+ auto te = +p;
+ unsigned int act HB_UNUSED;
+ int cs;
+
+#line 443 "hb-ot-shape-complex-use-machine.hh"
{
- cs = use_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
+ cs = (int)use_syllable_machine_start;
+ ts = 0;
+ te = 0;
}
-
-#line 198 "hb-ot-shape-complex-use-machine.rl"
-
-
- unsigned int syllable_serial = 1;
-
-#line 368 "hb-ot-shape-complex-use-machine.hh"
+
+#line 260 "hb-ot-shape-complex-use-machine.rl"
+
+
+ unsigned int syllable_serial = 1;
+
+#line 455 "hb-ot-shape-complex-use-machine.hh"
{
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _use_syllable_machine_from_state_actions[cs] ) {
- case 4:
+ unsigned int _trans = 0;
+ const unsigned char * _keys;
+ const signed char * _inds;
+ int _ic;
+ _resume: {}
+ if ( p == pe && p != eof )
+ goto _out;
+ switch ( _use_syllable_machine_from_state_actions[cs] ) {
+ case 4: {
+ {
#line 1 "NONE"
- {ts = p;}
- break;
-#line 382 "hb-ot-shape-complex-use-machine.hh"
- }
-
- _keys = _use_syllable_machine_trans_keys + (cs<<1);
- _inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
-
- _slen = _use_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( (*p).second.second.use_category()) &&
- ( (*p).second.second.use_category()) <= _keys[1] ?
- ( (*p).second.second.use_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _use_syllable_machine_trans_targs[_trans];
-
- if ( _use_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _use_syllable_machine_trans_actions[_trans] ) {
- case 2:
+ {ts = p;}}
+
+#line 470 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ }
+
+ if ( p == eof ) {
+ if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = (unsigned int)_use_syllable_machine_eof_trans[cs] - 1;
+ }
+ }
+ else {
+ _keys = ( _use_syllable_machine_trans_keys + ((cs<<1)));
+ _inds = ( _use_syllable_machine_indicies + (_use_syllable_machine_index_offsets[cs]));
+
+ if ( ((*p).second.second.use_category()) <= 52 ) {
+ _ic = (int)_use_syllable_machine_char_class[(int)((*p).second.second.use_category()) - 0];
+ if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) )
+ _trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) ));
+ else
+ _trans = (unsigned int)_use_syllable_machine_index_defaults[cs];
+ }
+ else {
+ _trans = (unsigned int)_use_syllable_machine_index_defaults[cs];
+ }
+
+ }
+ cs = (int)_use_syllable_machine_cond_targs[_trans];
+
+ if ( _use_syllable_machine_cond_actions[_trans] != 0 ) {
+
+ switch ( _use_syllable_machine_cond_actions[_trans] ) {
+ case 2: {
+ {
#line 1 "NONE"
- {te = p+1;}
- break;
- case 5:
-#line 141 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (independent_cluster); }}
- break;
- case 9:
-#line 144 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (standard_cluster); }}
- break;
- case 7:
-#line 149 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (broken_cluster); }}
- break;
- case 6:
-#line 150 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (non_cluster); }}
- break;
- case 10:
-#line 142 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (virama_terminated_cluster); }}
- break;
- case 11:
-#line 143 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (sakot_terminated_cluster); }}
- break;
- case 8:
-#line 144 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (standard_cluster); }}
- break;
- case 13:
-#line 145 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
- break;
- case 12:
-#line 146 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (numeral_cluster); }}
- break;
- case 14:
-#line 147 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (symbol_cluster); }}
- break;
- case 17:
-#line 148 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (hieroglyph_cluster); }}
- break;
- case 15:
-#line 149 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (broken_cluster); }}
- break;
- case 16:
-#line 150 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (non_cluster); }}
- break;
- case 1:
-#line 149 "hb-ot-shape-complex-use-machine.rl"
- {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
- break;
-#line 460 "hb-ot-shape-complex-use-machine.hh"
- }
-
-_again:
- switch ( _use_syllable_machine_to_state_actions[cs] ) {
- case 3:
+ {te = p+1;}}
+
+#line 508 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 5: {
+ {
+#line 163 "hb-ot-shape-complex-use-machine.rl"
+ {te = p+1;{
+#line 163 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_independent_cluster); }
+ }}
+
+#line 521 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 9: {
+ {
+#line 166 "hb-ot-shape-complex-use-machine.rl"
+ {te = p+1;{
+#line 166 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_standard_cluster); }
+ }}
+
+#line 534 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 7: {
+ {
+#line 171 "hb-ot-shape-complex-use-machine.rl"
+ {te = p+1;{
+#line 171 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_broken_cluster); }
+ }}
+
+#line 547 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 6: {
+ {
+#line 172 "hb-ot-shape-complex-use-machine.rl"
+ {te = p+1;{
+#line 172 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_non_cluster); }
+ }}
+
+#line 560 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 10: {
+ {
+#line 164 "hb-ot-shape-complex-use-machine.rl"
+ {te = p;p = p - 1;{
+#line 164 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_virama_terminated_cluster); }
+ }}
+
+#line 573 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 11: {
+ {
+#line 165 "hb-ot-shape-complex-use-machine.rl"
+ {te = p;p = p - 1;{
+#line 165 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_sakot_terminated_cluster); }
+ }}
+
+#line 586 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 8: {
+ {
+#line 166 "hb-ot-shape-complex-use-machine.rl"
+ {te = p;p = p - 1;{
+#line 166 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_standard_cluster); }
+ }}
+
+#line 599 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 13: {
+ {
+#line 167 "hb-ot-shape-complex-use-machine.rl"
+ {te = p;p = p - 1;{
+#line 167 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_number_joiner_terminated_cluster); }
+ }}
+
+#line 612 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 12: {
+ {
+#line 168 "hb-ot-shape-complex-use-machine.rl"
+ {te = p;p = p - 1;{
+#line 168 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_numeral_cluster); }
+ }}
+
+#line 625 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 14: {
+ {
+#line 169 "hb-ot-shape-complex-use-machine.rl"
+ {te = p;p = p - 1;{
+#line 169 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_symbol_cluster); }
+ }}
+
+#line 638 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 17: {
+ {
+#line 170 "hb-ot-shape-complex-use-machine.rl"
+ {te = p;p = p - 1;{
+#line 170 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_hieroglyph_cluster); }
+ }}
+
+#line 651 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 15: {
+ {
+#line 171 "hb-ot-shape-complex-use-machine.rl"
+ {te = p;p = p - 1;{
+#line 171 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_broken_cluster); }
+ }}
+
+#line 664 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 16: {
+ {
+#line 172 "hb-ot-shape-complex-use-machine.rl"
+ {te = p;p = p - 1;{
+#line 172 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_non_cluster); }
+ }}
+
+#line 677 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ case 1: {
+ {
+#line 171 "hb-ot-shape-complex-use-machine.rl"
+ {p = ((te))-1;
+ {
+#line 171 "hb-ot-shape-complex-use-machine.rl"
+ found_syllable (use_broken_cluster); }
+ }}
+
+#line 691 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ }
+
+ }
+
+ if ( p == eof ) {
+ if ( cs >= 2 )
+ goto _out;
+ }
+ else {
+ switch ( _use_syllable_machine_to_state_actions[cs] ) {
+ case 3: {
+ {
#line 1 "NONE"
- {ts = 0;}
- break;
-#line 469 "hb-ot-shape-complex-use-machine.hh"
+ {ts = 0;}}
+
+#line 711 "hb-ot-shape-complex-use-machine.hh"
+
+
+ break;
+ }
+ }
+
+ p += 1;
+ goto _resume;
+ }
+ _out: {}
}
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _use_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 203 "hb-ot-shape-complex-use-machine.rl"
-
+
+#line 265 "hb-ot-shape-complex-use-machine.rl"
+
}
#undef found_syllable
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh
index df3652b18a..a35894ce81 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh
@@ -31,56 +31,57 @@
* UnicodeData.txt does not have a header.
*/
-#include "hb.hh"
+#ifndef HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
+#define HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
-#ifndef HB_NO_OT_SHAPE
+#include "hb.hh"
-#include "hb-ot-shape-complex-use.hh"
+#include "hb-ot-shape-complex-use-machine.hh"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"
-#define B USE_B /* BASE */
-#define CS USE_CS /* CONS_WITH_STACKER */
-#define G USE_G /* HIEROGLYPH */
-#define GB USE_GB /* BASE_OTHER */
-#define H USE_H /* HALANT */
-#define HN USE_HN /* HALANT_NUM */
-#define HVM USE_HVM /* HALANT_OR_VOWEL_MODIFIER */
-#define J USE_J /* HIEROGLYPH_JOINER */
-#define N USE_N /* BASE_NUM */
-#define O USE_O /* OTHER */
-#define R USE_R /* REPHA */
-#define S USE_S /* SYM */
-#define SB USE_SB /* HIEROGLYPH_SEGMENT_BEGIN */
-#define SE USE_SE /* HIEROGLYPH_SEGMENT_END */
-#define SUB USE_SUB /* CONS_SUB */
-#define Sk USE_Sk /* SAKOT */
-#define ZWNJ USE_ZWNJ /* ZWNJ */
-#define CMAbv USE_CMAbv
-#define CMBlw USE_CMBlw
-#define FAbv USE_FAbv
-#define FBlw USE_FBlw
-#define FPst USE_FPst
-#define FMAbv USE_FMAbv
-#define FMBlw USE_FMBlw
-#define FMPst USE_FMPst
-#define MAbv USE_MAbv
-#define MBlw USE_MBlw
-#define MPst USE_MPst
-#define MPre USE_MPre
-#define SMAbv USE_SMAbv
-#define SMBlw USE_SMBlw
-#define VAbv USE_VAbv
-#define VBlw USE_VBlw
-#define VPst USE_VPst
-#define VPre USE_VPre
-#define VMAbv USE_VMAbv
-#define VMBlw USE_VMBlw
-#define VMPst USE_VMPst
-#define VMPre USE_VMPre
+#define B USE(B) /* BASE */
+#define CS USE(CS) /* CONS_WITH_STACKER */
+#define G USE(G) /* HIEROGLYPH */
+#define GB USE(GB) /* BASE_OTHER */
+#define H USE(H) /* HALANT */
+#define HN USE(HN) /* HALANT_NUM */
+#define HVM USE(HVM) /* HALANT_OR_VOWEL_MODIFIER */
+#define J USE(J) /* HIEROGLYPH_JOINER */
+#define N USE(N) /* BASE_NUM */
+#define O USE(O) /* OTHER */
+#define R USE(R) /* REPHA */
+#define S USE(S) /* SYM */
+#define SB USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */
+#define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */
+#define SUB USE(SUB) /* CONS_SUB */
+#define Sk USE(Sk) /* SAKOT */
+#define ZWNJ USE(ZWNJ) /* ZWNJ */
+#define CMAbv USE(CMAbv)
+#define CMBlw USE(CMBlw)
+#define FAbv USE(FAbv)
+#define FBlw USE(FBlw)
+#define FPst USE(FPst)
+#define FMAbv USE(FMAbv)
+#define FMBlw USE(FMBlw)
+#define FMPst USE(FMPst)
+#define MAbv USE(MAbv)
+#define MBlw USE(MBlw)
+#define MPst USE(MPst)
+#define MPre USE(MPre)
+#define SMAbv USE(SMAbv)
+#define SMBlw USE(SMBlw)
+#define VAbv USE(VAbv)
+#define VBlw USE(VBlw)
+#define VPst USE(VPst)
+#define VPre USE(VPre)
+#define VMAbv USE(VMAbv)
+#define VMBlw USE(VMBlw)
+#define VMPst USE(VMPst)
+#define VMPre USE(VMPre)
#pragma GCC diagnostic pop
-static const USE_TABLE_ELEMENT_TYPE use_table[] = {
+static const uint8_t use_table[] = {
#define use_offset_0x0028u 0
@@ -767,7 +768,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11710 */ B, B, B, B, B, B, B, B, B, B, B, O, O, MBlw, MPre, MAbv,
- /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VMAbv, O, O, O, O,
+ /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O,
/* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
#define use_offset_0x11800u 5848
@@ -1066,7 +1067,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
}; /* Table items: 8824; occupancy: 79% */
-USE_TABLE_ELEMENT_TYPE
+static inline uint8_t
hb_use_get_category (hb_codepoint_t u)
{
switch (u >> 12)
@@ -1154,7 +1155,7 @@ hb_use_get_category (hb_codepoint_t u)
default:
break;
}
- return USE_O;
+ return USE(O);
}
#undef B
@@ -1198,5 +1199,5 @@ hb_use_get_category (hb_codepoint_t u)
#undef VMPre
-#endif
+#endif /* HB_OT_SHAPE_COMPLEX_USE_TABLE_HH */
/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc
index 8ac569d8bf..0d0b7e771e 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc
@@ -30,14 +30,12 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-use.hh"
+#include "hb-ot-shape-complex-use-machine.hh"
+#include "hb-ot-shape-complex-use-table.hh"
#include "hb-ot-shape-complex-arabic.hh"
#include "hb-ot-shape-complex-arabic-joining-list.hh"
#include "hb-ot-shape-complex-vowel-constraints.hh"
-/* buffer var allocations */
-#define use_category() complex_var_u8_1()
-
/*
* Universal Shaping Engine.
@@ -69,11 +67,11 @@ use_topographical_features[] =
};
/* Same order as use_topographical_features. */
enum joining_form_t {
- USE_ISOL,
- USE_INIT,
- USE_MEDI,
- USE_FINA,
- _USE_NONE
+ JOINING_FORM_ISOL,
+ JOINING_FORM_INIT,
+ JOINING_FORM_MEDI,
+ JOINING_FORM_FINA,
+ _JOINING_FORM_NONE
};
static const hb_tag_t
use_other_features[] =
@@ -186,22 +184,6 @@ data_destroy_use (void *data)
free (data);
}
-enum use_syllable_type_t {
- use_independent_cluster,
- use_virama_terminated_cluster,
- use_sakot_terminated_cluster,
- use_standard_cluster,
- use_number_joiner_terminated_cluster,
- use_numeral_cluster,
- use_symbol_cluster,
- use_hieroglyph_cluster,
- use_broken_cluster,
- use_non_cluster,
-};
-
-#include "hb-ot-shape-complex-use-machine.hh"
-
-
static void
setup_masks_use (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
@@ -239,7 +221,7 @@ setup_rphf_mask (const hb_ot_shape_plan_t *plan,
foreach_syllable (buffer, start, end)
{
- unsigned int limit = info[start].use_category() == USE_R ? 1 : hb_min (3u, end - start);
+ unsigned int limit = info[start].use_category() == USE(R) ? 1 : hb_min (3u, end - start);
for (unsigned int i = start; i < start + limit; i++)
info[i].mask |= mask;
}
@@ -253,7 +235,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
if (use_plan->arabic_plan)
return;
- static_assert ((USE_INIT < 4 && USE_ISOL < 4 && USE_MEDI < 4 && USE_FINA < 4), "");
+ static_assert ((JOINING_FORM_INIT < 4 && JOINING_FORM_ISOL < 4 && JOINING_FORM_MEDI < 4 && JOINING_FORM_FINA < 4), "");
hb_mask_t masks[4], all_masks = 0;
for (unsigned int i = 0; i < 4; i++)
{
@@ -267,7 +249,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
hb_mask_t other_masks = ~all_masks;
unsigned int last_start = 0;
- joining_form_t last_form = _USE_NONE;
+ joining_form_t last_form = _JOINING_FORM_NONE;
hb_glyph_info_t *info = buffer->info;
foreach_syllable (buffer, start, end)
{
@@ -279,7 +261,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
case use_hieroglyph_cluster:
case use_non_cluster:
/* These don't join. Nothing to do. */
- last_form = _USE_NONE;
+ last_form = _JOINING_FORM_NONE;
break;
case use_virama_terminated_cluster:
@@ -289,18 +271,18 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
case use_numeral_cluster:
case use_broken_cluster:
- bool join = last_form == USE_FINA || last_form == USE_ISOL;
+ bool join = last_form == JOINING_FORM_FINA || last_form == JOINING_FORM_ISOL;
if (join)
{
/* Fixup previous syllable's form. */
- last_form = last_form == USE_FINA ? USE_MEDI : USE_INIT;
+ last_form = last_form == JOINING_FORM_FINA ? JOINING_FORM_MEDI : JOINING_FORM_INIT;
for (unsigned int i = last_start; i < start; i++)
info[i].mask = (info[i].mask & other_masks) | masks[last_form];
}
/* Form for this syllable. */
- last_form = join ? USE_FINA : USE_ISOL;
+ last_form = join ? JOINING_FORM_FINA : JOINING_FORM_ISOL;
for (unsigned int i = start; i < end; i++)
info[i].mask = (info[i].mask & other_masks) | masks[last_form];
@@ -336,11 +318,11 @@ record_rphf_use (const hb_ot_shape_plan_t *plan,
foreach_syllable (buffer, start, end)
{
- /* Mark a substituted repha as USE_R. */
+ /* Mark a substituted repha as USE(R). */
for (unsigned int i = start; i < end && (info[i].mask & mask); i++)
if (_hb_glyph_info_substituted (&info[i]))
{
- info[i].use_category() = USE_R;
+ info[i].use_category() = USE(R);
break;
}
}
@@ -359,7 +341,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
for (unsigned int i = start; i < end; i++)
if (_hb_glyph_info_substituted (&info[i]))
{
- info[i].use_category() = USE_VPre;
+ info[i].use_category() = USE(VPre);
break;
}
}
@@ -368,7 +350,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
static inline bool
is_halant_use (const hb_glyph_info_t &info)
{
- return (info.use_category() == USE_H || info.use_category() == USE_HVM) &&
+ return (info.use_category() == USE(H) || info.use_category() == USE(HVM)) &&
!_hb_glyph_info_ligated (&info);
}
@@ -387,24 +369,24 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
hb_glyph_info_t *info = buffer->info;
-#define POST_BASE_FLAGS64 (FLAG64 (USE_FAbv) | \
- FLAG64 (USE_FBlw) | \
- FLAG64 (USE_FPst) | \
- FLAG64 (USE_MAbv) | \
- FLAG64 (USE_MBlw) | \
- FLAG64 (USE_MPst) | \
- FLAG64 (USE_MPre) | \
- FLAG64 (USE_VAbv) | \
- FLAG64 (USE_VBlw) | \
- FLAG64 (USE_VPst) | \
- FLAG64 (USE_VPre) | \
- FLAG64 (USE_VMAbv) | \
- FLAG64 (USE_VMBlw) | \
- FLAG64 (USE_VMPst) | \
- FLAG64 (USE_VMPre))
+#define POST_BASE_FLAGS64 (FLAG64 (USE(FAbv)) | \
+ FLAG64 (USE(FBlw)) | \
+ FLAG64 (USE(FPst)) | \
+ FLAG64 (USE(MAbv)) | \
+ FLAG64 (USE(MBlw)) | \
+ FLAG64 (USE(MPst)) | \
+ FLAG64 (USE(MPre)) | \
+ FLAG64 (USE(VAbv)) | \
+ FLAG64 (USE(VBlw)) | \
+ FLAG64 (USE(VPst)) | \
+ FLAG64 (USE(VPre)) | \
+ FLAG64 (USE(VMAbv)) | \
+ FLAG64 (USE(VMBlw)) | \
+ FLAG64 (USE(VMPst)) | \
+ FLAG64 (USE(VMPre)))
/* Move things forward. */
- if (info[start].use_category() == USE_R && end - start > 1)
+ if (info[start].use_category() == USE(R) && end - start > 1)
{
/* Got a repha. Reorder it towards the end, but before the first post-base
* glyph. */
@@ -441,7 +423,7 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
* shift things in between forward. */
j = i + 1;
}
- else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) &&
+ else if (((flag) & (FLAG (USE(VPre)) | FLAG (USE(VMPre)))) &&
/* Only move the first component of a MultipleSubst. */
0 == _hb_glyph_info_get_lig_comp (&info[i]) &&
j < i)
@@ -454,76 +436,22 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
}
}
-static inline void
-insert_dotted_circles_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
- if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
- return;
-
- /* Note: This loop is extra overhead, but should not be measurable.
- * TODO Use a buffer scratch flag to remove the loop. */
- bool has_broken_syllables = false;
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- if ((info[i].syllable() & 0x0F) == use_broken_cluster)
- {
- has_broken_syllables = true;
- break;
- }
- if (likely (!has_broken_syllables))
- return;
-
- hb_glyph_info_t dottedcircle = {0};
- if (!font->get_nominal_glyph (0x25CCu, &dottedcircle.codepoint))
- return;
- dottedcircle.use_category() = hb_use_get_category (0x25CC);
-
- buffer->clear_output ();
-
- buffer->idx = 0;
- unsigned int last_syllable = 0;
- while (buffer->idx < buffer->len && buffer->successful)
- {
- unsigned int syllable = buffer->cur().syllable();
- use_syllable_type_t syllable_type = (use_syllable_type_t) (syllable & 0x0F);
- if (unlikely (last_syllable != syllable && syllable_type == use_broken_cluster))
- {
- last_syllable = syllable;
-
- hb_glyph_info_t ginfo = dottedcircle;
- ginfo.cluster = buffer->cur().cluster;
- ginfo.mask = buffer->cur().mask;
- ginfo.syllable() = buffer->cur().syllable();
-
- /* Insert dottedcircle after possible Repha. */
- while (buffer->idx < buffer->len && buffer->successful &&
- last_syllable == buffer->cur().syllable() &&
- buffer->cur().use_category() == USE_R)
- buffer->next_glyph ();
-
- buffer->output_info (ginfo);
- }
- else
- buffer->next_glyph ();
- }
- buffer->swap_buffers ();
-}
-
static void
reorder_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
- if (buffer->message (font, "start reordering USE")) {
- insert_dotted_circles_use (plan, font, buffer);
+ if (buffer->message (font, "start reordering USE"))
+ {
+ hb_syllabic_insert_dotted_circles (font, buffer,
+ use_broken_cluster,
+ USE(B),
+ USE(R));
- foreach_syllable (buffer, start, end)
- reorder_syllable_use (buffer, start, end);
+ foreach_syllable (buffer, start, end)
+ reorder_syllable_use (buffer, start, end);
- (void) buffer->message (font, "end reordering USE");
+ (void) buffer->message (font, "end reordering USE");
}
HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.hh
deleted file mode 100644
index 788fb6b6ac..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.hh
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright © 2015 Mozilla Foundation.
- * Copyright © 2015 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_HH
-
-#include "hb.hh"
-
-
-#include "hb-ot-shape-complex.hh"
-
-
-#define USE_TABLE_ELEMENT_TYPE uint8_t
-
-/* Cateories used in the Universal Shaping Engine spec:
- * https://docs.microsoft.com/en-us/typography/script-development/use
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum use_category_t {
- USE_O = 0, /* OTHER */
-
- USE_B = 1, /* BASE */
- USE_N = 4, /* BASE_NUM */
- USE_GB = 5, /* BASE_OTHER */
- USE_SUB = 11, /* CONS_SUB */
- USE_H = 12, /* HALANT */
-
- USE_HN = 13, /* HALANT_NUM */
- USE_ZWNJ = 14, /* Zero width non-joiner */
- USE_R = 18, /* REPHA */
- USE_S = 19, /* SYM */
- USE_CS = 43, /* CONS_WITH_STACKER */
-
- /* https://github.com/harfbuzz/harfbuzz/issues/1102 */
- USE_HVM = 44, /* HALANT_OR_VOWEL_MODIFIER */
-
- USE_Sk = 48, /* SAKOT */
- USE_G = 49, /* HIEROGLYPH */
- USE_J = 50, /* HIEROGLYPH_JOINER */
- USE_SB = 51, /* HIEROGLYPH_SEGMENT_BEGIN */
- USE_SE = 52, /* HIEROGLYPH_SEGMENT_END */
-
- USE_FAbv = 24, /* CONS_FINAL_ABOVE */
- USE_FBlw = 25, /* CONS_FINAL_BELOW */
- USE_FPst = 26, /* CONS_FINAL_POST */
- USE_MAbv = 27, /* CONS_MED_ABOVE */
- USE_MBlw = 28, /* CONS_MED_BELOW */
- USE_MPst = 29, /* CONS_MED_POST */
- USE_MPre = 30, /* CONS_MED_PRE */
- USE_CMAbv = 31, /* CONS_MOD_ABOVE */
- USE_CMBlw = 32, /* CONS_MOD_BELOW */
- USE_VAbv = 33, /* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */
- USE_VBlw = 34, /* VOWEL_BELOW / VOWEL_BELOW_POST */
- USE_VPst = 35, /* VOWEL_POST UIPC = Right */
- USE_VPre = 22, /* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
- USE_VMAbv = 37, /* VOWEL_MOD_ABOVE */
- USE_VMBlw = 38, /* VOWEL_MOD_BELOW */
- USE_VMPst = 39, /* VOWEL_MOD_POST */
- USE_VMPre = 23, /* VOWEL_MOD_PRE */
- USE_SMAbv = 41, /* SYM_MOD_ABOVE */
- USE_SMBlw = 42, /* SYM_MOD_BELOW */
- USE_FMAbv = 45, /* CONS_FINAL_MOD UIPC = Top */
- USE_FMBlw = 46, /* CONS_FINAL_MOD UIPC = Bottom */
- USE_FMPst = 47, /* CONS_FINAL_MOD UIPC = Not_Applicable */
-};
-
-HB_INTERNAL USE_TABLE_ELEMENT_TYPE
-hb_use_get_category (hb_codepoint_t u);
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc
index 1af546e4fa..1037626998 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc
@@ -23,15 +23,15 @@
static void
_output_dotted_circle (hb_buffer_t *buffer)
{
- hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu);
- _hb_glyph_info_reset_continuation (&dottedcircle);
+ (void) buffer->output_glyph (0x25CCu);
+ _hb_glyph_info_reset_continuation (&buffer->prev());
}
static void
_output_with_dotted_circle (hb_buffer_t *buffer)
{
_output_dotted_circle (buffer);
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
}
void
@@ -51,7 +51,6 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
*
* https://github.com/harfbuzz/harfbuzz/issues/1019
*/
- bool processed = false;
buffer->clear_output ();
unsigned int count = buffer->len;
switch ((unsigned) buffer->props.script)
@@ -97,15 +96,14 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
buffer->idx + 2 < count &&
0x0907u == buffer->cur (2).codepoint)
{
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
matched = true;
}
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_BENGALI:
@@ -124,10 +122,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x09E2u == buffer->cur (1).codepoint;
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_GURMUKHI:
@@ -161,10 +158,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_GUJARATI:
@@ -186,10 +182,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x0ABEu == buffer->cur (1).codepoint;
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_ORIYA:
@@ -205,10 +200,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x0B57u == buffer->cur (1).codepoint;
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_TAMIL:
@@ -220,10 +214,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
{
matched = true;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_TELUGU:
@@ -244,10 +237,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x0C55u == buffer->cur (1).codepoint;
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_KANNADA:
@@ -263,10 +255,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x0CCCu == buffer->cur (1).codepoint;
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_MALAYALAM:
@@ -290,10 +281,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_SINHALA:
@@ -326,10 +316,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_BRAHMI:
@@ -348,10 +337,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x11042u == buffer->cur (1).codepoint;
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_KHUDAWADI:
@@ -370,10 +358,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_TIRHUTA:
@@ -397,10 +384,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_MODI:
@@ -418,10 +404,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
case HB_SCRIPT_TAKRI:
@@ -442,21 +427,15 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x116B2u == buffer->cur (1).codepoint;
break;
}
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer);
}
- processed = true;
break;
default:
break;
}
- if (processed)
- {
- if (buffer->idx < count)
- buffer->next_glyph ();
- buffer->swap_buffers ();
- }
+ buffer->swap_buffers ();
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh
index a1a7a6a47b..19e24b9f30 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh
@@ -35,8 +35,8 @@
/* buffer var allocations, used by complex shapers */
-#define complex_var_u8_0() var2.u8[2]
-#define complex_var_u8_1() var2.u8[3]
+#define complex_var_u8_category() var2.u8[2]
+#define complex_var_u8_auxiliary() var2.u8[3]
#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
@@ -186,27 +186,8 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_ARABIC:
/* Unicode-3.0 additions */
- case HB_SCRIPT_MONGOLIAN:
case HB_SCRIPT_SYRIAC:
- /* Unicode-5.0 additions */
- case HB_SCRIPT_NKO:
- case HB_SCRIPT_PHAGS_PA:
-
- /* Unicode-6.0 additions */
- case HB_SCRIPT_MANDAIC:
-
- /* Unicode-7.0 additions */
- case HB_SCRIPT_MANICHAEAN:
- case HB_SCRIPT_PSALTER_PAHLAVI:
-
- /* Unicode-9.0 additions */
- case HB_SCRIPT_ADLAM:
-
- /* Unicode-11.0 additions */
- case HB_SCRIPT_HANIFI_ROHINGYA:
- case HB_SCRIPT_SOGDIAN:
-
/* For Arabic script, use the Arabic shaper even if no OT script tag was found.
* This is because we do fallback shaping for Arabic script (and not others).
* But note that Arabic shaping is applicable only to horizontal layout; for
@@ -284,8 +265,9 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
return &_hb_ot_complex_shaper_myanmar;
- /* https://github.com/harfbuzz/harfbuzz/issues/1162 */
+#define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g'))
case HB_SCRIPT_MYANMAR_ZAWGYI:
+ /* https://github.com/harfbuzz/harfbuzz/issues/1162 */
return &_hb_ot_complex_shaper_myanmar_zawgyi;
@@ -294,7 +276,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_TIBETAN:
/* Unicode-3.0 additions */
- //case HB_SCRIPT_MONGOLIAN:
+ case HB_SCRIPT_MONGOLIAN:
//case HB_SCRIPT_SINHALA:
/* Unicode-3.2 additions */
@@ -315,8 +297,8 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-5.0 additions */
case HB_SCRIPT_BALINESE:
- //case HB_SCRIPT_NKO:
- //case HB_SCRIPT_PHAGS_PA:
+ case HB_SCRIPT_NKO:
+ case HB_SCRIPT_PHAGS_PA:
/* Unicode-5.1 additions */
case HB_SCRIPT_CHAM:
@@ -337,7 +319,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-6.0 additions */
case HB_SCRIPT_BATAK:
case HB_SCRIPT_BRAHMI:
- //case HB_SCRIPT_MANDAIC:
+ case HB_SCRIPT_MANDAIC:
/* Unicode-6.1 additions */
case HB_SCRIPT_CHAKMA:
@@ -351,10 +333,10 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_KHOJKI:
case HB_SCRIPT_KHUDAWADI:
case HB_SCRIPT_MAHAJANI:
- //case HB_SCRIPT_MANICHAEAN:
+ case HB_SCRIPT_MANICHAEAN:
case HB_SCRIPT_MODI:
case HB_SCRIPT_PAHAWH_HMONG:
- //case HB_SCRIPT_PSALTER_PAHLAVI:
+ case HB_SCRIPT_PSALTER_PAHLAVI:
case HB_SCRIPT_SIDDHAM:
case HB_SCRIPT_TIRHUTA:
@@ -363,7 +345,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_MULTANI:
/* Unicode-9.0 additions */
- //case HB_SCRIPT_ADLAM:
+ case HB_SCRIPT_ADLAM:
case HB_SCRIPT_BHAIKSUKI:
case HB_SCRIPT_MARCHEN:
case HB_SCRIPT_NEWA:
@@ -376,11 +358,11 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-11.0 additions */
case HB_SCRIPT_DOGRA:
case HB_SCRIPT_GUNJALA_GONDI:
- //case HB_SCRIPT_HANIFI_ROHINGYA:
+ case HB_SCRIPT_HANIFI_ROHINGYA:
case HB_SCRIPT_MAKASAR:
case HB_SCRIPT_MEDEFAIDRIN:
case HB_SCRIPT_OLD_SOGDIAN:
- //case HB_SCRIPT_SOGDIAN:
+ case HB_SCRIPT_SOGDIAN:
/* Unicode-12.0 additions */
case HB_SCRIPT_ELYMAIC:
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
index 3eabae1b45..778b5b8bd8 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
@@ -101,8 +101,9 @@ set_glyph (hb_glyph_info_t &info, hb_font_t *font)
static inline void
output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph)
{
+ /* This is very confusing indeed. */
buffer->cur().glyph_index() = glyph;
- buffer->output_glyph (unichar); /* This is very confusing indeed. */
+ (void) buffer->output_glyph (unichar);
_hb_glyph_info_set_unicode_props (&buffer->prev(), buffer);
}
@@ -110,7 +111,7 @@ static inline void
next_char (hb_buffer_t *buffer, hb_codepoint_t glyph)
{
buffer->cur().glyph_index() = glyph;
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
}
static inline void
@@ -229,30 +230,35 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c,
if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
{
hb_codepoint_t unicode = buffer->cur().codepoint;
- buffer->replace_glyphs (2, 1, &unicode);
+ (void) buffer->replace_glyphs (2, 1, &unicode);
}
else
{
/* Just pass on the two characters separately, let GSUB do its magic. */
set_glyph (buffer->cur(), font);
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
set_glyph (buffer->cur(), font);
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
}
/* Skip any further variation selectors. */
- while (buffer->idx < end && unlikely (buffer->unicode->is_variation_selector (buffer->cur().codepoint)))
+ while (buffer->idx < end &&
+ buffer->successful &&
+ unlikely (buffer->unicode->is_variation_selector (buffer->cur().codepoint)))
{
set_glyph (buffer->cur(), font);
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
}
- } else {
+ }
+ else
+ {
set_glyph (buffer->cur(), font);
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
}
}
- if (likely (buffer->idx < end)) {
+ if (likely (buffer->idx < end))
+ {
set_glyph (buffer->cur(), font);
- buffer->next_glyph ();
+ (void) buffer->next_glyph ();
}
}
@@ -348,7 +354,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
sizeof (buffer->info[0]),
&buffer->cur().glyph_index(),
sizeof (buffer->info[0]));
- buffer->next_glyphs (done);
+ if (unlikely (!buffer->next_glyphs (done))) break;
}
while (buffer->idx < end && buffer->successful)
decompose_current_character (&c, might_short_circuit);
@@ -419,6 +425,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
/* Third round, recompose */
if (!all_simple &&
+ buffer->successful &&
(mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS ||
mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT))
{
@@ -428,8 +435,8 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
buffer->clear_output ();
count = buffer->len;
unsigned int starter = 0;
- buffer->next_glyph ();
- while (buffer->idx < count && buffer->successful)
+ (void) buffer->next_glyph ();
+ while (buffer->idx < count /* No need for: && buffer->successful */)
{
hb_codepoint_t composed, glyph;
if (/* We don't try to compose a non-mark character with it's preceding starter.
@@ -451,9 +458,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
font->get_nominal_glyph (composed, &glyph))
{
/* Composes. */
- buffer->next_glyph (); /* Copy to out-buffer. */
- if (unlikely (!buffer->successful))
- return;
+ if (unlikely (!buffer->next_glyph ())) break; /* Copy to out-buffer. */
buffer->merge_out_clusters (starter, buffer->out_len);
buffer->out_len--; /* Remove the second composable. */
/* Modify starter and carry on. */
@@ -466,7 +471,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
}
/* Blocked, or doesn't compose. */
- buffer->next_glyph ();
+ if (unlikely (!buffer->next_glyph ())) break;
if (info_cc (buffer->prev()) == 0)
starter = buffer->out_len - 1;
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc
index 7d90558458..86ab0b4268 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc
@@ -534,9 +534,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
hb_glyph_info_t info = dottedcircle;
info.cluster = buffer->cur().cluster;
info.mask = buffer->cur().mask;
- buffer->output_info (info);
- while (buffer->idx < buffer->len && buffer->successful)
- buffer->next_glyph ();
+ (void) buffer->output_info (info);
buffer->swap_buffers ();
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.h b/thirdparty/harfbuzz/src/hb-ot-shape.h
index 7b1bcc0637..afdff72833 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape.h
+++ b/thirdparty/harfbuzz/src/hb-ot-shape.h
@@ -24,7 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_H_IN
+#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead."
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
index f1c391cf0e..87830b5462 100644
--- a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
@@ -6,8 +6,8 @@
*
* on files with these headers:
*
- * <meta name="updated_at" content="2020-11-17 08:21 AM" />
- * File-Date: 2020-09-29
+ * <meta name="updated_at" content="2021-02-12 04:08 PM" />
+ * File-Date: 2021-03-05
*/
#ifndef HB_OT_TAG_TABLE_HH
@@ -169,6 +169,7 @@ static const LangTag ot_languages[] = {
{"bko", HB_TAG('B','M','L',' ')}, /* Kwa' -> Bamileke */
{"bla", HB_TAG('B','K','F',' ')}, /* Siksika -> Blackfoot */
{"ble", HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe -> Balante */
+ {"blg", HB_TAG('I','B','A',' ')}, /* Balau (retired code) -> Iban */
{"bli", HB_TAG_NONE }, /* Bolia != Baluchi */
{"blk", HB_TAG('B','L','K',' ')}, /* Pa’o Karen */
{"blk", HB_TAG('K','R','N',' ')}, /* Pa'o Karen -> Karen */
@@ -358,6 +359,7 @@ static const LangTag ot_languages[] = {
{"czo", HB_TAG('Z','H','S',' ')}, /* Min Zhong Chinese -> Chinese, Simplified */
{"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin -> Chin */
{"da", HB_TAG('D','A','N',' ')}, /* Danish */
+/*{"dag", HB_TAG('D','A','G',' ')},*/ /* Dagbani */
{"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin -> Chin */
{"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) (retired code) */
/*{"dar", HB_TAG('D','A','R',' ')},*/ /* Dargwa */
@@ -834,6 +836,7 @@ static const LangTag ot_languages[] = {
{"lri", HB_TAG('L','U','H',' ')}, /* Marachi -> Luyia */
{"lrm", HB_TAG('L','U','H',' ')}, /* Marama -> Luyia */
{"lrt", HB_TAG('C','P','P',' ')}, /* Larantuka Malay -> Creoles */
+ {"lsb", HB_TAG_NONE }, /* Burundian Sign Language != Lower Sorbian */
{"lsm", HB_TAG('L','U','H',' ')}, /* Saamia -> Luyia */
{"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */
{"ltg", HB_TAG('L','V','I',' ')}, /* Latgalian -> Latvian */
@@ -990,7 +993,7 @@ static const LangTag ot_languages[] = {
/*{"nga", HB_TAG('N','G','A',' ')},*/ /* Ngbaka */
{"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */
{"ngm", HB_TAG('C','P','P',' ')}, /* Ngatik Men's Creole -> Creoles */
- {"ngo", HB_TAG('S','X','T',' ')}, /* Ngoni -> Sutu */
+ {"ngo", HB_TAG('S','X','T',' ')}, /* Ngoni (retired code) -> Sutu */
{"ngr", HB_TAG_NONE }, /* Engdewu != Nagari */
{"ngu", HB_TAG('N','A','H',' ')}, /* Guerrero Nahuatl -> Nahuatl */
{"nhc", HB_TAG('N','A','H',' ')}, /* Tabasco Nahuatl -> Nahuatl */
@@ -1520,6 +1523,8 @@ static const LangTag ot_languages[] = {
{"xmm", HB_TAG('C','P','P',' ')}, /* Manado Malay -> Creoles */
{"xmv", HB_TAG('M','L','G',' ')}, /* Antankarana Malagasy -> Malagasy */
{"xmw", HB_TAG('M','L','G',' ')}, /* Tsimihety Malagasy -> Malagasy */
+ {"xnj", HB_TAG('S','X','T',' ')}, /* Ngoni (Tanzania) -> Sutu */
+ {"xnq", HB_TAG('S','X','T',' ')}, /* Ngoni (Mozambique) -> Sutu */
{"xnr", HB_TAG('D','G','R',' ')}, /* Kangri -> Dogri (macrolanguage) */
/*{"xog", HB_TAG('X','O','G',' ')},*/ /* Soga */
{"xpe", HB_TAG('X','P','E',' ')}, /* Liberia Kpelle -> Kpelle (Liberia) */
@@ -2808,6 +2813,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("hnd", -1); /* Southern Hindko */
case HB_TAG('H','Y','E',' '): /* Armenian */
return hb_language_from_string ("hyw", -1); /* Western Armenian */
+ case HB_TAG('I','B','A',' '): /* Iban */
+ return hb_language_from_string ("iba", -1); /* Iban */
case HB_TAG('I','J','O',' '): /* Ijo */
return hb_language_from_string ("ijo", -1); /* Ijo [family] */
case HB_TAG('I','N','U',' '): /* Inuktitut */
@@ -2892,6 +2899,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("sq", -1); /* Albanian [macrolanguage] */
case HB_TAG('S','R','B',' '): /* Serbian */
return hb_language_from_string ("sr", -1); /* Serbian */
+ case HB_TAG('S','X','T',' '): /* Sutu */
+ return hb_language_from_string ("xnj", -1); /* Ngoni (Tanzania) */
case HB_TAG('S','Y','R',' '): /* Syriac */
return hb_language_from_string ("syr", -1); /* Syriac [macrolanguage] */
case HB_TAG('S','Y','R','E'): /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
diff --git a/thirdparty/harfbuzz/src/hb-ot-tag.cc b/thirdparty/harfbuzz/src/hb-ot-tag.cc
index 19bd3639d3..fc145a41f7 100644
--- a/thirdparty/harfbuzz/src/hb-ot-tag.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-tag.cc
@@ -164,6 +164,15 @@ hb_ot_all_tags_from_script (hb_script_t script,
*count = i;
}
+/**
+ * hb_ot_tag_to_script:
+ * @tag: a script tag
+ *
+ * Converts a script tag to an #hb_script_t.
+ *
+ * Return value: The #hb_script_t corresponding to @tag.
+ *
+ **/
hb_script_t
hb_ot_tag_to_script (hb_tag_t tag)
{
@@ -351,13 +360,13 @@ parse_private_use_subtag (const char *private_use_subtag,
* hb_ot_tags_from_script_and_language:
* @script: an #hb_script_t to convert.
* @language: an #hb_language_t to convert.
- * @script_count: (allow-none): maximum number of script tags to retrieve (IN)
+ * @script_count: (inout) (optional): maximum number of script tags to retrieve (IN)
* and actual number of script tags retrieved (OUT)
- * @script_tags: (out) (allow-none): array of size at least @script_count to store the
+ * @script_tags: (out) (optional): array of size at least @script_count to store the
* script tag results
- * @language_count: (allow-none): maximum number of language tags to retrieve
+ * @language_count: (inout) (optional): maximum number of language tags to retrieve
* (IN) and actual number of language tags retrieved (OUT)
- * @language_tags: (out) (allow-none): array of size at least @language_count to store
+ * @language_tags: (out) (optional): array of size at least @language_count to store
* the language tag results
*
* Converts an #hb_script_t and an #hb_language_t to script and language tags.
@@ -424,10 +433,12 @@ hb_ot_tags_from_script_and_language (hb_script_t script,
/**
* hb_ot_tag_to_language:
+ * @tag: an language tag
*
+ * Converts a language tag to an #hb_language_t.
*
- *
- * Return value: (transfer none):
+ * Return value: (transfer none) (nullable):
+ * The #hb_language_t corresponding to @tag.
*
* Since: 0.9.2
**/
@@ -478,9 +489,9 @@ hb_ot_tag_to_language (hb_tag_t tag)
* hb_ot_tags_to_script_and_language:
* @script_tag: a script tag
* @language_tag: a language tag
- * @script: (allow-none): the #hb_script_t corresponding to @script_tag (OUT).
- * @language: (allow-none): the #hb_language_t corresponding to @script_tag and
- * @language_tag (OUT).
+ * @script: (out) (optional): the #hb_script_t corresponding to @script_tag.
+ * @language: (out) (optional): the #hb_language_t corresponding to @script_tag and
+ * @language_tag.
*
* Converts a script tag and a language tag to an #hb_script_t and an
* #hb_language_t.
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
index 4d4e6dcae4..7e4eaaad95 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
@@ -652,8 +652,8 @@ no_more_gaps:
/* apply specified / inferred deltas to points */
for (unsigned int i = 0; i < points.length; i++)
{
- points[i].x += roundf (deltas[i].x);
- points[i].y += roundf (deltas[i].y);
+ points[i].x += deltas[i].x;
+ points[i].y += deltas[i].y;
}
} while (iterator.move_to_next ());
diff --git a/thirdparty/harfbuzz/src/hb-ot-var.cc b/thirdparty/harfbuzz/src/hb-ot-var.cc
index 1fe57383c0..6b42b45cd9 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-var.cc
@@ -56,7 +56,7 @@
*
* Tests whether a face includes any OpenType variation data in the `fvar` table.
*
- * Return value: true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 1.4.2
**/
@@ -87,7 +87,7 @@ hb_ot_var_get_axis_count (hb_face_t *face)
* hb_ot_var_get_axes:
* @face: #hb_face_t to work upon
* @start_offset: offset of the first lookup to retrieve
- * @axes_count: (inout) (allow-none): Input = the maximum number of variation axes to return;
+ * @axes_count: (inout) (optional): Input = the maximum number of variation axes to return;
* Output = the actual number of variation axes returned (may be zero)
* @axes_array: (out caller-allocates) (array length=axes_count): The array of variation axes found
*
@@ -133,7 +133,7 @@ hb_ot_var_find_axis (hb_face_t *face,
* hb_ot_var_get_axis_infos:
* @face: #hb_face_t to work upon
* @start_offset: offset of the first lookup to retrieve
- * @axes_count: (inout) (allow-none): Input = the maximum number of variation axes to return;
+ * @axes_count: (inout) (optional): Input = the maximum number of variation axes to return;
* Output = the actual number of variation axes returned (may be zero)
* @axes_array: (out caller-allocates) (array length=axes_count): The array of variation axes found
*
@@ -162,7 +162,7 @@ hb_ot_var_get_axis_infos (hb_face_t *face,
* Fetches the variation-axis information corresponding to the specified axis tag
* in the specified face.
*
- * Return value: true if data found, false otherwise
+ * Return value: %true if data found, %false otherwise
*
* Since: 2.2.0
**/
@@ -237,7 +237,7 @@ hb_ot_var_named_instance_get_postscript_name_id (hb_face_t *face,
* hb_ot_var_named_instance_get_design_coords:
* @face: The #hb_face_t to work on
* @instance_index: The index of the named instance to query
- * @coords_length: (inout) (allow-none): Input = the maximum number of coordinates to return;
+ * @coords_length: (inout) (optional): Input = the maximum number of coordinates to return;
* Output = the actual number of coordinates returned (may be zero)
* @coords: (out) (array length=coords_length): The array of coordinates found for the query
*
diff --git a/thirdparty/harfbuzz/src/hb-ot-var.h b/thirdparty/harfbuzz/src/hb-ot-var.h
index ef2ca0a716..ce201d3b4f 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var.h
+++ b/thirdparty/harfbuzz/src/hb-ot-var.h
@@ -24,7 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_H_IN
+#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead."
#endif
@@ -36,34 +36,38 @@
HB_BEGIN_DECLS
/**
- * hb_tag_t:
- * @HB_OT_TAG_VAR_AXIS_ITALIC: Registered tag for the roman/italic axis
+ * HB_OT_TAG_VAR_AXIS_ITALIC:
+ *
+ * Registered tag for the roman/italic axis.
*/
#define HB_OT_TAG_VAR_AXIS_ITALIC HB_TAG('i','t','a','l')
/**
- * hb_tag_t:
- * @HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE: Registered tag for the optical-size axis
+ * HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE:
*
+ * Registered tag for the optical-size axis.
* <note>Note: The optical-size axis supersedes the OpenType `size` feature.</note>
*/
#define HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE HB_TAG('o','p','s','z')
/**
- * hb_tag_t:
- * @HB_OT_TAG_VAR_AXIS_SLANT: Registered tag for the slant axis
+ * HB_OT_TAG_VAR_AXIS_SLANT:
+ *
+ * Registered tag for the slant axis
*/
#define HB_OT_TAG_VAR_AXIS_SLANT HB_TAG('s','l','n','t')
/**
- * hb_tag_t:
- * @HB_OT_TAG_VAR_AXIS_WIDTH: Registered tag for the width axis
+ * HB_OT_TAG_VAR_AXIS_WIDTH:
+ *
+ * Registered tag for the width axis.
*/
#define HB_OT_TAG_VAR_AXIS_WIDTH HB_TAG('w','d','t','h')
/**
- * hb_tag_t:
- * @HB_OT_TAG_VAR_AXIS_WEIGHT: Registered tag for the weight axis
+ * HB_OT_TAG_VAR_AXIS_WEIGHT:
+ *
+ * Registered tag for the weight axis.
*/
#define HB_OT_TAG_VAR_AXIS_WEIGHT HB_TAG('w','g','h','t')
@@ -88,11 +92,14 @@ hb_ot_var_get_axis_count (hb_face_t *face);
* hb_ot_var_axis_flags_t:
* @HB_OT_VAR_AXIS_FLAG_HIDDEN: The axis should not be exposed directly in user interfaces.
*
+ * Flags for #hb_ot_var_axis_info_t.
+ *
* Since: 2.2.0
*/
typedef enum { /*< flags >*/
HB_OT_VAR_AXIS_FLAG_HIDDEN = 0x00000001u,
+ /*< private >*/
_HB_OT_VAR_AXIS_FLAG_MAX_VALUE= HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_var_axis_flags_t;
diff --git a/thirdparty/harfbuzz/src/hb-sanitize.hh b/thirdparty/harfbuzz/src/hb-sanitize.hh
index 024b4d1c99..1675e8448a 100644
--- a/thirdparty/harfbuzz/src/hb-sanitize.hh
+++ b/thirdparty/harfbuzz/src/hb-sanitize.hh
@@ -73,7 +73,7 @@
* === The sanitize() contract ===
*
* The sanitize() method of each object type shall return true if it's safe to
- * call other methods of the object, and false otherwise.
+ * call other methods of the object, and %false otherwise.
*
* Note that what sanitize() checks for might align with what the specification
* describes as valid table data, but does not have to be. In particular, we
@@ -113,8 +113,8 @@
#ifndef HB_SANITIZE_MAX_OPS_MAX
#define HB_SANITIZE_MAX_OPS_MAX 0x3FFFFFFF
#endif
-#ifndef HB_SANITIZE_MAX_SUTABLES
-#define HB_SANITIZE_MAX_SUTABLES 0x4000
+#ifndef HB_SANITIZE_MAX_SUBTABLES
+#define HB_SANITIZE_MAX_SUBTABLES 0x4000
#endif
struct hb_sanitize_context_t :
@@ -139,7 +139,7 @@ struct hb_sanitize_context_t :
bool visit_subtables (unsigned count)
{
max_subtables += count;
- return max_subtables < HB_SANITIZE_MAX_SUTABLES;
+ return max_subtables < HB_SANITIZE_MAX_SUBTABLES;
}
private:
diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh
index 4566153a59..fe29bdf96e 100644
--- a/thirdparty/harfbuzz/src/hb-serialize.hh
+++ b/thirdparty/harfbuzz/src/hb-serialize.hh
@@ -256,10 +256,11 @@ struct hb_serialize_context_t
packed.push (obj);
- if (unlikely (packed.in_error ())) {
- // obj wasn't successfully added to packed, so clean it up otherwise it's
- // links will be leaked.
- propagate_error (packed);
+ if (unlikely (!propagate_error (packed)))
+ {
+ /* Obj wasn't successfully added to packed, so clean it up otherwise its
+ * links will be leaked. When we use constructor/destructors properly, we
+ * can remove these. */
obj->fini ();
return 0;
}
@@ -523,7 +524,7 @@ struct hb_serialize_context_t
template <typename T>
void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset)
{
- auto &off = * ((BEInt<T, sizeof (T)> *) (parent->head + link.position));
+ auto &off = * ((BEInt<T> *) (parent->head + link.position));
assert (0 == off);
check_assign (off, offset);
}
diff --git a/thirdparty/harfbuzz/src/hb-set.cc b/thirdparty/harfbuzz/src/hb-set.cc
index 3b4059ad32..86bf70034c 100644
--- a/thirdparty/harfbuzz/src/hb-set.cc
+++ b/thirdparty/harfbuzz/src/hb-set.cc
@@ -117,7 +117,7 @@ hb_set_destroy (hb_set_t *set)
* @set: A set
* @key: The user-data key to set
* @data: A pointer to the user data to set
- * @destroy: (optional): A callback to call when @data is not needed anymore
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the specified set.
@@ -162,7 +162,7 @@ hb_set_get_user_data (hb_set_t *set,
*
* Tests whether memory allocation for a set was successful.
*
- * Return value: %true if allocation succeeded, false otherwise
+ * Return value: %true if allocation succeeded, %false otherwise
*
* Since: 0.9.2
**/
@@ -183,6 +183,9 @@ hb_set_allocation_successful (const hb_set_t *set)
void
hb_set_clear (hb_set_t *set)
{
+ if (unlikely (hb_object_is_immutable (set)))
+ return;
+
set->clear ();
}
@@ -209,7 +212,7 @@ hb_set_is_empty (const hb_set_t *set)
*
* Tests whether @codepoint belongs to @set.
*
- * Return value: %true if @codepoint is in @set, false otherwise
+ * Return value: %true if @codepoint is in @set, %false otherwise
*
* Since: 0.9.2
**/
@@ -298,7 +301,7 @@ hb_set_del_range (hb_set_t *set,
* Tests whether @set and @other are equal (contain the same
* elements).
*
- * Return value: %TRUE if the two sets are equal, %FALSE otherwise.
+ * Return value: %true if the two sets are equal, %false otherwise.
*
* Since: 0.9.7
**/
@@ -316,7 +319,7 @@ hb_set_is_equal (const hb_set_t *set,
*
* Tests whether @set is a subset of @larger_set.
*
- * Return value: %TRUE if the @set is a subset of (or equal to) @larger_set, %FALSE otherwise.
+ * Return value: %true if the @set is a subset of (or equal to) @larger_set, %false otherwise.
*
* Since: 1.8.1
**/
@@ -447,7 +450,7 @@ hb_set_get_population (const hb_set_t *set)
*
* Finds the smallest element in the set.
*
- * Return value: minimum of @set, or %HB_SET_VALUE_INVALID if @set is empty.
+ * Return value: minimum of @set, or #HB_SET_VALUE_INVALID if @set is empty.
*
* Since: 0.9.7
**/
@@ -463,7 +466,7 @@ hb_set_get_min (const hb_set_t *set)
*
* Finds the largest element in the set.
*
- * Return value: maximum of @set, or %HB_SET_VALUE_INVALID if @set is empty.
+ * Return value: maximum of @set, or #HB_SET_VALUE_INVALID if @set is empty.
*
* Since: 0.9.7
**/
@@ -481,9 +484,9 @@ hb_set_get_max (const hb_set_t *set)
*
* Fetches the next element in @set that is greater than current value of @codepoint.
*
- * Set @codepoint to %HB_SET_VALUE_INVALID to get started.
+ * Set @codepoint to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a next value, false otherwise
+ * Return value: %true if there was a next value, %false otherwise
*
* Since: 0.9.2
**/
@@ -502,9 +505,9 @@ hb_set_next (const hb_set_t *set,
*
* Fetches the previous element in @set that is lower than current value of @codepoint.
*
- * Set @codepoint to %HB_SET_VALUE_INVALID to get started.
+ * Set @codepoint to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a previous value, false otherwise
+ * Return value: %true if there was a previous value, %false otherwise
*
* Since: 1.8.0
**/
@@ -525,9 +528,9 @@ hb_set_previous (const hb_set_t *set,
* Fetches the next consecutive range of elements in @set that
* are greater than current value of @last.
*
- * Set @last to %HB_SET_VALUE_INVALID to get started.
+ * Set @last to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a next range, false otherwise
+ * Return value: %true if there was a next range, %false otherwise
*
* Since: 0.9.7
**/
@@ -549,9 +552,9 @@ hb_set_next_range (const hb_set_t *set,
* Fetches the previous consecutive range of elements in @set that
* are greater than current value of @last.
*
- * Set @first to %HB_SET_VALUE_INVALID to get started.
+ * Set @first to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a previous range, false otherwise
+ * Return value: %true if there was a previous range, %false otherwise
*
* Since: 1.8.0
**/
diff --git a/thirdparty/harfbuzz/src/hb-set.h b/thirdparty/harfbuzz/src/hb-set.h
index cafc36dbad..0ad27f4bbd 100644
--- a/thirdparty/harfbuzz/src/hb-set.h
+++ b/thirdparty/harfbuzz/src/hb-set.h
@@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
@@ -36,7 +36,11 @@
HB_BEGIN_DECLS
-/*
+/**
+ * HB_SET_VALUE_INVALID:
+ *
+ * Unset #hb_set_t value.
+ *
* Since: 0.9.21
*/
#define HB_SET_VALUE_INVALID ((hb_codepoint_t) -1)
diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh
index b6e2086a2e..ae8b5eb10f 100644
--- a/thirdparty/harfbuzz/src/hb-set.hh
+++ b/thirdparty/harfbuzz/src/hb-set.hh
@@ -244,7 +244,7 @@ struct hb_set_t
bool resize (unsigned int count)
{
- if (unlikely (!successful)) return false;
+ if (unlikely (count > pages.length && !successful)) return false;
if (!pages.resize (count) || !page_map.resize (count))
{
pages.resize (page_map.length);
@@ -256,19 +256,14 @@ struct hb_set_t
void reset ()
{
- if (unlikely (hb_object_is_immutable (this)))
- return;
- clear ();
successful = true;
+ clear ();
}
void clear ()
{
- if (unlikely (hb_object_is_immutable (this)))
- return;
- population = 0;
- page_map.resize (0);
- pages.resize (0);
+ if (resize (0))
+ population = 0;
}
bool is_empty () const
{
@@ -278,6 +273,7 @@ struct hb_set_t
return false;
return true;
}
+ explicit operator bool () const { return !is_empty (); }
void dirty () { population = UINT_MAX; }
@@ -389,6 +385,11 @@ struct hb_set_t
{
if (ds <= de)
{
+ // Pre-allocate the workspace that compact() will need so we can bail on allocation failure
+ // before attempting to rewrite the page map.
+ hb_vector_t<unsigned> compact_workspace;
+ if (unlikely (!allocate_compact_workspace (compact_workspace))) return;
+
unsigned int write_index = 0;
for (unsigned int i = 0; i < page_map.length; i++)
{
@@ -396,11 +397,12 @@ struct hb_set_t
if (m < ds || de < m)
page_map[write_index++] = page_map[i];
}
- compact (write_index);
+ compact (compact_workspace, write_index);
resize (write_index);
}
}
+
public:
void del_range (hb_codepoint_t a, hb_codepoint_t b)
{
@@ -512,20 +514,37 @@ struct hb_set_t
return true;
}
- void compact (unsigned int length)
+ bool allocate_compact_workspace(hb_vector_t<unsigned>& workspace)
+ {
+ if (unlikely(!workspace.resize (pages.length)))
+ {
+ successful = false;
+ return false;
+ }
+
+ return true;
+ }
+
+
+ /*
+ * workspace should be a pre-sized vector allocated to hold at exactly pages.length
+ * elements.
+ */
+ void compact (hb_vector_t<unsigned>& workspace,
+ unsigned int length)
{
- hb_vector_t<uint32_t> old_index_to_page_map_index;
- old_index_to_page_map_index.resize(pages.length);
- for (uint32_t i = 0; i < old_index_to_page_map_index.length; i++)
- old_index_to_page_map_index[i] = 0xFFFFFFFF;
+ assert(workspace.length == pages.length);
+ hb_vector_t<unsigned>& old_index_to_page_map_index = workspace;
- for (uint32_t i = 0; i < length; i++)
+ hb_fill (old_index_to_page_map_index.writer(), 0xFFFFFFFF);
+ /* TODO(iter) Rewrite as dagger? */
+ for (unsigned i = 0; i < length; i++)
old_index_to_page_map_index[page_map[i].index] = i;
compact_pages (old_index_to_page_map_index);
}
- void compact_pages (const hb_vector_t<uint32_t>& old_index_to_page_map_index)
+ void compact_pages (const hb_vector_t<unsigned>& old_index_to_page_map_index)
{
unsigned int write_index = 0;
for (unsigned int i = 0; i < pages.length; i++)
@@ -543,6 +562,9 @@ struct hb_set_t
template <typename Op>
void process (const Op& op, const hb_set_t *other)
{
+ const bool passthru_left = op (1, 0);
+ const bool passthru_right = op (0, 1);
+
if (unlikely (!successful)) return;
dirty ();
@@ -554,11 +576,17 @@ struct hb_set_t
unsigned int count = 0, newCount = 0;
unsigned int a = 0, b = 0;
unsigned int write_index = 0;
+
+ // Pre-allocate the workspace that compact() will need so we can bail on allocation failure
+ // before attempting to rewrite the page map.
+ hb_vector_t<unsigned> compact_workspace;
+ if (!passthru_left && unlikely (!allocate_compact_workspace (compact_workspace))) return;
+
for (; a < na && b < nb; )
{
if (page_map[a].major == other->page_map[b].major)
{
- if (!Op::passthru_left)
+ if (!passthru_left)
{
// Move page_map entries that we're keeping from the left side set
// to the front of the page_map vector. This isn't necessary if
@@ -575,27 +603,27 @@ struct hb_set_t
}
else if (page_map[a].major < other->page_map[b].major)
{
- if (Op::passthru_left)
+ if (passthru_left)
count++;
a++;
}
else
{
- if (Op::passthru_right)
+ if (passthru_right)
count++;
b++;
}
}
- if (Op::passthru_left)
+ if (passthru_left)
count += na - a;
- if (Op::passthru_right)
+ if (passthru_right)
count += nb - b;
- if (!Op::passthru_left)
+ if (!passthru_left)
{
na = write_index;
next_page = write_index;
- compact (write_index);
+ compact (compact_workspace, write_index);
}
if (!resize (count))
@@ -619,7 +647,7 @@ struct hb_set_t
else if (page_map[a - 1].major > other->page_map[b - 1].major)
{
a--;
- if (Op::passthru_left)
+ if (passthru_left)
{
count--;
page_map[count] = page_map[a];
@@ -628,7 +656,7 @@ struct hb_set_t
else
{
b--;
- if (Op::passthru_right)
+ if (passthru_right)
{
count--;
page_map[count].major = other->page_map[b].major;
@@ -637,14 +665,14 @@ struct hb_set_t
}
}
}
- if (Op::passthru_left)
+ if (passthru_left)
while (a)
{
a--;
count--;
page_map[count] = page_map [a];
}
- if (Op::passthru_right)
+ if (passthru_right)
while (b)
{
b--;
@@ -655,6 +683,9 @@ struct hb_set_t
}
assert (!count);
if (pages.length > newCount)
+ // This resize() doesn't need to be checked because we can't get here
+ // if the set is currently in_error() and this only resizes downwards
+ // which will always succeed if the set is not in_error().
resize (newCount);
}
diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.cc b/thirdparty/harfbuzz/src/hb-shape-plan.cc
index 65a5fc4512..0d9eaddaa6 100644
--- a/thirdparty/harfbuzz/src/hb-shape-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-shape-plan.cc
@@ -329,12 +329,12 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
* @shape_plan: A shaping plan
* @key: The user-data key to set
* @data: A pointer to the user data
- * @destroy: (optional): A callback to call when @data is not needed anymore
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the given shaping plan.
*
- * Return value:
+ * Return value: %true if success, %false otherwise.
*
* Since: 0.9.7
**/
@@ -439,7 +439,7 @@ _hb_shape_plan_execute_internal (hb_shape_plan_t *shape_plan,
* Executes the given shaping plan on the specified buffer, using
* the given @font and @features.
*
- * Return value:
+ * Return value: %true if success, %false otherwise.
*
* Since: 0.9.7
**/
diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.h b/thirdparty/harfbuzz/src/hb-shape-plan.h
index 336524ee2f..fc7c041899 100644
--- a/thirdparty/harfbuzz/src/hb-shape-plan.h
+++ b/thirdparty/harfbuzz/src/hb-shape-plan.h
@@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
diff --git a/thirdparty/harfbuzz/src/hb-shape.cc b/thirdparty/harfbuzz/src/hb-shape.cc
index a3debce397..c442f4403b 100644
--- a/thirdparty/harfbuzz/src/hb-shape.cc
+++ b/thirdparty/harfbuzz/src/hb-shape.cc
@@ -111,10 +111,10 @@ hb_shape_list_shapers ()
* hb_shape_full:
* @font: an #hb_font_t to use for shaping
* @buffer: an #hb_buffer_t to shape
- * @features: (array length=num_features) (allow-none): an array of user
+ * @features: (array length=num_features) (nullable): an array of user
* specified #hb_feature_t or %NULL
* @num_features: the length of @features array
- * @shaper_list: (array zero-terminated=1) (allow-none): a %NULL-terminated
+ * @shaper_list: (array zero-terminated=1) (nullable): a %NULL-terminated
* array of shapers to use or %NULL
*
* See hb_shape() for details. If @shaper_list is not %NULL, the specified
@@ -146,7 +146,7 @@ hb_shape_full (hb_font_t *font,
* hb_shape:
* @font: an #hb_font_t to use for shaping
* @buffer: an #hb_buffer_t to shape
- * @features: (array length=num_features) (allow-none): an array of user
+ * @features: (array length=num_features) (nullable): an array of user
* specified #hb_feature_t or %NULL
* @num_features: the length of @features array
*
diff --git a/thirdparty/harfbuzz/src/hb-shape.h b/thirdparty/harfbuzz/src/hb-shape.h
index 39507ff744..922f8c011e 100644
--- a/thirdparty/harfbuzz/src/hb-shape.h
+++ b/thirdparty/harfbuzz/src/hb-shape.h
@@ -26,7 +26,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
diff --git a/thirdparty/harfbuzz/src/hb-style.cc b/thirdparty/harfbuzz/src/hb-style.cc
index 86b9f7da5f..2f45d119f9 100644
--- a/thirdparty/harfbuzz/src/hb-style.cc
+++ b/thirdparty/harfbuzz/src/hb-style.cc
@@ -65,6 +65,7 @@ typedef enum {
HB_STYLE_TAG_WIDTH = HB_TAG ('w','d','t','h'),
HB_STYLE_TAG_WEIGHT = HB_TAG ('w','g','h','t'),
+ /*< private >*/
_HB_STYLE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_style_tag_t;
diff --git a/thirdparty/harfbuzz/src/hb-style.h b/thirdparty/harfbuzz/src/hb-style.h
index 1209c79e94..f5776cee58 100644
--- a/thirdparty/harfbuzz/src/hb-style.h
+++ b/thirdparty/harfbuzz/src/hb-style.h
@@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc
index 24beada3e8..d055783a4d 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc
@@ -88,10 +88,17 @@ _gsub_closure_glyphs_lookups_features (hb_face_t *face,
&lookup_indices);
_remap_indexes (&lookup_indices, gsub_lookups);
- //closure features
+ // Collect and prune features
hb_set_t feature_indices;
- gsub->closure_features (gsub_lookups, &feature_indices);
+ hb_ot_layout_collect_features (face,
+ HB_OT_TAG_GSUB,
+ nullptr,
+ nullptr,
+ nullptr,
+ &feature_indices);
+ gsub->prune_features (gsub_lookups, &feature_indices);
_remap_indexes (&feature_indices, gsub_features);
+
gsub.destroy ();
}
@@ -114,9 +121,15 @@ _gpos_closure_lookups_features (hb_face_t *face,
&lookup_indices);
_remap_indexes (&lookup_indices, gpos_lookups);
- //closure features
+ // Collect and prune features
hb_set_t feature_indices;
- gpos->closure_features (gpos_lookups, &feature_indices);
+ hb_ot_layout_collect_features (face,
+ HB_OT_TAG_GPOS,
+ nullptr,
+ nullptr,
+ nullptr,
+ &feature_indices);
+ gpos->prune_features (gpos_lookups, &feature_indices);
_remap_indexes (&feature_indices, gpos_features);
gpos.destroy ();
}
@@ -243,7 +256,11 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
#ifndef HB_NO_VAR
if (close_over_gdef)
- _collect_layout_variation_indices (plan->source, plan->_glyphset, plan->gpos_lookups, plan->layout_variation_indices, plan->layout_variation_idx_map);
+ _collect_layout_variation_indices (plan->source,
+ plan->_glyphset_gsub,
+ plan->gpos_lookups,
+ plan->layout_variation_indices,
+ plan->layout_variation_idx_map);
#endif
#ifndef HB_NO_SUBSET_CFF
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh
index e9f603dd1d..cc9cb7a1a2 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh
@@ -172,12 +172,15 @@ struct hb_subset_plan_t
add_table (hb_tag_t tag,
hb_blob_t *contents)
{
- hb_blob_t *source_blob = source->reference_table (tag);
- DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes",
- HB_UNTAG(tag),
- hb_blob_get_length (contents),
- hb_blob_get_length (source_blob));
- hb_blob_destroy (source_blob);
+ if (HB_DEBUG_SUBSET)
+ {
+ hb_blob_t *source_blob = source->reference_table (tag);
+ DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes",
+ HB_UNTAG(tag),
+ hb_blob_get_length (contents),
+ hb_blob_get_length (source_blob));
+ hb_blob_destroy (source_blob);
+ }
return hb_face_builder_add_table (dest, tag, contents);
}
};
diff --git a/thirdparty/harfbuzz/src/hb-unicode.cc b/thirdparty/harfbuzz/src/hb-unicode.cc
index d7f6a6e130..7470bb1b6e 100644
--- a/thirdparty/harfbuzz/src/hb-unicode.cc
+++ b/thirdparty/harfbuzz/src/hb-unicode.cc
@@ -276,7 +276,7 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
* @ufuncs: The Unicode-functions structure
* @key: The user-data key
* @data: A pointer to the user data
- * @destroy: (optional): A callback to call when @data is not needed anymore
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the specified Unicode-functions structure.
@@ -340,7 +340,7 @@ hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
* Tests whether the specified Unicode-functions structure
* is immutable.
*
- * Return value: %true if @ufuncs is immutable, false otherwise
+ * Return value: %true if @ufuncs is immutable, %false otherwise
*
* Since: 0.9.2
**/
@@ -421,7 +421,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
* Calls the composition function of the specified
* Unicode-functions structure @ufuncs.
*
- * Return value: %true if @a and @b composed, false otherwise
+ * Return value: %true if @a and @b composed, %false otherwise
*
* Since: 0.9.2
**/
@@ -446,7 +446,7 @@ hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
* Calls the decomposition function of the specified
* Unicode-functions structure @ufuncs.
*
- * Return value: %true if @ab was decomposed, false otherwise
+ * Return value: %true if @ab was decomposed, %false otherwise
*
* Since: 0.9.2
**/
@@ -469,7 +469,7 @@ hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
* Fetches the compatibility decomposition of a Unicode
* code point. Deprecated.
*
- * Return value:
+ * Return value: length of @decomposed.
*
* Since: 0.9.2
* Deprecated: 2.0.0
diff --git a/thirdparty/harfbuzz/src/hb-unicode.h b/thirdparty/harfbuzz/src/hb-unicode.h
index 7ea0848c0f..c04ee15a09 100644
--- a/thirdparty/harfbuzz/src/hb-unicode.h
+++ b/thirdparty/harfbuzz/src/hb-unicode.h
@@ -28,7 +28,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
@@ -41,7 +41,9 @@ HB_BEGIN_DECLS
/**
- * HB_UNICODE_MAX
+ * HB_UNICODE_MAX:
+ *
+ * Maximum valid Unicode code point.
*
* Since: 1.9.0
**/
@@ -427,7 +429,7 @@ typedef hb_script_t (*hb_unicode_script_func_t) (hb_unicode_funcs_t *ufuncs,
* The method must return an #hb_bool_t indicating the success
* of the composition.
*
- * Return value: True is @a,@b composed, false otherwise
+ * Return value: %true is @a,@b composed, %false otherwise
*
**/
typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs,
@@ -451,7 +453,7 @@ typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs,
* output parameters (if successful). The method must return an
* #hb_bool_t indicating the success of the composition.
*
- * Return value: True if @ab decomposed, false otherwise
+ * Return value: %true if @ab decomposed, %false otherwise
*
**/
typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs,
@@ -467,7 +469,7 @@ typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs,
* @ufuncs: A Unicode-functions structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_unicode_combining_class_func_t.
*
@@ -483,7 +485,7 @@ hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs,
* @ufuncs: A Unicode-functions structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_unicode_general_category_func_t.
*
@@ -499,7 +501,7 @@ hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs,
* @ufuncs: A Unicode-functions structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_unicode_mirroring_func_t.
*
@@ -515,7 +517,7 @@ hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
* @ufuncs: A Unicode-functions structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_unicode_script_func_t.
*
@@ -531,7 +533,7 @@ hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs,
* @ufuncs: A Unicode-functions structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_unicode_compose_func_t.
*
@@ -547,7 +549,7 @@ hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs,
* @ufuncs: A Unicode-functions structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
- * @destroy: (optional): The function to call when @user_data is not needed anymore
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_unicode_decompose_func_t.
*
@@ -624,40 +626,12 @@ HB_EXTERN hb_script_t
hb_unicode_script (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
-/**
- * hb_unicode_compose:
- * @ufuncs: The Unicode-functions structure
- * @a: The first code point to compose
- * @b: The second code point to compose
- * @ab: (out): The composed code point
- *
- * Composes the code point sequence @a,@b by canonical equivalence into
- * code point @ab.
- *
- * Return value: True is @a,@b composed, false otherwise
- *
- * Since: 0.9.2
- **/
HB_EXTERN hb_bool_t
hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t a,
hb_codepoint_t b,
hb_codepoint_t *ab);
-/**
- * hb_unicode_decompose:
- * @ufuncs: The Unicode-functions structure
- * @ab: The code point to decompose
- * @a: (out): The first decomposed code point
- * @b: (out): The second decomposed code point
- *
- * Decomposes code point @ab by canonical equivalence, into code points
- * @a and @b.
- *
- * Return value: True if @ab decomposed, false otherwise
- *
- * Since: 0.9.2
- **/
HB_EXTERN hb_bool_t
hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t ab,
diff --git a/thirdparty/harfbuzz/src/hb-vector.hh b/thirdparty/harfbuzz/src/hb-vector.hh
index 079b94a6b4..13517a9c29 100644
--- a/thirdparty/harfbuzz/src/hb-vector.hh
+++ b/thirdparty/harfbuzz/src/hb-vector.hh
@@ -80,7 +80,12 @@ struct hb_vector_t
fini ();
}
- void reset () { resize (0); }
+ void reset ()
+ {
+ if (unlikely (in_error ()))
+ allocated = length; // Big hack!
+ resize (0);
+ }
hb_vector_t& operator = (const hb_vector_t &o)
{
@@ -181,7 +186,7 @@ struct hb_vector_t
/* Allocate for size but don't adjust length. */
bool alloc (unsigned int size)
{
- if (unlikely (allocated < 0))
+ if (unlikely (in_error ()))
return false;
if (likely (size <= (unsigned) allocated))
@@ -195,7 +200,7 @@ struct hb_vector_t
Type *new_array = nullptr;
bool overflows =
- (int) new_allocated < 0 ||
+ (int) in_error () ||
(new_allocated < (unsigned) allocated) ||
hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
if (likely (!overflows))
diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h
index da377b9df6..6db58c3f7c 100644
--- a/thirdparty/harfbuzz/src/hb-version.h
+++ b/thirdparty/harfbuzz/src/hb-version.h
@@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_H_IN
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead."
#endif
@@ -36,12 +36,41 @@
HB_BEGIN_DECLS
+/**
+ * HB_VERSION_MAJOR:
+ *
+ * The major component of the library version available at compile-time.
+ */
#define HB_VERSION_MAJOR 2
-#define HB_VERSION_MINOR 7
-#define HB_VERSION_MICRO 4
+/**
+ * HB_VERSION_MINOR:
+ *
+ * The minor component of the library version available at compile-time.
+ */
+#define HB_VERSION_MINOR 8
+/**
+ * HB_VERSION_MICRO:
+ *
+ * The micro component of the library version available at compile-time.
+ */
+#define HB_VERSION_MICRO 0
-#define HB_VERSION_STRING "2.7.4"
+/**
+ * HB_VERSION_STRING:
+ *
+ * A string literal containing the library version available at compile-time.
+ */
+#define HB_VERSION_STRING "2.8.0"
+/**
+ * HB_VERSION_ATLEAST:
+ * @major: the major component of the version number
+ * @minor: the minor component of the version number
+ * @micro: the micro component of the version number
+ *
+ * Tests the library version at compile-time against a minimum value,
+ * as three integer components.
+ */
#define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \
HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
diff --git a/thirdparty/harfbuzz/src/hb.hh b/thirdparty/harfbuzz/src/hb.hh
index 274a0e98db..18516581c7 100644
--- a/thirdparty/harfbuzz/src/hb.hh
+++ b/thirdparty/harfbuzz/src/hb.hh
@@ -62,7 +62,6 @@
/* Error. Should never happen. */
#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR
-#pragma GCC diagnostic error "-Wc++11-narrowing"
#pragma GCC diagnostic error "-Wcast-align"
#pragma GCC diagnostic error "-Wcast-function-type"
#pragma GCC diagnostic error "-Wdelete-non-virtual-dtor"
@@ -75,6 +74,7 @@
#pragma GCC diagnostic error "-Wmissing-braces"
#pragma GCC diagnostic error "-Wmissing-declarations"
#pragma GCC diagnostic error "-Wmissing-prototypes"
+#pragma GCC diagnostic error "-Wnarrowing"
#pragma GCC diagnostic error "-Wnested-externs"
#pragma GCC diagnostic error "-Wold-style-definition"
#pragma GCC diagnostic error "-Wpointer-arith"
@@ -126,6 +126,7 @@
#pragma GCC diagnostic ignored "-Wformat-zero-length"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang
+#pragma GCC diagnostic ignored "-Wrange-loop-analysis" // https://github.com/harfbuzz/harfbuzz/issues/2834
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#pragma GCC diagnostic ignored "-Wtype-limits"
#pragma GCC diagnostic ignored "-Wc++11-compat" // only gcc raises it
@@ -175,15 +176,15 @@
#include "hb-aat.h"
#define HB_AAT_H_IN
-#include <limits.h>
-#include <math.h>
-#include <float.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdarg.h>
+#include <cassert>
+#include <cfloat>
+#include <climits>
+#include <cmath>
+#include <cstdarg>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
#ifdef __MINGW32_VERSION
@@ -244,12 +245,8 @@ extern "C" void hb_free_impl(void *ptr);
#endif
#if defined(__GNUC__) && (__GNUC__ >= 3)
-#define HB_PURE_FUNC __attribute__((pure))
-#define HB_CONST_FUNC __attribute__((const))
#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
#else
-#define HB_PURE_FUNC
-#define HB_CONST_FUNC
#define HB_PRINTF_FUNC(format_idx, arg_idx)
#endif
#if defined(__GNUC__) && (__GNUC__ >= 4) || (__clang__)
@@ -394,7 +391,7 @@ extern "C" void hb_free_impl(void *ptr);
#endif
#ifndef HB_NO_ERRNO
-# include <errno.h>
+# include <cerrno>
#else
static int HB_UNUSED _hb_errno = 0;
# undef errno
@@ -440,181 +437,12 @@ static int HB_UNUSED _hb_errno = 0;
#define HB_STMT_START do
#define HB_STMT_END while (0)
-/* Static-assert as expression. */
-template <unsigned int cond> class hb_assert_constant_t;
-template <> class hb_assert_constant_t<1> {};
-#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
-
/* Lets assert int types. Saves trouble down the road. */
-static_assert ((sizeof (int8_t) == 1), "");
-static_assert ((sizeof (uint8_t) == 1), "");
-static_assert ((sizeof (int16_t) == 2), "");
-static_assert ((sizeof (uint16_t) == 2), "");
-static_assert ((sizeof (int32_t) == 4), "");
-static_assert ((sizeof (uint32_t) == 4), "");
-static_assert ((sizeof (int64_t) == 8), "");
-static_assert ((sizeof (uint64_t) == 8), "");
static_assert ((sizeof (hb_codepoint_t) == 4), "");
static_assert ((sizeof (hb_position_t) == 4), "");
static_assert ((sizeof (hb_mask_t) == 4), "");
static_assert ((sizeof (hb_var_int_t) == 4), "");
-#define HB_DELETE_COPY_ASSIGN(TypeName) \
- TypeName(const TypeName&) = delete; \
- void operator=(const TypeName&) = delete
-#define HB_DELETE_CREATE_COPY_ASSIGN(TypeName) \
- TypeName() = delete; \
- TypeName(const TypeName&) = delete; \
- void operator=(const TypeName&) = delete
-
-
-/* Flags */
-
-/* Enable bitwise ops on enums marked as flags_t */
-/* To my surprise, looks like the function resolver is happy to silently cast
- * one enum to another... So this doesn't provide the type-checking that I
- * originally had in mind... :(.
- *
- * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
- */
-#ifdef _MSC_VER
-# pragma warning(disable:4200)
-# pragma warning(disable:4800)
-#endif
-#define HB_MARK_AS_FLAG_T(T) \
- extern "C++" { \
- static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
- static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
- static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
- static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
- static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
- static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
- static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
- } \
- static_assert (true, "")
-
-/* Useful for set-operations on small enums.
- * For example, for testing "x ∈ {x1, x2, x3}" use:
- * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
- */
-#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
-#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
-#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
-#define FLAG64(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
-#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
-
-
-/* Size signifying variable-sized array */
-#ifndef HB_VAR_ARRAY
-#define HB_VAR_ARRAY 1
-#endif
-
-static inline float
-_hb_roundf (float x) { return floorf (x + .5f); }
-#define roundf(x) _hb_roundf(x)
-
-/* Endian swap, used in Windows related backends */
-static inline uint16_t hb_uint16_swap (const uint16_t v)
-{ return (v >> 8) | (v << 8); }
-static inline uint32_t hb_uint32_swap (const uint32_t v)
-{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
-
-/*
- * Big-endian integers. Here because fundamental.
- */
-
-template <typename Type, int Bytes> struct BEInt;
-
-template <typename Type>
-struct BEInt<Type, 1>
-{
- public:
- BEInt<Type, 1>& operator = (Type V)
- {
- v = V;
- return *this;
- }
- operator Type () const { return v; }
- private: uint8_t v;
-};
-template <typename Type>
-struct BEInt<Type, 2>
-{
- public:
- BEInt<Type, 2>& operator = (Type V)
- {
- v[0] = (V >> 8) & 0xFF;
- v[1] = (V ) & 0xFF;
- return *this;
- }
- operator Type () const
- {
-#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
- defined(__BYTE_ORDER) && \
- (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
- /* Spoon-feed the compiler a big-endian integer with alignment 1.
- * https://github.com/harfbuzz/harfbuzz/pull/1398 */
- struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- return __builtin_bswap16 (((packed_uint16_t *) this)->v);
-#else /* __BYTE_ORDER == __BIG_ENDIAN */
- return ((packed_uint16_t *) this)->v;
-#endif
-#endif
- return (v[0] << 8)
- + (v[1] );
- }
- private: uint8_t v[2];
-};
-template <typename Type>
-struct BEInt<Type, 3>
-{
- public:
- BEInt<Type, 3>& operator = (Type V)
- {
- v[0] = (V >> 16) & 0xFF;
- v[1] = (V >> 8) & 0xFF;
- v[2] = (V ) & 0xFF;
- return *this;
- }
- operator Type () const
- {
- return (v[0] << 16)
- + (v[1] << 8)
- + (v[2] );
- }
- private: uint8_t v[3];
-};
-template <typename Type>
-struct BEInt<Type, 4>
-{
- public:
- BEInt<Type, 4>& operator = (Type V)
- {
- v[0] = (V >> 24) & 0xFF;
- v[1] = (V >> 16) & 0xFF;
- v[2] = (V >> 8) & 0xFF;
- v[3] = (V ) & 0xFF;
- return *this;
- }
- operator Type () const
- {
- return (v[0] << 24)
- + (v[1] << 16)
- + (v[2] << 8)
- + (v[3] );
- }
- private: uint8_t v[4];
-};
-
-
-/*
- * For lack of a better place, put Zawgyi script hack here.
- * https://github.com/harfbuzz/harfbuzz/issues/1162
- */
-
-#define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g'))
-
/* Headers we include for everyone. Keep topologically sorted by dependency.
* They express dependency amongst themselves, but no other file should include
diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h
index e17bc7e306..610f5d1f50 100644
--- a/thirdparty/mbedtls/include/mbedtls/config.h
+++ b/thirdparty/mbedtls/include/mbedtls/config.h
@@ -1747,6 +1747,23 @@
//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT
/**
+ * \def MBEDTLS_TEST_HOOKS
+ *
+ * Enable features for invasive testing such as introspection functions and
+ * hooks for fault injection. This enables additional unit tests.
+ *
+ * Merely enabling this feature should not change the behavior of the product.
+ * It only adds new code, and new branching points where the default behavior
+ * is the same as when this feature is disabled.
+ * However, this feature increases the attack surface: there is an added
+ * risk of vulnerabilities, and more gadgets that can make exploits easier.
+ * Therefore this feature must never be enabled in production.
+ *
+ * Uncomment to enable invasive tests.
+ */
+//#define MBEDTLS_TEST_HOOKS
+
+/**
* \def MBEDTLS_THREADING_ALT
*
* Provide your own alternate threading implementation.
diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
index 278fbbbb7a..6c099adf4d 100644
--- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
+++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
@@ -214,6 +214,13 @@ typedef struct mbedtls_ctr_drbg_context
void *p_entropy; /*!< The context for the entropy function. */
#if defined(MBEDTLS_THREADING_C)
+ /* Invariant: the mutex is initialized if and only if f_entropy != NULL.
+ * This means that the mutex is initialized during the initial seeding
+ * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free().
+ *
+ * Note that this invariant may change without notice. Do not rely on it
+ * and do not access the mutex directly in application code.
+ */
mbedtls_threading_mutex_t mutex;
#endif
}
@@ -277,6 +284,15 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
* device.
*/
#endif
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note When Mbed TLS is built with threading support,
+ * after this function returns successfully,
+ * it is safe to call mbedtls_ctr_drbg_random()
+ * from multiple threads. Other operations, including
+ * reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
/**
* \param ctx The CTR_DRBG context to seed.
* It must have been initialized with
@@ -286,6 +302,8 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
* the same context unless you call
* mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()
* again first.
+ * After a failed call to mbedtls_ctr_drbg_seed(),
+ * you must call mbedtls_ctr_drbg_free().
* \param f_entropy The entropy callback, taking as arguments the
* \p p_entropy context, the buffer to fill, and the
* length of the buffer.
@@ -377,6 +395,11 @@ void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
* \brief This function reseeds the CTR_DRBG context, that is
* extracts data from the entropy source.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param ctx The CTR_DRBG context.
* \param additional Additional data to add to the state. Can be \c NULL.
* \param len The length of the additional data.
@@ -394,6 +417,11 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
/**
* \brief This function updates the state of the CTR_DRBG context.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param ctx The CTR_DRBG context.
* \param additional The data to update the state with. This must not be
* \c NULL unless \p add_len is \c 0.
@@ -417,6 +445,11 @@ int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param p_rng The CTR_DRBG context. This must be a pointer to a
* #mbedtls_ctr_drbg_context structure.
* \param output The buffer to fill.
@@ -445,8 +478,16 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
*
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
- *
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note When Mbed TLS is built with threading support,
+ * it is safe to call mbedtls_ctr_drbg_random()
+ * from multiple threads. Other operations, including
+ * reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
* \param p_rng The CTR_DRBG context. This must be a pointer to a
* #mbedtls_ctr_drbg_context structure.
* \param output The buffer to fill.
diff --git a/thirdparty/mbedtls/include/mbedtls/entropy.h b/thirdparty/mbedtls/include/mbedtls/entropy.h
index 1e1d3f56ec..1d6e9b821b 100644
--- a/thirdparty/mbedtls/include/mbedtls/entropy.h
+++ b/thirdparty/mbedtls/include/mbedtls/entropy.h
@@ -147,13 +147,15 @@ mbedtls_entropy_source_state;
*/
typedef struct mbedtls_entropy_context
{
- int accumulator_started;
+ int accumulator_started; /* 0 after init.
+ * 1 after the first update.
+ * -1 after free. */
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
mbedtls_sha512_context accumulator;
#else
mbedtls_sha256_context accumulator;
#endif
- int source_count;
+ int source_count; /* Number of entries used in source. */
mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES];
#if defined(MBEDTLS_HAVEGE_C)
mbedtls_havege_state havege_data;
diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
index 970c033c15..5718e187a9 100644
--- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
+++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
@@ -128,6 +128,14 @@ typedef struct mbedtls_hmac_drbg_context
void *p_entropy; /*!< context for the entropy function */
#if defined(MBEDTLS_THREADING_C)
+ /* Invariant: the mutex is initialized if and only if
+ * md_ctx->md_info != NULL. This means that the mutex is initialized
+ * during the initial seeding in mbedtls_hmac_drbg_seed() or
+ * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free().
+ *
+ * Note that this invariant may change without notice. Do not rely on it
+ * and do not access the mutex directly in application code.
+ */
mbedtls_threading_mutex_t mutex;
#endif
} mbedtls_hmac_drbg_context;
@@ -177,7 +185,17 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
* \note During the initial seeding, this function calls
* the entropy source to obtain a nonce
* whose length is half the entropy length.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note When Mbed TLS is built with threading support,
+ * after this function returns successfully,
+ * it is safe to call mbedtls_hmac_drbg_random()
+ * from multiple threads. Other operations, including
+ * reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
* \param ctx HMAC_DRBG context to be seeded.
* \param md_info MD algorithm to use for HMAC_DRBG.
* \param f_entropy The entropy callback, taking as arguments the
@@ -216,7 +234,17 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
*
* This function is meant for use in algorithms that need a pseudorandom
* input such as deterministic ECDSA.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note When Mbed TLS is built with threading support,
+ * after this function returns successfully,
+ * it is safe to call mbedtls_hmac_drbg_random()
+ * from multiple threads. Other operations, including
+ * reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
* \param ctx HMAC_DRBG context to be initialised.
* \param md_info MD algorithm to use for HMAC_DRBG.
* \param data Concatenation of the initial entropy string and
@@ -279,6 +307,11 @@ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
/**
* \brief This function updates the state of the HMAC_DRBG context.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param ctx The HMAC_DRBG context.
* \param additional The data to update the state with.
* If this is \c NULL, there is no additional data.
@@ -295,6 +328,11 @@ int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
* \brief This function reseeds the HMAC_DRBG context, that is
* extracts data from the entropy source.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param ctx The HMAC_DRBG context.
* \param additional Additional data to add to the state.
* If this is \c NULL, there is no additional data
@@ -320,6 +358,11 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
*
+ * \note This function is not thread-safe. It is not safe
+ * to call this function if another thread might be
+ * concurrently obtaining random numbers from the same
+ * context or updating or reseeding the same context.
+ *
* \param p_rng The HMAC_DRBG context. This must be a pointer to a
* #mbedtls_hmac_drbg_context structure.
* \param output The buffer to fill.
@@ -349,7 +392,16 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
*
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note When Mbed TLS is built with threading support,
+ * it is safe to call mbedtls_ctr_drbg_random()
+ * from multiple threads. Other operations, including
+ * reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
* \param p_rng The HMAC_DRBG context. This must be a pointer to a
* #mbedtls_hmac_drbg_context structure.
* \param output The buffer to fill.
diff --git a/thirdparty/mbedtls/include/mbedtls/net_sockets.h b/thirdparty/mbedtls/include/mbedtls/net_sockets.h
index 00fea7db19..c6e1a0270e 100644
--- a/thirdparty/mbedtls/include/mbedtls/net_sockets.h
+++ b/thirdparty/mbedtls/include/mbedtls/net_sockets.h
@@ -151,6 +151,7 @@ int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char
*
* \return 0 if successful, or one of:
* MBEDTLS_ERR_NET_SOCKET_FAILED,
+ * MBEDTLS_ERR_NET_UNKNOWN_HOST,
* MBEDTLS_ERR_NET_BIND_FAILED,
* MBEDTLS_ERR_NET_LISTEN_FAILED
*
@@ -170,6 +171,8 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
* can be NULL if client_ip is null
*
* \return 0 if successful, or
+ * MBEDTLS_ERR_NET_SOCKET_FAILED,
+ * MBEDTLS_ERR_NET_BIND_FAILED,
* MBEDTLS_ERR_NET_ACCEPT_FAILED, or
* MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small,
* MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to
@@ -182,6 +185,10 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
/**
* \brief Check and wait for the context to be ready for read/write
*
+ * \note The current implementation of this function uses
+ * select() and returns an error if the file descriptor
+ * is \c FD_SETSIZE or greater.
+ *
* \param ctx Socket to check
* \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and
* MBEDTLS_NET_POLL_WRITE specifying the events
@@ -263,16 +270,21 @@ int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len );
* 'timeout' seconds. If no error occurs, the actual amount
* read is returned.
*
+ * \note The current implementation of this function uses
+ * select() and returns an error if the file descriptor
+ * is \c FD_SETSIZE or greater.
+ *
* \param ctx Socket
* \param buf The buffer to write to
* \param len Maximum length of the buffer
* \param timeout Maximum number of milliseconds to wait for data
* 0 means no timeout (wait forever)
*
- * \return the number of bytes received,
- * or a non-zero error code:
- * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out,
+ * \return The number of bytes received if successful.
+ * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out.
* MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal.
+ * Another negative error code (MBEDTLS_ERR_NET_xxx)
+ * for other failures.
*
* \note This function will block (until data becomes available or
* timeout is reached) even if the socket is set to
diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h
index 188c37cf3a..b2f65334fe 100644
--- a/thirdparty/mbedtls/include/mbedtls/rsa.h
+++ b/thirdparty/mbedtls/include/mbedtls/rsa.h
@@ -124,7 +124,10 @@ extern "C" {
*/
typedef struct mbedtls_rsa_context
{
- int ver; /*!< Always 0.*/
+ int ver; /*!< Reserved for internal purposes.
+ * Do not set this field in application
+ * code. Its meaning might change without
+ * notice. */
size_t len; /*!< The size of \p N in Bytes. */
mbedtls_mpi N; /*!< The public modulus. */
@@ -154,6 +157,7 @@ typedef struct mbedtls_rsa_context
mask generating function used in the
EME-OAEP and EMSA-PSS encodings. */
#if defined(MBEDTLS_THREADING_C)
+ /* Invariant: the mutex is initialized iff ver != 0. */
mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */
#endif
}
diff --git a/thirdparty/mbedtls/include/mbedtls/threading.h b/thirdparty/mbedtls/include/mbedtls/threading.h
index a8183a6ef4..45161ce467 100644
--- a/thirdparty/mbedtls/include/mbedtls/threading.h
+++ b/thirdparty/mbedtls/include/mbedtls/threading.h
@@ -73,6 +73,9 @@ extern "C" {
typedef struct mbedtls_threading_mutex_t
{
pthread_mutex_t mutex;
+ /* is_valid is 0 after a failed init or a free, and nonzero after a
+ * successful init. This field is not considered part of the public
+ * API of Mbed TLS and may change without notice. */
char is_valid;
} mbedtls_threading_mutex_t;
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h
index 5f0a8f114c..bd5c730c1d 100644
--- a/thirdparty/mbedtls/include/mbedtls/version.h
+++ b/thirdparty/mbedtls/include/mbedtls/version.h
@@ -65,16 +65,16 @@
*/
#define MBEDTLS_VERSION_MAJOR 2
#define MBEDTLS_VERSION_MINOR 16
-#define MBEDTLS_VERSION_PATCH 9
+#define MBEDTLS_VERSION_PATCH 10
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
-#define MBEDTLS_VERSION_NUMBER 0x02100900
-#define MBEDTLS_VERSION_STRING "2.16.9"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.9"
+#define MBEDTLS_VERSION_NUMBER 0x02100A00
+#define MBEDTLS_VERSION_STRING "2.16.10"
+#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.10"
#if defined(MBEDTLS_VERSION_C)
diff --git a/thirdparty/mbedtls/library/base64.c b/thirdparty/mbedtls/library/base64.c
index bfafb05353..692e11e3fa 100644
--- a/thirdparty/mbedtls/library/base64.c
+++ b/thirdparty/mbedtls/library/base64.c
@@ -97,6 +97,99 @@ static const unsigned char base64_dec_map[128] =
#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
/*
+ * Constant flow conditional assignment to unsigned char
+ */
+static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src,
+ unsigned char condition )
+{
+ /* MSVC has a warning about unary minus on unsigned integer types,
+ * but this is well-defined and precisely what we want to do here. */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+
+ /* Generate bitmask from condition, mask will either be 0xFF or 0 */
+ unsigned char mask = ( condition | -condition );
+ mask >>= 7;
+ mask = -mask;
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+ *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask );
+}
+
+/*
+ * Constant flow conditional assignment to uint_32
+ */
+static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src,
+ uint32_t condition )
+{
+ /* MSVC has a warning about unary minus on unsigned integer types,
+ * but this is well-defined and precisely what we want to do here. */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+
+ /* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */
+ uint32_t mask = ( condition | -condition );
+ mask >>= 31;
+ mask = -mask;
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+ *dest = ( src & mask ) | ( ( *dest ) & ~mask );
+}
+
+/*
+ * Constant flow check for equality
+ */
+static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b )
+{
+ size_t difference = in_a ^ in_b;
+
+ /* MSVC has a warning about unary minus on unsigned integer types,
+ * but this is well-defined and precisely what we want to do here. */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+
+ difference |= -difference;
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+ /* cope with the varying size of size_t per platform */
+ difference >>= ( sizeof( difference ) * 8 - 1 );
+
+ return (unsigned char) ( 1 ^ difference );
+}
+
+/*
+ * Constant flow lookup into table.
+ */
+static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table,
+ const size_t table_size, const size_t table_index )
+{
+ size_t i;
+ unsigned char result = 0;
+
+ for( i = 0; i < table_size; ++i )
+ {
+ mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) );
+ }
+
+ return result;
+}
+
+/*
* Encode a buffer into base64 format
*/
int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
@@ -136,10 +229,17 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
C2 = *src++;
C3 = *src++;
- *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
- *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
- *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
- *p++ = base64_enc_map[C3 & 0x3F];
+ *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+ ( ( C1 >> 2 ) & 0x3F ) );
+
+ *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+ ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
+
+ *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+ ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) );
+
+ *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+ ( C3 & 0x3F ) );
}
if( i < slen )
@@ -147,11 +247,15 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
C1 = *src++;
C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
- *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
- *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+ *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+ ( ( C1 >> 2 ) & 0x3F ) );
+
+ *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+ ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
if( ( i + 1 ) < slen )
- *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
+ *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+ ( ( ( C2 & 15 ) << 2 ) & 0x3F ) );
else *p++ = '=';
*p++ = '=';
@@ -172,6 +276,7 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
size_t i, n;
uint32_t j, x;
unsigned char *p;
+ unsigned char dec_map_lookup;
/* First pass: check for validity and get output length */
for( i = n = j = 0; i < slen; i++ )
@@ -202,10 +307,12 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
if( src[i] == '=' && ++j > 2 )
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
- if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
+ dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] );
+
+ if( src[i] > 127 || dec_map_lookup == 127 )
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
- if( base64_dec_map[src[i]] < 64 && j != 0 )
+ if( dec_map_lookup < 64 && j != 0 )
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
n++;
@@ -235,8 +342,10 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
if( *src == '\r' || *src == '\n' || *src == ' ' )
continue;
- j -= ( base64_dec_map[*src] == 64 );
- x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
+ dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src );
+
+ mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) );
+ x = ( x << 6 ) | ( dec_map_lookup & 0x3F );
if( ++n == 4 )
{
diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c
index 2feb727d89..f133f6c13c 100644
--- a/thirdparty/mbedtls/library/bignum.c
+++ b/thirdparty/mbedtls/library/bignum.c
@@ -1354,6 +1354,12 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
for( n = B->n; n > 0; n-- )
if( B->p[n - 1] != 0 )
break;
+ if( n > A->n )
+ {
+ /* B >= (2^ciL)^n > A */
+ ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
+ goto cleanup;
+ }
carry = mpi_sub_hlp( n, X->p, B->p );
if( carry != 0 )
diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c
index e92008bbe8..90264e844a 100644
--- a/thirdparty/mbedtls/library/ctr_drbg.c
+++ b/thirdparty/mbedtls/library/ctr_drbg.c
@@ -83,10 +83,6 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
-
-#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_init( &ctx->mutex );
-#endif
}
/*
@@ -99,14 +95,13 @@ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
return;
#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_free( &ctx->mutex );
+ /* The mutex is initialized iff f_entropy is set. */
+ if( ctx->f_entropy != NULL )
+ mbedtls_mutex_free( &ctx->mutex );
#endif
mbedtls_aes_free( &ctx->aes_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
-#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_init( &ctx->mutex );
-#endif
}
void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
@@ -422,6 +417,11 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
+ /* The mutex is initialized iff f_entropy is set. */
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_mutex_init( &ctx->mutex );
+#endif
+
mbedtls_aes_init( &ctx->aes_ctx );
ctx->f_entropy = f_entropy;
diff --git a/thirdparty/mbedtls/library/ecdsa.c b/thirdparty/mbedtls/library/ecdsa.c
index da8df9cde2..2456238b17 100644
--- a/thirdparty/mbedtls/library/ecdsa.c
+++ b/thirdparty/mbedtls/library/ecdsa.c
@@ -247,6 +247,9 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
#endif /* MBEDTLS_ECP_RESTARTABLE */
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \
+ !defined(MBEDTLS_ECDSA_SIGN_ALT) || \
+ !defined(MBEDTLS_ECDSA_VERIFY_ALT)
/*
* Derive a suitable integer for group grp from a buffer of length len
* SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
@@ -269,6 +272,7 @@ static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
cleanup:
return( ret );
}
+#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */
#if !defined(MBEDTLS_ECDSA_SIGN_ALT)
/*
@@ -780,6 +784,8 @@ int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
(void) md_alg;
#if defined(MBEDTLS_ECDSA_SIGN_ALT)
+ (void) rs_ctx;
+
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
hash, hlen, f_rng, p_rng ) );
#else
@@ -888,6 +894,8 @@ int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
goto cleanup;
}
#if defined(MBEDTLS_ECDSA_VERIFY_ALT)
+ (void) rs_ctx;
+
if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
&ctx->Q, &r, &s ) ) != 0 )
goto cleanup;
diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c
index f6e24580c7..0532a295e6 100644
--- a/thirdparty/mbedtls/library/ecjpake.c
+++ b/thirdparty/mbedtls/library/ecjpake.c
@@ -850,6 +850,8 @@ static const unsigned char ecjpake_test_password[] = {
0x65, 0x73, 0x74
};
+#if !defined(MBEDTLS_ECJPAKE_ALT)
+
static const unsigned char ecjpake_test_x1[] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
@@ -994,6 +996,8 @@ cleanup:
return( ret );
}
+#endif /* ! MBEDTLS_ECJPAKE_ALT */
+
/* For tests we don't need a secure RNG;
* use the LGC from Numerical Recipes for simplicity */
static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
@@ -1089,6 +1093,12 @@ int mbedtls_ecjpake_self_test( int verbose )
if( verbose != 0 )
mbedtls_printf( "passed\n" );
+#if !defined(MBEDTLS_ECJPAKE_ALT)
+ /* 'reference handshake' tests can only be run against implementations
+ * for which we have 100% control over how the random ephemeral keys
+ * are generated. This is only the case for the internal mbed TLS
+ * implementation, so these tests are skipped in case the internal
+ * implementation is swapped out for an alternative one. */
if( verbose != 0 )
mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
@@ -1137,6 +1147,7 @@ int mbedtls_ecjpake_self_test( int verbose )
if( verbose != 0 )
mbedtls_printf( "passed\n" );
+#endif /* ! MBEDTLS_ECJPAKE_ALT */
cleanup:
mbedtls_ecjpake_free( &cli );
diff --git a/thirdparty/mbedtls/library/entropy.c b/thirdparty/mbedtls/library/entropy.c
index 666c55654c..c5f414a010 100644
--- a/thirdparty/mbedtls/library/entropy.c
+++ b/thirdparty/mbedtls/library/entropy.c
@@ -146,6 +146,11 @@ void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
{
+ /* If the context was already free, don't call free() again.
+ * This is important for mutexes which don't allow double-free. */
+ if( ctx->accumulator_started == -1 )
+ return;
+
#if defined(MBEDTLS_HAVEGE_C)
mbedtls_havege_free( &ctx->havege_data );
#endif
@@ -162,7 +167,7 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
#endif
ctx->source_count = 0;
mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) );
- ctx->accumulator_started = 0;
+ ctx->accumulator_started = -1;
}
int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
diff --git a/thirdparty/mbedtls/library/hmac_drbg.c b/thirdparty/mbedtls/library/hmac_drbg.c
index 10cbd462ba..b45d61616f 100644
--- a/thirdparty/mbedtls/library/hmac_drbg.c
+++ b/thirdparty/mbedtls/library/hmac_drbg.c
@@ -84,10 +84,6 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
-
-#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_init( &ctx->mutex );
-#endif
}
/*
@@ -159,6 +155,10 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
return( ret );
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_mutex_init( &ctx->mutex );
+#endif
+
/*
* Set initial working state.
* Use the V memory location, which is currently all 0, to initialize the
@@ -284,6 +284,11 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
return( ret );
+ /* The mutex is initialized iff the md context is set up. */
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_mutex_init( &ctx->mutex );
+#endif
+
md_size = mbedtls_md_get_size( md_info );
/*
@@ -451,14 +456,13 @@ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
return;
#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_free( &ctx->mutex );
+ /* The mutex is initialized iff the md context is set up. */
+ if( ctx->md_ctx.md_info != NULL )
+ mbedtls_mutex_free( &ctx->mutex );
#endif
mbedtls_md_free( &ctx->md_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
-#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_init( &ctx->mutex );
-#endif
}
#if defined(MBEDTLS_FS_IO)
diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c
index 1130408263..671115f15f 100644
--- a/thirdparty/mbedtls/library/net_sockets.c
+++ b/thirdparty/mbedtls/library/net_sockets.c
@@ -496,6 +496,13 @@ int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
if( fd < 0 )
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+ /* A limitation of select() is that it only works with file descriptors
+ * that are strictly less than FD_SETSIZE. This is a limitation of the
+ * fd_set type. Error out early, because attempting to call FD_SET on a
+ * large file descriptor is a buffer overflow on typical platforms. */
+ if( fd >= FD_SETSIZE )
+ return( MBEDTLS_ERR_NET_POLL_FAILED );
+
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
/* Ensure that memory sanitizers consider read_fds and write_fds as
@@ -615,6 +622,13 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
if( fd < 0 )
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+ /* A limitation of select() is that it only works with file descriptors
+ * that are strictly less than FD_SETSIZE. This is a limitation of the
+ * fd_set type. Error out early, because attempting to call FD_SET on a
+ * large file descriptor is a buffer overflow on typical platforms. */
+ if( fd >= FD_SETSIZE )
+ return( MBEDTLS_ERR_NET_POLL_FAILED );
+
FD_ZERO( &read_fds );
FD_SET( fd, &read_fds );
diff --git a/thirdparty/mbedtls/library/pkwrite.c b/thirdparty/mbedtls/library/pkwrite.c
index 150626c147..a770dfb93e 100644
--- a/thirdparty/mbedtls/library/pkwrite.c
+++ b/thirdparty/mbedtls/library/pkwrite.c
@@ -455,7 +455,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
* publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1
* }
*/
-#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE
+#define RSA_PUB_DER_MAX_BYTES ( 38 + 2 * MBEDTLS_MPI_MAX_SIZE )
/*
* RSA private keys:
@@ -472,10 +472,10 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
* otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported)
* }
*/
-#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \
- MBEDTLS_MPI_MAX_SIZE % 2
-#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \
- + 5 * MPI_MAX_SIZE_2
+#define MPI_MAX_SIZE_2 ( MBEDTLS_MPI_MAX_SIZE / 2 + \
+ MBEDTLS_MPI_MAX_SIZE % 2 )
+#define RSA_PRV_DER_MAX_BYTES ( 47 + 3 * MBEDTLS_MPI_MAX_SIZE \
+ + 5 * MPI_MAX_SIZE_2 )
#else /* MBEDTLS_RSA_C */
@@ -496,7 +496,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
* + 2 * ECP_MAX (coords) [1]
* }
*/
-#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES
+#define ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES )
/*
* EC private keys:
@@ -507,7 +507,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
* publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above
* }
*/
-#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES
+#define ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES )
#else /* MBEDTLS_ECP_C */
@@ -516,10 +516,10 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
#endif /* MBEDTLS_ECP_C */
-#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
- RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES
-#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
- RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES
+#define PUB_DER_MAX_BYTES ( RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
+ RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES )
+#define PRV_DER_MAX_BYTES ( RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
+ RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES )
int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
{
diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c
index a25c633bc6..c8c23dba8c 100644
--- a/thirdparty/mbedtls/library/rsa.c
+++ b/thirdparty/mbedtls/library/rsa.c
@@ -520,6 +520,9 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
mbedtls_rsa_set_padding( ctx, padding, hash_id );
#if defined(MBEDTLS_THREADING_C)
+ /* Set ctx->ver to nonzero to indicate that the mutex has been
+ * initialized and will need to be freed. */
+ ctx->ver = 1;
mbedtls_mutex_init( &ctx->mutex );
#endif
}
@@ -567,9 +570,6 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
RSA_VALIDATE_RET( ctx != NULL );
RSA_VALIDATE_RET( f_rng != NULL );
- if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
- return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
/*
* If the modulus is 1024 bit long or shorter, then the security strength of
* the RSA algorithm is less than or equal to 80 bits and therefore an error
@@ -582,6 +582,12 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
mbedtls_mpi_init( &G );
mbedtls_mpi_init( &L );
+ if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
+ {
+ ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
/*
* find primes P and Q with Q < P so that:
* 1. |P-Q| > 2^( nbits / 2 - 100 )
@@ -659,7 +665,9 @@ cleanup:
if( ret != 0 )
{
mbedtls_rsa_free( ctx );
- return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret );
+ if( ( -ret & ~0x7f ) == 0 )
+ ret = MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret;
+ return( ret );
}
return( 0 );
@@ -1106,10 +1114,10 @@ cleanup:
mbedtls_mpi_free( &C );
mbedtls_mpi_free( &I );
- if( ret != 0 )
+ if( ret != 0 && ret >= -0x007f )
return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );
- return( 0 );
+ return( ret );
}
#if defined(MBEDTLS_PKCS1_V21)
@@ -2502,7 +2510,6 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
RSA_VALIDATE_RET( dst != NULL );
RSA_VALIDATE_RET( src != NULL );
- dst->ver = src->ver;
dst->len = src->len;
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) );
@@ -2561,7 +2568,12 @@ void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
#endif /* MBEDTLS_RSA_NO_CRT */
#if defined(MBEDTLS_THREADING_C)
- mbedtls_mutex_free( &ctx->mutex );
+ /* Free the mutex, but only if it hasn't been freed already. */
+ if( ctx->ver != 0 )
+ {
+ mbedtls_mutex_free( &ctx->mutex );
+ ctx->ver = 0;
+ }
#endif
}
diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c
index f4f29cff5e..0dc5488c1a 100644
--- a/thirdparty/mbedtls/library/threading.c
+++ b/thirdparty/mbedtls/library/threading.c
@@ -98,6 +98,12 @@ static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex )
if( mutex == NULL )
return;
+ /* A nonzero value of is_valid indicates a successfully initialized
+ * mutex. This is a workaround for not being able to return an error
+ * code for this function. The lock/unlock functions return an error
+ * if is_valid is nonzero. The Mbed TLS unit test code uses this field
+ * to distinguish more states of the mutex; see helpers.function for
+ * details. */
mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0;
}
diff --git a/thirdparty/mbedtls/library/version_features.c b/thirdparty/mbedtls/library/version_features.c
index cbf38dc2c2..8c8e815e9d 100644
--- a/thirdparty/mbedtls/library/version_features.c
+++ b/thirdparty/mbedtls/library/version_features.c
@@ -553,6 +553,9 @@ static const char *features[] = {
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT)
"MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT",
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */
+#if defined(MBEDTLS_TEST_HOOKS)
+ "MBEDTLS_TEST_HOOKS",
+#endif /* MBEDTLS_TEST_HOOKS */
#if defined(MBEDTLS_THREADING_ALT)
"MBEDTLS_THREADING_ALT",
#endif /* MBEDTLS_THREADING_ALT */
diff --git a/thirdparty/miniupnpc/LICENSE b/thirdparty/miniupnpc/LICENSE
index 1460310752..6ddd381baa 100644
--- a/thirdparty/miniupnpc/LICENSE
+++ b/thirdparty/miniupnpc/LICENSE
@@ -1,5 +1,5 @@
-MiniUPnP Project
-Copyright (c) 2005-2019, Thomas BERNARD
+MiniUPnPc
+Copyright (c) 2005-2020, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -24,3 +24,4 @@ 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/miniupnpc/addr_is_reserved.c b/thirdparty/miniupnpc/miniupnpc/addr_is_reserved.c
new file mode 100644
index 0000000000..7e586d7da2
--- /dev/null
+++ b/thirdparty/miniupnpc/miniupnpc/addr_is_reserved.c
@@ -0,0 +1,79 @@
+/* $Id: addr_is_reserved.c,v 1.4 2021/03/02 23:40:32 nanard Exp $ */
+/* vim: tabstop=4 shiftwidth=4 noexpandtab
+ * Project : miniupnp
+ * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
+ * Author : Thomas BERNARD
+ * copyright (c) 2005-2021 Thomas Bernard
+ * This software is subjet to the conditions detailed in the
+ * provided LICENSE file. */
+#ifdef _WIN32
+/* Win32 Specific includes and defines */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#if !defined(_MSC_VER)
+#include <stdint.h>
+#else /* !defined(_MSC_VER) */
+typedef unsigned long uint32_t;
+#endif /* !defined(_MSC_VER) */
+#else /* _WIN32 */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif /* _WIN32 */
+
+/* List of IP address blocks which are private / reserved and therefore not suitable for public external IP addresses */
+#define IP(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
+#define MSK(m) (32-(m))
+static const struct { uint32_t address; uint32_t rmask; } reserved[] = {
+ { IP( 0, 0, 0, 0), MSK( 8) }, /* RFC1122 "This host on this network" */
+ { IP( 10, 0, 0, 0), MSK( 8) }, /* RFC1918 Private-Use */
+ { IP(100, 64, 0, 0), MSK(10) }, /* RFC6598 Shared Address Space */
+ { IP(127, 0, 0, 0), MSK( 8) }, /* RFC1122 Loopback */
+ { IP(169, 254, 0, 0), MSK(16) }, /* RFC3927 Link-Local */
+ { IP(172, 16, 0, 0), MSK(12) }, /* RFC1918 Private-Use */
+ { IP(192, 0, 0, 0), MSK(24) }, /* RFC6890 IETF Protocol Assignments */
+ { IP(192, 0, 2, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-1) */
+ { IP(192, 31, 196, 0), MSK(24) }, /* RFC7535 AS112-v4 */
+ { IP(192, 52, 193, 0), MSK(24) }, /* RFC7450 AMT */
+ { IP(192, 88, 99, 0), MSK(24) }, /* RFC7526 6to4 Relay Anycast */
+ { IP(192, 168, 0, 0), MSK(16) }, /* RFC1918 Private-Use */
+ { IP(192, 175, 48, 0), MSK(24) }, /* RFC7534 Direct Delegation AS112 Service */
+ { IP(198, 18, 0, 0), MSK(15) }, /* RFC2544 Benchmarking */
+ { IP(198, 51, 100, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-2) */
+ { IP(203, 0, 113, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-3) */
+ { IP(224, 0, 0, 0), MSK( 4) }, /* RFC1112 Multicast */
+ { IP(240, 0, 0, 0), MSK( 4) }, /* RFC1112 Reserved for Future Use + RFC919 Limited Broadcast */
+};
+#undef IP
+#undef MSK
+
+/**
+ * @return 1 or 0
+ */
+int addr_is_reserved(const char * addr_str)
+{
+ uint32_t addr_n, address;
+ size_t i;
+
+#if defined(_WIN32) && (!defined(_WIN32_WINNT_VISTA) || (_WIN32_WINNT < _WIN32_WINNT_VISTA))
+ addr_n = inet_addr(addr_str);
+ if (addr_n == INADDR_NONE)
+ return 1;
+#else
+ /* was : addr_n = inet_addr(addr_str); */
+ if (inet_pton(AF_INET, addr_str, &addr_n) <= 0) {
+ /* error */
+ return 1;
+ }
+#endif
+
+ address = ntohl(addr_n);
+
+ for (i = 0; i < sizeof(reserved)/sizeof(reserved[0]); ++i) {
+ if ((address >> reserved[i].rmask) == (reserved[i].address >> reserved[i].rmask))
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/thirdparty/miniupnpc/miniupnpc/addr_is_reserved.h b/thirdparty/miniupnpc/miniupnpc/addr_is_reserved.h
new file mode 100644
index 0000000000..f8b5d66a09
--- /dev/null
+++ b/thirdparty/miniupnpc/miniupnpc/addr_is_reserved.h
@@ -0,0 +1,14 @@
+/* $Id: $ */
+/* vim: tabstop=4 shiftwidth=4 noexpandtab
+ * Project: miniupnp
+ * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
+ * Author: Thomas Bernard
+ * Copyright (c) 2005-2020 Thomas Bernard
+ * This software is subjects to the conditions detailed
+ * in the LICENCE file provided within this distribution */
+#ifndef ADDR_IS_RESERVED_H_INCLUDED
+#define ADDR_IS_RESERVED_H_INCLUDED
+
+int addr_is_reserved(const char * addr_str);
+
+#endif /* ADDR_IS_RESERVED_H_INCLUDED */
diff --git a/thirdparty/miniupnpc/miniupnpc/connecthostport.c b/thirdparty/miniupnpc/miniupnpc/connecthostport.c
index f3982e1a77..79f832b8db 100644
--- a/thirdparty/miniupnpc/miniupnpc/connecthostport.c
+++ b/thirdparty/miniupnpc/miniupnpc/connecthostport.c
@@ -1,8 +1,8 @@
-/* $Id: connecthostport.c,v 1.22 2019/10/13 17:22:08 nanard Exp $ */
+/* $Id: connecthostport.c,v 1.24 2020/11/09 19:26:53 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Author : Thomas Bernard
- * Copyright (c) 2010-2019 Thomas Bernard
+ * Copyright (c) 2010-2020 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@@ -19,7 +19,7 @@
#include <ws2tcpip.h>
#include <io.h>
#define MAXHOSTNAMELEN 64
-#define snprintf _snprintf
+#include "win32_snprintf.h"
#define herror
#define socklen_t int
#else /* #ifdef _WIN32 */
diff --git a/thirdparty/miniupnpc/miniupnpc/listdevices.c b/thirdparty/miniupnpc/miniupnpc/listdevices.c
deleted file mode 100644
index bd9ba57efc..0000000000
--- a/thirdparty/miniupnpc/miniupnpc/listdevices.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/* $Id: listdevices.c,v 1.6 2015/07/23 20:40:08 nanard Exp $ */
-/* Project : miniupnp
- * Author : Thomas Bernard
- * Copyright (c) 2013-2015 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution. */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#ifdef _WIN32
-#include <winsock2.h>
-#endif /* _WIN32 */
-#include "miniupnpc.h"
-
-struct upnp_dev_list {
- struct upnp_dev_list * next;
- char * descURL;
- struct UPNPDev * * array;
- size_t count;
- size_t allocated_count;
-};
-
-#define ADD_DEVICE_COUNT_STEP 16
-
-void add_device(struct upnp_dev_list * * list_head, struct UPNPDev * dev)
-{
- struct upnp_dev_list * elt;
- size_t i;
-
- if(dev == NULL)
- return;
- for(elt = *list_head; elt != NULL; elt = elt->next) {
- if(strcmp(elt->descURL, dev->descURL) == 0) {
- for(i = 0; i < elt->count; i++) {
- if (strcmp(elt->array[i]->st, dev->st) == 0 && strcmp(elt->array[i]->usn, dev->usn) == 0) {
- return; /* already found */
- }
- }
- if(elt->count >= elt->allocated_count) {
- struct UPNPDev * * tmp;
- elt->allocated_count += ADD_DEVICE_COUNT_STEP;
- tmp = realloc(elt->array, elt->allocated_count * sizeof(struct UPNPDev *));
- if(tmp == NULL) {
- fprintf(stderr, "Failed to realloc(%p, %lu)\n", elt->array, (unsigned long)(elt->allocated_count * sizeof(struct UPNPDev *)));
- return;
- }
- elt->array = tmp;
- }
- elt->array[elt->count++] = dev;
- return;
- }
- }
- elt = malloc(sizeof(struct upnp_dev_list));
- if(elt == NULL) {
- fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)sizeof(struct upnp_dev_list));
- return;
- }
- elt->next = *list_head;
- elt->descURL = strdup(dev->descURL);
- if(elt->descURL == NULL) {
- fprintf(stderr, "Failed to strdup(%s)\n", dev->descURL);
- free(elt);
- return;
- }
- elt->allocated_count = ADD_DEVICE_COUNT_STEP;
- elt->array = malloc(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *));
- if(elt->array == NULL) {
- fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *)));
- free(elt->descURL);
- free(elt);
- return;
- }
- elt->array[0] = dev;
- elt->count = 1;
- *list_head = elt;
-}
-
-void free_device(struct upnp_dev_list * elt)
-{
- free(elt->descURL);
- free(elt->array);
- free(elt);
-}
-
-int main(int argc, char * * argv)
-{
- const char * searched_device = NULL;
- const char * * searched_devices = NULL;
- const char * multicastif = 0;
- const char * minissdpdpath = 0;
- int ipv6 = 0;
- unsigned char ttl = 2;
- int error = 0;
- struct UPNPDev * devlist = 0;
- struct UPNPDev * dev;
- struct upnp_dev_list * sorted_list = NULL;
- struct upnp_dev_list * dev_array;
- int i;
-
-#ifdef _WIN32
- WSADATA wsaData;
- int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
- if(nResult != NO_ERROR)
- {
- fprintf(stderr, "WSAStartup() failed.\n");
- return -1;
- }
-#endif
-
- for(i = 1; i < argc; i++) {
- if(strcmp(argv[i], "-6") == 0)
- ipv6 = 1;
- else if(strcmp(argv[i], "-d") == 0) {
- if(++i >= argc) {
- fprintf(stderr, "%s option needs one argument\n", "-d");
- return 1;
- }
- searched_device = argv[i];
- } else if(strcmp(argv[i], "-t") == 0) {
- if(++i >= argc) {
- fprintf(stderr, "%s option needs one argument\n", "-t");
- return 1;
- }
- ttl = (unsigned char)atoi(argv[i]);
- } else if(strcmp(argv[i], "-l") == 0) {
- if(++i >= argc) {
- fprintf(stderr, "-l option needs at least one argument\n");
- return 1;
- }
- searched_devices = (const char * *)(argv + i);
- break;
- } else if(strcmp(argv[i], "-m") == 0) {
- if(++i >= argc) {
- fprintf(stderr, "-m option needs one argument\n");
- return 1;
- }
- multicastif = argv[i];
- } else {
- printf("usage : %s [options] [-l <device1> <device2> ...]\n", argv[0]);
- printf("options :\n");
- printf(" -6 : use IPv6\n");
- printf(" -m address/ifname : network interface to use for multicast\n");
- printf(" -d <device string> : search only for this type of device\n");
- printf(" -l <device1> <device2> ... : search only for theses types of device\n");
- printf(" -t ttl : set multicast TTL. Default value is 2.\n");
- printf(" -h : this help\n");
- return 1;
- }
- }
-
- if(searched_device) {
- printf("searching UPnP device type %s\n", searched_device);
- devlist = upnpDiscoverDevice(searched_device,
- 2000, multicastif, minissdpdpath,
- 0/*localport*/, ipv6, ttl, &error);
- } else if(searched_devices) {
- printf("searching UPnP device types :\n");
- for(i = 0; searched_devices[i]; i++)
- printf("\t%s\n", searched_devices[i]);
- devlist = upnpDiscoverDevices(searched_devices,
- 2000, multicastif, minissdpdpath,
- 0/*localport*/, ipv6, ttl, &error, 1);
- } else {
- printf("searching all UPnP devices\n");
- devlist = upnpDiscoverAll(2000, multicastif, minissdpdpath,
- 0/*localport*/, ipv6, ttl, &error);
- }
- if(devlist) {
- for(dev = devlist, i = 1; dev != NULL; dev = dev->pNext, i++) {
- printf("%3d: %-48s\n", i, dev->st);
- printf(" %s\n", dev->descURL);
- printf(" %s\n", dev->usn);
- add_device(&sorted_list, dev);
- }
- putchar('\n');
- for (dev_array = sorted_list; dev_array != NULL ; dev_array = dev_array->next) {
- printf("%s :\n", dev_array->descURL);
- for(i = 0; (unsigned)i < dev_array->count; i++) {
- printf("%2d: %s\n", i+1, dev_array->array[i]->st);
- printf(" %s\n", dev_array->array[i]->usn);
- }
- putchar('\n');
- }
- freeUPNPDevlist(devlist);
- while(sorted_list != NULL) {
- dev_array = sorted_list;
- sorted_list = sorted_list->next;
- free_device(dev_array);
- }
- } else {
- printf("no device found.\n");
- }
-
- return 0;
-}
-
diff --git a/thirdparty/miniupnpc/miniupnpc/minisoap.c b/thirdparty/miniupnpc/miniupnpc/minisoap.c
index f92b36ce89..78606672d5 100644
--- a/thirdparty/miniupnpc/miniupnpc/minisoap.c
+++ b/thirdparty/miniupnpc/miniupnpc/minisoap.c
@@ -1,8 +1,8 @@
-/* $Id: minisoap.c,v 1.25 2017/04/21 10:03:24 nanard Exp $ */
+/* $Id: minisoap.c,v 1.30 2020/11/09 19:27:42 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Author : Thomas Bernard
- * Copyright (c) 2005-2018 Thomas Bernard
+ * Copyright (c) 2005-2020 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
*
@@ -13,7 +13,7 @@
#ifdef _WIN32
#include <io.h>
#include <winsock2.h>
-#define snprintf _snprintf
+#include "win32_snprintf.h"
#else
#include <unistd.h>
#include <sys/types.h>
diff --git a/thirdparty/miniupnpc/miniupnpc/minissdpc.c b/thirdparty/miniupnpc/miniupnpc/minissdpc.c
index 36244dedec..0ef7e12cfb 100644
--- a/thirdparty/miniupnpc/miniupnpc/minissdpc.c
+++ b/thirdparty/miniupnpc/miniupnpc/minissdpc.c
@@ -1,15 +1,15 @@
-/* $Id: minissdpc.c,v 1.40 2019/04/23 12:12:55 nanard Exp $ */
+/* $Id: minissdpc.c,v 1.47 2021/03/02 23:38:30 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
- * Web : http://miniupnp.free.fr/
+ * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas BERNARD
- * copyright (c) 2005-2019 Thomas Bernard
+ * copyright (c) 2005-2021 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
-/*#include <syslog.h>*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <time.h>
#include <sys/types.h>
#if defined (__NetBSD__)
#include <net/if.h>
@@ -20,7 +20,7 @@
#include <ws2tcpip.h>
#include <io.h>
#include <iphlpapi.h>
-#define snprintf _snprintf
+#include "win32_snprintf.h"
#if !defined(_MSC_VER)
#include <stdint.h>
#else /* !defined(_MSC_VER) */
@@ -33,6 +33,12 @@ typedef unsigned short uint16_t;
#define strncasecmp memicmp
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#endif /* #ifndef strncasecmp */
+#if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_PARTITION)
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP
+#define in6addr_any in6addr_any_init
+static const IN6_ADDR in6addr_any_init = {0};
+#endif
+#endif
#endif /* _WIN32 */
#if defined(__amigaos__) || defined(__amigaos4__)
#include <sys/socket.h>
@@ -66,7 +72,7 @@ struct sockaddr_un {
#define HAS_IP_MREQN
#endif
-#if !defined(HAS_IP_MREQN) && !defined(_WIN32)
+#ifndef _WIN32
#include <sys/ioctl.h>
#if defined(__sun) || defined(__HAIKU__)
#include <sys/sockio.h>
@@ -445,6 +451,36 @@ parseMSEARCHReply(const char * reply, int size,
}
}
+#if defined(CLOCK_MONOTONIC_FAST)
+#define UPNP_CLOCKID CLOCK_MONOTONIC_FAST
+#elif defined(CLOCK_MONOTONIC)
+#define UPNP_CLOCKID CLOCK_MONOTONIC
+#endif
+
+static int upnp_gettimeofday(struct timeval * tv)
+{
+#if defined(_WIN32)
+#if defined(_WIN32_WINNT_VISTA) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
+ ULONGLONG ts = GetTickCount64();
+#else
+ DWORD ts = GetTickCount();
+#endif
+ tv->tv_sec = (long)(ts / 1000);
+ tv->tv_usec = (ts % 1000) * 1000;
+ return 0; /* success */
+#elif defined(CLOCK_MONOTONIC_FAST) || defined(CLOCK_MONOTONIC)
+ struct timespec ts;
+ int ret_code = clock_gettime(UPNP_CLOCKID, &ts);
+ if (ret_code == 0)
+ {
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+ }
+ return ret_code;
+#else
+ return gettimeofday(tv, NULL);
+#endif
+}
/* port upnp discover : SSDP protocol */
#define SSDP_PORT 1900
#define XSTR(s) STR(s)
@@ -540,12 +576,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
* in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */
if(!ipv6) {
DWORD ifbestidx;
- SOCKADDR_IN destAddr;
- memset(&destAddr, 0, sizeof(destAddr));
- destAddr.sin_family = AF_INET;
- destAddr.sin_addr.s_addr = inet_addr("223.255.255.255");
- destAddr.sin_port = 0;
- if (GetBestInterfaceEx((struct sockaddr *)&destAddr, &ifbestidx) == NO_ERROR) {
+ if (GetBestInterface(inet_addr("223.255.255.255"), &ifbestidx) == NO_ERROR) {
DWORD dwRetVal = NO_ERROR;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
ULONG outBufLen = 15360;
@@ -672,6 +703,13 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
* MS Windows Vista and MS Windows Server 2008.
* http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */
unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */
+ if(ifindex == 0)
+ {
+ if(error)
+ *error = MINISSDPC_INVALID_INPUT;
+ fprintf(stderr, "Invalid multicast interface name %s\n", multicastif);
+ goto error;
+ }
if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt IPV6_MULTICAST_IF");
@@ -683,7 +721,18 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
#endif
} else {
struct in_addr mc_if;
- mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
+#if defined(_WIN32)
+#if defined(_WIN32_WINNT_VISTA) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
+ InetPtonA(AF_INET, multicastif, &mc_if);
+#else
+ mc_if.s_addr = inet_addr(multicastif); /* old Windows SDK do not support InetPtoA() */
+#endif
+#else
+ /* was : mc_if.s_addr = inet_addr(multicastif); */ /* ex: 192.168.x.x */
+ if (inet_pton(AF_INET, multicastif, &mc_if.s_addr) <= 0) {
+ mc_if.s_addr = INADDR_NONE;
+ }
+#endif
if(mc_if.s_addr != INADDR_NONE)
{
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
@@ -692,16 +741,11 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
}
} else {
-#ifdef HAS_IP_MREQN
/* was not an ip address, try with an interface name */
+#ifndef _WIN32
+#ifdef HAS_IP_MREQN
struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
- memset(&reqn, 0, sizeof(struct ip_mreqn));
- reqn.imr_ifindex = if_nametoindex(multicastif);
- if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
- {
- PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
- }
-#elif !defined(_WIN32)
+#endif
struct ifreq ifr;
int ifrlen = sizeof(ifr);
strncpy(ifr.ifr_name, multicastif, IFNAMSIZ);
@@ -709,12 +753,30 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0)
{
PRINT_SOCKET_ERROR("ioctl(...SIOCGIFADDR...)");
+ goto error;
}
mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
+#ifdef HAS_IP_MREQN
+ memset(&reqn, 0, sizeof(struct ip_mreqn));
+ reqn.imr_address.s_addr = mc_if.s_addr;
+ reqn.imr_ifindex = if_nametoindex(multicastif);
+ if(reqn.imr_ifindex == 0)
+ {
+ if(error)
+ *error = MINISSDPC_INVALID_INPUT;
+ fprintf(stderr, "Invalid multicast ip address / interface name %s\n", multicastif);
+ goto error;
+ }
+ if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
+ {
+ PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
+ }
+#else
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
}
+#endif
#else /* _WIN32 */
#ifdef DEBUG
printf("Setting of multicast interface not supported with interface name.\n");
@@ -838,73 +900,84 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
/* Waiting for SSDP REPLY packet to M-SEARCH
* if searchalltypes is set, enter the loop only
* when the last deviceType is reached */
- if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) do {
- n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
- if (n < 0) {
- /* error */
- if(error)
- *error = MINISSDPC_SOCKET_ERROR;
- goto error;
- } else if (n == 0) {
- /* no data or Time Out */
-#ifdef DEBUG
- printf("NODATA or TIMEOUT\n");
-#endif /* DEBUG */
- if (devlist && !searchalltypes) {
- /* found some devices, stop now*/
+ if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) {
+ struct timeval start = {0, 0}, current = {0, 0};
+ upnp_gettimeofday(&start);
+ do {
+ n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
+ if (n < 0) {
+ /* error */
if(error)
- *error = MINISSDPC_SUCCESS;
+ *error = MINISSDPC_SOCKET_ERROR;
goto error;
- }
- } else {
- const char * descURL=NULL;
- int urlsize=0;
- const char * st=NULL;
- int stsize=0;
- const char * usn=NULL;
- int usnsize=0;
- parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize);
- if(st&&descURL) {
+ } else if (n == 0) {
+ /* no data or Time Out */
#ifdef DEBUG
- printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n",
- stsize, st, usnsize, (usn?usn:""), urlsize, descURL);
+ printf("NODATA or TIMEOUT\n");
#endif /* DEBUG */
- for(tmp=devlist; tmp; tmp = tmp->pNext) {
- if(strncmp(tmp->descURL, descURL, urlsize) == 0 &&
- tmp->descURL[urlsize] == '\0' &&
- strncmp(tmp->st, st, stsize) == 0 &&
- tmp->st[stsize] == '\0' &&
- (usnsize == 0 || strncmp(tmp->usn, usn, usnsize) == 0) &&
- tmp->usn[usnsize] == '\0')
- break;
- }
- /* at the exit of the loop above, tmp is null if
- * no duplicate device was found */
- if(tmp)
- continue;
- tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
- if(!tmp) {
- /* memory allocation error */
+ if (devlist && !searchalltypes) {
+ /* found some devices, stop now*/
if(error)
- *error = MINISSDPC_MEMORY_ERROR;
+ *error = MINISSDPC_SUCCESS;
goto error;
}
- tmp->pNext = devlist;
- tmp->descURL = tmp->buffer;
- tmp->st = tmp->buffer + 1 + urlsize;
- tmp->usn = tmp->st + 1 + stsize;
- memcpy(tmp->buffer, descURL, urlsize);
- tmp->buffer[urlsize] = '\0';
- memcpy(tmp->st, st, stsize);
- tmp->buffer[urlsize+1+stsize] = '\0';
- if(usn != NULL)
- memcpy(tmp->usn, usn, usnsize);
- tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
- tmp->scope_id = scope_id;
- devlist = tmp;
+ } else {
+ const char * descURL=NULL;
+ int urlsize=0;
+ const char * st=NULL;
+ int stsize=0;
+ const char * usn=NULL;
+ int usnsize=0;
+ parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize);
+ if(st&&descURL) {
+#ifdef DEBUG
+ printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n",
+ stsize, st, usnsize, (usn?usn:""), urlsize, descURL);
+#endif /* DEBUG */
+ for(tmp=devlist; tmp; tmp = tmp->pNext) {
+ if(strncmp(tmp->descURL, descURL, urlsize) == 0 &&
+ tmp->descURL[urlsize] == '\0' &&
+ strncmp(tmp->st, st, stsize) == 0 &&
+ tmp->st[stsize] == '\0' &&
+ (usnsize == 0 || strncmp(tmp->usn, usn, usnsize) == 0) &&
+ tmp->usn[usnsize] == '\0')
+ break;
+ }
+ /* at the exit of the loop above, tmp is null if
+ * no duplicate device was found */
+ if(tmp)
+ continue;
+ tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize+3);
+ if(!tmp) {
+ /* memory allocation error */
+ if(error)
+ *error = MINISSDPC_MEMORY_ERROR;
+ goto error;
+ }
+ tmp->pNext = devlist;
+ tmp->descURL = tmp->buffer;
+ tmp->st = tmp->buffer + 1 + urlsize;
+ tmp->usn = tmp->st + 1 + stsize;
+ memcpy(tmp->buffer, descURL, urlsize);
+ tmp->buffer[urlsize] = '\0';
+ memcpy(tmp->st, st, stsize);
+ tmp->buffer[urlsize+1+stsize] = '\0';
+ if(usn != NULL)
+ memcpy(tmp->usn, usn, usnsize);
+ tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
+ tmp->scope_id = scope_id;
+ devlist = tmp;
+ }
+ if (upnp_gettimeofday(&current) >= 0) {
+ /* exit the loop if delay is reached */
+ long interval = (current.tv_sec - start.tv_sec) * 1000;
+ interval += (current.tv_usec - start.tv_usec) / 1000;
+ if (interval > (long)delay)
+ break;
+ }
}
- }
- } while(n > 0);
+ } while(n > 0);
+ }
if(ipv6) {
/* switch linklocal flag */
if(linklocal) {
@@ -919,4 +992,3 @@ error:
closesocket(sudp);
return devlist;
}
-
diff --git a/thirdparty/miniupnpc/miniupnpc/miniupnpc.c b/thirdparty/miniupnpc/miniupnpc/miniupnpc.c
index 95ab6cf56b..696af93237 100644
--- a/thirdparty/miniupnpc/miniupnpc/miniupnpc.c
+++ b/thirdparty/miniupnpc/miniupnpc/miniupnpc.c
@@ -1,9 +1,9 @@
-/* $Id: miniupnpc.c,v 1.154 2019/04/23 12:12:13 nanard Exp $ */
+/* $Id: miniupnpc.c,v 1.159 2021/03/02 23:36:32 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
- * Web : http://miniupnp.free.fr/
+ * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas BERNARD
- * copyright (c) 2005-2019 Thomas Bernard
+ * copyright (c) 2005-2021 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#include <stdlib.h>
@@ -15,7 +15,7 @@
#include <ws2tcpip.h>
#include <io.h>
#include <iphlpapi.h>
-#define snprintf _snprintf
+#include "win32_snprintf.h"
#define strdup _strdup
#ifndef strncasecmp
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
@@ -61,6 +61,7 @@
#include "minixml.h"
#include "upnpcommands.h"
#include "connecthostport.h"
+#include "addr_is_reserved.h"
/* compare the beginning of a string with a constant string */
#define COMPARE(str, cstr) (0==strncmp(str, cstr, sizeof(cstr) - 1))
@@ -73,24 +74,6 @@
#define SERVICEPREFIX "u"
#define SERVICEPREFIX2 'u'
-/* check if an ip address is a private (LAN) address
- * see https://tools.ietf.org/html/rfc1918 */
-static int is_rfc1918addr(const char * addr)
-{
- /* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) */
- if(COMPARE(addr, "192.168."))
- return 1;
- /* 10.0.0.0 - 10.255.255.255 (10/8 prefix) */
- if(COMPARE(addr, "10."))
- return 1;
- /* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */
- if(COMPARE(addr, "172.")) {
- if((atoi(addr + 4) | 0x0f) == 0x1f)
- return 1;
- }
- return 0;
-}
-
/* root description parsing */
MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data)
{
@@ -337,6 +320,8 @@ upnpDiscoverDevices(const char * const deviceTypes[],
return devlist;
}
}
+#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
+ (void)minissdpdsock; /* unused */
#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
/* direct discovery if minissdpd responses are not sufficient */
@@ -643,8 +628,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
/* checks that status is connected AND there is a external IP address assigned */
if(is_connected &&
(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) {
- if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0')
- && (0 != strcmp(extIpAddr, "0.0.0.0")))
+ if(!addr_is_reserved(extIpAddr))
goto free_and_return;
}
FreeUPNPUrls(urls);
@@ -665,8 +649,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
#endif
if(is_connected &&
(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) {
- if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0')
- && (0 != strcmp(extIpAddr, "0.0.0.0")))
+ if(!addr_is_reserved(extIpAddr))
goto free_and_return;
}
FreeUPNPUrls(urls);
diff --git a/thirdparty/miniupnpc/miniupnpc/miniupnpc.h b/thirdparty/miniupnpc/miniupnpc/miniupnpc.h
index 8ddc282bd1..3aef8ea443 100644
--- a/thirdparty/miniupnpc/miniupnpc/miniupnpc.h
+++ b/thirdparty/miniupnpc/miniupnpc/miniupnpc.h
@@ -1,9 +1,9 @@
-/* $Id: miniupnpc.h,v 1.53 2018/05/07 11:05:16 nanard Exp $ */
+/* $Id: miniupnpc.h,v 1.58 2021/03/02 23:49:52 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
- * Copyright (c) 2005-2018 Thomas Bernard
+ * Copyright (c) 2005-2021 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.1"
+#define MINIUPNPC_VERSION "2.2.2"
#define MINIUPNPC_API_VERSION 17
/* Source port:
diff --git a/thirdparty/miniupnpc/miniupnpc/miniupnpc_socketdef.h b/thirdparty/miniupnpc/miniupnpc/miniupnpc_socketdef.h
index d4f79a7bd6..5986e58c76 100644
--- a/thirdparty/miniupnpc/miniupnpc/miniupnpc_socketdef.h
+++ b/thirdparty/miniupnpc/miniupnpc/miniupnpc_socketdef.h
@@ -7,7 +7,7 @@
#ifndef MINIUPNPC_SOCKETDEF_H_INCLUDED
#define MINIUPNPC_SOCKETDEF_H_INCLUDED
-#ifdef _MSC_VER
+#ifdef _WIN32
#define ISINVALID(s) (INVALID_SOCKET==(s))
diff --git a/thirdparty/miniupnpc/miniupnpc/miniupnpcmodule.c b/thirdparty/miniupnpc/miniupnpc/miniupnpcmodule.c
deleted file mode 100644
index d9341ab5bf..0000000000
--- a/thirdparty/miniupnpc/miniupnpc/miniupnpcmodule.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/* $Id: miniupnpcmodule.c,v 1.34 2019/05/20 19:07:16 nanard Exp $*/
-/* vim: tabstop=4 shiftwidth=4 noexpandtab
- * Project : miniupnp
- * Author : Thomas BERNARD
- * website : https://miniupnp.tuxfamily.org/
- * copyright (c) 2007-2019 Thomas Bernard
- * This software is subjet to the conditions detailed in the
- * provided LICENCE file. */
-#include <Python.h>
-#define MINIUPNP_STATICLIB
-#include "structmember.h"
-#include "miniupnpc.h"
-#include "upnpcommands.h"
-#include "upnperrors.h"
-
-#ifdef _WIN32
-#include <winsock2.h>
-#endif
-
-/* for compatibility with Python < 2.4 */
-#ifndef Py_RETURN_NONE
-#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
-#endif
-
-#ifndef Py_RETURN_TRUE
-#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
-#endif
-
-#ifndef Py_RETURN_FALSE
-#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
-#endif
-
-/* for compatibility with Python < 3.0 */
-#ifndef PyVarObject_HEAD_INIT
-#define PyVarObject_HEAD_INIT(type, size) \
- PyObject_HEAD_INIT(type) size,
-#endif
-
-#ifndef Py_TYPE
-#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
-#endif
-
-typedef struct {
- PyObject_HEAD
- /* Type-specific fields go here. */
- struct UPNPDev * devlist;
- struct UPNPUrls urls;
- struct IGDdatas data;
- unsigned int discoverdelay; /* value passed to upnpDiscover() */
- unsigned int localport; /* value passed to upnpDiscover() */
- char lanaddr[40]; /* our ip address on the LAN */
- char * multicastif;
- char * minissdpdsocket;
-} UPnPObject;
-
-static PyMemberDef UPnP_members[] = {
- {"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr),
- READONLY, "ip address on the LAN"
- },
- {"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay),
- 0/*READWRITE*/, "value in ms used to wait for SSDP responses"
- },
- {"localport", T_UINT, offsetof(UPnPObject, localport),
- 0/*READWRITE*/,
- "If localport is set to UPNP_LOCAL_PORT_SAME(1) "
- "SSDP packets will be sent from the source port "
- "1900 (same as destination port), if set to "
- "UPNP_LOCAL_PORT_ANY(0) system assign a source "
- "port, any other value will be attempted as the "
- "source port"
- },
- /* T_STRING is allways readonly :( */
- {"multicastif", T_STRING, offsetof(UPnPObject, multicastif),
- 0, "IP of the network interface to be used for multicast operations"
- },
- {"minissdpdsocket", T_STRING, offsetof(UPnPObject, minissdpdsocket),
- 0, "path of the MiniSSDPd unix socket"
- },
- {NULL}
-};
-
-
-static int UPnP_init(UPnPObject *self, PyObject *args, PyObject *kwds)
-{
- char* multicastif = NULL;
- char* minissdpdsocket = NULL;
- static char *kwlist[] = {
- "multicastif", "minissdpdsocket", "discoverdelay",
- "localport", NULL
- };
-
- if(!PyArg_ParseTupleAndKeywords(args, kwds, "|zzII", kwlist,
- &multicastif,
- &minissdpdsocket,
- &self->discoverdelay,
- &self->localport))
- return -1;
-
- if(self->localport>1 &&
- (self->localport>65534||self->localport<1024)) {
- PyErr_SetString(PyExc_Exception, "Invalid localport value");
- return -1;
- }
- if(multicastif)
- self->multicastif = strdup(multicastif);
- if(minissdpdsocket)
- self->minissdpdsocket = strdup(minissdpdsocket);
-
- return 0;
-}
-
-static void
-UPnPObject_dealloc(UPnPObject *self)
-{
- freeUPNPDevlist(self->devlist);
- FreeUPNPUrls(&self->urls);
- free(self->multicastif);
- free(self->minissdpdsocket);
- Py_TYPE(self)->tp_free((PyObject*)self);
-}
-
-static PyObject *
-UPnP_discover(UPnPObject *self)
-{
- struct UPNPDev * dev;
- int i;
- PyObject *res = NULL;
- if(self->devlist)
- {
- freeUPNPDevlist(self->devlist);
- self->devlist = 0;
- }
- Py_BEGIN_ALLOW_THREADS
- self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
- self->multicastif,
- self->minissdpdsocket,
- (int)self->localport,
- 0/*ip v6*/,
- 2/* TTL */,
- 0/*error */);
- Py_END_ALLOW_THREADS
- /* Py_RETURN_NONE ??? */
- for(dev = self->devlist, i = 0; dev; dev = dev->pNext)
- i++;
- res = Py_BuildValue("i", i);
- return res;
-}
-
-static PyObject *
-UPnP_selectigd(UPnPObject *self)
-{
- int r;
-Py_BEGIN_ALLOW_THREADS
- r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
- self->lanaddr, sizeof(self->lanaddr));
-Py_END_ALLOW_THREADS
- if(r)
- {
- return Py_BuildValue("s", self->urls.controlURL);
- }
- else
- {
- /* TODO: have our own exception type ! */
- PyErr_SetString(PyExc_Exception, "No UPnP device discovered");
- return NULL;
- }
-}
-
-static PyObject *
-UPnP_totalbytesent(UPnPObject *self)
-{
- UNSIGNED_INTEGER i;
-Py_BEGIN_ALLOW_THREADS
- i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
- self->data.CIF.servicetype);
-Py_END_ALLOW_THREADS
-#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
- return Py_BuildValue("I", i);
-#else
- return Py_BuildValue("i", (int)i);
-#endif
-}
-
-static PyObject *
-UPnP_totalbytereceived(UPnPObject *self)
-{
- UNSIGNED_INTEGER i;
-Py_BEGIN_ALLOW_THREADS
- i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
- self->data.CIF.servicetype);
-Py_END_ALLOW_THREADS
-#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
- return Py_BuildValue("I", i);
-#else
- return Py_BuildValue("i", (int)i);
-#endif
-}
-
-static PyObject *
-UPnP_totalpacketsent(UPnPObject *self)
-{
- UNSIGNED_INTEGER i;
-Py_BEGIN_ALLOW_THREADS
- i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
- self->data.CIF.servicetype);
-Py_END_ALLOW_THREADS
-#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
- return Py_BuildValue("I", i);
-#else
- return Py_BuildValue("i", (int)i);
-#endif
-}
-
-static PyObject *
-UPnP_totalpacketreceived(UPnPObject *self)
-{
- UNSIGNED_INTEGER i;
-Py_BEGIN_ALLOW_THREADS
- i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
- self->data.CIF.servicetype);
-Py_END_ALLOW_THREADS
-#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
- return Py_BuildValue("I", i);
-#else
- return Py_BuildValue("i", (int)i);
-#endif
-}
-
-static PyObject *
-UPnP_statusinfo(UPnPObject *self)
-{
- char status[64];
- char lastconnerror[64];
- unsigned int uptime = 0;
- int r;
- status[0] = '\0';
- lastconnerror[0] = '\0';
-Py_BEGIN_ALLOW_THREADS
- r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.first.servicetype,
- status, &uptime, lastconnerror);
-Py_END_ALLOW_THREADS
- if(r==UPNPCOMMAND_SUCCESS) {
-#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
- return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror);
-#else
- return Py_BuildValue("(s,i,s)", status, (int)uptime, lastconnerror);
-#endif
- } else {
- /* TODO: have our own exception type ! */
- PyErr_SetString(PyExc_Exception, strupnperror(r));
- return NULL;
- }
-}
-
-static PyObject *
-UPnP_connectiontype(UPnPObject *self)
-{
- char connectionType[64];
- int r;
- connectionType[0] = '\0';
-Py_BEGIN_ALLOW_THREADS
- r = UPNP_GetConnectionTypeInfo(self->urls.controlURL,
- self->data.first.servicetype,
- connectionType);
-Py_END_ALLOW_THREADS
- if(r==UPNPCOMMAND_SUCCESS) {
- return Py_BuildValue("s", connectionType);
- } else {
- /* TODO: have our own exception type ! */
- PyErr_SetString(PyExc_Exception, strupnperror(r));
- return NULL;
- }
-}
-
-static PyObject *
-UPnP_externalipaddress(UPnPObject *self)
-{
- char externalIPAddress[40];
- int r;
- externalIPAddress[0] = '\0';
-Py_BEGIN_ALLOW_THREADS
- r = UPNP_GetExternalIPAddress(self->urls.controlURL,
- self->data.first.servicetype,
- externalIPAddress);
-Py_END_ALLOW_THREADS
- if(r==UPNPCOMMAND_SUCCESS) {
- return Py_BuildValue("s", externalIPAddress);
- } else {
- /* TODO: have our own exception type ! */
- PyErr_SetString(PyExc_Exception, strupnperror(r));
- return NULL;
- }
-}
-
-/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc,
- * remoteHost, leaseDuration)
- * protocol is 'UDP' or 'TCP' */
-static PyObject *
-UPnP_addportmapping(UPnPObject *self, PyObject *args)
-{
- char extPort[6];
- unsigned short ePort;
- char inPort[6];
- unsigned short iPort;
- const char * proto;
- const char * host;
- const char * desc;
- const char * remoteHost;
- unsigned int intLeaseDuration = 0;
- char strLeaseDuration[12];
- int r;
-#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
- if (!PyArg_ParseTuple(args, "HssHzz|I", &ePort, &proto,
- &host, &iPort, &desc, &remoteHost, &intLeaseDuration))
-#else
- if (!PyArg_ParseTuple(args, "HssHzz|i", &ePort, &proto,
- &host, &iPort, &desc, &remoteHost, (int *)&intLeaseDuration))
-#endif
- return NULL;
-Py_BEGIN_ALLOW_THREADS
- sprintf(extPort, "%hu", ePort);
- sprintf(inPort, "%hu", iPort);
- sprintf(strLeaseDuration, "%u", intLeaseDuration);
- r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype,
- extPort, inPort, host, desc, proto,
- remoteHost, strLeaseDuration);
-Py_END_ALLOW_THREADS
- if(r==UPNPCOMMAND_SUCCESS)
- {
- Py_RETURN_TRUE;
- }
- else
- {
- // TODO: RAISE an Exception. See upnpcommands.h for errors codes.
- // upnperrors.c
- //Py_RETURN_FALSE;
- /* TODO: have our own exception type ! */
- PyErr_SetString(PyExc_Exception, strupnperror(r));
- return NULL;
- }
-}
-
-/* AddAnyPortMapping(externalPort, protocol, internalHost, internalPort, desc,
- * remoteHost)
- * protocol is 'UDP' or 'TCP' */
-static PyObject *
-UPnP_addanyportmapping(UPnPObject *self, PyObject *args)
-{
- char extPort[6];
- unsigned short ePort;
- char inPort[6];
- unsigned short iPort;
- char reservedPort[6];
- const char * proto;
- const char * host;
- const char * desc;
- const char * remoteHost;
- const char * leaseDuration = "0";
- int r;
- if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto, &host, &iPort, &desc, &remoteHost))
- return NULL;
-Py_BEGIN_ALLOW_THREADS
- sprintf(extPort, "%hu", ePort);
- sprintf(inPort, "%hu", iPort);
- r = UPNP_AddAnyPortMapping(self->urls.controlURL, self->data.first.servicetype,
- extPort, inPort, host, desc, proto,
- remoteHost, leaseDuration, reservedPort);
-Py_END_ALLOW_THREADS
- if(r==UPNPCOMMAND_SUCCESS) {
- return Py_BuildValue("i", atoi(reservedPort));
- } else {
- /* TODO: have our own exception type ! */
- PyErr_SetString(PyExc_Exception, strupnperror(r));
- return NULL;
- }
-}
-
-
-/* DeletePortMapping(extPort, proto, removeHost='')
- * proto = 'UDP', 'TCP' */
-static PyObject *
-UPnP_deleteportmapping(UPnPObject *self, PyObject *args)
-{
- char extPort[6];
- unsigned short ePort;
- const char * proto;
- const char * remoteHost = "";
- int r;
- if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
- return NULL;
-Py_BEGIN_ALLOW_THREADS
- sprintf(extPort, "%hu", ePort);
- r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.first.servicetype,
- extPort, proto, remoteHost);
-Py_END_ALLOW_THREADS
- if(r==UPNPCOMMAND_SUCCESS) {
- Py_RETURN_TRUE;
- } else {
- /* TODO: have our own exception type ! */
- PyErr_SetString(PyExc_Exception, strupnperror(r));
- return NULL;
- }
-}
-
-/* DeletePortMappingRange(extPort, proto, removeHost='')
- * proto = 'UDP', 'TCP' */
-static PyObject *
-UPnP_deleteportmappingrange(UPnPObject *self, PyObject *args)
-{
- char extPortStart[6];
- unsigned short ePortStart;
- char extPortEnd[6];
- unsigned short ePortEnd;
- const char * proto;
- unsigned char manage;
- char manageStr[6];
- int r;
- if(!PyArg_ParseTuple(args, "HHsb", &ePortStart, &ePortEnd, &proto, &manage))
- return NULL;
-Py_BEGIN_ALLOW_THREADS
- sprintf(extPortStart, "%hu", ePortStart);
- sprintf(extPortEnd, "%hu", ePortEnd);
- sprintf(manageStr, "%hu", (unsigned short)manage);
- r = UPNP_DeletePortMappingRange(self->urls.controlURL, self->data.first.servicetype,
- extPortStart, extPortEnd, proto, manageStr);
-Py_END_ALLOW_THREADS
- if(r==UPNPCOMMAND_SUCCESS) {
- Py_RETURN_TRUE;
- } else {
- /* TODO: have our own exception type ! */
- PyErr_SetString(PyExc_Exception, strupnperror(r));
- return NULL;
- }
-}
-
-static PyObject *
-UPnP_getportmappingnumberofentries(UPnPObject *self)
-{
- unsigned int n = 0;
- int r;
-Py_BEGIN_ALLOW_THREADS
- r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL,
- self->data.first.servicetype,
- &n);
-Py_END_ALLOW_THREADS
- if(r==UPNPCOMMAND_SUCCESS) {
-#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
- return Py_BuildValue("I", n);
-#else
- return Py_BuildValue("i", (int)n);
-#endif
- } else {
- /* TODO: have our own exception type ! */
- PyErr_SetString(PyExc_Exception, strupnperror(r));
- return NULL;
- }
-}
-
-/* GetSpecificPortMapping(ePort, proto, remoteHost='')
- * proto = 'UDP' or 'TCP' */
-static PyObject *
-UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
-{
- char extPort[6];
- unsigned short ePort;
- const char * proto;
- const char * remoteHost = "";
- char intClient[40];
- char intPort[6];
- unsigned short iPort;
- char desc[80];
- char enabled[4];
- char leaseDuration[16];
- if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
- return NULL;
- extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0';
- desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0';
-Py_BEGIN_ALLOW_THREADS
- sprintf(extPort, "%hu", ePort);
- UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
- self->data.first.servicetype,
- extPort, proto, remoteHost,
- intClient, intPort,
- desc, enabled, leaseDuration);
-Py_END_ALLOW_THREADS
- if(intClient[0])
- {
- iPort = (unsigned short)atoi(intPort);
- return Py_BuildValue("(s,H,s,O,i)",
- intClient, iPort, desc,
- PyBool_FromLong(atoi(enabled)),
- atoi(leaseDuration));
- }
- else
- {
- Py_RETURN_NONE;
- }
-}
-
-/* GetGenericPortMapping(index) */
-static PyObject *
-UPnP_getgenericportmapping(UPnPObject *self, PyObject *args)
-{
- int i, r;
- char index[8];
- char intClient[40];
- char intPort[6];
- unsigned short iPort;
- char extPort[6];
- unsigned short ePort;
- char protocol[4];
- char desc[80];
- char enabled[6];
- char rHost[64];
- char duration[16]; /* lease duration */
- unsigned int dur;
- if(!PyArg_ParseTuple(args, "i", &i))
- return NULL;
-Py_BEGIN_ALLOW_THREADS
- snprintf(index, sizeof(index), "%d", i);
- rHost[0] = '\0'; enabled[0] = '\0';
- duration[0] = '\0'; desc[0] = '\0';
- extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
- r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL,
- self->data.first.servicetype,
- index,
- extPort, intClient, intPort,
- protocol, desc, enabled, rHost,
- duration);
-Py_END_ALLOW_THREADS
- if(r==UPNPCOMMAND_SUCCESS)
- {
- ePort = (unsigned short)atoi(extPort);
- iPort = (unsigned short)atoi(intPort);
- dur = (unsigned int)strtoul(duration, 0, 0);
-#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
- return Py_BuildValue("(H,s,(s,H),s,s,s,I)",
- ePort, protocol, intClient, iPort,
- desc, enabled, rHost, dur);
-#else
- return Py_BuildValue("(i,s,(s,i),s,s,s,i)",
- (int)ePort, protocol, intClient, (int)iPort,
- desc, enabled, rHost, (int)dur);
-#endif
- }
- else
- {
- Py_RETURN_NONE;
- }
-}
-
-/* miniupnpc.UPnP object Method Table */
-static PyMethodDef UPnP_methods[] = {
- {"discover", (PyCFunction)UPnP_discover, METH_NOARGS,
- "discover UPnP IGD devices on the network"
- },
- {"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS,
- "select a valid UPnP IGD among discovered devices"
- },
- {"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS,
- "return the total number of bytes sent by UPnP IGD"
- },
- {"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS,
- "return the total number of bytes received by UPnP IGD"
- },
- {"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS,
- "return the total number of packets sent by UPnP IGD"
- },
- {"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS,
- "return the total number of packets received by UPnP IGD"
- },
- {"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS,
- "return status and uptime"
- },
- {"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS,
- "return IGD WAN connection type"
- },
- {"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS,
- "return external IP address"
- },
- {"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS,
- "add a port mapping"
- },
- {"addanyportmapping", (PyCFunction)UPnP_addanyportmapping, METH_VARARGS,
- "add a port mapping, IGD to select alternative if necessary"
- },
- {"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS,
- "delete a port mapping"
- },
- {"deleteportmappingrange", (PyCFunction)UPnP_deleteportmappingrange, METH_VARARGS,
- "delete a range of port mappings"
- },
- {"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS,
- "-- non standard --"
- },
- {"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS,
- "get details about a specific port mapping entry"
- },
- {"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS,
- "get all details about the port mapping at index"
- },
- {NULL} /* Sentinel */
-};
-
-static PyTypeObject UPnPType = {
- PyVarObject_HEAD_INIT(NULL,
- 0) /*ob_size*/
- "miniupnpc.UPnP", /*tp_name*/
- sizeof(UPnPObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)UPnPObject_dealloc,/*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- "UPnP objects", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- UPnP_methods, /* tp_methods */
- UPnP_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)UPnP_init, /* tp_init */
- 0, /* tp_alloc */
-#ifndef _WIN32
- PyType_GenericNew,/*UPnP_new,*/ /* tp_new */
-#else
- 0,
-#endif
-};
-
-/* module methods */
-static PyMethodDef miniupnpc_methods[] = {
- {NULL} /* Sentinel */
-};
-
-#if PY_MAJOR_VERSION >= 3
-static struct PyModuleDef moduledef = {
- PyModuleDef_HEAD_INIT,
- "miniupnpc", /* m_name */
- "miniupnpc module.", /* m_doc */
- -1, /* m_size */
- miniupnpc_methods, /* m_methods */
- NULL, /* m_reload */
- NULL, /* m_traverse */
- NULL, /* m_clear */
- NULL, /* m_free */
-};
-#endif
-
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-
-PyMODINIT_FUNC
-#if PY_MAJOR_VERSION >= 3
-PyInit_miniupnpc(void)
-#else
-initminiupnpc(void)
-#endif
-{
- PyObject* m;
-
-#ifdef _WIN32
- /* initialize Winsock. */
- WSADATA wsaData;
- int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
- if (nResult != 0)
- {
- /* error code could be WSASYSNOTREADY WSASYSNOTREADY
- * WSASYSNOTREADY WSASYSNOTREADY WSASYSNOTREADY */
-#if PY_MAJOR_VERSION >= 3
- return 0;
-#else
- return;
-#endif
- }
-
- UPnPType.tp_new = PyType_GenericNew;
-#endif
- if (PyType_Ready(&UPnPType) < 0)
-#if PY_MAJOR_VERSION >= 3
- return 0;
-#else
- return;
-#endif
-
-#if PY_MAJOR_VERSION >= 3
- m = PyModule_Create(&moduledef);
-#else
- m = Py_InitModule3("miniupnpc", miniupnpc_methods,
- "miniupnpc module.");
-#endif
-
- Py_INCREF(&UPnPType);
- PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType);
-
-#if PY_MAJOR_VERSION >= 3
- return m;
-#endif
-}
-
diff --git a/thirdparty/miniupnpc/miniupnpc/miniupnpcstrings.h b/thirdparty/miniupnpc/miniupnpc/miniupnpcstrings.h
index a718cc7bbf..7b3d04074a 100644
--- a/thirdparty/miniupnpc/miniupnpc/miniupnpcstrings.h
+++ b/thirdparty/miniupnpc/miniupnpc/miniupnpcstrings.h
@@ -4,7 +4,7 @@
#include "core/version.h"
#define OS_STRING VERSION_NAME "/1.0"
-#define MINIUPNPC_VERSION_STRING "2.1"
+#define MINIUPNPC_VERSION_STRING "2.2.2"
#if 0
/* according to "UPnP Device Architecture 1.0" */
diff --git a/thirdparty/miniupnpc/miniupnpc/miniwget.c b/thirdparty/miniupnpc/miniupnpc/miniwget.c
index 5c135f4efd..d5b7970632 100644
--- a/thirdparty/miniupnpc/miniupnpc/miniwget.c
+++ b/thirdparty/miniupnpc/miniupnpc/miniwget.c
@@ -1,8 +1,8 @@
-/* $Id: miniwget.c,v 1.78 2018/03/13 23:22:18 nanard Exp $ */
+/* $Id: miniwget.c,v 1.82 2020/05/29 21:14:22 nanard Exp $ */
/* Project : miniupnp
- * Website : http://miniupnp.free.fr/
+ * Website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
- * Copyright (c) 2005-2018 Thomas Bernard
+ * Copyright (c) 2005-2020 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@@ -15,7 +15,7 @@
#include <ws2tcpip.h>
#include <io.h>
#define MAXHOSTNAMELEN 64
-#define snprintf _snprintf
+#include "win32_snprintf.h"
#define socklen_t int
#ifndef strncasecmp
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
@@ -176,11 +176,14 @@ getHTTPResponse(SOCKET s, int * size, int * status_code)
/* Status line
* HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
int sp;
- for(sp = 0; sp < i; sp++)
+ for(sp = 0; sp < i - 1; sp++)
if(header_buf[sp] == ' ')
{
if(*status_code < 0)
- *status_code = atoi(header_buf + sp + 1);
+ {
+ if (header_buf[sp+1] >= '1' && header_buf[sp+1] <= '9')
+ *status_code = atoi(header_buf + sp + 1);
+ }
else
{
#ifdef DEBUG
diff --git a/thirdparty/miniupnpc/miniupnpc/portlistingparse.c b/thirdparty/miniupnpc/miniupnpc/portlistingparse.c
index 18d967b877..162cf8b7ec 100644
--- a/thirdparty/miniupnpc/miniupnpc/portlistingparse.c
+++ b/thirdparty/miniupnpc/miniupnpc/portlistingparse.c
@@ -15,7 +15,7 @@
#if defined(__HAIKU__)
/* rename our private function because Haiku already defines a atoui() function */
#define atoui atoui2
-#endif
+#endif
/* list of the elements */
static const struct {
diff --git a/thirdparty/miniupnpc/miniupnpc/receivedata.c b/thirdparty/miniupnpc/miniupnpc/receivedata.c
index 7b9cc5b778..7f187f6e56 100644
--- a/thirdparty/miniupnpc/miniupnpc/receivedata.c
+++ b/thirdparty/miniupnpc/miniupnpc/receivedata.c
@@ -1,8 +1,8 @@
-/* $Id: receivedata.c,v 1.7 2015/11/09 21:51:41 nanard Exp $ */
+/* $Id: receivedata.c,v 1.10 2021/03/02 23:33:07 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
- * Copyright (c) 2011-2014 Thomas Bernard
+ * Copyright (c) 2011-2021 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@@ -92,7 +92,13 @@ receivedata(SOCKET socket,
#endif /* DEBUG */
if(scope_id)
*scope_id = src_addr6->sin6_scope_id;
+ } else {
+ if(scope_id)
+ *scope_id = 0;
}
+#else /* MINIUPNPC_GET_SRC_ADDR */
+ if(scope_id)
+ *scope_id = 0;
#endif /* MINIUPNPC_GET_SRC_ADDR */
return n;
}
diff --git a/thirdparty/miniupnpc/miniupnpc/upnpc.c b/thirdparty/miniupnpc/miniupnpc/upnpc.c
deleted file mode 100644
index cb7f18b5f6..0000000000
--- a/thirdparty/miniupnpc/miniupnpc/upnpc.c
+++ /dev/null
@@ -1,864 +0,0 @@
-/* $Id: upnpc.c,v 1.119 2018/03/13 23:34:46 nanard Exp $ */
-/* Project : miniupnp
- * Author : Thomas Bernard
- * Copyright (c) 2005-2020 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution. */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#ifdef _WIN32
-#include <winsock2.h>
-#define snprintf _snprintf
-#else
-/* for IPPROTO_TCP / IPPROTO_UDP */
-#include <netinet/in.h>
-#endif
-#include <ctype.h>
-#include "miniwget.h"
-#include "miniupnpc.h"
-#include "upnpcommands.h"
-#include "portlistingparse.h"
-#include "upnperrors.h"
-#include "miniupnpcstrings.h"
-
-/* protofix() checks if protocol is "UDP" or "TCP"
- * returns NULL if not */
-const char * protofix(const char * proto)
-{
- static const char proto_tcp[4] = { 'T', 'C', 'P', 0};
- static const char proto_udp[4] = { 'U', 'D', 'P', 0};
- int i, b;
- for(i=0, b=1; i<4; i++)
- b = b && ( (proto[i] == proto_tcp[i])
- || (proto[i] == (proto_tcp[i] | 32)) );
- if(b)
- return proto_tcp;
- for(i=0, b=1; i<4; i++)
- b = b && ( (proto[i] == proto_udp[i])
- || (proto[i] == (proto_udp[i] | 32)) );
- if(b)
- return proto_udp;
- return 0;
-}
-
-/* is_int() checks if parameter is an integer or not
- * 1 for integer
- * 0 for not an integer */
-int is_int(char const* s)
-{
- if(s == NULL)
- return 0;
- while(*s) {
- /* #define isdigit(c) ((c) >= '0' && (c) <= '9') */
- if(!isdigit(*s))
- return 0;
- s++;
- }
- return 1;
-}
-
-static void DisplayInfos(struct UPNPUrls * urls,
- struct IGDdatas * data)
-{
- char externalIPAddress[40];
- char connectionType[64];
- char status[64];
- char lastconnerr[64];
- unsigned int uptime = 0;
- unsigned int brUp, brDown;
- time_t timenow, timestarted;
- int r;
- if(UPNP_GetConnectionTypeInfo(urls->controlURL,
- data->first.servicetype,
- connectionType) != UPNPCOMMAND_SUCCESS)
- printf("GetConnectionTypeInfo failed.\n");
- else
- printf("Connection Type : %s\n", connectionType);
- if(UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
- status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS)
- printf("GetStatusInfo failed.\n");
- else
- printf("Status : %s, uptime=%us, LastConnectionError : %s\n",
- status, uptime, lastconnerr);
- if(uptime > 0) {
- timenow = time(NULL);
- timestarted = timenow - uptime;
- printf(" Time started : %s", ctime(&timestarted));
- }
- if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype,
- &brDown, &brUp) != UPNPCOMMAND_SUCCESS) {
- printf("GetLinkLayerMaxBitRates failed.\n");
- } else {
- printf("MaxBitRateDown : %u bps", brDown);
- if(brDown >= 1000000) {
- printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10);
- } else if(brDown >= 1000) {
- printf(" (%u Kbps)", brDown / 1000);
- }
- printf(" MaxBitRateUp %u bps", brUp);
- if(brUp >= 1000000) {
- printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10);
- } else if(brUp >= 1000) {
- printf(" (%u Kbps)", brUp / 1000);
- }
- printf("\n");
- }
- r = UPNP_GetExternalIPAddress(urls->controlURL,
- data->first.servicetype,
- externalIPAddress);
- if(r != UPNPCOMMAND_SUCCESS) {
- printf("GetExternalIPAddress failed. (errorcode=%d)\n", r);
- } else {
- printf("ExternalIPAddress = %s\n", externalIPAddress);
- }
-}
-
-static void GetConnectionStatus(struct UPNPUrls * urls,
- struct IGDdatas * data)
-{
- unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
- DisplayInfos(urls, data);
- bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
- bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
- packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
- packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
- printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
- printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
-}
-
-static void ListRedirections(struct UPNPUrls * urls,
- struct IGDdatas * data)
-{
- int r;
- int i = 0;
- char index[6];
- char intClient[40];
- char intPort[6];
- char extPort[6];
- char protocol[4];
- char desc[80];
- char enabled[6];
- char rHost[64];
- char duration[16];
- /*unsigned int num=0;
- UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num);
- printf("PortMappingNumberOfEntries : %u\n", num);*/
- printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
- do {
- snprintf(index, 6, "%d", i);
- rHost[0] = '\0'; enabled[0] = '\0';
- duration[0] = '\0'; desc[0] = '\0';
- extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
- r = UPNP_GetGenericPortMappingEntry(urls->controlURL,
- data->first.servicetype,
- index,
- extPort, intClient, intPort,
- protocol, desc, enabled,
- rHost, duration);
- if(r==0)
- /*
- printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n"
- " desc='%s' rHost='%s'\n",
- i, protocol, extPort, intClient, intPort,
- enabled, duration,
- desc, rHost);
- */
- printf("%2d %s %5s->%s:%-5s '%s' '%s' %s\n",
- i, protocol, extPort, intClient, intPort,
- desc, rHost, duration);
- else
- printf("GetGenericPortMappingEntry() returned %d (%s)\n",
- r, strupnperror(r));
- i++;
- } while(r==0);
-}
-
-static void NewListRedirections(struct UPNPUrls * urls,
- struct IGDdatas * data)
-{
- int r;
- int i = 0;
- struct PortMappingParserData pdata;
- struct PortMapping * pm;
-
- memset(&pdata, 0, sizeof(struct PortMappingParserData));
- r = UPNP_GetListOfPortMappings(urls->controlURL,
- data->first.servicetype,
- "0",
- "65535",
- "TCP",
- "1000",
- &pdata);
- if(r == UPNPCOMMAND_SUCCESS)
- {
- printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
- for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
- {
- printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
- i, pm->protocol, pm->externalPort, pm->internalClient,
- pm->internalPort,
- pm->description, pm->remoteHost,
- (unsigned)pm->leaseTime);
- i++;
- }
- FreePortListing(&pdata);
- }
- else
- {
- printf("GetListOfPortMappings() returned %d (%s)\n",
- r, strupnperror(r));
- }
- r = UPNP_GetListOfPortMappings(urls->controlURL,
- data->first.servicetype,
- "0",
- "65535",
- "UDP",
- "1000",
- &pdata);
- if(r == UPNPCOMMAND_SUCCESS)
- {
- for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
- {
- printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
- i, pm->protocol, pm->externalPort, pm->internalClient,
- pm->internalPort,
- pm->description, pm->remoteHost,
- (unsigned)pm->leaseTime);
- i++;
- }
- FreePortListing(&pdata);
- }
- else
- {
- printf("GetListOfPortMappings() returned %d (%s)\n",
- r, strupnperror(r));
- }
-}
-
-/* Test function
- * 1 - get connection type
- * 2 - get extenal ip address
- * 3 - Add port mapping
- * 4 - get this port mapping from the IGD */
-static int SetRedirectAndTest(struct UPNPUrls * urls,
- struct IGDdatas * data,
- const char * iaddr,
- const char * iport,
- const char * eport,
- const char * proto,
- const char * leaseDuration,
- const char * remoteHost,
- const char * description,
- int addAny)
-{
- char externalIPAddress[40];
- char intClient[40];
- char intPort[6];
- char reservedPort[6];
- char duration[16];
- int r;
-
- if(!iaddr || !iport || !eport || !proto)
- {
- fprintf(stderr, "Wrong arguments\n");
- return -1;
- }
- proto = protofix(proto);
- if(!proto)
- {
- fprintf(stderr, "invalid protocol\n");
- return -1;
- }
-
- r = UPNP_GetExternalIPAddress(urls->controlURL,
- data->first.servicetype,
- externalIPAddress);
- if(r!=UPNPCOMMAND_SUCCESS)
- printf("GetExternalIPAddress failed.\n");
- else
- printf("ExternalIPAddress = %s\n", externalIPAddress);
-
- if (addAny) {
- r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype,
- eport, iport, iaddr, description,
- proto, remoteHost, leaseDuration, reservedPort);
- if(r==UPNPCOMMAND_SUCCESS)
- eport = reservedPort;
- else
- printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n",
- eport, iport, iaddr, r, strupnperror(r));
- } else {
- r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
- eport, iport, iaddr, description,
- proto, remoteHost, leaseDuration);
- if(r!=UPNPCOMMAND_SUCCESS) {
- printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
- eport, iport, iaddr, r, strupnperror(r));
- return -2;
- }
- }
-
- r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
- data->first.servicetype,
- eport, proto, remoteHost,
- intClient, intPort, NULL/*desc*/,
- NULL/*enabled*/, duration);
- if(r!=UPNPCOMMAND_SUCCESS) {
- printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
- r, strupnperror(r));
- return -2;
- } else {
- printf("InternalIP:Port = %s:%s\n", intClient, intPort);
- printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
- externalIPAddress, eport, proto, intClient, intPort, duration);
- }
- return 0;
-}
-
-static int
-RemoveRedirect(struct UPNPUrls * urls,
- struct IGDdatas * data,
- const char * eport,
- const char * proto,
- const char * remoteHost)
-{
- int r;
- if(!proto || !eport)
- {
- fprintf(stderr, "invalid arguments\n");
- return -1;
- }
- proto = protofix(proto);
- if(!proto)
- {
- fprintf(stderr, "protocol invalid\n");
- return -1;
- }
- r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost);
- if(r!=UPNPCOMMAND_SUCCESS) {
- printf("UPNP_DeletePortMapping() failed with code : %d\n", r);
- return -2;
- }else {
- printf("UPNP_DeletePortMapping() returned : %d\n", r);
- }
- return 0;
-}
-
-static int
-RemoveRedirectRange(struct UPNPUrls * urls,
- struct IGDdatas * data,
- const char * ePortStart, char const * ePortEnd,
- const char * proto, const char * manage)
-{
- int r;
-
- if (!manage)
- manage = "0";
-
- if(!proto || !ePortStart || !ePortEnd)
- {
- fprintf(stderr, "invalid arguments\n");
- return -1;
- }
- proto = protofix(proto);
- if(!proto)
- {
- fprintf(stderr, "protocol invalid\n");
- return -1;
- }
- r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage);
- if(r!=UPNPCOMMAND_SUCCESS) {
- printf("UPNP_DeletePortMappingRange() failed with code : %d\n", r);
- return -2;
- }else {
- printf("UPNP_DeletePortMappingRange() returned : %d\n", r);
- }
- return 0;
-}
-
-/* IGD:2, functions for service WANIPv6FirewallControl:1 */
-static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data)
-{
- unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
- int firewallEnabled = 0, inboundPinholeAllowed = 0;
-
- UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed);
- printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed);
- printf("GetFirewallStatus:\n Firewall Enabled: %s\n Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No");
-
- bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
- bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
- packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
- packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
- printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
- printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
-}
-
-/* Test function
- * 1 - Add pinhole
- * 2 - Check if pinhole is working from the IGD side */
-static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data,
- const char * remoteaddr, const char * eport,
- const char * intaddr, const char * iport,
- const char * proto, const char * lease_time)
-{
- char uniqueID[8];
- /*int isWorking = 0;*/
- int r;
- char proto_tmp[8];
-
- if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time)
- {
- fprintf(stderr, "Wrong arguments\n");
- return;
- }
- if(atoi(proto) == 0)
- {
- const char * protocol;
- protocol = protofix(proto);
- if(protocol && (strcmp("TCP", protocol) == 0))
- {
- snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_TCP);
- proto = proto_tmp;
- }
- else if(protocol && (strcmp("UDP", protocol) == 0))
- {
- snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_UDP);
- proto = proto_tmp;
- }
- else
- {
- fprintf(stderr, "invalid protocol\n");
- return;
- }
- }
- r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID);
- if(r!=UPNPCOMMAND_SUCCESS)
- printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
- remoteaddr, eport, intaddr, iport, r, strupnperror(r));
- else
- {
- printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n",
- remoteaddr, eport, intaddr, iport, uniqueID);
- /*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking);
- if(r!=UPNPCOMMAND_SUCCESS)
- printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
- printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/
- }
-}
-
-/* Test function
- * 1 - Check if pinhole is working from the IGD side
- * 2 - Update pinhole */
-static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data,
- const char * uniqueID, const char * lease_time)
-{
- int isWorking = 0;
- int r;
-
- if(!uniqueID || !lease_time)
- {
- fprintf(stderr, "Wrong arguments\n");
- return;
- }
- r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
- printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
- if(r!=UPNPCOMMAND_SUCCESS)
- printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
- if(isWorking || r==709)
- {
- r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time);
- printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time);
- if(r!=UPNPCOMMAND_SUCCESS)
- printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r));
- }
-}
-
-/* Test function
- * Get pinhole timeout
- */
-static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data,
- const char * remoteaddr, const char * eport,
- const char * intaddr, const char * iport,
- const char * proto)
-{
- int timeout = 0;
- int r;
-
- if(!intaddr || !remoteaddr || !iport || !eport || !proto)
- {
- fprintf(stderr, "Wrong arguments\n");
- return;
- }
-
- r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout);
- if(r!=UPNPCOMMAND_SUCCESS)
- printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
- intaddr, iport, remoteaddr, eport, r, strupnperror(r));
- else
- printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout);
-}
-
-static void
-GetPinholePackets(struct UPNPUrls * urls,
- struct IGDdatas * data, const char * uniqueID)
-{
- int r, pinholePackets = 0;
- if(!uniqueID)
- {
- fprintf(stderr, "invalid arguments\n");
- return;
- }
- r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets);
- if(r!=UPNPCOMMAND_SUCCESS)
- printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r));
- else
- printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets);
-}
-
-static void
-CheckPinhole(struct UPNPUrls * urls,
- struct IGDdatas * data, const char * uniqueID)
-{
- int r, isWorking = 0;
- if(!uniqueID)
- {
- fprintf(stderr, "invalid arguments\n");
- return;
- }
- r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
- if(r!=UPNPCOMMAND_SUCCESS)
- printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
- else
- printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
-}
-
-static void
-RemovePinhole(struct UPNPUrls * urls,
- struct IGDdatas * data, const char * uniqueID)
-{
- int r;
- if(!uniqueID)
- {
- fprintf(stderr, "invalid arguments\n");
- return;
- }
- r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID);
- printf("UPNP_DeletePinhole() returned : %d\n", r);
-}
-
-
-/* sample upnp client program */
-int main(int argc, char ** argv)
-{
- char command = 0;
- char ** commandargv = 0;
- int commandargc = 0;
- struct UPNPDev * devlist = 0;
- char lanaddr[64] = "unset"; /* my ip address on the LAN */
- int i;
- const char * rootdescurl = 0;
- const char * multicastif = 0;
- const char * minissdpdpath = 0;
- int localport = UPNP_LOCAL_PORT_ANY;
- int retcode = 0;
- int error = 0;
- int ipv6 = 0;
- unsigned char ttl = 2; /* defaulting to 2 */
- const char * description = 0;
-
-#ifdef _WIN32
- WSADATA wsaData;
- int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
- if(nResult != NO_ERROR)
- {
- fprintf(stderr, "WSAStartup() failed.\n");
- return -1;
- }
-#endif
- printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING);
- printf(" (c) 2005-2020 Thomas Bernard.\n");
- printf("Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/\n"
- "for more information.\n");
- /* command line processing */
- for(i=1; i<argc; i++)
- {
- if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h"))
- {
- command = 0;
- break;
- }
- if(argv[i][0] == '-')
- {
- if(argv[i][1] == 'u')
- rootdescurl = argv[++i];
- else if(argv[i][1] == 'm')
- {
- multicastif = argv[++i];
- minissdpdpath = ""; /* Disable usage of minissdpd */
- }
- else if(argv[i][1] == 'z')
- {
- char junk;
- if(sscanf(argv[++i], "%d%c", &localport, &junk)!=1 ||
- localport<0 || localport>65535 ||
- (localport >1 && localport < 1024))
- {
- fprintf(stderr, "Invalid localport '%s'\n", argv[i]);
- localport = UPNP_LOCAL_PORT_ANY;
- break;
- }
- }
- else if(argv[i][1] == 'p')
- minissdpdpath = argv[++i];
- else if(argv[i][1] == '6')
- ipv6 = 1;
- else if(argv[i][1] == 'e')
- description = argv[++i];
- else if(argv[i][1] == 't')
- ttl = (unsigned char)atoi(argv[++i]);
- else
- {
- command = argv[i][1];
- i++;
- commandargv = argv + i;
- commandargc = argc - i;
- break;
- }
- }
- else
- {
- fprintf(stderr, "option '%s' invalid\n", argv[i]);
- }
- }
-
- if(!command
- || (command == 'a' && commandargc<4)
- || (command == 'd' && argc<2)
- || (command == 'r' && argc<2)
- || (command == 'A' && commandargc<6)
- || (command == 'U' && commandargc<2)
- || (command == 'D' && commandargc<1))
- {
- fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration] [remote host]\n\t\tAdd port redirection\n", argv[0]);
- fprintf(stderr, " \t%s [options] -d external_port protocol [remote host]\n\t\tDelete port redirection\n", argv[0]);
- fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
- fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]);
- fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]);
- fprintf(stderr, " \t%s [options] -n ip port external_port protocol [duration] [remote host]\n\t\tAdd (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]);
- fprintf(stderr, " \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]);
- fprintf(stderr, " \t%s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]);
- fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]);
- fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]);
- fprintf(stderr, " \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]);
- fprintf(stderr, " \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]);
- fprintf(stderr, " \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]);
- fprintf(stderr, " \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]);
- fprintf(stderr, " \t%s [options] -G remote_ip remote_port internal_ip internal_port protocol\n\t\tGet Outbound Pinhole Timeout (for IGD:2 only)\n", argv[0]);
- fprintf(stderr, " \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]);
- fprintf(stderr, "\nprotocol is UDP or TCP\n");
- fprintf(stderr, "Options:\n");
- fprintf(stderr, " -e description : set description for port mapping.\n");
- fprintf(stderr, " -6 : use ip v6 instead of ip v4.\n");
- fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n");
- fprintf(stderr, " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n");
- fprintf(stderr, " -z localport : SSDP packets local (source) port (1024-65535).\n");
- fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n");
- fprintf(stderr, " -t ttl : set multicast TTL. Default value is 2.\n");
- return 1;
- }
-
- if( rootdescurl
- || (devlist = upnpDiscover(2000, multicastif, minissdpdpath,
- localport, ipv6, ttl, &error)))
- {
- struct UPNPDev * device;
- struct UPNPUrls urls;
- struct IGDdatas data;
- if(devlist)
- {
- printf("List of UPNP devices found on the network :\n");
- for(device = devlist; device; device = device->pNext)
- {
- printf(" desc: %s\n st: %s\n\n",
- device->descURL, device->st);
- }
- }
- else if(!rootdescurl)
- {
- printf("upnpDiscover() error code=%d\n", error);
- }
- i = 1;
- if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr)))
- || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))))
- {
- switch(i) {
- case 1:
- printf("Found valid IGD : %s\n", urls.controlURL);
- break;
- case 2:
- printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
- printf("Trying to continue anyway\n");
- break;
- case 3:
- printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
- printf("Trying to continue anyway\n");
- break;
- default:
- printf("Found device (igd ?) : %s\n", urls.controlURL);
- printf("Trying to continue anyway\n");
- }
- printf("Local LAN ip address : %s\n", lanaddr);
- #if 0
- printf("getting \"%s\"\n", urls.ipcondescURL);
- descXML = miniwget(urls.ipcondescURL, &descXMLsize);
- if(descXML)
- {
- /*fwrite(descXML, 1, descXMLsize, stdout);*/
- free(descXML); descXML = NULL;
- }
- #endif
-
- switch(command)
- {
- case 'l':
- DisplayInfos(&urls, &data);
- ListRedirections(&urls, &data);
- break;
- case 'L':
- NewListRedirections(&urls, &data);
- break;
- case 'a':
- if (SetRedirectAndTest(&urls, &data,
- commandargv[0], commandargv[1],
- commandargv[2], commandargv[3],
- (commandargc > 4)&is_int(commandargv[4])?commandargv[4]:"0",
- (commandargc > 4)&!is_int(commandargv[4])?commandargv[4]:(commandargc > 5)?commandargv[5]:NULL,
- description, 0) < 0)
- retcode = 2;
- break;
- case 'd':
- if (RemoveRedirect(&urls, &data, commandargv[0], commandargv[1],
- commandargc > 2 ? commandargv[2] : NULL) < 0)
- retcode = 2;
- break;
- case 'n': /* aNy */
- if (SetRedirectAndTest(&urls, &data,
- commandargv[0], commandargv[1],
- commandargv[2], commandargv[3],
- (commandargc > 4)&is_int(commandargv[4])?commandargv[4]:"0",
- (commandargc > 4)&!is_int(commandargv[4])?commandargv[4]:(commandargc > 5)?commandargv[5]:NULL,
- description, 1) < 0)
- retcode = 2;
- break;
- case 'N':
- if (commandargc < 3)
- fprintf(stderr, "too few arguments\n");
-
- if (RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2],
- commandargc > 3 ? commandargv[3] : NULL) < 0)
- retcode = 2;
- break;
- case 's':
- GetConnectionStatus(&urls, &data);
- break;
- case 'r':
- i = 0;
- while(i<commandargc)
- {
- if(!is_int(commandargv[i])) {
- /* 1st parameter not an integer : error */
- fprintf(stderr, "command -r : %s is not an port number\n", commandargv[i]);
- retcode = 1;
- break;
- } else if(is_int(commandargv[i+1])){
- /* 2nd parameter is an integer : <port> <external_port> <protocol> */
- if (SetRedirectAndTest(&urls, &data,
- lanaddr, commandargv[i],
- commandargv[i+1], commandargv[i+2], "0", NULL,
- description, 0) < 0)
- retcode = 2;
- i+=3; /* 3 parameters parsed */
- } else {
- /* 2nd parameter not an integer : <port> <protocol> */
- if (SetRedirectAndTest(&urls, &data,
- lanaddr, commandargv[i],
- commandargv[i], commandargv[i+1], "0", NULL,
- description, 0) < 0)
- retcode = 2;
- i+=2; /* 2 parameters parsed */
- }
- }
- break;
- case 'A':
- SetPinholeAndTest(&urls, &data,
- commandargv[0], commandargv[1],
- commandargv[2], commandargv[3],
- commandargv[4], commandargv[5]);
- break;
- case 'U':
- GetPinholeAndUpdate(&urls, &data,
- commandargv[0], commandargv[1]);
- break;
- case 'C':
- for(i=0; i<commandargc; i++)
- {
- CheckPinhole(&urls, &data, commandargv[i]);
- }
- break;
- case 'K':
- for(i=0; i<commandargc; i++)
- {
- GetPinholePackets(&urls, &data, commandargv[i]);
- }
- break;
- case 'D':
- for(i=0; i<commandargc; i++)
- {
- RemovePinhole(&urls, &data, commandargv[i]);
- }
- break;
- case 'S':
- GetFirewallStatus(&urls, &data);
- break;
- case 'G':
- GetPinholeOutboundTimeout(&urls, &data,
- commandargv[0], commandargv[1],
- commandargv[2], commandargv[3],
- commandargv[4]);
- break;
- case 'P':
- printf("Presentation URL found:\n");
- printf(" %s\n", data.presentationurl);
- break;
- default:
- fprintf(stderr, "Unknown switch -%c\n", command);
- retcode = 1;
- }
-
- FreeUPNPUrls(&urls);
- }
- else
- {
- fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
- retcode = 1;
- }
- freeUPNPDevlist(devlist); devlist = 0;
- }
- else
- {
- fprintf(stderr, "No IGD UPnP Device found on the network !\n");
- retcode = 1;
- }
-#ifdef _WIN32
- nResult = WSACleanup();
- if(nResult != NO_ERROR) {
- fprintf(stderr, "WSACleanup() failed.\n");
- }
-#endif /* _WIN32 */
- return retcode;
-}
-
diff --git a/thirdparty/miniupnpc/miniupnpc/upnpdev.h b/thirdparty/miniupnpc/miniupnpc/upnpdev.h
index f4ae174426..9b2cb431ba 100644
--- a/thirdparty/miniupnpc/miniupnpc/upnpdev.h
+++ b/thirdparty/miniupnpc/miniupnpc/upnpdev.h
@@ -1,8 +1,8 @@
-/* $Id: upnpdev.h,v 1.1 2015/08/28 12:14:19 nanard Exp $ */
+/* $Id: upnpdev.h,v 1.3 2020/05/29 15:57:42 nanard Exp $ */
/* Project : miniupnp
- * Web : http://miniupnp.free.fr/
+ * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas BERNARD
- * copyright (c) 2005-2018 Thomas Bernard
+ * copyright (c) 2005-2020 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#ifndef UPNPDEV_H_INCLUDED
@@ -20,7 +20,15 @@ struct UPNPDev {
char * st;
char * usn;
unsigned int scope_id;
- char buffer[3];
+#if defined(__STDC_VERSION) && __STDC_VERSION__ >= 199901L
+ /* C99 flexible array member */
+ char buffer[];
+#elif defined(__GNUC__)
+ char buffer[0];
+#else
+ /* Fallback to a hack */
+ char buffer[1];
+#endif
};
/* freeUPNPDevlist()
diff --git a/thirdparty/miniupnpc/miniupnpc/upnperrors.c b/thirdparty/miniupnpc/miniupnpc/upnperrors.c
deleted file mode 100644
index 4496e8622c..0000000000
--- a/thirdparty/miniupnpc/miniupnpc/upnperrors.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/* $Id: upnperrors.c,v 1.10 2019/08/24 08:49:53 nanard Exp $ */
-/* vim: tabstop=4 shiftwidth=4 noexpandtab
- * Project : miniupnp
- * Author : Thomas BERNARD
- * copyright (c) 2007-2019 Thomas Bernard
- * All Right reserved.
- * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
- * This software is subjet to the conditions detailed in the
- * provided LICENCE file. */
-#include <string.h>
-#include "upnperrors.h"
-#include "upnpcommands.h"
-#include "miniupnpc.h"
-
-const char * strupnperror(int err)
-{
- const char * s = NULL;
- switch(err) {
- case UPNPCOMMAND_SUCCESS:
- s = "Success";
- break;
- case UPNPCOMMAND_UNKNOWN_ERROR:
- s = "Miniupnpc Unknown Error";
- break;
- case UPNPCOMMAND_INVALID_ARGS:
- s = "Miniupnpc Invalid Arguments";
- break;
- case UPNPCOMMAND_INVALID_RESPONSE:
- s = "Miniupnpc Invalid response";
- break;
- case UPNPCOMMAND_HTTP_ERROR:
- s = "Miniupnpc HTTP error";
- break;
- case UPNPDISCOVER_SOCKET_ERROR:
- s = "Miniupnpc Socket error";
- break;
- case UPNPDISCOVER_MEMORY_ERROR:
- case UPNPCOMMAND_MEM_ALLOC_ERROR:
- s = "Miniupnpc Memory allocation error";
- break;
- case 401:
- s = "Invalid Action";
- break;
- case 402:
- s = "Invalid Args";
- break;
- case 501:
- s = "Action Failed";
- break;
- case 606:
- s = "Action not authorized";
- break;
- case 701:
- s = "PinholeSpaceExhausted";
- break;
- case 702:
- s = "FirewallDisabled";
- break;
- case 703:
- s = "InboundPinholeNotAllowed";
- break;
- case 704:
- s = "NoSuchEntry";
- break;
- case 705:
- s = "ProtocolNotSupported";
- break;
- case 706:
- s = "InternalPortWildcardingNotAllowed";
- break;
- case 707:
- s = "ProtocolWildcardingNotAllowed";
- break;
- case 708:
- s = "InvalidLayer2Address";
- break;
- case 709:
- s = "NoPacketSent";
- break;
- case 713:
- s = "SpecifiedArrayIndexInvalid";
- break;
- case 714:
- s = "NoSuchEntryInArray";
- break;
- case 715:
- s = "WildCardNotPermittedInSrcIP";
- break;
- case 716:
- s = "WildCardNotPermittedInExtPort";
- break;
- case 718:
- s = "ConflictInMappingEntry";
- break;
- case 724:
- s = "SamePortValuesRequired";
- break;
- case 725:
- s = "OnlyPermanentLeasesSupported";
- break;
- case 726:
- s = "RemoteHostOnlySupportsWildcard";
- break;
- case 727:
- s = "ExternalPortOnlySupportsWildcard";
- break;
- default:
- s = "UnknownError";
- break;
- }
- return s;
-}
diff --git a/thirdparty/miniupnpc/miniupnpc/upnperrors.h b/thirdparty/miniupnpc/miniupnpc/upnperrors.h
deleted file mode 100644
index 8499d9a1c9..0000000000
--- a/thirdparty/miniupnpc/miniupnpc/upnperrors.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* $Id: upnperrors.h,v 1.2 2008/07/02 23:31:15 nanard Exp $ */
-/* (c) 2007-2015 Thomas Bernard
- * All rights reserved.
- * MiniUPnP Project.
- * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * This software is subjet to the conditions detailed in the
- * provided LICENCE file. */
-#ifndef UPNPERRORS_H_INCLUDED
-#define UPNPERRORS_H_INCLUDED
-
-#include "miniupnpc_declspec.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* strupnperror()
- * Return a string description of the UPnP error code
- * or NULL for undefinded errors */
-MINIUPNP_LIBSPEC const char * strupnperror(int err);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/miniupnpc/miniupnpc/win32_snprintf.h b/thirdparty/miniupnpc/miniupnpc/win32_snprintf.h
new file mode 100644
index 0000000000..1fc284ecff
--- /dev/null
+++ b/thirdparty/miniupnpc/miniupnpc/win32_snprintf.h
@@ -0,0 +1,71 @@
+/* vim: tabstop=4 shiftwidth=4 noexpandtab
+ * MiniUPnP project
+ * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
+ * (c) 2020 Pali Rohár
+ * This software is subject to the conditions detailed
+ * in the LICENCE file provided within the distribution */
+
+#ifndef WIN32_SNPRINTF_H
+#define WIN32_SNPRINTF_H
+
+#ifdef _WIN32
+
+#include <stdio.h>
+
+/* snprintf is supported by:
+ * - Visual Studio 2015 or new
+ * - mingw32 with iso c ext
+ * - mingw-w64 with ansi stdio
+ * - mingw-w64 6.0.0 or new with ucrt
+ * - mingw-w64 8.0.0 or new with iso c ext
+ */
+#if ( \
+ (defined(_MSC_VER) && _MSC_VER < 1900) /* Visual Studio older than 2015 */ || \
+ (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) && defined(__NO_ISOCEXT)) /* mingw32 without iso c ext */ || \
+ (defined(__MINGW64_VERSION_MAJOR) && /* mingw-w64 not ... */ !( \
+ (defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO != 0)) /* ... with ansi stdio */ || \
+ (__MINGW64_VERSION_MAJOR >= 6 && defined(_UCRT)) /* ... at least 6.0.0 with ucrt */ || \
+ (__MINGW64_VERSION_MAJOR >= 8 && !defined(__NO_ISOCEXT)) /* ... at least 8.0.0 with iso c ext */ || \
+ 0) || \
+0)
+
+/* _scprintf is supported by:
+ * - Visual Studio 2002 or new
+ * - msvcr70.dll or new
+ * - msvcrt.dll on Windows XP or new
+ */
+#if ( \
+ (defined(_MSC_VER) && _MSC_VER < 1300) /* Visual Studio older than 2002 */ || \
+ (defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x700) /* msvcrt older than 7.0 */ || \
+0)
+#define CHECK_SCPRINTF 0
+#define IF_SCPRINTF(expr) 0
+#define ELSE_SCPRINTF(expr) expr
+#else
+#define CHECK_SCPRINTF 1
+#define IF_SCPRINTF(expr) expr
+#define ELSE_SCPRINTF(expr) 0
+#endif
+
+/* Emulation of snprintf for win32 */
+#define snprintf(buf, size, fmt, ...) ( \
+ (((size) != 0 && (buf) != NULL) ? ( /* _snprintf does not work with NULL buffer */ \
+ _snprintf((buf), (size), (fmt), __VA_ARGS__), /* _snprintf returns -1 on overflow, so ignore its value */ \
+ (((char *)buf)[(size_t)(size)-1] = 0), /* _snprintf does not fill nul byte on overflow */ \
+ 0) : 0), \
+ (CHECK_SCPRINTF ? IF_SCPRINTF( \
+ _scprintf((fmt), __VA_ARGS__) /* calculate return value for snprintf via _scprintf */ \
+ ) : ELSE_SCPRINTF( \
+ ((size) != 0 && (buf) != NULL) ? \
+ strlen((buf)) /* return just length of buffer */ \
+ : \
+ 1 /* no buffer, impossible to calculate, return just non-zero number */ \
+ ) \
+ ) \
+)
+
+#endif
+
+#endif /* _WIN32 */
+
+#endif /* WIN32_SNPRINTF_H */
diff --git a/thirdparty/miniupnpc/windows_fix.diff b/thirdparty/miniupnpc/windows_fix.diff
deleted file mode 100644
index 460b596888..0000000000
--- a/thirdparty/miniupnpc/windows_fix.diff
+++ /dev/null
@@ -1,16 +0,0 @@
-diff --git a/thirdparty/miniupnpc/miniupnpc/minissdpc.c b/thirdparty/miniupnpc/miniupnpc/minissdpc.c
-index 29f8110155..ea9af02e1f 100644
---- a/thirdparty/miniupnpc/miniupnpc/minissdpc.c
-+++ b/thirdparty/miniupnpc/miniupnpc/minissdpc.c
-@@ -683,11 +683,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
- #endif
- } else {
- struct in_addr mc_if;
--#if defined(_WIN32) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
-- InetPtonA(AF_INET, multicastif, &mc_if);
--#else
- mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
--#endif
- if(mc_if.s_addr != INADDR_NONE)
- {
- ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;